diff --git binutils-2.30/bfd/bfd-in2.h binutils-2.30-nds32/bfd/bfd-in2.h index f4b3720b4b..49ac0a3a18 100644 --- binutils-2.30/bfd/bfd-in2.h +++ binutils-2.30-nds32/bfd/bfd-in2.h @@ -4137,6 +4137,9 @@ and shift left by 1 for use in lhi.gp, shi.gp... */ and shift left by 0 for use in lbi.gp, sbi.gp... */ BFD_RELOC_NDS32_SDA19S0, +/* This is a 24-bit reloc for security check sum. */ + BFD_RELOC_NDS32_SECURITY_16, + /* for PIC */ BFD_RELOC_NDS32_GOT20, BFD_RELOC_NDS32_9_PLTREL, @@ -4248,18 +4251,43 @@ This is a 5 bit absolute address. */ /* For TLS. */ BFD_RELOC_NDS32_TPOFF, + BFD_RELOC_NDS32_GOTTPOFF, BFD_RELOC_NDS32_TLS_LE_HI20, BFD_RELOC_NDS32_TLS_LE_LO12, - BFD_RELOC_NDS32_TLS_LE_ADD, - BFD_RELOC_NDS32_TLS_LE_LS, - BFD_RELOC_NDS32_GOTTPOFF, - BFD_RELOC_NDS32_TLS_IE_HI20, - BFD_RELOC_NDS32_TLS_IE_LO12S2, - BFD_RELOC_NDS32_TLS_TPOFF, BFD_RELOC_NDS32_TLS_LE_20, BFD_RELOC_NDS32_TLS_LE_15S0, BFD_RELOC_NDS32_TLS_LE_15S1, BFD_RELOC_NDS32_TLS_LE_15S2, + BFD_RELOC_NDS32_TLS_LE_ADD, + BFD_RELOC_NDS32_TLS_LE_LS, + BFD_RELOC_NDS32_TLS_IE_HI20, + BFD_RELOC_NDS32_TLS_IE_LO12, + BFD_RELOC_NDS32_TLS_IE_LO12S2, + BFD_RELOC_NDS32_TLS_IEGP_HI20, + BFD_RELOC_NDS32_TLS_IEGP_LO12, + BFD_RELOC_NDS32_TLS_IEGP_LO12S2, + BFD_RELOC_NDS32_TLS_IEGP_LW, + BFD_RELOC_NDS32_TLS_DESC, + BFD_RELOC_NDS32_TLS_DESC_HI20, + BFD_RELOC_NDS32_TLS_DESC_LO12, + BFD_RELOC_NDS32_TLS_DESC_20, + BFD_RELOC_NDS32_TLS_DESC_SDA17S2, + BFD_RELOC_NDS32_TLS_DESC_ADD, + BFD_RELOC_NDS32_TLS_DESC_FUNC, + BFD_RELOC_NDS32_TLS_DESC_CALL, + BFD_RELOC_NDS32_TLS_DESC_MEM, + BFD_RELOC_NDS32_REMOVE, + BFD_RELOC_NDS32_GROUP, + +/* Jump-patch table relative relocations. */ + BFD_RELOC_NDS32_ICT, + BFD_RELOC_NDS32_ICT_HI20, + BFD_RELOC_NDS32_ICT_LO12, + BFD_RELOC_NDS32_ICT_25PC, + BFD_RELOC_NDS32_ICT_LO12S2, + +/* For bug 12566. */ + BFD_RELOC_NDS32_LSI, /* This is a 9-bit reloc */ BFD_RELOC_V850_9_PCREL, diff --git binutils-2.30/bfd/config.bfd binutils-2.30-nds32/bfd/config.bfd index f04a993f06..9aa2fc63a8 100644 --- binutils-2.30/bfd/config.bfd +++ binutils-2.30-nds32/bfd/config.bfd @@ -1260,11 +1260,13 @@ case "${targ}" in nds32*le-*-linux*) targ_defvec=nds32_elf32_linux_le_vec targ_selvecs=nds32_elf32_linux_be_vec + targ_cflags=-DNDS32_LINUX_TOOLCHAIN ;; nds32*be-*-linux*) targ_defvec=nds32_elf32_linux_be_vec targ_selvecs=nds32_elf32_linux_le_vec + targ_cflags=-DNDS32_LINUX_TOOLCHAIN ;; nds32*le-*-*) diff --git binutils-2.30/bfd/elf32-nds32.c binutils-2.30-nds32/bfd/elf32-nds32.c index 5ceb0a0b26..06be7a24bd 100644 --- binutils-2.30/bfd/elf32-nds32.c +++ binutils-2.30-nds32/bfd/elf32-nds32.c @@ -20,6 +20,8 @@ 02110-1301, USA. */ +#pragma GCC diagnostic ignored "-Wstack-usage=" + #include "sysdep.h" #include "bfd.h" #include "bfd_stdint.h" @@ -33,6 +35,7 @@ #include "elf32-nds32.h" #include "opcode/cgen.h" #include "../opcodes/nds32-opc.h" +#include /* Relocation HOWTO functions. */ static bfd_reloc_status_type nds32_elf_ignore_reloc @@ -56,36 +59,72 @@ static bfd_reloc_status_type nds32_elf_sda15_reloc static bfd_reloc_status_type nds32_elf_do_9_pcrel_reloc (bfd *, reloc_howto_type *, asection *, bfd_byte *, bfd_vma, asection *, bfd_vma, bfd_vma); +static void nds32_elf_relocate_hi20 + (bfd *, int, Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_byte *, bfd_vma); +static reloc_howto_type *bfd_elf32_bfd_reloc_type_table_lookup + (enum elf_nds32_reloc_type); +static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup + (bfd *, bfd_reloc_code_real_type); + +/* Target hooks. */ +static void nds32_info_to_howto_rel + (bfd *, arelent *, Elf_Internal_Rela *); +static void nds32_info_to_howto + (bfd *, arelent *, Elf_Internal_Rela *); +static bfd_boolean nds32_elf_add_symbol_hook + (bfd *, struct bfd_link_info *, Elf_Internal_Sym *, const char **, + flagword *, asection **, bfd_vma *); +static bfd_boolean nds32_elf_relocate_section + (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, + Elf_Internal_Rela *, Elf_Internal_Sym *, asection **); +static bfd_boolean nds32_elf_object_p (bfd *); +static void nds32_elf_final_write_processing (bfd *, bfd_boolean); +static bfd_boolean nds32_elf_set_private_flags (bfd *, flagword); +static bfd_boolean nds32_elf_merge_private_bfd_data (bfd *, struct bfd_link_info *); +static bfd_boolean nds32_elf_print_private_bfd_data (bfd *, void *); +static bfd_boolean nds32_elf_check_relocs + (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *); +static asection *nds32_elf_gc_mark_hook + (asection *, struct bfd_link_info *, Elf_Internal_Rela *, + struct elf_link_hash_entry *, Elf_Internal_Sym *); +static bfd_boolean nds32_elf_adjust_dynamic_symbol + (struct bfd_link_info *, struct elf_link_hash_entry *); +static bfd_boolean nds32_elf_size_dynamic_sections + (bfd *, struct bfd_link_info *); +static bfd_boolean nds32_elf_create_dynamic_sections + (bfd *, struct bfd_link_info *); +static bfd_boolean nds32_elf_finish_dynamic_sections + (bfd *, struct bfd_link_info *info); +static bfd_boolean nds32_elf_finish_dynamic_symbol + (bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, + Elf_Internal_Sym *); +static bfd_boolean nds32_elf_mkobject (bfd *); /* Nds32 helper functions. */ +static bfd_reloc_status_type nds32_elf_final_sda_base + (bfd *, struct bfd_link_info *, bfd_vma *, bfd_boolean); +static bfd_boolean allocate_dynrelocs (struct elf_link_hash_entry *, void *); +static bfd_boolean readonly_dynrelocs (struct elf_link_hash_entry *, void *); +static Elf_Internal_Rela *find_relocs_at_address + (Elf_Internal_Rela *, Elf_Internal_Rela *, + Elf_Internal_Rela *, enum elf_nds32_reloc_type); static bfd_vma calculate_memory_address -(bfd *, Elf_Internal_Rela *, Elf_Internal_Sym *, Elf_Internal_Shdr *); + (bfd *, Elf_Internal_Rela *, Elf_Internal_Sym *, Elf_Internal_Shdr *); static int nds32_get_section_contents (bfd *, asection *, bfd_byte **, bfd_boolean); -static bfd_boolean nds32_elf_ex9_build_hash_table -(bfd *, asection *, struct bfd_link_info *); -static bfd_boolean nds32_elf_ex9_itb_base (struct bfd_link_info *); -static void nds32_elf_ex9_import_table (struct bfd_link_info *); -static void nds32_elf_ex9_finish (struct bfd_link_info *); -static void nds32_elf_ex9_reloc_jmp (struct bfd_link_info *); -static void nds32_elf_get_insn_with_reg - (Elf_Internal_Rela *, uint32_t, uint32_t *); static int nds32_get_local_syms (bfd *, asection *ATTRIBUTE_UNUSED, Elf_Internal_Sym **); -static bfd_boolean nds32_elf_ex9_replace_instruction - (struct bfd_link_info *, bfd *, asection *); -static bfd_boolean nds32_elf_ifc_calc (struct bfd_link_info *, bfd *, - asection *); -static bfd_boolean nds32_elf_ifc_finish (struct bfd_link_info *); -static bfd_boolean nds32_elf_ifc_replace (struct bfd_link_info *); -static bfd_boolean nds32_elf_ifc_reloc (void); -static bfd_boolean nds32_relax_fp_as_gp - (struct bfd_link_info *link_info, bfd *abfd, asection *sec, - Elf_Internal_Rela *internal_relocs, Elf_Internal_Rela *irelend, - Elf_Internal_Sym *isymbuf); +static bfd_boolean nds32_relax_fp_as_gp + (struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *, + Elf_Internal_Rela *, Elf_Internal_Sym *); static bfd_boolean nds32_fag_remove_unused_fpbase - (bfd *abfd, asection *sec, Elf_Internal_Rela *internal_relocs, - Elf_Internal_Rela *irelend); + (bfd *, asection *, Elf_Internal_Rela *, Elf_Internal_Rela *); +static bfd_byte *nds32_elf_get_relocated_section_contents + (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *, + bfd_boolean, asymbol **); +static void nds32_elf_ict_hash_init (void); +static void nds32_elf_ict_relocate (bfd *, struct bfd_link_info *); +static asection* nds32_elf_get_target_section (struct bfd_link_info *, char *); enum { @@ -95,13 +134,24 @@ enum MACH_V3M = bfd_mach_n1h_v3m }; +/* If ABI is set by the option --mabi, without + checking the ABI compatible. */ +static char *output_abi; + #define MIN(a, b) ((a) > (b) ? (b) : (a)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) +/* True if insn is 4byte. */ +#define INSN_32BIT(insn) ((((insn) & 0x80000000) == 0 ? (TRUE) : (FALSE))) + /* The name of the dynamic interpreter. This is put in the .interp section. */ #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" +#define NDS32_GUARD_SEC_P(flags) ((flags) & SEC_ALLOC \ + && (flags) & SEC_LOAD \ + && (flags) & SEC_READONLY) + /* The nop opcode we use. */ #define NDS32_NOP32 0x40000009 #define NDS32_NOP16 0x9200 @@ -113,32 +163,32 @@ enum /* The first entry in a procedure linkage table are reserved, and the initial contents are unimportant (we zero them out). Subsequent entries look like this. */ -#define PLT0_ENTRY_WORD0 0x46f00000 /* sethi r15, HI20(.got+4) */ -#define PLT0_ENTRY_WORD1 0x58f78000 /* ori r15, r25, LO12(.got+4) */ -#define PLT0_ENTRY_WORD2 0x05178000 /* lwi r17, [r15+0] */ -#define PLT0_ENTRY_WORD3 0x04f78001 /* lwi r15, [r15+4] */ -#define PLT0_ENTRY_WORD4 0x4a003c00 /* jr r15 */ +#define PLT0_ENTRY_WORD0 0x46f00000 /* sethi r15, HI20(.got+4) */ +#define PLT0_ENTRY_WORD1 0x58f78000 /* ori r15, r25, LO12(.got+4) */ +#define PLT0_ENTRY_WORD2 0x05178000 /* lwi r17, [r15+0] */ +#define PLT0_ENTRY_WORD3 0x04f78001 /* lwi r15, [r15+4] */ +#define PLT0_ENTRY_WORD4 0x4a003c00 /* jr r15 */ /* $ta is change to $r15 (from $r25). */ #define PLT0_PIC_ENTRY_WORD0 0x46f00000 /* sethi r15, HI20(got[1]@GOT) */ -#define PLT0_PIC_ENTRY_WORD1 0x58f78000 /* ori r15, r15, LO12(got[1]@GOT) */ -#define PLT0_PIC_ENTRY_WORD2 0x40f7f400 /* add r15, gp, r15 */ -#define PLT0_PIC_ENTRY_WORD3 0x05178000 /* lwi r17, [r15+0] */ -#define PLT0_PIC_ENTRY_WORD4 0x04f78001 /* lwi r15, [r15+4] */ -#define PLT0_PIC_ENTRY_WORD5 0x4a003c00 /* jr r15 */ - -#define PLT_ENTRY_WORD0 0x46f00000 /* sethi r15, HI20(&got[n+3]) */ -#define PLT_ENTRY_WORD1 0x04f78000 /* lwi r15, r15, LO12(&got[n+3]) */ -#define PLT_ENTRY_WORD2 0x4a003c00 /* jr r15 */ -#define PLT_ENTRY_WORD3 0x45000000 /* movi r16, sizeof(RELA) * n */ -#define PLT_ENTRY_WORD4 0x48000000 /* j .plt0. */ - -#define PLT_PIC_ENTRY_WORD0 0x46f00000 /* sethi r15, HI20(got[n+3]@GOT) */ -#define PLT_PIC_ENTRY_WORD1 0x58f78000 /* ori r15, r15, LO12(got[n+3]@GOT) */ -#define PLT_PIC_ENTRY_WORD2 0x38febc02 /* lw r15, [gp+r15] */ -#define PLT_PIC_ENTRY_WORD3 0x4a003c00 /* jr r15 */ -#define PLT_PIC_ENTRY_WORD4 0x45000000 /* movi r16, sizeof(RELA) * n */ -#define PLT_PIC_ENTRY_WORD5 0x48000000 /* j .plt0 */ +#define PLT0_PIC_ENTRY_WORD1 0x58f78000 /* ori r15, r15, LO12(got[1]@GOT) */ +#define PLT0_PIC_ENTRY_WORD2 0x40f7f400 /* add r15, gp, r15 */ +#define PLT0_PIC_ENTRY_WORD3 0x05178000 /* lwi r17, [r15+0] */ +#define PLT0_PIC_ENTRY_WORD4 0x04f78001 /* lwi r15, [r15+4] */ +#define PLT0_PIC_ENTRY_WORD5 0x4a003c00 /* jr r15 */ + +#define PLT_ENTRY_WORD0 0x46f00000 /* sethi r15, HI20(&got[n+3]) */ +#define PLT_ENTRY_WORD1 0x04f78000 /* lwi r15, r15, LO12(&got[n+3]) */ +#define PLT_ENTRY_WORD2 0x4a003c00 /* jr r15 */ +#define PLT_ENTRY_WORD3 0x45000000 /* movi r16, sizeof(RELA) * n */ +#define PLT_ENTRY_WORD4 0x48000000 /* j .plt0 */ + +#define PLT_PIC_ENTRY_WORD0 0x46f00000 /* sethi r15, HI20(got[n+3]@GOT) */ +#define PLT_PIC_ENTRY_WORD1 0x58f78000 /* ori r15, r15, LO12(got[n+3]@GOT) */ +#define PLT_PIC_ENTRY_WORD2 0x38febc02 /* lw r15, [gp+r15] */ +#define PLT_PIC_ENTRY_WORD3 0x4a003c00 /* jr r15 */ +#define PLT_PIC_ENTRY_WORD4 0x45000000 /* movi r16, sizeof(RELA) * n */ +#define PLT_PIC_ENTRY_WORD5 0x48000000 /* j .plt0 */ /* These are macros used to get the relocation accurate value. */ #define ACCURATE_8BIT_S1 (0x100) @@ -160,10 +210,11 @@ enum #define CONSERVATIVE_19BIT (0x40000 - 0x1000) #define CONSERVATIVE_20BIT (0x80000 - 0x1000) +#define NDS32_ICT_SECTION ".nds32.ict" + /* Size of small data/bss sections, used to calculate SDA_BASE. */ static long got_size = 0; static int is_SDA_BASE_set = 0; -static int is_ITB_BASE_set = 0; /* Convert ELF-VER in eflags to string for debugging purpose. */ static const char *const nds32_elfver_strtab[] = @@ -192,37 +243,108 @@ struct elf_nds32_pcrel_relocs_copied bfd_size_type count; }; +/* The sh linker needs to keep track of the number of relocs that it + decides to copy as dynamic relocs in check_relocs for each symbol. + This is so that it can later discard them if they are found to be + unnecessary. We store the information in a field extending the + regular ELF linker hash table. */ + +struct elf_nds32_dyn_relocs +{ + struct elf_nds32_dyn_relocs *next; + + /* The input section of the reloc. */ + asection *sec; + + /* Total number of relocs copied for the input section. */ + bfd_size_type count; + + /* Number of pc-relative relocs copied for the input section. */ + bfd_size_type pc_count; +}; + /* Nds32 ELF linker hash entry. */ +enum elf_nds32_tls_type +{ + GOT_UNKNOWN = (0), + GOT_NORMAL = (1 << 0), + GOT_TLS_LE = (1 << 1), + GOT_TLS_IE = (1 << 2), + GOT_TLS_IEGP = (1 << 3), + GOT_TLS_LD = (1 << 4), + GOT_TLS_GD = (1 << 5), + GOT_TLS_DESC = (1 << 6), +}; + struct elf_nds32_link_hash_entry { struct elf_link_hash_entry root; /* Track dynamic relocs copied for this symbol. */ - struct elf_dyn_relocs *dyn_relocs; + struct elf_nds32_dyn_relocs *dyn_relocs; /* For checking relocation type. */ -#define GOT_UNKNOWN 0 -#define GOT_NORMAL 1 -#define GOT_TLS_IE 2 - unsigned int tls_type; + enum elf_nds32_tls_type tls_type; + + int offset_to_gp; + + /* For saving function attribute indirect_call and entry address. */ + bfd_boolean indirect_call; }; /* Get the nds32 ELF linker hash table from a link_info structure. */ #define FP_BASE_NAME "_FP_BASE_" static int check_start_export_sym = 0; -static size_t ex9_relax_size = 0; /* Save ex9 predicted reducing size. */ +/* File for exporting indirect call table. */ +static FILE *ict_file = NULL; +/* Save object ict model. */ +static unsigned int ict_model = 0; +/* True if _INDIRECT_CALL_TABLE_BASE_ is defined. */ +static bfd_boolean ignore_indirect_call = FALSE; +/* Be used to set ifc bit in elf header. */ +static bfd_boolean ifc_flag = FALSE; + +/* Rom-patch symbol hash table. */ +struct elf_nds32_ict_hash_entry +{ + struct bfd_hash_entry root; + struct elf_link_hash_entry *h; + unsigned int order; +}; + +/* Rom-patch hash table. */ +static struct bfd_hash_table indirect_call_table; /* The offset for executable tls relaxation. */ #define TP_OFFSET 0x0 +typedef struct +{ + int min_id; + int max_id; + int count; + int bias; + int init; +} elf32_nds32_relax_group_t; + struct elf_nds32_obj_tdata { struct elf_obj_tdata root; /* tls_type for each local got entry. */ char *local_got_tls_type; + + unsigned int hdr_size; + + /* GOTPLT entries for TLS descriptors. */ + bfd_vma *local_tlsdesc_gotent; + + int* offset_to_gp; + + /* for R_NDS32_RELAX_GROUP handling. */ + elf32_nds32_relax_group_t relax_group; }; #define elf_nds32_tdata(bfd) \ @@ -231,6 +353,12 @@ struct elf_nds32_obj_tdata #define elf32_nds32_local_got_tls_type(bfd) \ (elf_nds32_tdata (bfd)->local_got_tls_type) +#define elf32_nds32_local_gp_offset(bfd) \ + (elf_nds32_tdata (bfd)->offset_to_gp) + +#define elf32_nds32_relax_group_ptr(bfd) \ + &(elf_nds32_tdata (bfd)->relax_group) + #define elf32_nds32_hash_entry(ent) ((struct elf_nds32_link_hash_entry *)(ent)) static bfd_boolean @@ -240,68 +368,75 @@ nds32_elf_mkobject (bfd *abfd) NDS32_ELF_DATA); } + /* Relocations used for relocation. */ -static reloc_howto_type nds32_elf_howto_table[] = -{ +/* NOTE! + the index order must be the same with elf_nds32_reloc_type in + include/elf/nds32.h + */ +#define HOWTO2(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ + [C] = HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) + +static reloc_howto_type nds32_elf_howto_table[] = { /* This reloc does nothing. */ - HOWTO (R_NDS32_NONE, /* type */ - 0, /* rightshift */ - 3, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_NONE", /* name */ - FALSE, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_NONE, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_NONE", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ /* A 16 bit absolute relocation. */ - HOWTO (R_NDS32_16, /* type */ - 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - nds32_elf_generic_reloc, /* special_function */ - "R_NDS32_16", /* name */ - FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_16, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + nds32_elf_generic_reloc,/* special_function */ + "R_NDS32_16", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* A 32 bit absolute relocation. */ - HOWTO (R_NDS32_32, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - nds32_elf_generic_reloc, /* special_function */ - "R_NDS32_32", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + nds32_elf_generic_reloc,/* special_function */ + "R_NDS32_32", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* A 20 bit address. */ - HOWTO (R_NDS32_20, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 20, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_unsigned, /* complain_on_overflow */ - nds32_elf_generic_reloc, /* special_function */ - "R_NDS32_20", /* name */ - FALSE, /* partial_inplace */ - 0xfffff, /* src_mask */ - 0xfffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_20, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned,/* complain_on_overflow */ + nds32_elf_generic_reloc,/* special_function */ + "R_NDS32_20", /* name */ + FALSE, /* partial_inplace */ + 0xfffff, /* src_mask */ + 0xfffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* An PC Relative 9-bit relocation, shifted by 2. This reloc is complicated because relocations are relative to pc & -4. @@ -311,1910 +446,2264 @@ static reloc_howto_type nds32_elf_howto_table[] = Branch relaxing in the assembler can store the addend in the insn, and if bfd_install_relocation gets called the addend may get added again. */ - HOWTO (R_NDS32_9_PCREL, /* type */ - 1, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 8, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - nds32_elf_9_pcrel_reloc, /* special_function */ - "R_NDS32_9_PCREL", /* name */ - FALSE, /* partial_inplace */ - 0xff, /* src_mask */ - 0xff, /* dst_mask */ - TRUE), /* pcrel_offset */ + HOWTO2 (R_NDS32_9_PCREL, /* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + nds32_elf_9_pcrel_reloc,/* special_function */ + "R_NDS32_9_PCREL", /* name */ + FALSE, /* partial_inplace */ + 0xff, /* src_mask */ + 0xff, /* dst_mask */ + TRUE), /* pcrel_offset */ /* A relative 15 bit relocation, right shifted by 1. */ - HOWTO (R_NDS32_15_PCREL, /* type */ - 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 14, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_15_PCREL", /* name */ - FALSE, /* partial_inplace */ - 0x3fff, /* src_mask */ - 0x3fff, /* dst_mask */ - TRUE), /* pcrel_offset */ + HOWTO2 (R_NDS32_15_PCREL, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 14, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_15_PCREL", /* name */ + FALSE, /* partial_inplace */ + 0x3fff, /* src_mask */ + 0x3fff, /* dst_mask */ + TRUE), /* pcrel_offset */ /* A relative 17 bit relocation, right shifted by 1. */ - HOWTO (R_NDS32_17_PCREL, /* type */ - 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_17_PCREL", /* name */ - FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + HOWTO2 (R_NDS32_17_PCREL, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_17_PCREL", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + TRUE), /* pcrel_offset */ /* A relative 25 bit relocation, right shifted by 1. */ /* ??? It's not clear whether this should have partial_inplace set or not. Branch relaxing in the assembler can store the addend in the insn, and if bfd_install_relocation gets called the addend may get added again. */ - HOWTO (R_NDS32_25_PCREL, /* type */ - 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 24, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_25_PCREL", /* name */ - FALSE, /* partial_inplace */ - 0xffffff, /* src_mask */ - 0xffffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + HOWTO2 (R_NDS32_25_PCREL, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 24, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_25_PCREL", /* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + TRUE), /* pcrel_offset */ /* High 20 bits of address when lower 12 is or'd in. */ - HOWTO (R_NDS32_HI20, /* type */ - 12, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 20, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_hi20_reloc, /* special_function */ - "R_NDS32_HI20", /* name */ - FALSE, /* partial_inplace */ - 0x000fffff, /* src_mask */ - 0x000fffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_HI20, /* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_hi20_reloc, /* special_function */ + "R_NDS32_HI20", /* name */ + FALSE, /* partial_inplace */ + 0x000fffff, /* src_mask */ + 0x000fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Lower 12 bits of address. */ - HOWTO (R_NDS32_LO12S3, /* type */ - 3, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 9, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_lo12_reloc, /* special_function */ - "R_NDS32_LO12S3", /* name */ - FALSE, /* partial_inplace */ - 0x000001ff, /* src_mask */ - 0x000001ff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LO12S3, /* type */ + 3, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 9, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_lo12_reloc, /* special_function */ + "R_NDS32_LO12S3", /* name */ + FALSE, /* partial_inplace */ + 0x000001ff, /* src_mask */ + 0x000001ff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Lower 12 bits of address. */ - HOWTO (R_NDS32_LO12S2, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 10, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_lo12_reloc, /* special_function */ - "R_NDS32_LO12S2", /* name */ - FALSE, /* partial_inplace */ - 0x000003ff, /* src_mask */ - 0x000003ff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LO12S2, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 10, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_lo12_reloc, /* special_function */ + "R_NDS32_LO12S2", /* name */ + FALSE, /* partial_inplace */ + 0x000003ff, /* src_mask */ + 0x000003ff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Lower 12 bits of address. */ - HOWTO (R_NDS32_LO12S1, /* type */ - 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 11, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_lo12_reloc, /* special_function */ - "R_NDS32_LO12S1", /* name */ - FALSE, /* partial_inplace */ - 0x000007ff, /* src_mask */ - 0x000007ff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LO12S1, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 11, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_lo12_reloc, /* special_function */ + "R_NDS32_LO12S1", /* name */ + FALSE, /* partial_inplace */ + 0x000007ff, /* src_mask */ + 0x000007ff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Lower 12 bits of address. */ - HOWTO (R_NDS32_LO12S0, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_lo12_reloc, /* special_function */ - "R_NDS32_LO12S0", /* name */ - FALSE, /* partial_inplace */ - 0x00000fff, /* src_mask */ - 0x00000fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LO12S0, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_lo12_reloc, /* special_function */ + "R_NDS32_LO12S0", /* name */ + FALSE, /* partial_inplace */ + 0x00000fff, /* src_mask */ + 0x00000fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Small data area 15 bits offset. */ - HOWTO (R_NDS32_SDA15S3, /* type */ - 3, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 15, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - nds32_elf_sda15_reloc, /* special_function */ - "R_NDS32_SDA15S3", /* name */ - FALSE, /* partial_inplace */ - 0x00007fff, /* src_mask */ - 0x00007fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_SDA15S3, /* type */ + 3, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + nds32_elf_sda15_reloc, /* special_function */ + "R_NDS32_SDA15S3", /* name */ + FALSE, /* partial_inplace */ + 0x00007fff, /* src_mask */ + 0x00007fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Small data area 15 bits offset. */ - HOWTO (R_NDS32_SDA15S2, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 15, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - nds32_elf_sda15_reloc, /* special_function */ - "R_NDS32_SDA15S2", /* name */ - FALSE, /* partial_inplace */ - 0x00007fff, /* src_mask */ - 0x00007fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_SDA15S2, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + nds32_elf_sda15_reloc, /* special_function */ + "R_NDS32_SDA15S2", /* name */ + FALSE, /* partial_inplace */ + 0x00007fff, /* src_mask */ + 0x00007fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Small data area 15 bits offset. */ - HOWTO (R_NDS32_SDA15S1, /* type */ - 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 15, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - nds32_elf_sda15_reloc, /* special_function */ - "R_NDS32_SDA15S1", /* name */ - FALSE, /* partial_inplace */ - 0x00007fff, /* src_mask */ - 0x00007fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_SDA15S1, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + nds32_elf_sda15_reloc, /* special_function */ + "R_NDS32_SDA15S1", /* name */ + FALSE, /* partial_inplace */ + 0x00007fff, /* src_mask */ + 0x00007fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Small data area 15 bits offset. */ - HOWTO (R_NDS32_SDA15S0, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 15, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - nds32_elf_sda15_reloc, /* special_function */ - "R_NDS32_SDA15S0", /* name */ - FALSE, /* partial_inplace */ - 0x00007fff, /* src_mask */ - 0x00007fff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* GNU extension to record C++ vtable hierarchy */ - HOWTO (R_NDS32_GNU_VTINHERIT, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - NULL, /* special_function */ - "R_NDS32_GNU_VTINHERIT", /* name */ - FALSE, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* GNU extension to record C++ vtable member usage */ - HOWTO (R_NDS32_GNU_VTENTRY, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - _bfd_elf_rel_vtable_reloc_fn, /* special_function */ - "R_NDS32_GNU_VTENTRY", /* name */ - FALSE, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_SDA15S0, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + nds32_elf_sda15_reloc, /* special_function */ + "R_NDS32_SDA15S0", /* name */ + FALSE, /* partial_inplace */ + 0x00007fff, /* src_mask */ + 0x00007fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* GNU extension to record C++ vtable hierarchy */ + HOWTO2 (R_NDS32_GNU_VTINHERIT,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + NULL, /* special_function */ + "R_NDS32_GNU_VTINHERIT",/* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* GNU extension to record C++ vtable member usage */ + HOWTO2 (R_NDS32_GNU_VTENTRY, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + _bfd_elf_rel_vtable_reloc_fn,/* special_function */ + "R_NDS32_GNU_VTENTRY", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ /* A 16 bit absolute relocation. */ - HOWTO (R_NDS32_16_RELA, /* type */ - 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_16_RELA", /* name */ - FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_16_RELA, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_16_RELA", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* A 32 bit absolute relocation. */ - HOWTO (R_NDS32_32_RELA, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_32_RELA", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_32_RELA, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_32_RELA", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* A 20 bit address. */ - HOWTO (R_NDS32_20_RELA, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 20, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_20_RELA", /* name */ - FALSE, /* partial_inplace */ - 0xfffff, /* src_mask */ - 0xfffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - HOWTO (R_NDS32_9_PCREL_RELA, /* type */ - 1, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 8, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_9_PCREL_RELA",/* name */ - FALSE, /* partial_inplace */ - 0xff, /* src_mask */ - 0xff, /* dst_mask */ - TRUE), /* pcrel_offset */ + HOWTO2 (R_NDS32_20_RELA, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_20_RELA", /* name */ + FALSE, /* partial_inplace */ + 0xfffff, /* src_mask */ + 0xfffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO2 (R_NDS32_9_PCREL_RELA, /* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_9_PCREL_RELA",/* name */ + FALSE, /* partial_inplace */ + 0xff, /* src_mask */ + 0xff, /* dst_mask */ + TRUE), /* pcrel_offset */ /* A relative 15 bit relocation, right shifted by 1. */ - HOWTO (R_NDS32_15_PCREL_RELA, /* type */ - 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 14, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_15_PCREL_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x3fff, /* src_mask */ - 0x3fff, /* dst_mask */ - TRUE), /* pcrel_offset */ + HOWTO2 (R_NDS32_15_PCREL_RELA,/* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 14, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_15_PCREL_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x3fff, /* src_mask */ + 0x3fff, /* dst_mask */ + TRUE), /* pcrel_offset */ /* A relative 17 bit relocation, right shifted by 1. */ - HOWTO (R_NDS32_17_PCREL_RELA, /* type */ - 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_17_PCREL_RELA", /* name */ - FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + HOWTO2 (R_NDS32_17_PCREL_RELA,/* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_17_PCREL_RELA",/* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + TRUE), /* pcrel_offset */ /* A relative 25 bit relocation, right shifted by 2. */ - HOWTO (R_NDS32_25_PCREL_RELA, /* type */ - 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 24, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_25_PCREL_RELA", /* name */ - FALSE, /* partial_inplace */ - 0xffffff, /* src_mask */ - 0xffffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + HOWTO2 (R_NDS32_25_PCREL_RELA,/* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 24, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_25_PCREL_RELA",/* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + TRUE), /* pcrel_offset */ /* High 20 bits of address when lower 16 is or'd in. */ - HOWTO (R_NDS32_HI20_RELA, /* type */ - 12, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 20, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_HI20_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x000fffff, /* src_mask */ - 0x000fffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_HI20_RELA, /* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_HI20_RELA", /* name */ + FALSE, /* partial_inplace */ + 0x000fffff, /* src_mask */ + 0x000fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Lower 12 bits of address. */ - HOWTO (R_NDS32_LO12S3_RELA, /* type */ - 3, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 9, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_LO12S3_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x000001ff, /* src_mask */ - 0x000001ff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LO12S3_RELA, /* type */ + 3, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 9, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_LO12S3_RELA", /* name */ + FALSE, /* partial_inplace */ + 0x000001ff, /* src_mask */ + 0x000001ff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Lower 12 bits of address. */ - HOWTO (R_NDS32_LO12S2_RELA, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 10, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_LO12S2_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x000003ff, /* src_mask */ - 0x000003ff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LO12S2_RELA, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 10, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_LO12S2_RELA", /* name */ + FALSE, /* partial_inplace */ + 0x000003ff, /* src_mask */ + 0x000003ff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Lower 12 bits of address. */ - HOWTO (R_NDS32_LO12S1_RELA, /* type */ - 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 11, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_LO12S1_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x000007ff, /* src_mask */ - 0x000007ff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LO12S1_RELA, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 11, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_LO12S1_RELA", /* name */ + FALSE, /* partial_inplace */ + 0x000007ff, /* src_mask */ + 0x000007ff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Lower 12 bits of address. */ - HOWTO (R_NDS32_LO12S0_RELA, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_LO12S0_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x00000fff, /* src_mask */ - 0x00000fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LO12S0_RELA, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_LO12S0_RELA", /* name */ + FALSE, /* partial_inplace */ + 0x00000fff, /* src_mask */ + 0x00000fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Small data area 15 bits offset. */ - HOWTO (R_NDS32_SDA15S3_RELA, /* type */ - 3, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 15, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_SDA15S3_RELA",/* name */ - FALSE, /* partial_inplace */ - 0x00007fff, /* src_mask */ - 0x00007fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_SDA15S3_RELA, /* type */ + 3, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_SDA15S3_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x00007fff, /* src_mask */ + 0x00007fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Small data area 15 bits offset. */ - HOWTO (R_NDS32_SDA15S2_RELA, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 15, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_SDA15S2_RELA",/* name */ - FALSE, /* partial_inplace */ - 0x00007fff, /* src_mask */ - 0x00007fff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - HOWTO (R_NDS32_SDA15S1_RELA, /* type */ - 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 15, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_SDA15S1_RELA",/* name */ - FALSE, /* partial_inplace */ - 0x00007fff, /* src_mask */ - 0x00007fff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - HOWTO (R_NDS32_SDA15S0_RELA, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 15, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_SDA15S0_RELA",/* name */ - FALSE, /* partial_inplace */ - 0x00007fff, /* src_mask */ - 0x00007fff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* GNU extension to record C++ vtable hierarchy */ - HOWTO (R_NDS32_RELA_GNU_VTINHERIT, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - NULL, /* special_function */ - "R_NDS32_RELA_GNU_VTINHERIT", /* name */ - FALSE, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* GNU extension to record C++ vtable member usage */ - HOWTO (R_NDS32_RELA_GNU_VTENTRY, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - _bfd_elf_rel_vtable_reloc_fn, /* special_function */ - "R_NDS32_RELA_GNU_VTENTRY", /* name */ - FALSE, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_SDA15S2_RELA, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_SDA15S2_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x00007fff, /* src_mask */ + 0x00007fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO2 (R_NDS32_SDA15S1_RELA, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_SDA15S1_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x00007fff, /* src_mask */ + 0x00007fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO2 (R_NDS32_SDA15S0_RELA, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_SDA15S0_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x00007fff, /* src_mask */ + 0x00007fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* GNU extension to record C++ vtable hierarchy */ + HOWTO2 (R_NDS32_RELA_GNU_VTINHERIT,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + NULL, /* special_function */ + "R_NDS32_RELA_GNU_VTINHERIT",/* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* GNU extension to record C++ vtable member usage */ + HOWTO2 (R_NDS32_RELA_GNU_VTENTRY,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + _bfd_elf_rel_vtable_reloc_fn,/* special_function */ + "R_NDS32_RELA_GNU_VTENTRY",/* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Like R_NDS32_20, but referring to the GOT table entry for the symbol. */ - HOWTO (R_NDS32_GOT20, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 20, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_GOT20", /* name */ - FALSE, /* partial_inplace */ - 0xfffff, /* src_mask */ - 0xfffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_GOT20, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_GOT20", /* name */ + FALSE, /* partial_inplace */ + 0xfffff, /* src_mask */ + 0xfffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Like R_NDS32_PCREL, but referring to the procedure linkage table entry for the symbol. */ - HOWTO (R_NDS32_25_PLTREL, /* type */ - 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 24, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_25_PLTREL", /* name */ - FALSE, /* partial_inplace */ - 0xffffff, /* src_mask */ - 0xffffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + HOWTO2 (R_NDS32_25_PLTREL, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 24, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_25_PLTREL", /* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + TRUE), /* pcrel_offset */ /* This is used only by the dynamic linker. The symbol should exist both in the object being run and in some shared library. The dynamic linker copies the data addressed by the symbol from the shared library into the object, because the object being run has to have the data at some particular address. */ - HOWTO (R_NDS32_COPY, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_COPY", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_COPY, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_COPY", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Like R_NDS32_20, but used when setting global offset table entries. */ - HOWTO (R_NDS32_GLOB_DAT, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_GLOB_DAT", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_GLOB_DAT, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_GLOB_DAT", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Marks a procedure linkage table entry for a symbol. */ - HOWTO (R_NDS32_JMP_SLOT, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_JMP_SLOT", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_JMP_SLOT, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_JMP_SLOT", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Used only by the dynamic linker. When the object is run, this longword is set to the load address of the object, plus the addend. */ - HOWTO (R_NDS32_RELATIVE, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_RELATIVE", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - HOWTO (R_NDS32_GOTOFF, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 20, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_GOTOFF", /* name */ - FALSE, /* partial_inplace */ - 0xfffff, /* src_mask */ - 0xfffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_RELATIVE, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_RELATIVE", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO2 (R_NDS32_GOTOFF, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_GOTOFF", /* name */ + FALSE, /* partial_inplace */ + 0xfffff, /* src_mask */ + 0xfffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* An PC Relative 20-bit relocation used when setting PIC offset table register. */ - HOWTO (R_NDS32_GOTPC20, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 20, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_GOTPC20", /* name */ - FALSE, /* partial_inplace */ - 0xfffff, /* src_mask */ - 0xfffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + HOWTO2 (R_NDS32_GOTPC20, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_GOTPC20", /* name */ + FALSE, /* partial_inplace */ + 0xfffff, /* src_mask */ + 0xfffff, /* dst_mask */ + TRUE), /* pcrel_offset */ /* Like R_NDS32_HI20, but referring to the GOT table entry for the symbol. */ - HOWTO (R_NDS32_GOT_HI20, /* type */ - 12, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 20, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_GOT_HI20", /* name */ - FALSE, /* partial_inplace */ - 0x000fffff, /* src_mask */ - 0x000fffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_GOT_LO12, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_GOT_LO12", /* name */ - FALSE, /* partial_inplace */ - 0x00000fff, /* src_mask */ - 0x00000fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_GOT_HI20, /* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_GOT_HI20", /* name */ + FALSE, /* partial_inplace */ + 0x000fffff, /* src_mask */ + 0x000fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_GOT_LO12, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_GOT_LO12", /* name */ + FALSE, /* partial_inplace */ + 0x00000fff, /* src_mask */ + 0x00000fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* An PC Relative relocation used when setting PIC offset table register. Like R_NDS32_HI20, but referring to the GOT table entry for the symbol. */ - HOWTO (R_NDS32_GOTPC_HI20, /* type */ - 12, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 20, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_GOTPC_HI20", /* name */ - FALSE, /* partial_inplace */ - 0x000fffff, /* src_mask */ - 0x000fffff, /* dst_mask */ - TRUE), /* pcrel_offset */ - HOWTO (R_NDS32_GOTPC_LO12, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_GOTPC_LO12", /* name */ - FALSE, /* partial_inplace */ - 0x00000fff, /* src_mask */ - 0x00000fff, /* dst_mask */ - TRUE), /* pcrel_offset */ - - HOWTO (R_NDS32_GOTOFF_HI20, /* type */ - 12, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 20, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_GOTOFF_HI20", /* name */ - FALSE, /* partial_inplace */ - 0x000fffff, /* src_mask */ - 0x000fffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_GOTOFF_LO12, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_GOTOFF_LO12", /* name */ - FALSE, /* partial_inplace */ - 0x00000fff, /* src_mask */ - 0x00000fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_GOTPC_HI20, /* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_GOTPC_HI20", /* name */ + FALSE, /* partial_inplace */ + 0x000fffff, /* src_mask */ + 0x000fffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + HOWTO2 (R_NDS32_GOTPC_LO12, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_GOTPC_LO12", /* name */ + FALSE, /* partial_inplace */ + 0x00000fff, /* src_mask */ + 0x00000fff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO2 (R_NDS32_GOTOFF_HI20, /* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_GOTOFF_HI20", /* name */ + FALSE, /* partial_inplace */ + 0x000fffff, /* src_mask */ + 0x000fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_GOTOFF_LO12, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_GOTOFF_LO12", /* name */ + FALSE, /* partial_inplace */ + 0x00000fff, /* src_mask */ + 0x00000fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Alignment hint for relaxable instruction. This is used with R_NDS32_LABEL as a pair. Relax this instruction from 4 bytes to 2 in order to make next label aligned on word boundary. */ - HOWTO (R_NDS32_INSN16, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_INSN16", /* name */ - FALSE, /* partial_inplace */ - 0x00000fff, /* src_mask */ - 0x00000fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_INSN16, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_INSN16", /* name */ + FALSE, /* partial_inplace */ + 0x00000fff, /* src_mask */ + 0x00000fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Alignment hint for label. */ - HOWTO (R_NDS32_LABEL, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_LABEL", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LABEL, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_LABEL", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for unconditional call sequence */ - HOWTO (R_NDS32_LONGCALL1, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_LONGCALL1", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LONGCALL1, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_LONGCALL1", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for conditional call sequence. */ - HOWTO (R_NDS32_LONGCALL2, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_LONGCALL2", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LONGCALL2, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_LONGCALL2", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for conditional call sequence. */ - HOWTO (R_NDS32_LONGCALL3, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_LONGCALL3", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LONGCALL3, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_LONGCALL3", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for unconditional branch sequence. */ - HOWTO (R_NDS32_LONGJUMP1, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_LONGJUMP1", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LONGJUMP1, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_LONGJUMP1", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for conditional branch sequence. */ - HOWTO (R_NDS32_LONGJUMP2, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_LONGJUMP2", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LONGJUMP2, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_LONGJUMP2", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for conditional branch sequence. */ - HOWTO (R_NDS32_LONGJUMP3, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_LONGJUMP3", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LONGJUMP3, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_LONGJUMP3", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for load/store sequence. */ - HOWTO (R_NDS32_LOADSTORE, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_LOADSTORE", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LOADSTORE, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_LOADSTORE", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for load/store sequence. */ - HOWTO (R_NDS32_9_FIXED_RELA, /* type */ - 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_9_FIXED_RELA",/* name */ - FALSE, /* partial_inplace */ - 0x000000ff, /* src_mask */ - 0x000000ff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_9_FIXED_RELA, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_9_FIXED_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x000000ff, /* src_mask */ + 0x000000ff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for load/store sequence. */ - HOWTO (R_NDS32_15_FIXED_RELA, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_15_FIXED_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x00003fff, /* src_mask */ - 0x00003fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_15_FIXED_RELA,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_15_FIXED_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x00003fff, /* src_mask */ + 0x00003fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for load/store sequence. */ - HOWTO (R_NDS32_17_FIXED_RELA, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_17_FIXED_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_17_FIXED_RELA,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_17_FIXED_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for load/store sequence. */ - HOWTO (R_NDS32_25_FIXED_RELA, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_25_FIXED_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x00ffffff, /* src_mask */ - 0x00ffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_25_FIXED_RELA,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_25_FIXED_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x00ffffff, /* src_mask */ + 0x00ffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* High 20 bits of PLT symbol offset relative to PC. */ - HOWTO (R_NDS32_PLTREL_HI20, /* type */ - 12, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 20, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_PLTREL_HI20", /* name */ - FALSE, /* partial_inplace */ - 0x000fffff, /* src_mask */ - 0x000fffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_PLTREL_HI20, /* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_PLTREL_HI20", /* name */ + FALSE, /* partial_inplace */ + 0x000fffff, /* src_mask */ + 0x000fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Low 12 bits of PLT symbol offset relative to PC. */ - HOWTO (R_NDS32_PLTREL_LO12, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_PLTREL_LO12", /* name */ - FALSE, /* partial_inplace */ - 0x00000fff, /* src_mask */ - 0x00000fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_PLTREL_LO12, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_PLTREL_LO12", /* name */ + FALSE, /* partial_inplace */ + 0x00000fff, /* src_mask */ + 0x00000fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* High 20 bits of PLT symbol offset relative to GOT (GP). */ - HOWTO (R_NDS32_PLT_GOTREL_HI20, /* type */ - 12, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 20, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_PLT_GOTREL_HI20", /* name */ - FALSE, /* partial_inplace */ - 0x000fffff, /* src_mask */ - 0x000fffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_PLT_GOTREL_HI20, /* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_PLT_GOTREL_HI20",/* name */ + FALSE, /* partial_inplace */ + 0x000fffff, /* src_mask */ + 0x000fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Low 12 bits of PLT symbol offset relative to GOT (GP). */ - HOWTO (R_NDS32_PLT_GOTREL_LO12, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_PLT_GOTREL_LO12", /* name */ - FALSE, /* partial_inplace */ - 0x00000fff, /* src_mask */ - 0x00000fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_PLT_GOTREL_LO12,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_PLT_GOTREL_LO12",/* name */ + FALSE, /* partial_inplace */ + 0x00000fff, /* src_mask */ + 0x00000fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Small data area 12 bits offset. */ - HOWTO (R_NDS32_SDA12S2_DP_RELA, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_SDA12S2_DP_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x00000fff, /* src_mask */ - 0x00000fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_SDA12S2_DP_RELA,/* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_SDA12S2_DP_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x00000fff, /* src_mask */ + 0x00000fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Small data area 12 bits offset. */ - HOWTO (R_NDS32_SDA12S2_SP_RELA, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_SDA12S2_SP_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x00000fff, /* src_mask */ - 0x00000fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_SDA12S2_SP_RELA,/* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_SDA12S2_SP_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x00000fff, /* src_mask */ + 0x00000fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Lower 12 bits of address. */ - HOWTO (R_NDS32_LO12S2_DP_RELA, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 10, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_LO12S2_DP_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x000003ff, /* src_mask */ - 0x000003ff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LO12S2_DP_RELA, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 10, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_LO12S2_DP_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x000003ff, /* src_mask */ + 0x000003ff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Lower 12 bits of address. */ - HOWTO (R_NDS32_LO12S2_SP_RELA,/* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 10, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_LO12S2_SP_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x000003ff, /* src_mask */ - 0x000003ff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LO12S2_SP_RELA,/* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 10, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_LO12S2_SP_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x000003ff, /* src_mask */ + 0x000003ff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Lower 12 bits of address. Special identity for or case. */ - HOWTO (R_NDS32_LO12S0_ORI_RELA, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_LO12S0_ORI_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x00000fff, /* src_mask */ - 0x00000fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LO12S0_ORI_RELA,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_LO12S0_ORI_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x00000fff, /* src_mask */ + 0x00000fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Small data area 19 bits offset. */ - HOWTO (R_NDS32_SDA16S3_RELA, /* type */ - 3, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_SDA16S3_RELA",/* name */ - FALSE, /* partial_inplace */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_SDA16S3_RELA, /* type */ + 3, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_SDA16S3_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Small data area 15 bits offset. */ - HOWTO (R_NDS32_SDA17S2_RELA, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 17, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_SDA17S2_RELA",/* name */ - FALSE, /* partial_inplace */ - 0x0001ffff, /* src_mask */ - 0x0001ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - HOWTO (R_NDS32_SDA18S1_RELA, /* type */ - 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 18, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_SDA18S1_RELA",/* name */ - FALSE, /* partial_inplace */ - 0x0003ffff, /* src_mask */ - 0x0003ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - HOWTO (R_NDS32_SDA19S0_RELA, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 19, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_SDA19S0_RELA",/* name */ - FALSE, /* partial_inplace */ - 0x0007ffff, /* src_mask */ - 0x0007ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_DWARF2_OP1_RELA, /* type */ - 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ - 8, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_DWARF2_OP1_RELA", /* name */ - FALSE, /* partial_inplace */ - 0xff, /* src_mask */ - 0xff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_DWARF2_OP2_RELA, /* type */ - 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_DWARF2_OP2_RELA", /* name */ - FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_DWARF2_LEB_RELA, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_DWARF2_LEB_RELA", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_UPDATE_TA_RELA,/* type */ - 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_UPDATE_TA_RELA", /* name */ - FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_SDA17S2_RELA, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 17, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_SDA17S2_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x0001ffff, /* src_mask */ + 0x0001ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO2 (R_NDS32_SDA18S1_RELA, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 18, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_SDA18S1_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x0003ffff, /* src_mask */ + 0x0003ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO2 (R_NDS32_SDA19S0_RELA, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 19, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_SDA19S0_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x0007ffff, /* src_mask */ + 0x0007ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_DWARF2_OP1_RELA,/* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_DWARF2_OP1_RELA",/* name */ + FALSE, /* partial_inplace */ + 0xff, /* src_mask */ + 0xff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_DWARF2_OP2_RELA,/* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_DWARF2_OP2_RELA",/* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_DWARF2_LEB_RELA,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_DWARF2_LEB_RELA",/* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_UPDATE_TA_RELA,/* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_UPDATE_TA_RELA",/* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Like R_NDS32_PCREL, but referring to the procedure linkage table entry for the symbol. */ - HOWTO (R_NDS32_9_PLTREL, /* type */ - 1, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 8, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_9_PLTREL", /* name */ - FALSE, /* partial_inplace */ - 0xff, /* src_mask */ - 0xff, /* dst_mask */ - TRUE), /* pcrel_offset */ + HOWTO2 (R_NDS32_9_PLTREL, /* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_9_PLTREL", /* name */ + FALSE, /* partial_inplace */ + 0xff, /* src_mask */ + 0xff, /* dst_mask */ + TRUE), /* pcrel_offset */ /* Low 20 bits of PLT symbol offset relative to GOT (GP). */ - HOWTO (R_NDS32_PLT_GOTREL_LO20, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 20, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_PLT_GOTREL_LO20", /* name */ - FALSE, /* partial_inplace */ - 0x000fffff, /* src_mask */ - 0x000fffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - /* low 15 bits of PLT symbol offset relative to GOT (GP) */ - HOWTO (R_NDS32_PLT_GOTREL_LO15, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 15, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_PLT_GOTREL_LO15", /* name */ - FALSE, /* partial_inplace */ - 0x00007fff, /* src_mask */ - 0x00007fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_PLT_GOTREL_LO20,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_PLT_GOTREL_LO20",/* name */ + FALSE, /* partial_inplace */ + 0x000fffff, /* src_mask */ + 0x000fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* low 15 bits of PLT symbol offset relative to GOT (GP) */ + HOWTO2 (R_NDS32_PLT_GOTREL_LO15,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_PLT_GOTREL_LO15",/* name */ + FALSE, /* partial_inplace */ + 0x00007fff, /* src_mask */ + 0x00007fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Low 19 bits of PLT symbol offset relative to GOT (GP). */ - HOWTO (R_NDS32_PLT_GOTREL_LO19, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 19, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_PLT_GOTREL_LO19", /* name */ - FALSE, /* partial_inplace */ - 0x0007ffff, /* src_mask */ - 0x0007ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_GOT_LO15, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 15, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_GOT_LO15", /* name */ - FALSE, /* partial_inplace */ - 0x00007fff, /* src_mask */ - 0x00007fff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_GOT_LO19, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 19, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_GOT_LO19", /* name */ - FALSE, /* partial_inplace */ - 0x0007ffff, /* src_mask */ - 0x0007ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_GOTOFF_LO15, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 15, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_GOTOFF_LO15", /* name */ - FALSE, /* partial_inplace */ - 0x00007fff, /* src_mask */ - 0x00007fff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_GOTOFF_LO19, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 19, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_GOTOFF_LO19", /* name */ - FALSE, /* partial_inplace */ - 0x0007ffff, /* src_mask */ - 0x0007ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_PLT_GOTREL_LO19,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 19, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_PLT_GOTREL_LO19",/* name */ + FALSE, /* partial_inplace */ + 0x0007ffff, /* src_mask */ + 0x0007ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_GOT_LO15, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_GOT_LO15", /* name */ + FALSE, /* partial_inplace */ + 0x00007fff, /* src_mask */ + 0x00007fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_GOT_LO19, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 19, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_GOT_LO19", /* name */ + FALSE, /* partial_inplace */ + 0x0007ffff, /* src_mask */ + 0x0007ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_GOTOFF_LO15, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_GOTOFF_LO15", /* name */ + FALSE, /* partial_inplace */ + 0x00007fff, /* src_mask */ + 0x00007fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_GOTOFF_LO19, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 19, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_GOTOFF_LO19", /* name */ + FALSE, /* partial_inplace */ + 0x0007ffff, /* src_mask */ + 0x0007ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* GOT 15 bits offset. */ - HOWTO (R_NDS32_GOT15S2_RELA, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 15, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_GOT15S2_RELA",/* name */ - FALSE, /* partial_inplace */ - 0x00007fff, /* src_mask */ - 0x00007fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_GOT15S2_RELA, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_GOT15S2_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x00007fff, /* src_mask */ + 0x00007fff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* GOT 17 bits offset. */ - HOWTO (R_NDS32_GOT17S2_RELA, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 17, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_GOT17S2_RELA",/* name */ - FALSE, /* partial_inplace */ - 0x0001ffff, /* src_mask */ - 0x0001ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_GOT17S2_RELA, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 17, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_GOT17S2_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x0001ffff, /* src_mask */ + 0x0001ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* A 5 bit address. */ - HOWTO (R_NDS32_5_RELA, /* type */ - 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 5, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_5_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x1f, /* src_mask */ - 0x1f, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_10_UPCREL_RELA,/* type */ - 1, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 9, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_unsigned, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_10_UPCREL_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x1ff, /* src_mask */ - 0x1ff, /* dst_mask */ - TRUE), /* pcrel_offset */ - HOWTO (R_NDS32_SDA_FP7U2_RELA,/* type */ - 2, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 7, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_unsigned, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_SDA_FP7U2_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x0000007f, /* src_mask */ - 0x0000007f, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_WORD_9_PCREL_RELA, /* type */ - 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 8, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_WORD_9_PCREL_RELA", /* name */ - FALSE, /* partial_inplace */ - 0xff, /* src_mask */ - 0xff, /* dst_mask */ - TRUE), /* pcrel_offset */ - HOWTO (R_NDS32_25_ABS_RELA, /* type */ - 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 24, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_25_ABS_RELA", /* name */ - FALSE, /* partial_inplace */ - 0xffffff, /* src_mask */ - 0xffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_5_RELA, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 5, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_5_RELA", /* name */ + FALSE, /* partial_inplace */ + 0x1f, /* src_mask */ + 0x1f, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_10_UPCREL_RELA,/* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 9, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_10_UPCREL_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x1ff, /* src_mask */ + 0x1ff, /* dst_mask */ + TRUE), /* pcrel_offset */ + HOWTO2 (R_NDS32_SDA_FP7U2_RELA,/* type */ + 2, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 7, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_SDA_FP7U2_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x0000007f, /* src_mask */ + 0x0000007f, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_WORD_9_PCREL_RELA,/* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_WORD_9_PCREL_RELA",/* name */ + FALSE, /* partial_inplace */ + 0xff, /* src_mask */ + 0xff, /* dst_mask */ + TRUE), /* pcrel_offset */ + HOWTO2 (R_NDS32_25_ABS_RELA, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 24, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_25_ABS_RELA", /* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* A relative 17 bit relocation for ifc, right shifted by 1. */ - HOWTO (R_NDS32_17IFC_PCREL_RELA, /* type */ - 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_17IFC_PCREL_RELA", /* name */ - FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + HOWTO2 (R_NDS32_17IFC_PCREL_RELA,/* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_17IFC_PCREL_RELA",/* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + TRUE), /* pcrel_offset */ /* A relative unsigned 10 bit relocation for ifc, right shifted by 1. */ - HOWTO (R_NDS32_10IFCU_PCREL_RELA, /* type */ - 1, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 9, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_unsigned, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_10IFCU_PCREL_RELA", /* name */ - FALSE, /* partial_inplace */ - 0x1ff, /* src_mask */ - 0x1ff, /* dst_mask */ - TRUE), /* pcrel_offset */ - - /* Like R_NDS32_HI20, but referring to the TLS entry for the symbol. */ - HOWTO (R_NDS32_TLS_LE_HI20, /* type */ - 12, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 20, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_TLS_LE_HI20", /* name */ - FALSE, /* partial_inplace */ - 0x000fffff, /* src_mask */ - 0x000fffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_TLS_LE_LO12, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_TLS_LE_LO12", /* name */ - FALSE, /* partial_inplace */ - 0x00000fff, /* src_mask */ - 0x00000fff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* Like R_NDS32_HI20, but referring to the TLS entry for the symbol. */ - HOWTO (R_NDS32_TLS_IE_HI20, /* type */ - 12, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 20, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_TLS_IE_HI20", /* name */ - FALSE, /* partial_inplace */ - 0x000fffff, /* src_mask */ - 0x000fffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_TLS_IE_LO12S2, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 10, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_TLS_IE_LO12S2", /* name */ - FALSE, /* partial_inplace */ - 0x000003ff, /* src_mask */ - 0x000003ff, /* dst_mask */ - FALSE), /* pcrel_offset */ - /* Mark a TLS IE entry in GOT. */ - HOWTO (R_NDS32_TLS_TPOFF, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_TLS_TPOFF", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - /* A 20 bit address. */ - HOWTO (R_NDS32_TLS_LE_20, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 20, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_TLS_LE_20", /* name */ - FALSE, /* partial_inplace */ - 0xfffff, /* src_mask */ - 0xfffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_TLS_LE_15S0, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 15, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_TLS_LE_15S0", /* name */ - FALSE, /* partial_inplace */ - 0x7fff, /* src_mask */ - 0x7fff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_TLS_LE_15S1, /* type */ - 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 15, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_TLS_LE_15S1", /* name */ - FALSE, /* partial_inplace */ - 0x7fff, /* src_mask */ - 0x7fff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_TLS_LE_15S2, /* type */ - 2, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 15, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_NDS32_TLS_LE_15S2", /* name */ - FALSE, /* partial_inplace */ - 0x7fff, /* src_mask */ - 0x7fff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_10IFCU_PCREL_RELA,/* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 9, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_10IFCU_PCREL_RELA",/* name */ + FALSE, /* partial_inplace */ + 0x1ff, /* src_mask */ + 0x1ff, /* dst_mask */ + TRUE), /* pcrel_offset */ /* Relax hint for unconditional call sequence */ - HOWTO (R_NDS32_LONGCALL4, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - nds32_elf_ignore_reloc, /* special_function */ - "R_NDS32_LONGCALL4", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LONGCALL4, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_LONGCALL4", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for conditional call sequence. */ - HOWTO (R_NDS32_LONGCALL5, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - nds32_elf_ignore_reloc, /* special_function */ - "R_NDS32_LONGCALL5", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LONGCALL5, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_LONGCALL5", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for conditional call sequence. */ - HOWTO (R_NDS32_LONGCALL6, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - nds32_elf_ignore_reloc, /* special_function */ - "R_NDS32_LONGCALL6", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LONGCALL6, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_LONGCALL6", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for unconditional branch sequence. */ - HOWTO (R_NDS32_LONGJUMP4, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - nds32_elf_ignore_reloc, /* special_function */ - "R_NDS32_LONGJUMP4", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LONGJUMP4, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_LONGJUMP4", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for conditional branch sequence. */ - HOWTO (R_NDS32_LONGJUMP5, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - nds32_elf_ignore_reloc, /* special_function */ - "R_NDS32_LONGJUMP5", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LONGJUMP5, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_LONGJUMP5", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for conditional branch sequence. */ - HOWTO (R_NDS32_LONGJUMP6, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - nds32_elf_ignore_reloc, /* special_function */ - "R_NDS32_LONGJUMP6", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LONGJUMP6, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_LONGJUMP6", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* Relax hint for conditional branch sequence. */ - HOWTO (R_NDS32_LONGJUMP7, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - nds32_elf_ignore_reloc, /* special_function */ - "R_NDS32_LONGJUMP7", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_LONGJUMP7, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_LONGJUMP7", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Check sum value for security. */ + HOWTO2 (R_NDS32_SECURITY_16, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 5, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_SECURITY_16", /* name */ + FALSE, /* partial_inplace */ + 0x1fffe0, /* src_mask */ + 0x1fffe0, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* TLS LE TP offset relocation */ + HOWTO2 (R_NDS32_TLS_TPOFF, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_TLS_TPOFF", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like R_NDS32_HI20, but referring to the TLS LE entry for the symbol. */ + HOWTO2 (R_NDS32_TLS_LE_HI20, /* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_TLS_LE_HI20", /* name */ + FALSE, /* partial_inplace */ + 0x000fffff, /* src_mask */ + 0x000fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_TLS_LE_LO12, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_TLS_LE_LO12", /* name */ + FALSE, /* partial_inplace */ + 0x00000fff, /* src_mask */ + 0x00000fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 20 bit address. */ + HOWTO2 (R_NDS32_TLS_LE_20, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_TLS_LE_20", /* name */ + FALSE, /* partial_inplace */ + 0xfffff, /* src_mask */ + 0xfffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_TLS_LE_15S0, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_TLS_LE_15S0", /* name */ + FALSE, /* partial_inplace */ + 0x7fff, /* src_mask */ + 0x7fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_TLS_LE_15S1, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_TLS_LE_15S1", /* name */ + FALSE, /* partial_inplace */ + 0x7fff, /* src_mask */ + 0x7fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_TLS_LE_15S2, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_TLS_LE_15S2", /* name */ + FALSE, /* partial_inplace */ + 0x7fff, /* src_mask */ + 0x7fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like R_NDS32_HI20, but referring to the TLS IE entry for the symbol. */ + HOWTO2 (R_NDS32_TLS_IE_HI20, /* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_TLS_IE_HI20", /* name */ + FALSE, /* partial_inplace */ + 0x000fffff, /* src_mask */ + 0x000fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_TLS_IE_LO12, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_TLS_IE_LO12", /* name */ + FALSE, /* partial_inplace */ + 0x00000fff, /* src_mask */ + 0x00000fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_TLS_IE_LO12S2,/* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 10, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_TLS_IE_LO12S2",/* name */ + FALSE, /* partial_inplace */ + 0x000003ff, /* src_mask */ + 0x000003ff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like R_NDS32_HI20, but referring to the TLS IE (PIE) entry for the symbol. */ + HOWTO2 (R_NDS32_TLS_IEGP_HI20,/* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_TLS_IEGP_HI20",/* name */ + FALSE, /* partial_inplace */ + 0x000fffff, /* src_mask */ + 0x000fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO2 (R_NDS32_TLS_IEGP_LO12,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_TLS_IEGP_LO12",/* name */ + FALSE, /* partial_inplace */ + 0x00000fff, /* src_mask */ + 0x00000fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO2 (R_NDS32_TLS_IEGP_LO12S2,/* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 10, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_TLS_IEGP_LO12S2",/* name */ + FALSE, /* partial_inplace */ + 0x000003ff, /* src_mask */ + 0x000003ff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* TLS description relocation */ + HOWTO2 (R_NDS32_TLS_DESC, /* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_hi20_reloc, /* special_function */ + "R_NDS32_TLS_DESC_HI20",/* name */ + FALSE, /* partial_inplace */ + 0x000fffff, /* src_mask */ + 0x000fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* TLS GD/LD description offset high part. */ + HOWTO2 (R_NDS32_TLS_DESC_HI20,/* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_hi20_reloc, /* special_function */ + "R_NDS32_TLS_DESC_HI20",/* name */ + FALSE, /* partial_inplace */ + 0x000fffff, /* src_mask */ + 0x000fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* TLS GD/LD description offset low part. */ + HOWTO2 (R_NDS32_TLS_DESC_LO12,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_lo12_reloc, /* special_function */ + "R_NDS32_TLS_DESC_LO12",/* name */ + FALSE, /* partial_inplace */ + 0x00000fff, /* src_mask */ + 0x00000fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* TLS GD/LD description offset set (movi). */ + HOWTO2 (R_NDS32_TLS_DESC_20, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_TLS_DESC_20", /* name */ + FALSE, /* partial_inplace */ + 0x000fffff, /* src_mask */ + 0x000fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* TLS GD/LD description offset set (lwi.gp). */ + HOWTO2 (R_NDS32_TLS_DESC_SDA17S2,/* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 17, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_TLS_DESC_SDA17S2",/* name */ + FALSE, /* partial_inplace */ + 0x0001ffff, /* src_mask */ + 0x0001ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Jump-patch table relocations. */ + /* High 20 bits of jump-patch table address. */ + HOWTO2 (R_NDS32_ICT_HI20, /* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 20, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_ICT_HI20", /* name */ + FALSE, /* partial_inplace */ + 0x000fffff, /* src_mask */ + 0x000fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* Lower 12 bits of jump-patch table address. */ + HOWTO2 (R_NDS32_ICT_LO12,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_ICT_LO12",/* name */ + FALSE, /* partial_inplace */ + 0x00000fff, /* src_mask */ + 0x00000fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO2 (R_NDS32_ICT_LO12S2,/* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 10, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_ICT_LO12S2",/* name */ + FALSE, /* partial_inplace */ + 0x000003ff, /* src_mask */ + 0x000003ff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A relative 25 bit relocation, right shifted by 2. */ + HOWTO2 (R_NDS32_ICT_25PC,/* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 24, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_NDS32_ICT_25PC",/* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + TRUE), /* pcrel_offset */ }; /* Relocations used for relaxation. */ -static reloc_howto_type nds32_elf_relax_howto_table[] = -{ - HOWTO (R_NDS32_RELAX_ENTRY, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_RELAX_ENTRY", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_GOT_SUFF, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_GOT_SUFF", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_GOTOFF_SUFF, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_GOTOFF_SUFF", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_PLT_GOT_SUFF, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_PLT_GOT_SUFF",/* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_MULCALL_SUFF, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_MULCALL_SUFF",/* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_PTR, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_PTR", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_PTR_COUNT, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_PTR_COUNT", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_PTR_RESOLVED, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_PTR_RESOLVED",/* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_PLTBLOCK, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_PLTBLOCK", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_RELAX_REGION_BEGIN, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_RELAX_REGION_BEGIN", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_RELAX_REGION_END, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_RELAX_REGION_END", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_MINUEND, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_MINUEND", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_SUBTRAHEND, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_SUBTRAHEND", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_DIFF8, /* type */ - 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ - 8, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_DIFF8", /* name */ - FALSE, /* partial_inplace */ - 0x000000ff, /* src_mask */ - 0x000000ff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_DIFF16, /* type */ - 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_DIFF16", /* name */ - FALSE, /* partial_inplace */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_DIFF32, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_DIFF32", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_DIFF_ULEB128, /* type */ - 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_DIFF_ULEB128",/* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_DATA, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_DATA", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_TRAN, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - nds32_elf_ignore_reloc,/* special_function */ - "R_NDS32_TRAN", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_TLS_LE_ADD, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - nds32_elf_ignore_reloc, /* special_function */ - "R_NDS32_TLS_LE_ADD", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_TLS_LE_LS, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - nds32_elf_ignore_reloc, /* special_function */ - "R_NDS32_TLS_LE_LS", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - HOWTO (R_NDS32_EMPTY, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - nds32_elf_ignore_reloc, /* special_function */ - "R_NDS32_EMPTY", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ +#define HOWTO3(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ + [C-R_NDS32_RELAX_ENTRY] = HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) + +static reloc_howto_type nds32_elf_relax_howto_table[] = { + HOWTO3 (R_NDS32_RELAX_ENTRY, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_RELAX_ENTRY", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_GOT_SUFF, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_GOT_SUFF", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_GOTOFF_SUFF, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_GOTOFF_SUFF", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_PLT_GOT_SUFF, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_PLT_GOT_SUFF",/* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_MULCALL_SUFF, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_MULCALL_SUFF",/* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_PTR, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_PTR", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_PTR_COUNT, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_PTR_COUNT", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_PTR_RESOLVED, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_PTR_RESOLVED",/* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_PLTBLOCK, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_PLTBLOCK", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_RELAX_REGION_BEGIN,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_RELAX_REGION_BEGIN",/* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_RELAX_REGION_END,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_RELAX_REGION_END",/* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_MINUEND, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_MINUEND", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_SUBTRAHEND, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_SUBTRAHEND", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_DIFF8, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_DIFF8", /* name */ + FALSE, /* partial_inplace */ + 0x000000ff, /* src_mask */ + 0x000000ff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_DIFF16, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_DIFF16", /* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_DIFF32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_DIFF32", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_DIFF_ULEB128, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_DIFF_ULEB128",/* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_DATA, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_DATA", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_TRAN, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_TRAN", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_EMPTY, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_EMPTY", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO3 (R_NDS32_TLS_LE_ADD, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_TLS_LE_ADD", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO3 (R_NDS32_TLS_LE_LS, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_TLS_LE_LS", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO3 (R_NDS32_TLS_IEGP_LW, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_TLS_IEGP_LW", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* TLS GD/LD description address base addition. */ + HOWTO3 (R_NDS32_TLS_DESC_ADD, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_TLS_DESC_ADD",/* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* TLS GD/LD description function load. */ + HOWTO3 (R_NDS32_TLS_DESC_FUNC,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_TLS_DESC_FUNC",/* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* TLS DESC resolve function call. */ + HOWTO3 (R_NDS32_TLS_DESC_CALL,/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_TLS_DESC_CALL",/* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* TLS DESC variable access. */ + HOWTO3 (R_NDS32_TLS_DESC_MEM, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_TLS_DESC_MEM",/* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* TLS GD/LD description mark (@tlsdec). */ + HOWTO3 (R_NDS32_RELAX_REMOVE, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_REMOVE", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* TLS GD/LD description mark (@tlsdec). */ + HOWTO3 (R_NDS32_RELAX_GROUP, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_GROUP", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* LA and FLSI relaxation. */ + HOWTO3 (R_NDS32_LSI, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + nds32_elf_ignore_reloc,/* special_function */ + "R_NDS32_LSI", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ }; - + +static unsigned long dl_tlsdesc_lazy_trampoline[] = +{ + 0x46200000, /* sethi $r2,#0x0 */ + 0x58210000, /* ori $r2,$r2,#0x0 */ + 0x40217400, /* add $r2,$r2,$gp */ + 0x04210000, /* lwi $r2,[$r2+#0x0] */ + 0x46300000, /* sethi $r3,#0x0 */ + 0x58318000, /* ori $r3,$r3,#0x0 */ + 0x4031f400, /* add $r3,$r3,$gp */ + 0x4a000800, /* jr $r2 */ +}; + +/* === code === */ + +static void +nds32_put_trampoline (void *contents, const unsigned long *template, + unsigned count) +{ + unsigned ix; + + for (ix = 0; ix != count; ix++) + { + unsigned long insn = template[ix]; + bfd_putb32 (insn, (char *) contents + ix * 4); + } +} + /* nds32_insertion_sort sorts an array with nmemb elements of size size. This prototype is the same as qsort (). */ @@ -2224,7 +2713,7 @@ nds32_insertion_sort (void *base, size_t nmemb, size_t size, { char *ptr = (char *) base; int i, j; - char *tmp = xmalloc (size); + char *tmp = alloca (size); /* If i is less than j, i is inserted before j. @@ -2248,7 +2737,6 @@ nds32_insertion_sort (void *base, size_t nmemb, size_t size, memmove (ptr + (j + 1) * size, ptr + j * size, (i - j) * size); memcpy (ptr + j * size, tmp, size); } - free (tmp); } /* Sort relocation by r_offset. @@ -2277,14 +2765,13 @@ compar_reloc (const void *lhs, const void *rhs) } /* Functions listed below are only used for old relocs. - * nds32_elf_9_pcrel_reloc - * nds32_elf_do_9_pcrel_reloc - * nds32_elf_hi20_reloc - * nds32_elf_relocate_hi20 - * nds32_elf_lo12_reloc - * nds32_elf_sda15_reloc - * nds32_elf_generic_reloc - */ + nds32_elf_9_pcrel_reloc + nds32_elf_do_9_pcrel_reloc + nds32_elf_hi20_reloc + nds32_elf_relocate_hi20 + nds32_elf_lo12_reloc + nds32_elf_sda15_reloc + nds32_elf_generic_reloc */ /* Handle the R_NDS32_9_PCREL & R_NDS32_9_PCREL_RELA reloc. */ @@ -2705,8 +3192,7 @@ struct nds32_reloc_map_entry unsigned char elf_reloc_val; }; -static const struct nds32_reloc_map_entry nds32_reloc_map[] = -{ +static const struct nds32_reloc_map_entry nds32_reloc_map[] = { {BFD_RELOC_NONE, R_NDS32_NONE}, {BFD_RELOC_16, R_NDS32_16_RELA}, {BFD_RELOC_32, R_NDS32_32_RELA}, @@ -2765,6 +3251,7 @@ static const struct nds32_reloc_map_entry nds32_reloc_map[] = {BFD_RELOC_NDS32_LONGJUMP5, R_NDS32_LONGJUMP5}, {BFD_RELOC_NDS32_LONGJUMP6, R_NDS32_LONGJUMP6}, {BFD_RELOC_NDS32_LONGJUMP7, R_NDS32_LONGJUMP7}, + {BFD_RELOC_NDS32_SECURITY_16, R_NDS32_SECURITY_16}, {BFD_RELOC_NDS32_LOADSTORE, R_NDS32_LOADSTORE}, {BFD_RELOC_NDS32_9_FIXED, R_NDS32_9_FIXED_RELA}, {BFD_RELOC_NDS32_15_FIXED, R_NDS32_15_FIXED_RELA}, @@ -2822,15 +3309,52 @@ static const struct nds32_reloc_map_entry nds32_reloc_map[] = {BFD_RELOC_NDS32_TLS_LE_LS, R_NDS32_TLS_LE_LS}, {BFD_RELOC_NDS32_TLS_IE_HI20, R_NDS32_TLS_IE_HI20}, {BFD_RELOC_NDS32_TLS_IE_LO12S2, R_NDS32_TLS_IE_LO12S2}, - {BFD_RELOC_NDS32_TLS_TPOFF, R_NDS32_TLS_TPOFF}, {BFD_RELOC_NDS32_TLS_LE_20, R_NDS32_TLS_LE_20}, {BFD_RELOC_NDS32_TLS_LE_15S0, R_NDS32_TLS_LE_15S0}, {BFD_RELOC_NDS32_TLS_LE_15S1, R_NDS32_TLS_LE_15S1}, {BFD_RELOC_NDS32_TLS_LE_15S2, R_NDS32_TLS_LE_15S2}, + + {BFD_RELOC_NDS32_TLS_DESC, R_NDS32_TLS_DESC}, + {BFD_RELOC_NDS32_TLS_DESC_HI20, R_NDS32_TLS_DESC_HI20}, + {BFD_RELOC_NDS32_TLS_DESC_LO12, R_NDS32_TLS_DESC_LO12}, + {BFD_RELOC_NDS32_TLS_DESC_ADD, R_NDS32_TLS_DESC_ADD}, + {BFD_RELOC_NDS32_TLS_DESC_FUNC, R_NDS32_TLS_DESC_FUNC}, + {BFD_RELOC_NDS32_TLS_DESC_CALL, R_NDS32_TLS_DESC_CALL}, + {BFD_RELOC_NDS32_TLS_DESC_MEM, R_NDS32_TLS_DESC_MEM}, + {BFD_RELOC_NDS32_TLS_DESC_20, R_NDS32_TLS_DESC_20}, + {BFD_RELOC_NDS32_TLS_DESC_SDA17S2, R_NDS32_TLS_DESC_SDA17S2}, + {BFD_RELOC_NDS32_TLS_IE_LO12, R_NDS32_TLS_IE_LO12}, + {BFD_RELOC_NDS32_TLS_IEGP_HI20, R_NDS32_TLS_IEGP_HI20}, + {BFD_RELOC_NDS32_TLS_IEGP_LO12, R_NDS32_TLS_IEGP_LO12}, + {BFD_RELOC_NDS32_TLS_IEGP_LO12S2, R_NDS32_TLS_IEGP_LO12S2}, + {BFD_RELOC_NDS32_TLS_IEGP_LW, R_NDS32_TLS_IEGP_LW}, + + {BFD_RELOC_NDS32_REMOVE, R_NDS32_RELAX_REMOVE}, + {BFD_RELOC_NDS32_GROUP, R_NDS32_RELAX_GROUP}, + + {BFD_RELOC_NDS32_ICT_HI20, R_NDS32_ICT_HI20}, + {BFD_RELOC_NDS32_ICT_LO12, R_NDS32_ICT_LO12}, + {BFD_RELOC_NDS32_ICT_25PC, R_NDS32_ICT_25PC}, + {BFD_RELOC_NDS32_ICT_LO12S2, R_NDS32_ICT_LO12S2}, + + {BFD_RELOC_NDS32_LSI, R_NDS32_LSI}, }; /* Patch tag. */ +/* Reserve space for COUNT dynamic relocations in relocation selection + SRELOC. */ + +static inline void +elf32_nds32_allocate_dynrelocs (struct bfd_link_info *info, asection *sreloc, + bfd_size_type count) +{ + BFD_ASSERT (elf_hash_table (info)->dynamic_sections_created); + if (sreloc == NULL) + abort (); + sreloc->size += sizeof (Elf32_External_Rela) * count; +} + static reloc_howto_type * bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) @@ -2860,6 +3384,13 @@ bfd_elf32_bfd_reloc_type_table_lookup (enum elf_nds32_reloc_type code) } else { + if ((size_t) (code - R_NDS32_RELAX_ENTRY) >= + ARRAY_SIZE (nds32_elf_relax_howto_table)) + { + int i = code; + i += 1; + } + BFD_ASSERT ((size_t) (code - R_NDS32_RELAX_ENTRY) < ARRAY_SIZE (nds32_elf_relax_howto_table)); return &nds32_elf_relax_howto_table[code - R_NDS32_RELAX_ENTRY]; @@ -2876,7 +3407,7 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, { if (nds32_reloc_map[i].bfd_reloc_val == code) return bfd_elf32_bfd_reloc_type_table_lookup - (nds32_reloc_map[i].elf_reloc_val); + (nds32_reloc_map[i].elf_reloc_val); } return NULL; @@ -2897,6 +3428,8 @@ nds32_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, _bfd_error_handler (_("%B: invalid NDS32 reloc number: %d"), abfd, r_type); r_type = 0; } + + BFD_ASSERT (ELF32_R_TYPE (dst->r_info) <= R_NDS32_GNU_VTENTRY); cache_ptr->howto = bfd_elf32_bfd_reloc_type_table_lookup (r_type); } @@ -2922,29 +3455,29 @@ nds32_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) switch (note->descsz) { case 0x114: - /* Linux/NDS32 32-bit, ABI1 */ + /* Linux/NDS32 32-bit, ABI1 */ - /* pr_cursig */ + /* pr_cursig */ elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12); - /* pr_pid */ + /* pr_pid */ elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 24); - /* pr_reg */ + /* pr_reg */ offset = 72; size = 200; break; case 0xfc: - /* Linux/NDS32 32-bit */ + /* Linux/NDS32 32-bit */ - /* pr_cursig */ + /* pr_cursig */ elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12); - /* pr_pid */ + /* pr_pid */ elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 24); - /* pr_reg */ + /* pr_reg */ offset = 72; size = 176; break; @@ -2964,7 +3497,7 @@ nds32_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) switch (note->descsz) { case 124: - /* Linux/NDS32 */ + /* Linux/NDS32 */ /* __kernel_uid_t, __kernel_gid_t are short on NDS32 platform. */ elf_tdata (abfd)->core->program = @@ -3097,20 +3630,20 @@ nds32_elf_final_sda_base (bfd *output_bfd, struct bfd_link_info *info, struct elf_nds32_link_hash_table *table; struct bfd_link_hash_entry *h, *h2; long unsigned int total = 0; + asection *first = NULL, *final = NULL, *temp; + bfd_vma sda_base = 0; h = bfd_link_hash_lookup (info->hash, "_SDA_BASE_", FALSE, FALSE, TRUE); if (!h || (h->type != bfd_link_hash_defined && h->type != bfd_link_hash_defweak)) { - asection *first = NULL, *final = NULL, *temp; - bfd_vma sda_base; /* The first section must be 4-byte aligned to promise _SDA_BASE_ being 4 byte-aligned. Therefore, it has to set the first section ".data" 4 byte-aligned. */ static const char sec_name[SDA_SECTION_NUM][10] = - { - ".data", ".got", ".sdata_d", ".sdata_w", ".sdata_h", ".sdata_b", - ".sbss_b", ".sbss_h", ".sbss_w", ".sbss_d" - }; + { + ".data", ".got", ".sdata_d", ".sdata_w", ".sdata_h", ".sdata_b", + ".sbss_b", ".sbss_h", ".sbss_w", ".sbss_d" + }; size_t i = 0; if (output_bfd->sections == NULL) @@ -3120,7 +3653,7 @@ nds32_elf_final_sda_base (bfd *output_bfd, struct bfd_link_info *info, } /* Get the first and final section. */ - while (i < sizeof (sec_name) / sizeof (sec_name [0])) + while (i < ARRAY_SIZE (sec_name)) { temp = bfd_get_section_by_name (output_bfd, sec_name[i]); if (temp && !first && (temp->size != 0 || temp->rawsize != 0)) @@ -3162,7 +3695,7 @@ nds32_elf_final_sda_base (bfd *output_bfd, struct bfd_link_info *info, /* Find the section sda_base located. */ i = 0; - while (i < sizeof (sec_name) / sizeof (sec_name [0])) + while (i < ARRAY_SIZE (sec_name)) { final = bfd_get_section_by_name (output_bfd, sec_name[i]); if (final && (final->size != 0 || final->rawsize != 0) @@ -3177,17 +3710,44 @@ nds32_elf_final_sda_base (bfd *output_bfd, struct bfd_link_info *info, } else { - /* There is not any data section in output bfd, and set _SDA_BASE_ in - first output section. */ - first = output_bfd->sections; - while (first && first->size == 0 && first->rawsize == 0) - first = first->next; + /* If there is not any default data section in output bfd, try to find + the first data section. If no data section be found, just simplily + choose the first output section. */ + temp = output_bfd->sections; + while (temp) + { + if (temp->flags & SEC_ALLOC + && (((temp->flags & SEC_DATA) + && ((temp->flags & SEC_READONLY) == 0)) + || (temp->flags & SEC_LOAD) == 0) + && (temp->size != 0 || temp->rawsize != 0)) + { + if (!first) + first = temp; + final = temp; + } + temp = temp->next; + } + + /* There is no data or bss section. */ + if (!first || (first->size == 0 && first->rawsize == 0)) + { + first = output_bfd->sections; + while (first && first->size == 0 && first->rawsize == 0) + first = first->next; + } + + /* There is no concrete section. */ if (!first) { *psb = elf_gp (output_bfd); return bfd_reloc_ok; } - sda_base = first->vma + first->rawsize; + + if (final && (final->vma + final->rawsize - first->vma) <= 0x4000) + sda_base = final->vma / 2 + final->rawsize / 2 + first->vma / 2; + else + sda_base = first->vma + 0x2000; } sda_base -= first->vma; @@ -3201,24 +3761,34 @@ nds32_elf_final_sda_base (bfd *output_bfd, struct bfd_link_info *info, sda_rela_sec = first; - table = nds32_elf_hash_table (info); - relax_fp_as_gp = table->relax_fp_as_gp; - if (relax_fp_as_gp) - { - h2 = bfd_link_hash_lookup (info->hash, FP_BASE_NAME, - FALSE, FALSE, FALSE); - /* Define a weak FP_BASE_NAME here to prevent the undefined symbol. - And set FP equal to SDA_BASE to do relaxation for - la $fp, _FP_BASE_. */ - if (!_bfd_generic_link_add_one_symbol - (info, output_bfd, FP_BASE_NAME, BSF_GLOBAL | BSF_WEAK, - first, (bfd_vma) sda_base, (const char *) NULL, - FALSE, get_elf_backend_data (output_bfd)->collect, &h2)) - return FALSE; - } } - if (add_symbol) + /* Set _FP_BASE_ to _SDA_BASE_. */ + table = nds32_elf_hash_table (info); + relax_fp_as_gp = table->relax_fp_as_gp; + h2 = bfd_link_hash_lookup (info->hash, FP_BASE_NAME, FALSE, FALSE, FALSE); + /* _SDA_BASE_ is difined in linker script. */ + if (!first) + { + first = h->u.def.section; + sda_base = h->u.def.value; + } + + if (relax_fp_as_gp && h2 + && (h2->type == bfd_link_hash_undefweak + || h2->type == bfd_link_hash_undefined)) + { + /* Define a weak FP_BASE_NAME here to prevent the undefined symbol. + And set FP equal to SDA_BASE to do relaxation for + la $fp, _FP_BASE_. */ + if (!_bfd_generic_link_add_one_symbol + (info, output_bfd, FP_BASE_NAME, BSF_GLOBAL | BSF_WEAK, + first, sda_base, (const char *) NULL, + FALSE, get_elf_backend_data (output_bfd)->collect, &h2)) + return FALSE; + } + + if (add_symbol == TRUE) { if (h) { @@ -3275,6 +3845,8 @@ nds32_elf_link_hash_newfunc (struct bfd_hash_entry *entry, eh = (struct elf_nds32_link_hash_entry *) ret; eh->dyn_relocs = NULL; eh->tls_type = GOT_UNKNOWN; + eh->offset_to_gp = 0; + eh->indirect_call = FALSE; } return (struct bfd_hash_entry *) ret; @@ -3303,22 +3875,61 @@ nds32_elf_link_hash_table_create (bfd *abfd) return NULL; } + ret->sdynbss = NULL; + ret->srelbss = NULL; + ret->sym_ld_script = NULL; + return &ret->root.root; } +/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up + shortcuts to them in our hash table. */ + +static bfd_boolean +create_got_section (bfd *dynobj, struct bfd_link_info *info) +{ + struct elf_link_hash_table *ehtab; + + if (!_bfd_elf_create_got_section (dynobj, info)) + return FALSE; + + ehtab = elf_hash_table (info); + ehtab->sgot = bfd_get_section_by_name (dynobj, ".got"); + ehtab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); + if (!ehtab->sgot || !ehtab->sgotplt) + abort (); + + /* _bfd_elf_create_got_section will create it for us. */ + ehtab->srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); + if (ehtab->srelgot == NULL + || !bfd_set_section_flags (dynobj, ehtab->srelgot, + (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS + | SEC_IN_MEMORY | SEC_LINKER_CREATED + | SEC_READONLY)) + || !bfd_set_section_alignment (dynobj, ehtab->srelgot, 2)) + return FALSE; + + return TRUE; +} + /* Create dynamic sections when linking against a dynamic object. */ static bfd_boolean nds32_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) { + struct elf_link_hash_table *ehtab; struct elf_nds32_link_hash_table *htab; flagword flags, pltflags; register asection *s; const struct elf_backend_data *bed; int ptralign = 2; /* 32-bit */ + const char *secname; + char *relname; + flagword secflags; + asection *sec; bed = get_elf_backend_data (abfd); - + ehtab = elf_hash_table (info); htab = nds32_elf_hash_table (info); /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and @@ -3335,7 +3946,7 @@ nds32_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) pltflags |= SEC_READONLY; s = bfd_make_section (abfd, ".plt"); - htab->root.splt = s; + ehtab->splt = s; if (s == NULL || !bfd_set_section_flags (abfd, s, pltflags) || !bfd_set_section_alignment (abfd, s, bed->plt_alignment)) @@ -3364,40 +3975,33 @@ nds32_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) s = bfd_make_section (abfd, bed->default_use_rela_p ? ".rela.plt" : ".rel.plt"); - htab->root.srelplt = s; + ehtab->srelplt = s; if (s == NULL || !bfd_set_section_flags (abfd, s, flags | SEC_READONLY) || !bfd_set_section_alignment (abfd, s, ptralign)) return FALSE; - if (htab->root.sgot == NULL && !_bfd_elf_create_got_section (abfd, info)) + if (ehtab->sgot == NULL && !create_got_section (abfd, info)) return FALSE; - { - const char *secname; - char *relname; - flagword secflags; - asection *sec; - - for (sec = abfd->sections; sec; sec = sec->next) - { - secflags = bfd_get_section_flags (abfd, sec); - if ((secflags & (SEC_DATA | SEC_LINKER_CREATED)) - || ((secflags & SEC_HAS_CONTENTS) != SEC_HAS_CONTENTS)) - continue; - secname = bfd_get_section_name (abfd, sec); - relname = (char *) bfd_malloc ((bfd_size_type) strlen (secname) + 6); - strcpy (relname, ".rela"); - strcat (relname, secname); - if (bfd_get_section_by_name (abfd, secname)) - continue; - s = bfd_make_section (abfd, relname); - if (s == NULL - || !bfd_set_section_flags (abfd, s, flags | SEC_READONLY) - || !bfd_set_section_alignment (abfd, s, ptralign)) - return FALSE; - } - } + for (sec = abfd->sections; sec; sec = sec->next) + { + secflags = bfd_get_section_flags (abfd, sec); + if ((secflags & (SEC_DATA | SEC_LINKER_CREATED)) + || ((secflags & SEC_HAS_CONTENTS) != SEC_HAS_CONTENTS)) + continue; + secname = bfd_get_section_name (abfd, sec); + relname = (char *) bfd_malloc ((bfd_size_type) strlen (secname) + 6); + strcpy (relname, ".rela"); + strcat (relname, secname); + if (bfd_get_section_by_name (abfd, secname)) + continue; + s = bfd_make_section (abfd, relname); + if (s == NULL + || !bfd_set_section_flags (abfd, s, flags | SEC_READONLY) + || !bfd_set_section_alignment (abfd, s, ptralign)) + return FALSE; + } if (bed->want_dynbss) { @@ -3453,8 +4057,8 @@ nds32_elf_copy_indirect_symbol (struct bfd_link_info *info, { if (edir->dyn_relocs != NULL) { - struct elf_dyn_relocs **pp; - struct elf_dyn_relocs *p; + struct elf_nds32_dyn_relocs **pp; + struct elf_nds32_dyn_relocs *p; if (ind->root.type == bfd_link_hash_indirect) abort (); @@ -3463,7 +4067,7 @@ nds32_elf_copy_indirect_symbol (struct bfd_link_info *info, list. Merge any entries against the same section. */ for (pp = &eind->dyn_relocs; (p = *pp) != NULL;) { - struct elf_dyn_relocs *q; + struct elf_nds32_dyn_relocs *q; for (q = edir->dyn_relocs; q != NULL; q = q->next) if (q->sec == p->sec) @@ -3483,25 +4087,18 @@ nds32_elf_copy_indirect_symbol (struct bfd_link_info *info, eind->dyn_relocs = NULL; } - _bfd_elf_link_hash_copy_indirect (info, dir, ind); -} - -/* Find dynamic relocs for H that apply to read-only sections. */ - -static asection * -readonly_dynrelocs (struct elf_link_hash_entry *h) -{ - struct elf_dyn_relocs *p; - - for (p = elf32_nds32_hash_entry (h)->dyn_relocs; p != NULL; p = p->next) + if (ind->root.type == bfd_link_hash_indirect) { - asection *s = p->sec->output_section; - - if (s != NULL && (s->flags & SEC_READONLY) != 0) - return p->sec; + if (dir->got.refcount <= 0) + { + edir->tls_type = eind->tls_type; + eind->tls_type = GOT_UNKNOWN; + } } - return NULL; + + _bfd_elf_link_hash_copy_indirect (info, dir, ind); } + /* Adjust a symbol defined by a dynamic object and referenced by a regular object. The current definition is in some section of the @@ -3514,6 +4111,8 @@ nds32_elf_adjust_dynamic_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h) { struct elf_nds32_link_hash_table *htab; + struct elf_nds32_link_hash_entry *eh; + struct elf_nds32_dyn_relocs *p; bfd *dynobj; asection *s; unsigned int power_of_two; @@ -3558,7 +4157,8 @@ nds32_elf_adjust_dynamic_symbol (struct bfd_link_info *info, if (h->is_weakalias) { struct elf_link_hash_entry *def = weakdef (h); - BFD_ASSERT (def->root.type == bfd_link_hash_defined); + BFD_ASSERT (def->root.type == bfd_link_hash_defined + || def->root.type == bfd_link_hash_defweak); h->root.u.def.section = def->root.u.def.section; h->root.u.def.value = def->root.u.def.value; return TRUE; @@ -3580,15 +4180,24 @@ nds32_elf_adjust_dynamic_symbol (struct bfd_link_info *info, return TRUE; /* If -z nocopyreloc was given, we won't generate them either. */ - if (0 && info->nocopyreloc) + if (info->nocopyreloc) { h->non_got_ref = 0; return TRUE; } - /* If we don't find any dynamic relocs in read-only sections, then - we'll be keeping the dynamic relocs and avoiding the copy reloc. */ - if (0 && !readonly_dynrelocs (h)) + eh = (struct elf_nds32_link_hash_entry *) h; + for (p = eh->dyn_relocs; p != NULL; p = p->next) + { + s = p->sec->output_section; + if (s != NULL && (s->flags & (SEC_READONLY | SEC_HAS_CONTENTS)) != 0) + break; + } + + /* If we didn't find any dynamic relocs in sections which needs the + copy reloc, then we'll be keeping the dynamic relocs and avoiding + the copy reloc. */ + if (p == NULL) { h->non_got_ref = 0; return TRUE; @@ -3653,25 +4262,31 @@ static bfd_boolean allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { struct bfd_link_info *info; + struct elf_link_hash_table *ehtab; struct elf_nds32_link_hash_table *htab; struct elf_nds32_link_hash_entry *eh; - struct elf_dyn_relocs *p; + struct elf_nds32_dyn_relocs *p; if (h->root.type == bfd_link_hash_indirect) return TRUE; + /* When warning symbols are created, they **replace** the "real" + entry in the hash table, thus we never get to see the real + symbol in a hash traversal. So look at it now. */ if (h->root.type == bfd_link_hash_warning) - /* When warning symbols are created, they **replace** the "real" - entry in the hash table, thus we never get to see the real - symbol in a hash traversal. So look at it now. */ h = (struct elf_link_hash_entry *) h->root.u.i.link; + eh = (struct elf_nds32_link_hash_entry *) h; + info = (struct bfd_link_info *) inf; + ehtab = elf_hash_table (info); htab = nds32_elf_hash_table (info); + if (htab == NULL) + return FALSE; - eh = (struct elf_nds32_link_hash_entry *) h; - - if (htab->root.dynamic_sections_created && h->plt.refcount > 0) + if ((htab->root.dynamic_sections_created || h->type == STT_GNU_IFUNC) + && h->plt.refcount > 0 + && !(bfd_link_pie (info) && h->def_regular)) { /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ @@ -3683,7 +4298,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h)) { - asection *s = htab->root.splt; + asection *s = ehtab->splt; /* If this is the first .plt entry, make room for the special first entry. */ @@ -3708,10 +4323,12 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* We also need to make an entry in the .got.plt section, which will be placed in the .got section by the linker script. */ - htab->root.sgotplt->size += 4; + ehtab->sgotplt->size += 4; /* We also need to make an entry in the .rel.plt section. */ - htab->root.srelplt->size += sizeof (Elf32_External_Rela); + ehtab->srelplt->size += sizeof (Elf32_External_Rela); + if (htab->tls_desc_trampoline) + htab->next_tls_desc_index++; } else { @@ -3727,7 +4344,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (h->got.refcount > 0) { - asection *s; + asection *sgot; bfd_boolean dyn; int tls_type = elf32_nds32_hash_entry (h)->tls_type; @@ -3739,22 +4356,44 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) return FALSE; } - s = htab->root.sgot; - h->got.offset = s->size; + sgot = elf_hash_table (info)->sgot; + h->got.offset = sgot->size; if (tls_type == GOT_UNKNOWN) abort (); - else if (tls_type == GOT_NORMAL - || tls_type == GOT_TLS_IE) - /* Need a GOT slot. */ - s->size += 4; + + /* Non-TLS symbols, and TLS_IE need one GOT slot. */ + if (tls_type & (GOT_NORMAL | GOT_TLS_IE | GOT_TLS_IEGP)) + sgot->size += 4; + else + { + /* TLS_DESC, TLS_GD, and TLS_LD need 2 consecutive GOT slots. */ + if (tls_type & GOT_TLS_DESC) + sgot->size += 8; + } dyn = htab->root.dynamic_sections_created; + if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h)) - htab->root.srelgot->size += sizeof (Elf32_External_Rela); + { + if (tls_type == GOT_TLS_DESC && htab->tls_desc_trampoline) + { + /* TLS_DESC with trampoline needs a relocation slot + within .rela.plt. */ + htab->num_tls_desc++; + ehtab->srelplt->size += sizeof (Elf32_External_Rela); + htab->tls_trampoline = -1; + } + else + { + /* other relocations, including TLS_DESC without trampoline, need + a relocation slot within .rela.got. */ + ehtab->srelgot->size += sizeof (Elf32_External_Rela); + } + } } else - h->got.offset = (bfd_vma) - 1; + h->got.offset = (bfd_vma) -1; if (eh->dyn_relocs == NULL) return TRUE; @@ -3769,7 +4408,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { if (h->def_regular && (h->forced_local || info->symbolic)) { - struct elf_dyn_relocs **pp; + struct elf_nds32_dyn_relocs **pp; for (pp = &eh->dyn_relocs; (p = *pp) != NULL;) { @@ -3810,7 +4449,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) eh->dyn_relocs = NULL; - keep:; +keep:; } /* Finally, allocate space. */ @@ -3823,29 +4462,50 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) return TRUE; } -/* Set DF_TEXTREL if we find any dynamic relocs that apply to - read-only sections. */ +/* Add relocation REL to the end of relocation section SRELOC. */ + +static void +elf32_nds32_add_dynreloc (bfd *output_bfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + asection *sreloc, Elf_Internal_Rela *rel) +{ + bfd_byte *loc; + if (sreloc == NULL) + abort (); + + loc = sreloc->contents; + loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela); + if (sreloc->reloc_count * sizeof (Elf32_External_Rela) > sreloc->size) + abort (); + + bfd_elf32_swap_reloca_out (output_bfd, rel, loc); +} + +/* Find any dynamic relocs that apply to read-only sections. */ static bfd_boolean -maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p) +readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf) { - asection *sec; + struct elf_nds32_link_hash_entry *eh; + struct elf_nds32_dyn_relocs *p; - if (h->root.type == bfd_link_hash_indirect) - return TRUE; + if (h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; - sec = readonly_dynrelocs (h); - if (sec != NULL) + eh = (struct elf_nds32_link_hash_entry *) h; + for (p = eh->dyn_relocs; p != NULL; p = p->next) { - struct bfd_link_info *info = (struct bfd_link_info *) info_p; + asection *s = p->sec->output_section; + + if (s != NULL && (s->flags & SEC_READONLY) != 0) + { + struct bfd_link_info *info = (struct bfd_link_info *) inf; - info->flags |= DF_TEXTREL; - info->callbacks->minfo - (_("%B: dynamic relocation against `%T' in read-only section `%A'\n"), - sec->owner, h->root.root.string, sec); + info->flags |= DF_TEXTREL; - /* Not an error, just cut short the traversal. */ - return FALSE; + /* Not an error, just cut short the traversal. */ + return FALSE; + } } return TRUE; } @@ -3856,20 +4516,24 @@ static bfd_boolean nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) { - struct elf_nds32_link_hash_table *htab; bfd *dynobj; asection *s; + bfd_boolean plt; bfd_boolean relocs; bfd *ibfd; + struct elf_nds32_link_hash_table *htab; htab = nds32_elf_hash_table (info); - dynobj = htab->root.dynobj; + if (htab == NULL) + return FALSE; + + dynobj = elf_hash_table (info)->dynobj; BFD_ASSERT (dynobj != NULL); - if (htab->root.dynamic_sections_created) + if (elf_hash_table (info)->dynamic_sections_created) { /* Set the contents of the .interp section to the interpreter. */ - if (bfd_link_executable (info) && !info->nointerp) + if (bfd_link_executable (info)) { s = bfd_get_section_by_name (dynobj, ".interp"); BFD_ASSERT (s != NULL); @@ -3886,16 +4550,19 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, bfd_signed_vma *end_local_got; bfd_size_type locsymcount; Elf_Internal_Shdr *symtab_hdr; - asection *srel; + asection *sgot; + char *local_tls_type; + unsigned long symndx; + bfd_vma *local_tlsdesc_gotent; if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) continue; for (s = ibfd->sections; s != NULL; s = s->next) { - struct elf_dyn_relocs *p; + struct elf_nds32_dyn_relocs *p; - for (p = ((struct elf_dyn_relocs *) + for (p = ((struct elf_nds32_dyn_relocs *) elf_section_data (s)->local_dynrel); p != NULL; p = p->next) { @@ -3909,8 +4576,8 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, } else if (p->count != 0) { - srel = elf_section_data (p->sec)->sreloc; - srel->size += p->count * sizeof (Elf32_External_Rela); + asection *sreloc = elf_section_data (p->sec)->sreloc; + sreloc->size += p->count * sizeof (Elf32_External_Rela); if ((p->sec->output_section->flags & SEC_READONLY) != 0) info->flags |= DF_TEXTREL; } @@ -3924,19 +4591,57 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; locsymcount = symtab_hdr->sh_info; end_local_got = local_got + locsymcount; - s = htab->root.sgot; - srel = htab->root.srelgot; - for (; local_got < end_local_got; ++local_got) + sgot = elf_hash_table (info)->sgot; + local_tls_type = elf32_nds32_local_got_tls_type (ibfd); + local_tlsdesc_gotent = elf32_nds32_local_tlsdesc_gotent (ibfd); + for (symndx = 0; local_got < end_local_got; + ++local_got, ++local_tls_type, ++local_tlsdesc_gotent, ++symndx) { if (*local_got > 0) { - *local_got = s->size; - s->size += 4; - if (bfd_link_pic (info)) - srel->size += sizeof (Elf32_External_Rela); + int num_of_got_entry_needed = 0; + *local_got = sgot->size; + *local_tlsdesc_gotent = sgot->size; + + /* TLS_NORMAL, and TLS_IE need one slot in .got. */ + if (*local_tls_type & (GOT_NORMAL | GOT_TLS_IE | GOT_TLS_IEGP)) + num_of_got_entry_needed = 1; + /* TLS_GD, TLS_LD, and TLS_DESC need an 8-byte structure in the GOT. */ + else if (*local_tls_type & GOT_TLS_DESC) + num_of_got_entry_needed = 2; + + sgot->size += (num_of_got_entry_needed << 2); + + /* non-relax-able TLS_DESCs need a slot in .rela.plt. + others need a slot in .rela.got. */ + if (*local_tls_type == GOT_TLS_DESC) + { + if (bfd_link_pic (info)) + { + if (htab->tls_desc_trampoline) + { + htab->num_tls_desc++; + htab->root.srelplt->size += sizeof (Elf32_External_Rela); + htab->tls_trampoline = -1; + } + else + htab->root.srelgot->size += sizeof (Elf32_External_Rela); + } + else + { + /* TLS_DESC -> TLS_LE */ + } + } + else + { + htab->root.srelgot->size += sizeof (Elf32_External_Rela); + } } else - *local_got = (bfd_vma) - 1; + { + *local_got = (bfd_vma) -1; + *local_tlsdesc_gotent = (bfd_vma) -1; + } } } @@ -3944,8 +4649,36 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, sym dynamic relocs. */ elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (void *) info); + /* For every jump slot reserved in the sgotplt, reloc_count is + incremented. However, when we reserve space for TLS descriptors, + it's not incremented, so in order to compute the space reserved + for them, it suffices to multiply the reloc count by the jump + slot size. */ + if (htab->tls_desc_trampoline && htab->root.srelplt) + htab->sgotplt_jump_table_size = elf32_nds32_compute_jump_table_size (htab); + + if (htab->tls_trampoline) + { + htab->tls_trampoline = htab->root.splt->size; + + /* If we're not using lazy TLS relocations, don't generate the + PLT and GOT entries they require. */ + if (!(info->flags & DF_BIND_NOW)) + { + htab->dt_tlsdesc_got = htab->root.sgot->size; + htab->root.sgot->size += 4; + + htab->dt_tlsdesc_plt = htab->root.splt->size; + htab->root.splt->size += 4 * ARRAY_SIZE (dl_tlsdesc_lazy_trampoline); + } + } + /* We now have determined the sizes of the various dynamic sections. Allocate memory for them. */ + /* The check_relocs and adjust_dynamic_symbol entry points have + determined the sizes of the various dynamic sections. Allocate + memory for them. */ + plt = FALSE; relocs = FALSE; for (s = dynobj->sections; s != NULL; s = s->next) { @@ -3956,18 +4689,19 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, { /* Strip this section if we don't need it; see the comment below. */ + plt = s->size != 0; } - else if (s == htab->root.sgot) + else if (s == elf_hash_table (info)->sgot) { got_size += s->size; } - else if (s == htab->root.sgotplt) + else if (s == elf_hash_table (info)->sgotplt) { got_size += s->size; } else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) { - if (s->size != 0 && s != htab->root.srelplt) + if (s->size != 0 && s != elf_hash_table (info)->srelplt) relocs = TRUE; /* We use the reloc_count field as a counter if we need @@ -4013,16 +4747,15 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, must add the entries now so that we get the correct size for the .dynamic section. The DT_DEBUG entry is filled in by the dynamic linker and used by the debugger. */ -#define add_dynamic_entry(TAG, VAL) \ - _bfd_elf_add_dynamic_entry (info, TAG, VAL) +#define add_dynamic_entry(TAG, VAL) _bfd_elf_add_dynamic_entry (info, TAG, VAL) - if (!bfd_link_pic (info)) + if (bfd_link_executable (info)) { if (!add_dynamic_entry (DT_DEBUG, 0)) return FALSE; } - if (htab->root.splt->size != 0) + if (elf_hash_table (info)->splt->size != 0) { if (!add_dynamic_entry (DT_PLTGOT, 0) || !add_dynamic_entry (DT_PLTRELSZ, 0) @@ -4031,6 +4764,14 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, return FALSE; } + if (htab->tls_desc_trampoline && plt) + { + if (htab->dt_tlsdesc_plt + && (!add_dynamic_entry (DT_TLSDESC_PLT, 0) + || !add_dynamic_entry (DT_TLSDESC_GOT, 0))) + return FALSE; + } + if (relocs) { if (!add_dynamic_entry (DT_RELA, 0) @@ -4041,7 +4782,7 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, /* If any dynamic relocs apply to a read-only section, then we need a DT_TEXTREL entry. */ if ((info->flags & DF_TEXTREL) == 0) - elf_link_hash_traverse (&htab->root, maybe_set_textrel, + elf_link_hash_traverse (&htab->root, readonly_dynrelocs, (void *) info); if ((info->flags & DF_TEXTREL) != 0) @@ -4076,10 +4817,11 @@ nds32_relocate_contents (reloc_howto_type *howto, bfd *input_bfd, switch (size) { default: + case 0: + case 1: + case 8: abort (); break; - case 0: - return bfd_reloc_ok; case 2: x = bfd_getb16 (location); break; @@ -4297,9 +5039,9 @@ nds32_elf_output_symbol_hook (struct bfd_link_info *info, else source = input_sec->owner->filename; - fprintf (sym_ld_script, "\t%s = 0x%08lx;\t /* %s */\n", + fprintf (sym_ld_script, "\t%s = 0x%08lx;\t /* %s */\n", h->root.root.string, - (long) (h->root.u.def.value + (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset), source); } @@ -4340,59 +5082,252 @@ nds32_elf_output_symbol_hook (struct bfd_link_info *info, section, which means that the addend must be adjusted accordingly. */ +/* Return the base VMA address which should be subtracted from real addresses + when resolving @dtpoff relocation. + This is PT_TLS segment p_vaddr. */ + +/* Return the relocation value for @tpoff relocation + if STT_TLS virtual address is ADDRESS. */ + +/* Return the relocation value for @gottpoff relocation + if STT_TLS virtual address is ADDRESS. */ static bfd_vma -dtpoff_base (struct bfd_link_info *info) +gottpoff (struct bfd_link_info *info, bfd_vma address) { + bfd_vma tp_base; + bfd_vma tp_offset; + /* If tls_sec is NULL, we should have signalled an error already. */ if (elf_hash_table (info)->tls_sec == NULL) return 0; - return elf_hash_table (info)->tls_sec->vma; -} - -static bfd_boolean -nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, - struct bfd_link_info * info, - bfd * input_bfd, - asection * input_section, - bfd_byte * contents, - Elf_Internal_Rela * relocs, - Elf_Internal_Sym * local_syms, - asection ** local_sections) -{ - Elf_Internal_Shdr *symtab_hdr; - struct elf_link_hash_entry **sym_hashes; - Elf_Internal_Rela *rel, *relend; - bfd_boolean ret = TRUE; /* Assume success. */ - int align = 0; - bfd_reloc_status_type r; - const char *errmsg = NULL; - bfd_vma gp; - struct elf_nds32_link_hash_table *htab; - bfd *dynobj; - bfd_vma *local_got_offsets; - asection *sgot, *splt, *sreloc; - bfd_vma high_address; - struct elf_nds32_link_hash_table *table; - int eliminate_gc_relocs; - bfd_vma fpbase_addr; - symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; - sym_hashes = elf_sym_hashes (input_bfd); - htab = nds32_elf_hash_table (info); - high_address = bfd_get_section_limit (input_bfd, input_section); + tp_base = elf_hash_table (info)->tls_sec->vma; + tp_offset = address - tp_base; - dynobj = htab->root.dynobj; - local_got_offsets = elf_local_got_offsets (input_bfd); + return tp_offset; +} - sgot = htab->root.sgot; - splt = htab->root.splt; - sreloc = NULL; +/* Move all SECURITY_16 to the final one for each instruction. */ - rel = relocs; +static void +nds32_elf_crc_adjust_reloc (Elf_Internal_Rela *relocs, + Elf_Internal_Rela *relend) +{ + Elf_Internal_Rela *rel, *crc_rel = NULL; + Elf_Internal_Rela rel_temp; + + for (rel = relocs; rel < relend; rel++) + { + if (crc_rel && crc_rel->r_offset == rel->r_offset) + { + memcpy (&rel_temp, rel, sizeof (Elf_Internal_Rela)); + memcpy (rel, crc_rel, sizeof (Elf_Internal_Rela)); + memcpy (crc_rel, &rel_temp, sizeof (Elf_Internal_Rela)); + crc_rel = rel; + } + else if (ELF32_R_TYPE (rel->r_info) == R_NDS32_SECURITY_16) + { + crc_rel = rel; + continue; + } + } +} + +static bfd_boolean +patch_tls_desc_to_ie (bfd_byte *contents, Elf_Internal_Rela *rel, bfd *ibfd) +{ + /* TLS_GD/TLS_LD model #1 + 46 00 00 00 sethi $r0,#0x0 + 58 00 00 00 ori $r0,$r0,#0x0 + 40 00 74 00 add $r0,$r0,$gp + 04 10 00 00 lwi $r1,[$r0+#0x0] + 4b e0 04 01 jral $lp,$r1 */ + + /* TLS_GD/TLS_LD model #2 + 46 00 00 00 sethi $r0,#0x0 + 58 00 00 00 ori $r0,$r0,#0x0 + 38 10 74 02 lw $r1,[$r0+($gp<<#0x0)] <= TODO: not necessary $r1 register allocation + 40 00 74 00 add $r0,$r0,$gp + 4b e0 04 01 jral $lp,$r1 */ + + /* TLS_IE model (non-PIC) + 46 00 00 00 sethi $r0,#0x0 + 04 00 00 00 lwi $r0,[$r0+#0x0] + 38 00 64 02 lw $r0,[$r0+($r25<<#0x0)] */ + + /* TLS_IE model (PIC) + 46 00 00 00 sethi $r0,#0x0 + 58 00 00 00 ori $r0,$r0,#0x0 + 38 00 74 02 lw $r0,[$r0+($gp<<#0x0)] + 38 00 64 02 lw $r0,[$r0+($r25<<#0x0)] */ + + /* TLS_GD_TO_IE model + 46 00 00 00 sethi $r0,#0x0 + 58 00 00 00 ori $r0,$r0,#0x0 + 40 00 74 00 add $r0,$rM,$gp + 04 00 00 01 lwi $r0,[$r0+#0x4] + 40 00 64 00 add $r0,$r0,$r25 */ + + bfd_boolean rz = FALSE; + + typedef struct + { + uint32_t opcode; + uint32_t mask; + } pat_t; + + uint32_t patch[3] = + { + 0x40007400, /* add $r0,$rM,$gp */ + 0x04000001, /* lwi $r0,[$r0+#0x4] */ + 0x40006400, /* add $r0,$r0,$r25 */ + }; + + pat_t mode0[3] = + { + { 0x40000000, 0xfe0003ff }, + { 0x04000000, 0xfe000000 }, + { 0x4be00001, 0xffff83ff }, + }; + + pat_t mode1[3] = + { + { 0x38007402, 0xfe007fff }, + { 0x40007400, 0xfe007fff }, + { 0x4be00001, 0xffff83ff }, + }; + + unsigned char *p = contents + rel->r_offset; + + uint32_t insn; + uint32_t regidx = 0; + insn = bfd_getb32 (p); + if (INSN_SETHI == (0xfe0fffffu & insn)) + { + regidx = 0x1f & (insn >> 20); + p += 4; + } + + insn = bfd_getb32 (p); + if (INSN_ORI == (0xfe007fffu & insn)) + { + regidx = 0x1f & (insn >> 20); + p += 4; + } + + if (patch[2] == bfd_getb32 (p + 8)) /* character instruction */ + { + /* already patched? */ + if ((patch[0] == (0xfff07fffu & bfd_getb32 (p + 0))) && + (patch[1] == bfd_getb32 (p + 4))) + rz = TRUE; + } + else if (mode0[0].opcode == (mode0[0].mask & bfd_getb32 (p + 0))) + { + if ((mode0[1].opcode == (mode0[1].mask & bfd_getb32 (p + 4))) && + (mode0[2].opcode == (mode0[2].mask & bfd_getb32 (p + 8)))) + { + bfd_putb32 (patch[0] | (regidx << 15), p + 0); + bfd_putb32 (patch[1], p + 4); + bfd_putb32 (patch[2], p + 8); + rz = TRUE; + } + } + else if (mode1[0].opcode == (mode1[0].mask & bfd_getb32 (p + 0))) + { + if ((mode1[1].opcode == (mode1[1].mask & bfd_getb32 (p + 4))) && + (mode1[2].opcode == (mode1[2].mask & bfd_getb32 (p + 8)))) + { + bfd_putb32 (patch[0] | (regidx << 15), p + 0); + bfd_putb32 (patch[1], p + 4); + bfd_putb32 (patch[2], p + 8); + rz = TRUE; + } + } + + if (!rz) + { + printf ("%s: %s @ 0x%08x\n", __func__, ibfd->filename, + (int) rel->r_offset); + BFD_ASSERT(0); /* unsupported pattern */ + } + + return rz; +} + +static enum elf_nds32_tls_type +get_tls_type (enum elf_nds32_reloc_type r_type, struct elf_link_hash_entry *h); + +static unsigned int +ones32 (register unsigned int x) +{ + /* 32-bit recursive reduction using SWAR... + but first step is mapping 2-bit values + into sum of 2 1-bit values in sneaky way. */ + x -= ((x >> 1) & 0x55555555); + x = (((x >> 2) & 0x33333333) + (x & 0x33333333)); + x = (((x >> 4) + x) & 0x0f0f0f0f); + x += (x >> 8); + x += (x >> 16); + return (x & 0x0000003f); +} + +static unsigned int +fls (register unsigned int x) +{ + return ffs (x & (-x)); +} + +#define nds32_elf_local_tlsdesc_gotent(bfd) \ + (elf_nds32_tdata (bfd)->local_tlsdesc_gotent) + +static bfd_boolean +nds32_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info, bfd *input_bfd, + asection *input_section, bfd_byte *contents, + Elf_Internal_Rela *relocs, + Elf_Internal_Sym *local_syms, + asection **local_sections) +{ + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes; + Elf_Internal_Rela *rel, *relend; + bfd_boolean ret = TRUE; /* Assume success. */ + int align = 0; + bfd_reloc_status_type r; + const char *errmsg = NULL; + bfd_vma gp; + struct elf_link_hash_table *ehtab; + struct elf_nds32_link_hash_table *htab; + bfd *dynobj; + bfd_vma *local_got_offsets; + asection *sgot, *splt, *sreloc; + bfd_vma high_address; + struct elf_nds32_link_hash_table *table; + int eliminate_gc_relocs; + bfd_vma fpbase_addr; + Elf_Internal_Rela *crc_rel = NULL; + + symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + sym_hashes = elf_sym_hashes (input_bfd); + ehtab = elf_hash_table (info); + htab = nds32_elf_hash_table (info); + high_address = bfd_get_section_limit (input_bfd, input_section); + + dynobj = htab->root.dynobj; + local_got_offsets = elf_local_got_offsets (input_bfd); + + sgot = ehtab->sgot; + splt = ehtab->splt; + sreloc = NULL; + + rel = relocs; relend = relocs + input_section->reloc_count; table = nds32_elf_hash_table (info); eliminate_gc_relocs = table->eliminate_gc_relocs; + + /* explain _SDA_BASE_ */ /* By this time, we can adjust the value of _SDA_BASE_. */ if ((!bfd_link_relocatable (info))) { @@ -4402,40 +5337,37 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, return FALSE; } - if (is_ITB_BASE_set == 0) - { - /* Set the _ITB_BASE_. */ - if (!nds32_elf_ex9_itb_base (info)) - { - _bfd_error_handler (_("%B: error: Cannot set _ITB_BASE_"), - output_bfd); - bfd_set_error (bfd_error_bad_value); - } - } - - if (table->target_optimize & NDS32_RELAX_JUMP_IFC_ON) - if (!nds32_elf_ifc_reloc ()) - _bfd_error_handler (_("error: IFC relocation error.")); +#ifdef NDS32_LINUX_TOOLCHAIN + /* Do TLS model conversion once at first. */ + nds32_elf_unify_tls_model (input_bfd, input_section, contents, info); +#endif - /* Relocation for .ex9.itable. */ - if (table->target_optimize & NDS32_RELAX_EX9_ON - || (table->ex9_import_file && table->update_ex9_table)) - nds32_elf_ex9_reloc_jmp (info); + if (indirect_call_table.count > 0) + nds32_elf_ict_relocate (output_bfd, info); /* Use gp as fp to prevent truncated fit. Because in relaxation time the fp value is set as gp, and it has be reverted for instruction setting fp. */ fpbase_addr = elf_gp (output_bfd); + /* Move all SECURITY_16 to the final one for each instruction. */ + nds32_elf_crc_adjust_reloc (relocs, relend); + + /* Deal with (dynamic) relocations. */ for (rel = relocs; rel < relend; rel++) { enum elf_nds32_reloc_type r_type; reloc_howto_type *howto = NULL; unsigned long r_symndx; struct elf_link_hash_entry *h = NULL; + struct bfd_link_hash_entry *h2; Elf_Internal_Sym *sym = NULL; asection *sec; bfd_vma relocation; + struct elf_nds32_ict_hash_entry *entry; + bfd_vma relocation_sym = 0xdeadbeef; + Elf_Internal_Rela *lorel; + bfd_vma off; /* We can't modify r_addend here as elf_link_input_bfd has an assert to ensure it's zero (we use REL relocs, not RELA). Therefore this @@ -4463,12 +5395,17 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, || r_type == R_NDS32_RELA_GNU_VTINHERIT || (r_type >= R_NDS32_INSN16 && r_type <= R_NDS32_25_FIXED_RELA) || r_type == R_NDS32_DATA - || r_type == R_NDS32_TRAN - || (r_type >= R_NDS32_LONGCALL4 && r_type <= R_NDS32_LONGJUMP7)) + || r_type == R_NDS32_TRAN) continue; - /* If we enter the fp-as-gp region. Resolve the address - of best fp-base. */ + /* Save security beginning. */ + if (r_type == R_NDS32_SECURITY_16 && crc_rel == NULL) + { + crc_rel = rel; + continue; + } + + /* If we enter the fp-as-gp region. Resolve the address of best fp-base. */ if (ELF32_R_TYPE (rel->r_info) == R_NDS32_RELAX_REGION_BEGIN && (rel->r_addend & R_NDS32_RELAX_REGION_OMIT_FP_FLAG)) { @@ -4485,9 +5422,13 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, fpbase_addr = elf_gp (output_bfd); } - if (((r_type >= R_NDS32_DWARF2_OP1_RELA - && r_type <= R_NDS32_DWARF2_LEB_RELA) - || r_type >= R_NDS32_RELAX_ENTRY) && !bfd_link_relocatable (info)) + /* Skip the relocations used for relaxation. */ + /* Fix ticket-11832, we have to update LONGCALL and LONGJUMP + relocations when generating the relocatable files. */ + if (!bfd_link_relocatable (info) + && (r_type >= R_NDS32_RELAX_ENTRY + || (r_type >= R_NDS32_LONGCALL4 + && r_type <= R_NDS32_LONGJUMP7))) continue; howto = bfd_elf32_bfd_reloc_type_table_lookup (r_type); @@ -4506,10 +5447,26 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); addend = rel->r_addend; + + /* keep symbol location for static TLS_IE GOT entry */ + relocation_sym = relocation; + if (bfd_link_relocatable (info)) + { + /* This is a relocatable link. We don't have to change + anything, unless the reloc is against a section symbol, + in which case we have to adjust according to where the + section symbol winds up in the output section. */ + if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION) + rel->r_addend += sec->output_offset + sym->st_value; + + continue; + } } else { /* External symbol. */ + if (bfd_link_relocatable (info)) + continue; bfd_boolean warned, ignored, unresolved_reloc; int symndx = r_symndx - symtab_hdr->sh_info; @@ -4518,10 +5475,27 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, relocation, unresolved_reloc, warned, ignored); + /* keep symbol location for static TLS_IE GOT entry */ + relocation_sym = relocation; + /* la $fp, _FP_BASE_ is per-function (region). Handle it specially. */ switch ((int) r_type) { + case R_NDS32_HI20_RELA: + case R_NDS32_LO12S0_RELA: + if (strcmp (elf_sym_hashes (input_bfd)[symndx]->root.root.string, + FP_BASE_NAME) == 0) + { + if (!bfd_link_pie (info)) + { + _bfd_error_handler + ("%pB: warning: _FP_BASE_ setting insns relaxation failed.", + input_bfd); + } + relocation = fpbase_addr; + break; + } case R_NDS32_SDA19S0_RELA: case R_NDS32_SDA15S0_RELA: case R_NDS32_20_RELA: @@ -4532,19 +5506,6 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, break; } } - - } - - if (bfd_link_relocatable (info)) - { - /* This is a relocatable link. We don't have to change - anything, unless the reloc is against a section symbol, - in which case we have to adjust according to where the - section symbol winds up in the output section. */ - if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION) - rel->r_addend += sec->output_offset + sym->st_value; - - continue; } /* Sanity check the address. */ @@ -4554,16 +5515,14 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, goto check_reloc; } - if ((r_type >= R_NDS32_DWARF2_OP1_RELA - && r_type <= R_NDS32_DWARF2_LEB_RELA) - || r_type >= R_NDS32_RELAX_ENTRY) + if (r_type >= R_NDS32_RELAX_ENTRY) continue; switch ((int) r_type) { case R_NDS32_GOTOFF: /* Relocation is relative to the start of the global offset - table (for ld24 rx, #uimm24), e.g. access at label+addend + table (for ld24 rx, #uimm24), e.g. access at label + addend ld24 rx. #label@GOTOFF + addend sub rx, r12. */ @@ -4605,12 +5564,18 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, case R_NDS32_PLT_GOTREL_LO15: case R_NDS32_PLT_GOTREL_LO19: case R_NDS32_PLT_GOTREL_LO20: - if (h == NULL || h->forced_local || h->plt.offset == (bfd_vma) - 1) + if (h == NULL + || h->forced_local + || h->plt.offset == (bfd_vma) -1 + || (bfd_link_pie (info) && h->def_regular)) { + /* TODO: find better checking to optimize PIE PLT relocations. */ /* We didn't make a PLT entry for this symbol. This happens when statically linking PIC code, or when using -Bsymbolic. */ - relocation -= elf_gp (output_bfd); + if (h) + h->plt.offset = (bfd_vma) -1; /* cancel PLT trampoline. */ + relocation -= elf_gp(output_bfd); break; } @@ -4661,21 +5626,18 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, case R_NDS32_GOTPC_HI20: case R_NDS32_GOTPC_LO12: - { - /* .got(_GLOBAL_OFFSET_TABLE_) - pc relocation - bl .+4 - seth rx,#high(_GLOBAL_OFFSET_TABLE_) - or3 rx,rx,#low(_GLOBAL_OFFSET_TABLE_ +4) - or - bl .+4 - seth rx,#shigh(_GLOBAL_OFFSET_TABLE_) - add3 rx,rx,#low(_GLOBAL_OFFSET_TABLE_ +4) - */ - relocation = elf_gp (output_bfd); - relocation -= (input_section->output_section->vma - + input_section->output_offset + rel->r_offset); - break; - } + /* .got(_GLOBAL_OFFSET_TABLE_) - pc relocation + bl .+4 + seth rx,#high(_GLOBAL_OFFSET_TABLE_) + or3 rx,rx,#low(_GLOBAL_OFFSET_TABLE_ +4) + or + bl .+4 + seth rx,#shigh(_GLOBAL_OFFSET_TABLE_) + add3 rx,rx,#low(_GLOBAL_OFFSET_TABLE_ +4) */ + relocation = elf_gp (output_bfd); + relocation -= (input_section->output_section->vma + + input_section->output_offset + rel->r_offset); + break; case R_NDS32_GOT20: /* Fall through. */ @@ -4687,17 +5649,14 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, offset table. */ BFD_ASSERT (sgot != NULL); - if (h != NULL) + if (h != NULL) /* External symbol */ { bfd_boolean dyn; - bfd_vma off; off = h->got.offset; BFD_ASSERT (off != (bfd_vma) - 1); dyn = htab->root.dynamic_sections_created; - if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, - bfd_link_pic (info), - h) + if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h) || (bfd_link_pic (info) && (info->symbolic || h->dynindx == -1 @@ -4707,28 +5666,27 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, -Bsymbolic link and the symbol is defined locally, or the symbol was forced to be local because of a version file. We must initialize - this entry in the global offset table. Since the + this entry in the global offset table. Since the offset must always be a multiple of 4, we use the least significant bit to record whether we have initialized it already. When doing a dynamic link, we create a .rela.got - relocation entry to initialize the value. This + relocation entry to initialize the value. This is done in the finish_dynamic_symbol routine. */ - if ((off & 1) != 0) + if ((off & 1) != 0) /* clear LSB */ off &= ~1; else { bfd_put_32 (output_bfd, relocation, sgot->contents + off); - h->got.offset |= 1; + h->got.offset |= 1; /* mark initialized */ } } relocation = sgot->output_section->vma + sgot->output_offset + off - - elf_gp (output_bfd); + - elf_gp (output_bfd); } - else + else /* Local symbol */ { - bfd_vma off; bfd_byte *loc; BFD_ASSERT (local_got_offsets != NULL @@ -4736,10 +5694,10 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, off = local_got_offsets[r_symndx]; - /* The offset must always be a multiple of 4. We use + /* The offset must always be a multiple of 4. We use the least significant bit to record whether we have already processed this entry. */ - if ((off & 1) != 0) + if ((off & 1) != 0) /* clear LSB */ off &= ~1; else { @@ -4752,7 +5710,7 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, /* We need to generate a R_NDS32_RELATIVE reloc for the dynamic linker. */ - srelgot = htab->root.srelgot; + srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); BFD_ASSERT (srelgot != NULL); outrel.r_offset = (elf_gp (output_bfd) @@ -4768,11 +5726,57 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, local_got_offsets[r_symndx] |= 1; } relocation = sgot->output_section->vma + sgot->output_offset + off - - elf_gp (output_bfd); + - elf_gp (output_bfd); } break; + case R_NDS32_25_PCREL_RELA: + case R_NDS32_HI20_RELA: + case R_NDS32_LO12S0_RELA: + case R_NDS32_LO12S2_RELA: + /* Merge normal and indirect call functions. */ + if (!ignore_indirect_call && h + && elf32_nds32_hash_entry (h)->indirect_call) + { + if (ict_model == R_NDS32_RELAX_ENTRY_ICT_LARGE) + { + _bfd_error_handler + (_("%pB: Error: there are mixed indirect call function in" + " ICT large model\'%s\'\n"), + input_bfd, h->root.root.string); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + else + _bfd_error_handler + (_("%pB: Warning: there are mixed indirect call function" + " \'%s\'\n"), input_bfd, h->root.root.string); + + entry = (struct elf_nds32_ict_hash_entry*) + bfd_hash_lookup (&indirect_call_table, h->root.root.string, + FALSE, FALSE); + if (!entry) + { + _bfd_error_handler + (_("%pB %pA: internal error indirect call relocation " + "0x%lx without hash.\n"), + input_bfd, sec, rel->r_offset); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + + h2 = bfd_link_hash_lookup (info->hash, + "_INDIRECT_CALL_TABLE_BASE_", + FALSE, FALSE, FALSE); + relocation = ((h2->u.def.value + + h2->u.def.section->output_section->vma + + h2->u.def.section->output_offset) + + (entry->order * 4)); + break; + } + + /* Fall through. */ case R_NDS32_16_RELA: case R_NDS32_20_RELA: case R_NDS32_5_RELA: @@ -4782,14 +5786,10 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, case R_NDS32_10_UPCREL_RELA: case R_NDS32_15_PCREL_RELA: case R_NDS32_17_PCREL_RELA: - case R_NDS32_25_PCREL_RELA: - case R_NDS32_HI20_RELA: case R_NDS32_LO12S3_RELA: - case R_NDS32_LO12S2_RELA: case R_NDS32_LO12S2_DP_RELA: case R_NDS32_LO12S2_SP_RELA: case R_NDS32_LO12S1_RELA: - case R_NDS32_LO12S0_RELA: case R_NDS32_LO12S0_ORI_RELA: if (bfd_link_pic (info) && r_symndx != 0 && (input_section->flags & SEC_ALLOC) != 0 @@ -4863,15 +5863,37 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, become local. */ if (h == NULL || ((info->symbolic || h->dynindx == -1) - && h->def_regular)) + && h->def_regular) + || (bfd_link_pie (info) && h->def_regular)) { relocate = TRUE; outrel.r_info = ELF32_R_INFO (0, R_NDS32_RELATIVE); outrel.r_addend = relocation + rel->r_addend; + if (h) + { + h->plt.offset = (bfd_vma) -1; /* cancel PLT trampoline. */ + + BFD_ASSERT (sgot != NULL); + /* If we did not allocate got entry for the symbol, we can not + fill the nonexistent got entry. */ + if (h->got.offset != (bfd_vma) -1 && (h->got.offset & 1) == 0) + { + bfd_put_32 (output_bfd, outrel.r_addend, + sgot->contents + h->got.offset); + } + } } else { - BFD_ASSERT (h->dynindx != -1); + if (h->dynindx == -1) + { + _bfd_error_handler + (_("%pB: relocation %s against `%s' can not be used when" + "making a shared object; recompile with -fPIC"), + input_bfd, nds32_elf_howto_table[r_type].name, h->root.root.string); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); outrel.r_addend = rel->r_addend; } @@ -4895,8 +5917,8 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, if (bfd_link_pic (info)) { _bfd_error_handler - (_("%B: warning: cannot deal R_NDS32_25_ABS_RELA in shared " - "mode."), input_bfd); + (_("%s: warning: cannot deal R_NDS32_25_ABS_RELA in shared mode."), + bfd_get_filename (input_bfd)); return FALSE; } break; @@ -4908,123 +5930,115 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, goto check_reloc; case R_NDS32_HI20: + /* We allow an arbitrary number of HI20 relocs before the + LO12 reloc. This permits GCC to emit the HI and LO relocs + itself. */ + for (lorel = rel + 1; + (lorel < relend + && ELF32_R_TYPE (lorel->r_info) == R_NDS32_HI20); lorel++) + continue; + if (lorel < relend + && (ELF32_R_TYPE (lorel->r_info) == R_NDS32_LO12S3 + || ELF32_R_TYPE (lorel->r_info) == R_NDS32_LO12S2 + || ELF32_R_TYPE (lorel->r_info) == R_NDS32_LO12S1 + || ELF32_R_TYPE (lorel->r_info) == R_NDS32_LO12S0)) { - Elf_Internal_Rela *lorel; - - /* We allow an arbitrary number of HI20 relocs before the - LO12 reloc. This permits gcc to emit the HI and LO relocs - itself. */ - for (lorel = rel + 1; - (lorel < relend - && ELF32_R_TYPE (lorel->r_info) == R_NDS32_HI20); lorel++) - continue; - if (lorel < relend - && (ELF32_R_TYPE (lorel->r_info) == R_NDS32_LO12S3 - || ELF32_R_TYPE (lorel->r_info) == R_NDS32_LO12S2 - || ELF32_R_TYPE (lorel->r_info) == R_NDS32_LO12S1 - || ELF32_R_TYPE (lorel->r_info) == R_NDS32_LO12S0)) - { - nds32_elf_relocate_hi20 (input_bfd, r_type, rel, lorel, - contents, relocation + addend); - r = bfd_reloc_ok; - } - else - r = _bfd_final_link_relocate (howto, input_bfd, input_section, - contents, offset, relocation, - addend); + nds32_elf_relocate_hi20 (input_bfd, r_type, rel, lorel, + contents, relocation + addend); + r = bfd_reloc_ok; } + else + r = _bfd_final_link_relocate (howto, input_bfd, input_section, + contents, offset, relocation, + addend); goto check_reloc; case R_NDS32_GOT17S2_RELA: case R_NDS32_GOT15S2_RELA: + BFD_ASSERT (sgot != NULL); + + if (h != NULL) { - bfd_vma off; + bfd_boolean dyn; - BFD_ASSERT (sgot != NULL); + off = h->got.offset; + BFD_ASSERT (off != (bfd_vma) - 1); - if (h != NULL) + dyn = htab->root.dynamic_sections_created; + if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL + (dyn, bfd_link_pic (info), h) || (bfd_link_pic (info) + && (info->symbolic + || h->dynindx == -1 + || h->forced_local) + && h->def_regular)) { - bfd_boolean dyn; - - off = h->got.offset; - BFD_ASSERT (off != (bfd_vma) - 1); - - dyn = htab->root.dynamic_sections_created; - if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL - (dyn, bfd_link_pic (info), h) - || (bfd_link_pic (info) - && (info->symbolic - || h->dynindx == -1 - || h->forced_local) - && h->def_regular)) + /* This is actually a static link, or it is a + -Bsymbolic link and the symbol is defined + locally, or the symbol was forced to be local + because of a version file. We must initialize + this entry in the global offset table. Since the + offset must always be a multiple of 4, we use the + least significant bit to record whether we have + initialized it already. + + When doing a dynamic link, we create a .rela.got + relocation entry to initialize the value. This + is done in the finish_dynamic_symbol routine. */ + if ((off & 1) != 0) + off &= ~1; + else { - /* This is actually a static link, or it is a - -Bsymbolic link and the symbol is defined - locally, or the symbol was forced to be local - because of a version file. We must initialize - this entry in the global offset table. Since the - offset must always be a multiple of 4, we use the - least significant bit to record whether we have - initialized it already. - - When doing a dynamic link, we create a .rela.got - relocation entry to initialize the value. This - is done in the finish_dynamic_symbol routine. */ - if ((off & 1) != 0) - off &= ~1; - else - { - bfd_put_32 (output_bfd, relocation, - sgot->contents + off); - h->got.offset |= 1; - } + bfd_put_32 (output_bfd, relocation, + sgot->contents + off); + h->got.offset |= 1; } } - else - { - bfd_byte *loc; + } + else + { + bfd_byte *loc; - BFD_ASSERT (local_got_offsets != NULL - && local_got_offsets[r_symndx] != (bfd_vma) - 1); + BFD_ASSERT (local_got_offsets != NULL + && local_got_offsets[r_symndx] != (bfd_vma) - 1); - off = local_got_offsets[r_symndx]; + off = local_got_offsets[r_symndx]; - /* The offset must always be a multiple of 4. We use - the least significant bit to record whether we have - already processed this entry. */ - if ((off & 1) != 0) - off &= ~1; - else + /* The offset must always be a multiple of 4. We use + the least significant bit to record whether we have + already processed this entry. */ + if ((off & 1) != 0) + off &= ~1; + else + { + bfd_put_32 (output_bfd, relocation, sgot->contents + off); + + if (bfd_link_pic (info)) { - bfd_put_32 (output_bfd, relocation, sgot->contents + off); + asection *srelgot; + Elf_Internal_Rela outrel; - if (bfd_link_pic (info)) - { - asection *srelgot; - Elf_Internal_Rela outrel; - - /* We need to generate a R_NDS32_RELATIVE reloc - for the dynamic linker. */ - srelgot = htab->root.srelgot; - BFD_ASSERT (srelgot != NULL); - - outrel.r_offset = (elf_gp (output_bfd) - + sgot->output_offset + off); - outrel.r_info = ELF32_R_INFO (0, R_NDS32_RELATIVE); - outrel.r_addend = relocation; - loc = srelgot->contents; - loc += - srelgot->reloc_count * sizeof (Elf32_External_Rela); - bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); - ++srelgot->reloc_count; - } - local_got_offsets[r_symndx] |= 1; + /* We need to generate a R_NDS32_RELATIVE reloc + for the dynamic linker. */ + srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); + BFD_ASSERT (srelgot != NULL); + + outrel.r_offset = (elf_gp (output_bfd) + + sgot->output_offset + off); + outrel.r_info = ELF32_R_INFO (0, R_NDS32_RELATIVE); + outrel.r_addend = relocation; + loc = srelgot->contents; + loc += + srelgot->reloc_count * sizeof (Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); + ++srelgot->reloc_count; } + local_got_offsets[r_symndx] |= 1; } - relocation = sgot->output_section->vma + sgot->output_offset + off - - elf_gp (output_bfd); } + relocation = sgot->output_section->vma + sgot->output_offset + off + - elf_gp (output_bfd); + if (relocation & align) { /* Incorrect alignment. */ @@ -5060,50 +6074,48 @@ nds32_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, case R_NDS32_SDA19S0_RELA: case R_NDS32_SDA15S0_RELA: case R_NDS32_SDA15S0: - { - align = 0x0; + align = 0x0; handle_sda: - BFD_ASSERT (sec != NULL); + BFD_ASSERT (sec != NULL); - /* If the symbol is in the abs section, the out_bfd will be null. - This happens when the relocation has a symbol@GOTOFF. */ - r = nds32_elf_final_sda_base (output_bfd, info, &gp, FALSE); - if (r != bfd_reloc_ok) - { - _bfd_error_handler - (_("%B: warning: relocate SDA_BASE failed."), input_bfd); - ret = FALSE; - goto check_reloc; - } + /* If the symbol is in the abs section, the out_bfd will be null. + This happens when the relocation has a symbol@GOTOFF. */ + r = nds32_elf_final_sda_base (output_bfd, info, &gp, FALSE); + if (r != bfd_reloc_ok) + { + _bfd_error_handler + (_("%B: warning: relocate SDA_BASE failed."), input_bfd); + ret = FALSE; + goto check_reloc; + } - /* At this point `relocation' contains the object's - address. */ - if (r_type == R_NDS32_SDA_FP7U2_RELA) - { - relocation -= fpbase_addr; - } - else - relocation -= gp; - /* Now it contains the offset from _SDA_BASE_. */ + /* At this point `relocation' contains the object's + address. */ + if (r_type == R_NDS32_SDA_FP7U2_RELA) + { + relocation -= fpbase_addr; + } + else + relocation -= gp; + /* Now it contains the offset from _SDA_BASE_. */ - /* Make sure alignment is correct. */ + /* Make sure alignment is correct. */ - if (relocation & align) - { - /* Incorrect alignment. */ - _bfd_error_handler - /* xgettext:c-format */ - (_("%B(%A): warning: unaligned small data access of type %d."), - input_bfd, input_section, r_type); - ret = FALSE; - goto check_reloc; - } + if (relocation & align) + { + /* Incorrect alignment. */ + _bfd_error_handler + (_("%B(%A): warning: unaligned small data access of type %d."), + input_bfd, input_section, r_type); + ret = FALSE; + goto check_reloc; } break; case R_NDS32_17IFC_PCREL_RELA: case R_NDS32_10IFCU_PCREL_RELA: - /* do nothing */ + ifc_flag = TRUE; + /* do nothing */ break; case R_NDS32_TLS_LE_HI20: @@ -5112,28 +6124,38 @@ handle_sda: case R_NDS32_TLS_LE_15S0: case R_NDS32_TLS_LE_15S1: case R_NDS32_TLS_LE_15S2: + /* TODO: we do not have garbage collection for got entries. + IE to LE may have one empty entry, and DESC to LE may + have two. */ if (elf_hash_table (info)->tls_sec != NULL) relocation -= (elf_hash_table (info)->tls_sec->vma + TP_OFFSET); break; case R_NDS32_TLS_IE_HI20: case R_NDS32_TLS_IE_LO12S2: + case R_NDS32_TLS_DESC_HI20: + case R_NDS32_TLS_DESC_LO12: + case R_NDS32_TLS_IE_LO12: + case R_NDS32_TLS_IEGP_HI20: + case R_NDS32_TLS_IEGP_LO12: + case R_NDS32_TLS_IEGP_LO12S2: { /* Relocation is to the entry for this symbol in the global offset table. */ - unsigned int tls_type; + enum elf_nds32_tls_type tls_type, org_tls_type, eff_tls_type; asection *srelgot; Elf_Internal_Rela outrel; - bfd_vma off; bfd_byte *loc; int indx = 0; + eff_tls_type = org_tls_type = get_tls_type (r_type, h); + BFD_ASSERT (sgot != NULL); if (h != NULL) { bfd_boolean dyn; off = h->got.offset; - BFD_ASSERT (off != (bfd_vma) - 1); + BFD_ASSERT (off != (bfd_vma) -1); dyn = htab->root.dynamic_sections_created; tls_type = ((struct elf_nds32_link_hash_entry *) h)->tls_type; if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h) @@ -5143,64 +6165,184 @@ handle_sda: } else { - /* Never happen currently. */ BFD_ASSERT (local_got_offsets != NULL && local_got_offsets[r_symndx] != (bfd_vma) - 1); off = local_got_offsets[r_symndx]; - tls_type = elf32_nds32_local_got_tls_type (input_bfd)[r_symndx]; } + relocation = sgot->output_section->vma + sgot->output_offset + off; - if (r_type == R_NDS32_TLS_IE_LO12S2) - break; + if (1 < ones32 (tls_type)) + { + eff_tls_type = 1 << (fls (tls_type) - 1); + /* TLS model shall be handled in nds32_elf_unify_tls_model () */ + + /* TLS model X -> LE is not implement yet! + * workaround here! */ + if (eff_tls_type == GOT_TLS_LE) + { + eff_tls_type = 1 << (fls (tls_type ^ eff_tls_type) - 1); + } + } /* The offset must always be a multiple of 4. We use the least significant bit to record whether we have already processed this entry. */ - if ((off & 1) != 0) - off &= ~1; + bfd_boolean need_relocs = FALSE; + srelgot = ehtab->srelgot; + if ((bfd_link_pic (info) || indx != 0) + && (h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || h->root.type != bfd_link_hash_undefweak)) + { + need_relocs = TRUE; + BFD_ASSERT (srelgot != NULL); + } + + if (off & 1) + { + off &= ~1; + relocation &= ~1; + + if (eff_tls_type & GOT_TLS_DESC) + { + relocation -= elf_gp (output_bfd); + if ((R_NDS32_TLS_DESC_HI20 == r_type) && (!need_relocs)) + { + /* TLS model shall be converted */ + BFD_ASSERT(0); + } + } + else if (eff_tls_type & GOT_TLS_IEGP) + { + relocation -= elf_gp (output_bfd); + } + } else { - bfd_boolean need_relocs = FALSE; - srelgot = htab->root.srelgot; - if ((bfd_link_pic (info) || indx != 0) - && (h == NULL - || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT - || h->root.type != bfd_link_hash_undefweak)) + if ((eff_tls_type & GOT_TLS_LE) && (tls_type ^ eff_tls_type)) { - need_relocs = TRUE; - BFD_ASSERT (srelgot != NULL); + /* TLS model workaround shall be applied */ + BFD_ASSERT(0); } - if (tls_type & GOT_TLS_IE) + else if (eff_tls_type & (GOT_TLS_IE | GOT_TLS_IEGP)) { + if (eff_tls_type & GOT_TLS_IEGP) + relocation -= elf_gp(output_bfd); + if (need_relocs) { - if (h->dynindx == 0) - outrel.r_addend = relocation - dtpoff_base (info); + if (indx == 0) + outrel.r_addend = gottpoff (info, relocation_sym); else outrel.r_addend = 0; outrel.r_offset = (sgot->output_section->vma - + sgot->output_offset - + off); - outrel.r_info = - ELF32_R_INFO (h->dynindx, R_NDS32_TLS_TPOFF); - - loc = srelgot->contents; - loc += - srelgot->reloc_count * sizeof (Elf32_External_Rela); - bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); - ++srelgot->reloc_count; + + sgot->output_offset + off); + outrel.r_info = ELF32_R_INFO (indx, R_NDS32_TLS_TPOFF); + + elf32_nds32_add_dynreloc (output_bfd, info, srelgot, + &outrel); } else - bfd_put_32 (output_bfd, h->root.u.def.value - TP_OFFSET, - sgot->contents + off); + { + bfd_put_32 (output_bfd, gottpoff (info, relocation_sym), + sgot->contents + off); + } + } + else if (eff_tls_type & GOT_TLS_DESC) + { + relocation -= elf_gp (output_bfd); + if (need_relocs) + { + if (indx == 0) + outrel.r_addend = gottpoff (info, relocation_sym); + else + outrel.r_addend = 0; + outrel.r_offset = (sgot->output_section->vma + + sgot->output_offset + off); + outrel.r_info = ELF32_R_INFO (indx, R_NDS32_TLS_DESC); + + if (htab->tls_desc_trampoline) + { + asection *srelplt; + srelplt = ehtab->srelplt; + loc = srelplt->contents; + loc += htab->next_tls_desc_index++ * sizeof (Elf32_External_Rela); + BFD_ASSERT (loc + sizeof (Elf32_External_Rela) + <= srelplt->contents + srelplt->size); + + bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); + } + else + { + loc = srelgot->contents; + loc += srelgot->reloc_count * sizeof (Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); + ++srelgot->reloc_count; + } + } + else + { + /* feed me! */ + bfd_put_32 (output_bfd, 0xdeadbeef, + sgot->contents + off); + bfd_put_32 (output_bfd, gottpoff (info, relocation_sym), + sgot->contents + off + 4); + patch_tls_desc_to_ie (contents, rel, input_bfd); + BFD_ASSERT(0); + } + } + else + { + /* TLS model workaround shall be applied */ + BFD_ASSERT(0); } + + if (h != NULL) + h->got.offset |= 1; + else + local_got_offsets[r_symndx] |= 1; } } - break; + break; + + case R_NDS32_SECURITY_16: + relocation = 0; + crc_rel->r_addend = NDS32_SECURITY_NONE; + r = nds32_elf_final_link_relocate (howto, input_bfd, + input_section, contents, + crc_rel->r_offset, relocation, + crc_rel->r_addend); + crc_rel = NULL; + goto check_reloc; + break; + /* DON'T fall through. */ + case R_NDS32_ICT_HI20: + case R_NDS32_ICT_LO12: + case R_NDS32_ICT_25PC: + case R_NDS32_ICT_LO12S2: + entry = (struct elf_nds32_ict_hash_entry*) + bfd_hash_lookup (&indirect_call_table, h->root.root.string, + FALSE, FALSE); + if (!entry) + { + _bfd_error_handler + (_("%pB %pA: internal error indirect call relocation " + "0x%lx without hash.\n"), + input_bfd, sec, rel->r_offset); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + h2 = bfd_link_hash_lookup (info->hash, + "_INDIRECT_CALL_TABLE_BASE_", + FALSE, FALSE, FALSE); + relocation = ((h2->u.def.value + + h2->u.def.section->output_section->vma + + h2->u.def.section->output_offset) + + (entry->order * 4)); + break; /* DON'T fall through. */ default: @@ -5275,6 +6417,12 @@ handle_sda: case R_NDS32_TLS_LE_15S0: case R_NDS32_TLS_LE_15S1: case R_NDS32_TLS_LE_15S2: + case R_NDS32_TLS_DESC_HI20: + case R_NDS32_TLS_DESC_LO12: + case R_NDS32_TLS_IE_LO12: + case R_NDS32_TLS_IEGP_HI20: + case R_NDS32_TLS_IEGP_LO12: + case R_NDS32_TLS_IEGP_LO12S2: /* Instruction related relocs must handle endian properly. */ /* NOTE: PIC IS NOT HANDLE YET; DO IT LATER. */ r = nds32_elf_final_link_relocate (howto, input_bfd, @@ -5283,6 +6431,15 @@ handle_sda: rel->r_addend); break; + case R_NDS32_ICT_HI20: + case R_NDS32_ICT_LO12: + case R_NDS32_ICT_25PC: + case R_NDS32_ICT_LO12S2: + r = nds32_elf_final_link_relocate (howto, input_bfd, input_section, + contents, rel->r_offset, + relocation, 0); + break; + default: /* All other relocs can use default handler. */ r = _bfd_final_link_relocate (howto, input_bfd, input_section, @@ -5314,6 +6471,17 @@ check_reloc: switch (r) { case bfd_reloc_overflow: + if (r_type == R_NDS32_17IFC_PCREL_RELA) + { + _bfd_error_handler + (_("\n%pB: (%pA+0x%x): The IFC optimization range exceeded.\n" + "Please turn off the IFC optimization (-mno-ifc) when " + "compiling the file %s.\n"), + input_bfd, sec, (int) rel->r_offset, + h->root.u.def.section->owner->filename); + bfd_set_error (bfd_error_bad_value); + } + (*info->callbacks->reloc_overflow) (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0, input_bfd, input_section, offset); @@ -5340,14 +6508,18 @@ check_reloc: errmsg = _("internal error: unknown error"); /* Fall through. */ - common_error: - (*info->callbacks->warning) (info, errmsg, name, input_bfd, - input_section, offset); +common_error: + (*info->callbacks->warning) + (info, errmsg, name, input_bfd, input_section, offset); break; } } } + /* Resotre header size to avoid overflow load. */ + if (elf_nds32_tdata (input_bfd)->hdr_size != 0) + symtab_hdr->sh_size = elf_nds32_tdata (input_bfd)->hdr_size; + return ret; } @@ -5356,12 +6528,15 @@ check_reloc: static bfd_boolean nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, - struct elf_link_hash_entry *h, Elf_Internal_Sym *sym) + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) { - struct elf_nds32_link_hash_table *htab; + struct elf_link_hash_table *ehtab; + struct elf_nds32_link_hash_entry *hent; bfd_byte *loc; - htab = nds32_elf_hash_table (info); + ehtab = elf_hash_table (info); + hent = (struct elf_nds32_link_hash_entry *) h; if (h->plt.offset != (bfd_vma) - 1) { @@ -5379,9 +6554,9 @@ nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, BFD_ASSERT (h->dynindx != -1); - splt = htab->root.splt; - sgot = htab->root.sgotplt; - srela = htab->root.srelplt; + splt = ehtab->splt; + sgot = ehtab->sgotplt; + srela = ehtab->srelplt; BFD_ASSERT (splt != NULL && sgot != NULL && srela != NULL); /* Get the index in the procedure linkage table which @@ -5417,7 +6592,7 @@ nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, bfd_putb32 (insn, splt->contents + h->plt.offset + 12); insn = PLT_ENTRY_WORD4 - + (((unsigned int) ((-(h->plt.offset + 16)) >> 1)) & 0xffffff); + + (((unsigned int) ((-(h->plt.offset + 16)) >> 1)) & 0xffffff); bfd_putb32 (insn, splt->contents + h->plt.offset + 16); local_plt_offset = 12; } @@ -5428,9 +6603,8 @@ nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, long offset; /* FIXME, sda_base is 65536, it will damage opcode. */ - /* insn = PLT_PIC_ENTRY_WORD0 + (((got_offset - sda_base) >> 2) & 0x7fff); */ offset = sgot->output_section->vma + sgot->output_offset + got_offset - - elf_gp (output_bfd); + - elf_gp (output_bfd); insn = PLT_PIC_ENTRY_WORD0 + ((offset >> 12) & 0xfffff); bfd_putb32 (insn, splt->contents + h->plt.offset); @@ -5479,18 +6653,18 @@ nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, } } - if (h->got.offset != (bfd_vma) - 1) + if ((h->got.offset != (bfd_vma) -1) && (hent->tls_type == GOT_NORMAL)) { asection *sgot; - asection *srela; + asection *srelagot; Elf_Internal_Rela rela; /* This symbol has an entry in the global offset table. Set it up. */ - sgot = htab->root.sgot; - srela = htab->root.srelgot; - BFD_ASSERT (sgot != NULL && srela != NULL); + sgot = ehtab->sgot; + srelagot = ehtab->srelgot; + BFD_ASSERT (sgot != NULL && srelagot != NULL); rela.r_offset = (sgot->output_section->vma + sgot->output_offset + (h->got.offset & ~1)); @@ -5500,14 +6674,24 @@ nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, the symbol was forced to be local because of a version file. The entry in the global offset table will already have been initialized in the relocate_section function. */ - if (bfd_link_pic (info) - && (info->symbolic - || h->dynindx == -1 || h->forced_local) && h->def_regular) + if ((bfd_link_pic (info) + && (info->symbolic || h->dynindx == -1 || h->forced_local) + && h->def_regular) + || (bfd_link_pie (info) && h->def_regular)) { rela.r_info = ELF32_R_INFO (0, R_NDS32_RELATIVE); rela.r_addend = (h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset); + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + + /* FIXME: cancel PLT trampoline, too late ?? */ + /* h->plt.offset = (bfd_vma) -1; */ + + if ((h->got.offset & 1) == 0) + { + bfd_put_32 (output_bfd, rela.r_addend, + sgot->contents + h->got.offset); + } } else { @@ -5518,10 +6702,11 @@ nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, rela.r_addend = 0; } - loc = srela->contents; - loc += srela->reloc_count * sizeof (Elf32_External_Rela); + loc = srelagot->contents; + loc += srelagot->reloc_count * sizeof (Elf32_External_Rela); bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); - ++srela->reloc_count; + ++srelagot->reloc_count; + BFD_ASSERT (loc < (srelagot->contents + srelagot->size)); } if (h->needs_copy) @@ -5563,23 +6748,32 @@ nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, static bfd_boolean nds32_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { - struct elf_nds32_link_hash_table *htab; bfd *dynobj; asection *sdyn; - asection *sgot; + asection *sgotplt; + struct elf_link_hash_table *ehtab; + struct elf_nds32_link_hash_table *htab; + ehtab = elf_hash_table (info); htab = nds32_elf_hash_table (info); - dynobj = htab->root.dynobj; + if (htab == NULL) + return FALSE; + + dynobj = elf_hash_table (info)->dynobj; - sgot = htab->root.sgotplt; + sgotplt = ehtab->sgotplt; + /* A broken linker script might have discarded the dynamic sections. + Catch this here so that we do not seg-fault later on. */ + if (sgotplt != NULL && bfd_is_abs_section (sgotplt->output_section)) + return FALSE; sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); - if (htab->root.dynamic_sections_created) + if (elf_hash_table (info)->dynamic_sections_created) { asection *splt; Elf32_External_Dyn *dyncon, *dynconend; - BFD_ASSERT (sgot != NULL && sdyn != NULL); + BFD_ASSERT (sgotplt != NULL && sdyn != NULL); dyncon = (Elf32_External_Dyn *) sdyn->contents; dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); @@ -5597,25 +6791,60 @@ nds32_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) break; case DT_PLTGOT: - s = htab->root.sgotplt; + /* name = ".got"; */ + s = ehtab->sgot->output_section; goto get_vma; case DT_JMPREL: - s = htab->root.srelplt; - get_vma: - dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; + s = ehtab->srelplt->output_section; +get_vma: + BFD_ASSERT (s != NULL); + dyn.d_un.d_ptr = s->vma; bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); break; case DT_PLTRELSZ: - s = htab->root.srelplt; + s = ehtab->srelplt->output_section; + BFD_ASSERT (s != NULL); dyn.d_un.d_val = s->size; bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); break; + + case DT_RELASZ: + /* My reading of the SVR4 ABI indicates that the + procedure linkage table relocs (DT_JMPREL) should be + included in the overall relocs (DT_RELA). This is + what Solaris does. However, UnixWare can not handle + that case. Therefore, we override the DT_RELASZ entry + here to make it not include the JMPREL relocs. Since + the linker script arranges for .rela.plt to follow all + other relocation sections, we don't have to worry + about changing the DT_RELA entry. */ + if (ehtab->srelplt != NULL) + { + s = ehtab->srelplt->output_section; + dyn.d_un.d_val -= s->size; + } + bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); + break; + + case DT_TLSDESC_PLT: + s = htab->root.splt; + dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset + + htab->dt_tlsdesc_plt); + bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); + break; + + case DT_TLSDESC_GOT: + s = htab->root.sgot; + dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset + + htab->dt_tlsdesc_got); + bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); + break; } } /* Fill in the first entry in the procedure linkage table. */ - splt = htab->root.splt; + splt = ehtab->splt; if (splt && splt->size > 0) { if (bfd_link_pic (info)) @@ -5624,13 +6853,11 @@ nds32_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) long offset; /* FIXME, sda_base is 65536, it will damage opcode. */ - /* insn = PLT_PIC_ENTRY_WORD0 + (((got_offset - sda_base) >> 2) & 0x7fff); */ - offset = sgot->output_section->vma + sgot->output_offset + 4 - - elf_gp (output_bfd); + offset = sgotplt->output_section->vma + sgotplt->output_offset + 4 + - elf_gp (output_bfd); insn = PLT0_PIC_ENTRY_WORD0 | ((offset >> 12) & 0xfffff); bfd_putb32 (insn, splt->contents); - /* insn = PLT0_PIC_ENTRY_WORD0 | (((8 - sda_base) >> 2) & 0x7fff) ; */ /* here has a typo? */ insn = PLT0_PIC_ENTRY_WORD1 | (offset & 0xfff); bfd_putb32 (insn, splt->contents + 4); @@ -5652,8 +6879,8 @@ nds32_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) unsigned long insn; unsigned long addr; - /* addr = .got + 4 */ - addr = sgot->output_section->vma + sgot->output_offset + 4; + /* addr = .got + 4 */ + addr = sgotplt->output_section->vma + sgotplt->output_offset + 4; insn = PLT0_ENTRY_WORD0 | ((addr >> 12) & 0xfffff); bfd_putb32 (insn, splt->contents); @@ -5673,21 +6900,48 @@ nds32_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) elf_section_data (splt->output_section)->this_hdr.sh_entsize = PLT_ENTRY_SIZE; } + + if (htab->dt_tlsdesc_plt) + { + /* Calculate addresses. */ + asection *sgot = sgot = ehtab->sgot; + bfd_vma pltgot = sgotplt->output_section->vma + + sgotplt->output_offset; + bfd_vma tlsdesc_got = sgot->output_section->vma + sgot->output_offset + + htab->dt_tlsdesc_got; + + /* Get GP offset. */ + pltgot -= elf_gp (output_bfd) - 4; /* PLTGOT[1] */ + tlsdesc_got -= elf_gp (output_bfd); + + /* Do relocation. */ + dl_tlsdesc_lazy_trampoline[0] += ((1 << 20) - 1) & (tlsdesc_got >> 12); + dl_tlsdesc_lazy_trampoline[1] += 0xfff & tlsdesc_got; + dl_tlsdesc_lazy_trampoline[4] += ((1 << 20) - 1) & (pltgot >> 12); + dl_tlsdesc_lazy_trampoline[5] += 0xfff & pltgot; + + /* TODO: relaxation. */ + + /* Insert .plt. */ + nds32_put_trampoline (splt->contents + htab->dt_tlsdesc_plt, + dl_tlsdesc_lazy_trampoline, + ARRAY_SIZE (dl_tlsdesc_lazy_trampoline)); + } } /* Fill in the first three entries in the global offset table. */ - if (sgot && sgot->size > 0) + if (sgotplt && sgotplt->size > 0) { if (sdyn == NULL) - bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents); + bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents); else bfd_put_32 (output_bfd, sdyn->output_section->vma + sdyn->output_offset, - sgot->contents); - bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 4); - bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 8); + sgotplt->contents); + bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents + 4); + bfd_put_32 (output_bfd, (bfd_vma) 0, sgotplt->contents + 8); - elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; + elf_section_data (sgotplt->output_section)->this_hdr.sh_entsize = 4; } return TRUE; @@ -5738,6 +6992,7 @@ nds32_elf_final_write_processing (bfd *abfd, { unsigned long val; static unsigned int cur_mach = 0; + unsigned int i; if (bfd_mach_n1 != bfd_get_mach (abfd)) { @@ -5771,6 +7026,36 @@ nds32_elf_final_write_processing (bfd *abfd, elf_elfheader (abfd)->e_flags &= ~EF_NDS_ARCH; elf_elfheader (abfd)->e_flags |= val; + if (ifc_flag) + elf_elfheader (abfd)->e_flags |= E_NDS32_HAS_IFC_INST ; + + if (ict_file) + { + fprintf (ict_file, ".section " NDS32_ICT_SECTION ", \"ax\"\n"); + if (ict_model == R_NDS32_RELAX_ENTRY_ICT_LARGE) + fprintf (ict_file, ".ict_model\tlarge\n"); + else + fprintf (ict_file, ".ict_model\tsmall\n"); + fprintf (ict_file, ".globl _INDIRECT_CALL_TABLE_BASE_\n" + "_INDIRECT_CALL_TABLE_BASE_:\n"); + /* Output rom patch entries. */ + indirect_call_table.frozen = 1; + for (i = 0; i < indirect_call_table.size; i++) + { + struct bfd_hash_entry *p; + struct elf_nds32_ict_hash_entry *entry; + + for (p = indirect_call_table.table[i]; p != NULL; p = p->next) + { + entry = (struct elf_nds32_ict_hash_entry *) p; + if (ict_model == R_NDS32_RELAX_ENTRY_ICT_LARGE) + fprintf (ict_file, "\t.word\t%s\n", entry->root.string); + else + fprintf (ict_file, "\tj\t%s\n", entry->root.string); + } + } + indirect_call_table.frozen = 0; + } } /* Function to keep NDS32 specific file flags. */ @@ -5856,13 +7141,27 @@ nds32_check_vec_size (bfd *ibfd) return TRUE; } +static unsigned int +nds32_elf_force_to_set_output_abi (char *str) +{ + flagword flags; + + if (strcmp (str, "AABI") == 0) + flags = E_NDS_ABI_AABI; + else if (strcmp (str, "V2FP+") == 0) + flags = E_NDS_ABI_V2FP_PLUS; + else + flags = 0; + + return flags; +} + /* Merge backend specific data from an object file to the output object file when linking. */ static bfd_boolean nds32_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) { - bfd *obfd = info->output_bfd; flagword out_flags; flagword in_flags; flagword out_16regs; @@ -5873,6 +7172,7 @@ nds32_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) flagword in_version; flagword out_fpu_config; flagword in_fpu_config; + bfd *obfd = info->output_bfd; /* TODO: Revise to use object-attributes instead. */ if (!nds32_check_vec_size (ibfd)) @@ -5891,135 +7191,171 @@ nds32_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) return FALSE; } - in_version = elf_elfheader (ibfd)->e_flags & EF_NDS32_ELF_VERSION; - if (in_version == E_NDS32_ELF_VER_1_2) - { - _bfd_error_handler - (_("%B: warning: Older version of object file encountered, " - "Please recompile with current tool chain."), ibfd); - } - - /* We may need to merge V1 and V2 arch object files to V2. */ - if ((elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH) - != (elf_elfheader (obfd)->e_flags & EF_NDS_ARCH)) + /* [Bug 11585] [Ticket 7067] -B option in objcopy cannot work as expected. + e_flags = 0 shall be treat as generic one. + no checking, and no merging. */ + if (elf_elfheader (ibfd)->e_flags) { - /* Need to convert version. */ - if ((elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH) - == E_NDS_ARCH_STAR_RESERVED) + in_version = elf_elfheader (ibfd)->e_flags & EF_NDS32_ELF_VERSION; + if (in_version == E_NDS32_ELF_VER_1_2) { - elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; + _bfd_error_handler + (_("%pB: warning: Older version of object file encountered, " + "Please recompile with current tool chain."), ibfd); } - else if ((elf_elfheader (obfd)->e_flags & EF_NDS_ARCH) == E_NDS_ARCH_STAR_V0_9 - || (elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH) - > (elf_elfheader (obfd)->e_flags & EF_NDS_ARCH)) + + if (output_abi != NULL) { - elf_elfheader (obfd)->e_flags = - convert_e_flags (elf_elfheader (obfd)->e_flags, - (elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH)); + elf_elfheader (ibfd)->e_flags &= ~(EF_NDS_ABI); + elf_elfheader (ibfd)->e_flags + |= nds32_elf_force_to_set_output_abi (output_abi); + elf_elfheader (obfd)->e_flags &= ~(EF_NDS_ABI); + elf_elfheader (obfd)->e_flags + |= nds32_elf_force_to_set_output_abi (output_abi); } - else + + /* We may need to merge V1 and V2 arch object files to V2. */ + if ((elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH) + != (elf_elfheader (obfd)->e_flags & EF_NDS_ARCH)) { - elf_elfheader (ibfd)->e_flags = - convert_e_flags (elf_elfheader (ibfd)->e_flags, - (elf_elfheader (obfd)->e_flags & EF_NDS_ARCH)); - } - } - - /* Extract some flags. */ - in_flags = elf_elfheader (ibfd)->e_flags - & (~(E_NDS32_HAS_REDUCED_REGS | EF_NDS32_ELF_VERSION - | E_NDS32_HAS_NO_MAC_INST | E_NDS32_FPU_REG_CONF)); - - /* The following flags need special treatment. */ - in_16regs = elf_elfheader (ibfd)->e_flags & E_NDS32_HAS_REDUCED_REGS; - in_no_mac = elf_elfheader (ibfd)->e_flags & E_NDS32_HAS_NO_MAC_INST; - in_fpu_config = elf_elfheader (ibfd)->e_flags & E_NDS32_FPU_REG_CONF; - - /* Extract some flags. */ - out_flags = elf_elfheader (obfd)->e_flags - & (~(E_NDS32_HAS_REDUCED_REGS | EF_NDS32_ELF_VERSION - | E_NDS32_HAS_NO_MAC_INST | E_NDS32_FPU_REG_CONF)); - - /* The following flags need special treatment. */ - out_16regs = elf_elfheader (obfd)->e_flags & E_NDS32_HAS_REDUCED_REGS; - out_no_mac = elf_elfheader (obfd)->e_flags & E_NDS32_HAS_NO_MAC_INST; - out_fpu_config = elf_elfheader (obfd)->e_flags & E_NDS32_FPU_REG_CONF; - out_version = elf_elfheader (obfd)->e_flags & EF_NDS32_ELF_VERSION; - if (!elf_flags_init (obfd)) - { - /* If the input is the default architecture then do not - bother setting the flags for the output architecture, - instead allow future merges to do this. If no future - merges ever set these flags then they will retain their - unitialised values, which surprise surprise, correspond - to the default values. */ - if (bfd_get_arch_info (ibfd)->the_default) - return TRUE; + /* Need to convert version. */ + if ((elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH) + == E_NDS_ARCH_STAR_RESERVED) + { + elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; + } + else if ((elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH) + == E_NDS_ARCH_STAR_V3_M + && (elf_elfheader (obfd)->e_flags & EF_NDS_ARCH) + == E_NDS_ARCH_STAR_V3_0) + { + elf_elfheader (ibfd)->e_flags = + (elf_elfheader (ibfd)->e_flags & (~EF_NDS_ARCH)) + | E_NDS_ARCH_STAR_V3_0; + } + else if ((elf_elfheader (obfd)->e_flags & EF_NDS_ARCH) + == E_NDS_ARCH_STAR_V0_9 + || (elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH) + > (elf_elfheader (obfd)->e_flags & EF_NDS_ARCH)) + { + elf_elfheader (obfd)->e_flags = + convert_e_flags (elf_elfheader (obfd)->e_flags, + (elf_elfheader (ibfd)->e_flags & EF_NDS_ARCH)); + } + else + { + elf_elfheader (ibfd)->e_flags = + convert_e_flags (elf_elfheader (ibfd)->e_flags, + (elf_elfheader (obfd)->e_flags & EF_NDS_ARCH)); + } + } - elf_flags_init (obfd) = TRUE; - elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; + /* Extract some flags. */ + in_flags = elf_elfheader (ibfd)->e_flags + & (~(E_NDS32_HAS_REDUCED_REGS | EF_NDS32_ELF_VERSION + | E_NDS32_HAS_NO_MAC_INST | E_NDS32_FPU_REG_CONF)); + + /* The following flags need special treatment. */ + in_16regs = elf_elfheader (ibfd)->e_flags & E_NDS32_HAS_REDUCED_REGS; + in_no_mac = elf_elfheader (ibfd)->e_flags & E_NDS32_HAS_NO_MAC_INST; + in_fpu_config = elf_elfheader (ibfd)->e_flags & E_NDS32_FPU_REG_CONF; + + /* Extract some flags. */ + out_flags = elf_elfheader (obfd)->e_flags + & (~(E_NDS32_HAS_REDUCED_REGS | EF_NDS32_ELF_VERSION + | E_NDS32_HAS_NO_MAC_INST | E_NDS32_FPU_REG_CONF)); + + /* The following flags need special treatment. */ + out_16regs = elf_elfheader (obfd)->e_flags & E_NDS32_HAS_REDUCED_REGS; + out_no_mac = elf_elfheader (obfd)->e_flags & E_NDS32_HAS_NO_MAC_INST; + out_fpu_config = elf_elfheader (obfd)->e_flags & E_NDS32_FPU_REG_CONF; + out_version = elf_elfheader (obfd)->e_flags & EF_NDS32_ELF_VERSION; + if (!elf_flags_init (obfd)) + { + /* If the input is the default architecture then do not + bother setting the flags for the output architecture, + instead allow future merges to do this. If no future + merges ever set these flags then they will retain their + unitialised values, which surprise surprise, correspond + to the default values. */ + if (bfd_get_arch_info (ibfd)->the_default) + return TRUE; - if (bfd_get_arch (obfd) == bfd_get_arch (ibfd) - && bfd_get_arch_info (obfd)->the_default) - { - return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), - bfd_get_mach (ibfd)); + elf_flags_init (obfd) = TRUE; + elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; + + if (bfd_get_arch (obfd) == bfd_get_arch (ibfd) + && bfd_get_arch_info (obfd)->the_default) + { + return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), + bfd_get_mach (ibfd)); + } + + return TRUE; } - return TRUE; - } + /* Check flag compatibility. */ + if ((in_flags & EF_NDS_ABI) != (out_flags & EF_NDS_ABI)) + { + asection *section = NULL; + bfd_byte *contents = NULL; + section = bfd_get_section_by_name (ibfd, ".note.v2abi_compatible"); + if (section) + bfd_get_full_section_contents (ibfd, section, &contents); - /* Check flag compatibility. */ - if ((in_flags & EF_NDS_ABI) != (out_flags & EF_NDS_ABI)) - { - _bfd_error_handler - (_("%B: error: ABI mismatch with previous modules."), ibfd); + /* Only enable v3f/v3s toolchain to link v2abi compatible objects. */ + if ((contents == NULL) + || bfd_getb32 (contents) != 1 + || (out_flags & EF_NDS_ABI) != E_NDS_ABI_V2FP_PLUS) + { + _bfd_error_handler + (_("%pB: error: ABI mismatch with previous modules."), ibfd); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + } - if ((in_flags & EF_NDS_ARCH) != (out_flags & EF_NDS_ARCH)) - { - if (((in_flags & EF_NDS_ARCH) != E_N1_ARCH)) + if ((in_flags & EF_NDS_ARCH) != (out_flags & EF_NDS_ARCH)) { - _bfd_error_handler - (_("%B: error: Instruction set mismatch with previous modules."), ibfd); + if (((in_flags & EF_NDS_ARCH) != E_N1_ARCH)) + { + _bfd_error_handler + (_("%B: error: Instruction set mismatch with previous modules."), ibfd); - bfd_set_error (bfd_error_bad_value); - return FALSE; + bfd_set_error (bfd_error_bad_value); + return FALSE; + } } - } - /* When linking with V1.2 and V1.3 objects together the output is V1.2. - and perf ext1 and DIV are mergerd to perf ext1. */ - if (in_version == E_NDS32_ELF_VER_1_2 || out_version == E_NDS32_ELF_VER_1_2) - { - elf_elfheader (obfd)->e_flags = - (in_flags & (~(E_NDS32_HAS_EXT_INST | E_NDS32_HAS_DIV_INST))) - | (out_flags & (~(E_NDS32_HAS_EXT_INST | E_NDS32_HAS_DIV_INST))) - | (((in_flags & (E_NDS32_HAS_EXT_INST | E_NDS32_HAS_DIV_INST))) - ? E_NDS32_HAS_EXT_INST : 0) - | (((out_flags & (E_NDS32_HAS_EXT_INST | E_NDS32_HAS_DIV_INST))) - ? E_NDS32_HAS_EXT_INST : 0) - | (in_16regs & out_16regs) | (in_no_mac & out_no_mac) - | ((in_version > out_version) ? out_version : in_version); - } - else - { - if (in_version != out_version) - _bfd_error_handler - /* xgettext:c-format */ - (_("%B: warning: Incompatible elf-versions %s and %s."), - ibfd, nds32_elfver_strtab[out_version], - nds32_elfver_strtab[in_version]); + /* When linking with V1.2 and V1.3 objects together the output is V1.2. + and perf ext1 and DIV are mergerd to perf ext1. */ + if (in_version == E_NDS32_ELF_VER_1_2 || out_version == E_NDS32_ELF_VER_1_2) + { + elf_elfheader (obfd)->e_flags = + (in_flags & (~(E_NDS32_HAS_EXT_INST | E_NDS32_HAS_DIV_INST))) + | (out_flags & (~(E_NDS32_HAS_EXT_INST | E_NDS32_HAS_DIV_INST))) + | (((in_flags & (E_NDS32_HAS_EXT_INST | E_NDS32_HAS_DIV_INST))) + ? E_NDS32_HAS_EXT_INST : 0) + | (((out_flags & (E_NDS32_HAS_EXT_INST | E_NDS32_HAS_DIV_INST))) + ? E_NDS32_HAS_EXT_INST : 0) + | (in_16regs & out_16regs) | (in_no_mac & out_no_mac) + | ((in_version > out_version) ? out_version : in_version); + } + else + { + if (in_version != out_version) + _bfd_error_handler + (_("%B: warning: Incompatible elf-versions %s and %s."), ibfd, + nds32_elfver_strtab[out_version], + nds32_elfver_strtab[in_version]); - elf_elfheader (obfd)->e_flags = in_flags | out_flags - | (in_16regs & out_16regs) | (in_no_mac & out_no_mac) - | (in_fpu_config > out_fpu_config ? in_fpu_config : out_fpu_config) - | (in_version > out_version ? out_version : in_version); + elf_elfheader (obfd)->e_flags = in_flags | out_flags + | (in_16regs & out_16regs) | (in_no_mac & out_no_mac) + | (in_fpu_config > out_fpu_config ? in_fpu_config : out_fpu_config) + | (in_version > out_version ? out_version : in_version); + } } - return TRUE; } @@ -6081,6 +7417,79 @@ nds32_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info, return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); } +static enum elf_nds32_tls_type +get_tls_type (enum elf_nds32_reloc_type r_type, + struct elf_link_hash_entry *h ATTRIBUTE_UNUSED) +{ + enum elf_nds32_tls_type tls_type; + switch (r_type) + { + case R_NDS32_TLS_LE_HI20: + case R_NDS32_TLS_LE_LO12: + tls_type = GOT_TLS_LE; + break; + case R_NDS32_TLS_IE_HI20: + case R_NDS32_TLS_IE_LO12S2: + case R_NDS32_TLS_IE_LO12: + tls_type = GOT_TLS_IE; + break; + case R_NDS32_TLS_IEGP_HI20: + case R_NDS32_TLS_IEGP_LO12: + case R_NDS32_TLS_IEGP_LO12S2: + tls_type = GOT_TLS_IEGP; + break; + case R_NDS32_TLS_DESC_HI20: + case R_NDS32_TLS_DESC_LO12: + case R_NDS32_TLS_DESC_ADD: + case R_NDS32_TLS_DESC_FUNC: + case R_NDS32_TLS_DESC_CALL: + tls_type = GOT_TLS_DESC; + break; + default: + tls_type = GOT_NORMAL; + break; + } + return tls_type; +} + +/* Ensure that we have allocated bookkeeping structures for ABFD's local + symbols. */ + +static bfd_boolean +elf32_nds32_allocate_local_sym_info (bfd *abfd) +{ + if (elf_local_got_refcounts (abfd) == NULL) + { + bfd_size_type num_syms; + bfd_size_type size; + char *data; + + num_syms = elf_tdata (abfd)->symtab_hdr.sh_info; + /* This space is for got_refcounts, got_tls_type, tlsdesc_gotent, and + gp_offset. The details can refer to struct elf_nds32_obj_tdata. */ + size = num_syms * (sizeof (bfd_signed_vma) + sizeof (char) + + sizeof (bfd_vma) + sizeof (int) + + sizeof (bfd_boolean) + sizeof (bfd_vma)); + data = bfd_zalloc (abfd, size); + if (data == NULL) + return FALSE; + + elf_local_got_refcounts (abfd) = (bfd_signed_vma *) data; + data += num_syms * sizeof (bfd_signed_vma); + + elf32_nds32_local_got_tls_type (abfd) = (char *) data; + data += num_syms * sizeof (char); + + elf32_nds32_local_tlsdesc_gotent (abfd) = (bfd_vma *) data; + data += num_syms * sizeof (bfd_vma); + + elf32_nds32_local_gp_offset (abfd) = (int *) data; + data += num_syms * sizeof (int); + } + + return TRUE; +} + /* Look through the relocs for a section during the first phase. Since we don't do .gots or .plts, we just need to consider the virtual table relocs for gc. */ @@ -6093,21 +7502,17 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel_end; + struct elf_link_hash_table *ehtab; struct elf_nds32_link_hash_table *htab; bfd *dynobj; asection *sreloc = NULL; + /* No need for relocation if relocatable already. */ if (bfd_link_relocatable (info)) - return TRUE; - - /* Don't do anything special with non-loaded, non-alloced sections. - In particular, any relocs in such sections should not affect GOT - and PLT reference counting (ie. we don't allow them to create GOT - or PLT entries), there's no possibility or desire to optimize TLS - relocs, and there's not much point in propagating relocs to shared - libs that the dynamic linker won't relocate. */ - if ((sec->flags & SEC_ALLOC) == 0) - return TRUE; + { + elf32_nds32_check_relax_group (abfd, sec); + return TRUE; + } symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); @@ -6116,6 +7521,7 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, if (!elf_bad_symtab (abfd)) sym_hashes_end -= symtab_hdr->sh_info; + ehtab = elf_hash_table (info); htab = nds32_elf_hash_table (info); dynobj = htab->root.dynobj; @@ -6125,7 +7531,8 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, enum elf_nds32_reloc_type r_type; struct elf_link_hash_entry *h; unsigned long r_symndx; - int tls_type, old_tls_type; + enum elf_nds32_tls_type tls_type, old_tls_type; + struct elf_nds32_ict_hash_entry *entry; r_symndx = ELF32_R_SYM (rel->r_info); r_type = ELF32_R_TYPE (rel->r_info); @@ -6139,10 +7546,11 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, h = (struct elf_link_hash_entry *) h->root.u.i.link; } - /* Some relocs require a global offset table. We create - got section here, since these relocation need got section - and it is not created yet. */ - if (htab->root.sgot == NULL) + /* create .got section if necessary + Some relocs require a global offset table. We create + got section here, since these relocation need a got section + and if it is not created yet. */ + if (ehtab->sgot == NULL) { switch (r_type) { @@ -6162,10 +7570,16 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_NDS32_GOTPC_LO12: case R_NDS32_GOT20: case R_NDS32_TLS_IE_HI20: + case R_NDS32_TLS_IE_LO12: case R_NDS32_TLS_IE_LO12S2: + case R_NDS32_TLS_IEGP_HI20: + case R_NDS32_TLS_IEGP_LO12: + case R_NDS32_TLS_IEGP_LO12S2: + case R_NDS32_TLS_DESC_HI20: + case R_NDS32_TLS_DESC_LO12: if (dynobj == NULL) htab->root.dynobj = dynobj = abfd; - if (!_bfd_elf_create_got_section (dynobj, info)) + if (!create_got_section (dynobj, info)) return FALSE; break; @@ -6174,59 +7588,54 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, } } + /* Check relocation type. */ switch ((int) r_type) { + case R_NDS32_TLS_LE_HI20: + case R_NDS32_TLS_LE_LO12: case R_NDS32_GOT_HI20: case R_NDS32_GOT_LO12: case R_NDS32_GOT_LO15: case R_NDS32_GOT_LO19: case R_NDS32_GOT20: case R_NDS32_TLS_IE_HI20: + case R_NDS32_TLS_IE_LO12: case R_NDS32_TLS_IE_LO12S2: - switch (r_type) - { - case R_NDS32_TLS_IE_HI20: - case R_NDS32_TLS_IE_LO12S2: - tls_type = GOT_TLS_IE; - break; - default: - tls_type = GOT_NORMAL; - break; - } - if (h != NULL) + case R_NDS32_TLS_IEGP_HI20: + case R_NDS32_TLS_IEGP_LO12: + case R_NDS32_TLS_IEGP_LO12S2: + case R_NDS32_TLS_DESC_HI20: + case R_NDS32_TLS_DESC_LO12: + tls_type = get_tls_type (r_type, h); + if (h) { + if (tls_type != GOT_TLS_LE) + h->got.refcount += 1; old_tls_type = elf32_nds32_hash_entry (h)->tls_type; - h->got.refcount += 1; } else { - bfd_signed_vma *local_got_refcounts; - - /* This is a global offset table entry for a local - symbol. */ - local_got_refcounts = elf_local_got_refcounts (abfd); - if (local_got_refcounts == NULL) - { - bfd_size_type size; + /* This is a global offset table entry for a local symbol. */ + if (!elf32_nds32_allocate_local_sym_info (abfd)) + return FALSE; - size = symtab_hdr->sh_info; - size *= sizeof (bfd_signed_vma); - local_got_refcounts = (bfd_signed_vma *) bfd_zalloc (abfd, size); - if (local_got_refcounts == NULL) - return FALSE; - elf_local_got_refcounts (abfd) = local_got_refcounts; - } - local_got_refcounts[r_symndx] += 1; + BFD_ASSERT (r_symndx < symtab_hdr->sh_info); + if (tls_type != GOT_TLS_LE) + elf_local_got_refcounts (abfd)[r_symndx] += 1; old_tls_type = elf32_nds32_local_got_tls_type (abfd)[r_symndx]; } - /* We will already have issued an error message if there + /* We would already issued an error message if there is a TLS/non-TLS mismatch, based on the symbol - type. So just combine any TLS types needed. */ + type. So just combine any TLS types needed. */ if (old_tls_type != GOT_UNKNOWN && old_tls_type != GOT_NORMAL && tls_type != GOT_NORMAL) tls_type |= old_tls_type; + /* DESC to IE/IEGP if link to executable */ + if ((tls_type & (GOT_TLS_DESC | GOT_TLS_IEGP)) && (bfd_link_executable (info))) + tls_type |= (bfd_link_pie (info) ? GOT_TLS_IEGP : GOT_TLS_IE); + if (old_tls_type != tls_type) { if (h != NULL) @@ -6235,6 +7644,7 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, elf32_nds32_local_got_tls_type (abfd)[r_symndx] = tls_type; } break; + case R_NDS32_9_PLTREL: case R_NDS32_25_PLTREL: case R_NDS32_PLTREL_HI20: @@ -6244,19 +7654,20 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_NDS32_PLT_GOTREL_LO15: case R_NDS32_PLT_GOTREL_LO19: case R_NDS32_PLT_GOTREL_LO20: - - /* This symbol requires a procedure linkage table entry. We - actually build the entry in adjust_dynamic_symbol, + /* This symbol requires a procedure linkage table entry. + We actually build the entry in adjust_dynamic_symbol, because this might be a case of linking PIC code without linking in any dynamic objects, in which case we don't need to generate a procedure linkage table after all. */ /* If this is a local symbol, we resolve it directly without creating a procedure linkage table entry. */ + /* explain: continue v.s. break here following: */ if (h == NULL) continue; - if (h->forced_local) + if (h->forced_local + || (bfd_link_pie (info) && h->def_regular)) break; elf32_nds32_hash_entry (h)->tls_type = GOT_NORMAL; @@ -6330,8 +7741,8 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, && (h->root.type == bfd_link_hash_defweak || !h->def_regular))) { - struct elf_dyn_relocs *p; - struct elf_dyn_relocs **head; + struct elf_nds32_dyn_relocs *p; + struct elf_nds32_dyn_relocs **head; if (dynobj == NULL) htab->root.dynobj = dynobj = abfd; @@ -6380,7 +7791,6 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, else { asection *s; - void *vpp; Elf_Internal_Sym *isym; isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd, r_symndx); @@ -6392,15 +7802,15 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, if (s == NULL) return FALSE; - vpp = &elf_section_data (s)->local_dynrel; - head = (struct elf_dyn_relocs **) vpp; + head = ((struct elf_nds32_dyn_relocs **) + &elf_section_data (s)->local_dynrel); } p = *head; if (p == NULL || p->sec != sec) { bfd_size_type amt = sizeof (*p); - p = (struct elf_dyn_relocs *) bfd_alloc (dynobj, amt); + p = (struct elf_nds32_dyn_relocs *) bfd_alloc (dynobj, amt); if (p == NULL) return FALSE; p->next = *head; @@ -6411,19 +7821,98 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, } p->count += 1; + + /* FIXME: Since eh_frame is readonly, R_NDS32_32_RELA + reloc for eh_frame will cause shared library has + TEXTREL entry in the dynamic section. This lead glibc + testsuites to failure (bug-13092) and cause kernel fail + (bug-11819). I think the best solution is to replace + absolute reloc with pc relative reloc in the eh_frame. + To do that, we need to support the following issues: + + === For GCC === + * gcc/config/nds32/nds32.h: Define + ASM_PREFERRED_EH_DATA_FORMAT to encode DW_EH_PE_pcrel + and DW_EH_PE_sdata4 into DWARF exception header when + option have '-fpic'. + + === For binutils === + * bfd/: Define new reloc R_NDS32_32_PCREL_RELA. + * gas/config/tc-nds32.h: Define DIFF_EXPR_OK. This + may break our nds DIFF mechanism, therefore, we + must disable all linker relaxations to ensure + correctness. + * gas/config/tc-nds32.c (nds32_apply_fix): Replace + R_NDS32_32_RELA with R_NDS32_32_PCREL_RELA, and + do the necessary modification. + + Unfortunately, it still have some problems for nds32 + to support pc relative reloc in the eh_frame. So I use + another solution to fix this issue. + + However, I find that ld always emit TEXTREL marker for + R_NDS32_NONE relocs in rel.dyn. These none relocs are + correspond to R_NDS32_32_RELA for .eh_frame section. + It means that we always reserve redundant entries of rel.dyn + for these relocs which actually do nothing in dynamic linker. + + Therefore, we regard these relocs as pc relative relocs + here and increase the pc_count. */ if (ELF32_R_TYPE (rel->r_info) == R_NDS32_25_PCREL_RELA || ELF32_R_TYPE (rel->r_info) == R_NDS32_15_PCREL_RELA - || ELF32_R_TYPE (rel->r_info) == R_NDS32_17_PCREL_RELA) + || ELF32_R_TYPE (rel->r_info) == R_NDS32_17_PCREL_RELA + || (r_type == R_NDS32_32_RELA + && strcmp (sec->name, ".eh_frame") == 0)) p->pc_count += 1; } break; - /* This relocation describes the C++ object vtable hierarchy. - Reconstruct it for later use during GC. */ - case R_NDS32_RELA_GNU_VTINHERIT: - case R_NDS32_GNU_VTINHERIT: - if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) - return FALSE; + /* Merge jump-patch table symbol here. */ + case R_NDS32_ICT_HI20: + case R_NDS32_ICT_LO12: + case R_NDS32_ICT_25PC: + if (rel->r_addend != 0) + { + _bfd_error_handler + (_("%pB %s: Error: Rom-patch relocation offset: 0x%lx " + "with addend 0x%lx\n"), + abfd, sec->name, rel->r_offset, rel->r_addend); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + + if (h) + { + elf32_nds32_hash_entry (h)->indirect_call = TRUE; + entry = (struct elf_nds32_ict_hash_entry *) + bfd_hash_lookup (&indirect_call_table, h->root.root.string, + TRUE, TRUE); + entry->h = h; + if (entry == NULL) + { + _bfd_error_handler + (_("%pB: failed creating indirect call %s hash table\n"), + abfd, h->root.root.string); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + } + else + { + /* Rom-patch functions cannot be local. */ + _bfd_error_handler + (_("%pB: indirect call relocation with local symbol.\n"), abfd); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + break; + + /* This relocation describes the C++ object vtable hierarchy. + Reconstruct it for later use during GC. */ + case R_NDS32_RELA_GNU_VTINHERIT: + case R_NDS32_GNU_VTINHERIT: + if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) + return FALSE; break; /* This relocation describes which C++ vtable entries are actually @@ -6436,6 +7925,18 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) return FALSE; break; + case R_NDS32_RELAX_ENTRY: + if (ict_model == 0) + ict_model = rel->r_addend & R_NDS32_RELAX_ENTRY_ICT_MASK; + else if (ict_model != (rel->r_addend & R_NDS32_RELAX_ENTRY_ICT_MASK) + && (rel->r_addend & R_NDS32_RELAX_ENTRY_ICT_MASK) != 0) + { + _bfd_error_handler + (_("%pB Error: mixed ict model objects.\n"), abfd); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + break; } } @@ -6464,8 +7965,7 @@ write_uleb128 (bfd_byte *p, unsigned int val) static bfd_signed_vma calculate_offset (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, - Elf_Internal_Sym *isymbuf, Elf_Internal_Shdr *symtab_hdr, - int *pic_ext_target) + Elf_Internal_Sym *isymbuf, Elf_Internal_Shdr *symtab_hdr) { bfd_signed_vma foff; bfd_vma symval, addend; @@ -6494,7 +7994,6 @@ calculate_offset (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, { unsigned long indx; struct elf_link_hash_entry *h; - bfd *owner; /* An external symbol. */ indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; @@ -6507,9 +8006,6 @@ calculate_offset (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, symbol. Just ignore it--it will be caught by the regular reloc processing. */ return 0; - owner = h->root.u.def.section->owner; - if (owner && (elf_elfheader (owner)->e_flags & E_NDS32_HAS_PIC)) - *pic_ext_target = 1; if (h->root.u.def.section->flags & SEC_MERGE) { @@ -6563,15 +8059,15 @@ calculate_plt_memory_address (bfd *abfd, struct bfd_link_info *link_info, { unsigned long indx; struct elf_link_hash_entry *h; - struct elf_nds32_link_hash_table *htab; + struct elf_link_hash_table *ehtab; asection *splt; /* An external symbol. */ indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; h = elf_sym_hashes (abfd)[indx]; BFD_ASSERT (h != NULL); - htab = nds32_elf_hash_table (link_info); - splt = htab->root.splt; + ehtab = elf_hash_table (link_info); + splt = ehtab->splt; while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) @@ -6582,8 +8078,8 @@ calculate_plt_memory_address (bfd *abfd, struct bfd_link_info *link_info, if (h->root.type != bfd_link_hash_defined && h->root.type != bfd_link_hash_defweak) /* This appears to be a reference to an undefined - * symbol. Just ignore it--it will be caught by the - * regular reloc processing. */ + symbol. Just ignore it--it will be caught by the + regular reloc processing. */ return 0; symval = (h->root.u.def.value + h->root.u.def.section->output_section->vma @@ -6620,7 +8116,7 @@ nds32_convert_32_to_16_alu1 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, int *pinsn_type) { uint16_t insn16 = 0; - int insn_type = 0; + int insn_type; unsigned long mach = bfd_get_mach (abfd); if (N32_SH5 (insn) != 0) @@ -6919,8 +8415,7 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, else if (N32_IS_RT4 (insn) && N32_RT5 (insn) == N32_RA5 (insn) && N32_IMM15S (insn) > -32) { - insn16 = N16_TYPE45 (SUBI45, N32_RT54 (insn), - 0 - N32_IMM15S (insn)); + insn16 = N16_TYPE45 (SUBI45, N32_RT54 (insn), 0 - N32_IMM15S (insn)); insn_type = NDS32_INSN_SUBI45; } else if (mach >= MACH_V2 && N32_RT5 (insn) == REG_SP @@ -6981,7 +8476,7 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, if (__builtin_popcount (imm15u) == 1) { - /* BMSKI33 */ + /* BMSKI33 */ int imm3u = __builtin_ctz (imm15u); insn16 = N16_BFMI333 (BMSKI33, N32_RT5 (insn), imm3u); @@ -6989,7 +8484,7 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, } else if (imm15u != 0 && __builtin_popcount (imm15u + 1) == 1) { - /* FEXTI33 */ + /* FEXTI33 */ int imm3u = __builtin_ctz (imm15u + 1) - 1; insn16 = N16_BFMI333 (FEXTI33, N32_RT5 (insn), imm3u); @@ -7150,7 +8645,7 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, if ((insn & N32_BIT (14)) == 0) { - /* N32_BR1_BEQ */ + /* N32_BR1_BEQ */ if (N32_IS_RT3 (insn) && N32_RA5 (insn) == REG_R5 && N32_RT5 (insn) != REG_R5) insn16 = N16_TYPE38 (BEQS38, N32_RT5 (insn), N32_IMM14S (insn)); @@ -7162,7 +8657,7 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, } else { - /* N32_BR1_BNE */ + /* N32_BR1_BNE */ if (N32_IS_RT3 (insn) && N32_RA5 (insn) == REG_R5 && N32_RT5 (insn) != REG_R5) insn16 = N16_TYPE38 (BNES38, N32_RT5 (insn), N32_IMM14S (insn)); @@ -7183,8 +8678,7 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, insn16 = N16_TYPE38 (BEQZ38, N32_RT5 (insn), N32_IMM16S (insn)); insn_type = NDS32_INSN_BEQZ38; } - else if (N32_RT5 (insn) == REG_R15 - && IS_WITHIN_S (N32_IMM16S (insn), 8)) + else if (N32_RT5 (insn) == REG_R15 && IS_WITHIN_S (N32_IMM16S (insn), 8)) { insn16 = N16_TYPE8 (BEQZS8, N32_IMM16S (insn)); insn_type = NDS32_INSN_BEQZS8; @@ -7197,16 +8691,15 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, insn16 = N16_TYPE38 (BNEZ38, N32_RT5 (insn), N32_IMM16S (insn)); insn_type = NDS32_INSN_BNEZ38; } - else if (N32_RT5 (insn) == REG_R15 - && IS_WITHIN_S (N32_IMM16S (insn), 8)) + else if (N32_RT5 (insn) == REG_R15 && IS_WITHIN_S (N32_IMM16S (insn), 8)) { insn16 = N16_TYPE8 (BNEZS8, N32_IMM16S (insn)); insn_type = NDS32_INSN_BNEZS8; } break; - case N32_BR2_IFCALL: - if (IS_WITHIN_U (N32_IMM16S (insn), 9)) + case N32_BR2_SOP0: + if (__GF (insn, 20, 5) == 0 && IS_WITHIN_U (N32_IMM16S (insn), 9)) { insn16 = N16_TYPE9 (IFCALL9, N32_IMM16S (insn)); insn_type = NDS32_INSN_IFCALL9; @@ -7218,7 +8711,7 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, case N32_OP6_JI: if ((insn & N32_BIT (24)) == 0) { - /* N32_JI_J */ + /* N32_JI_J */ if (IS_WITHIN_S (N32_IMM24S (insn), 8)) { insn16 = N16_TYPE8 (J8, N32_IMM24S (insn)); @@ -7236,19 +8729,19 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16, case N32_JREG_JR: if (N32_JREG_HINT (insn) == 0) { - /* jr */ + /* jr */ insn16 = N16_TYPE5 (JR5, N32_RB5 (insn)); insn_type = NDS32_INSN_JR5; } else if (N32_JREG_HINT (insn) == 1) { - /* ret */ + /* ret */ insn16 = N16_TYPE5 (RET5, N32_RB5 (insn)); insn_type = NDS32_INSN_RET5; } else if (N32_JREG_HINT (insn) == 3) { - /* ifret = mov55 $sp, $sp */ + /* ifret = mov55 $sp, $sp */ insn16 = N16_TYPE55 (MOV55, REG_SP, REG_SP); insn_type = NDS32_INSN_IFRET; } @@ -7347,184 +8840,162 @@ nds32_convert_16_to_32 (bfd *abfd, uint16_t insn16, uint32_t *pinsn) switch (__GF (insn16, 9, 6)) { - case 0x4: /* add45 */ - insn = N32_ALU1 (ADD, N16_RT4 (insn16), N16_RT4 (insn16), - N16_RA5 (insn16)); + case 0x4: /* add45 */ + insn = N32_ALU1 (ADD, N16_RT4 (insn16), N16_RT4 (insn16), N16_RA5 (insn16)); goto done; - case 0x5: /* sub45 */ - insn = N32_ALU1 (SUB, N16_RT4 (insn16), N16_RT4 (insn16), - N16_RA5 (insn16)); + case 0x5: /* sub45 */ + insn = N32_ALU1 (SUB, N16_RT4 (insn16), N16_RT4 (insn16), N16_RA5 (insn16)); goto done; - case 0x6: /* addi45 */ - insn = N32_TYPE2 (ADDI, N16_RT4 (insn16), N16_RT4 (insn16), - N16_IMM5U (insn16)); + case 0x6: /* addi45 */ + insn = N32_TYPE2 (ADDI, N16_RT4 (insn16), N16_RT4 (insn16), N16_IMM5U (insn16)); goto done; - case 0x7: /* subi45 */ - insn = N32_TYPE2 (ADDI, N16_RT4 (insn16), N16_RT4 (insn16), - -N16_IMM5U (insn16)); + case 0x7: /* subi45 */ + insn = N32_TYPE2 (ADDI, N16_RT4 (insn16), N16_RT4 (insn16), -N16_IMM5U (insn16)); goto done; - case 0x8: /* srai45 */ - insn = N32_ALU1 (SRAI, N16_RT4 (insn16), N16_RT4 (insn16), - N16_IMM5U (insn16)); + case 0x8: /* srai45 */ + insn = N32_ALU1 (SRAI, N16_RT4 (insn16), N16_RT4 (insn16), N16_IMM5U (insn16)); goto done; - case 0x9: /* srli45 */ - insn = N32_ALU1 (SRLI, N16_RT4 (insn16), N16_RT4 (insn16), - N16_IMM5U (insn16)); + case 0x9: /* srli45 */ + insn = N32_ALU1 (SRLI, N16_RT4 (insn16), N16_RT4 (insn16), N16_IMM5U (insn16)); goto done; - case 0xa: /* slli333 */ - insn = N32_ALU1 (SLLI, N16_RT3 (insn16), N16_RA3 (insn16), - N16_IMM3U (insn16)); + + case 0xa: /* slli333 */ + insn = N32_ALU1 (SLLI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); goto done; - case 0xc: /* add333 */ - insn = N32_ALU1 (ADD, N16_RT3 (insn16), N16_RA3 (insn16), - N16_RB3 (insn16)); + case 0xc: /* add333 */ + insn = N32_ALU1 (ADD, N16_RT3 (insn16), N16_RA3 (insn16), N16_RB3 (insn16)); goto done; - case 0xd: /* sub333 */ - insn = N32_ALU1 (SUB, N16_RT3 (insn16), N16_RA3 (insn16), - N16_RB3 (insn16)); + case 0xd: /* sub333 */ + insn = N32_ALU1 (SUB, N16_RT3 (insn16), N16_RA3 (insn16), N16_RB3 (insn16)); goto done; - case 0xe: /* addi333 */ - insn = N32_TYPE2 (ADDI, N16_RT3 (insn16), N16_RA3 (insn16), - N16_IMM3U (insn16)); + case 0xe: /* addi333 */ + insn = N32_TYPE2 (ADDI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); goto done; - case 0xf: /* subi333 */ - insn = N32_TYPE2 (ADDI, N16_RT3 (insn16), N16_RA3 (insn16), - -N16_IMM3U (insn16)); + case 0xf: /* subi333 */ + insn = N32_TYPE2 (ADDI, N16_RT3 (insn16), N16_RA3 (insn16), -N16_IMM3U (insn16)); goto done; - case 0x10: /* lwi333 */ - insn = N32_TYPE2 (LWI, N16_RT3 (insn16), N16_RA3 (insn16), - N16_IMM3U (insn16)); + + case 0x10: /* lwi333 */ + insn = N32_TYPE2 (LWI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); goto done; - case 0x12: /* lhi333 */ - insn = N32_TYPE2 (LHI, N16_RT3 (insn16), N16_RA3 (insn16), - N16_IMM3U (insn16)); + case 0x12: /* lhi333 */ + insn = N32_TYPE2 (LHI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); goto done; - case 0x13: /* lbi333 */ - insn = N32_TYPE2 (LBI, N16_RT3 (insn16), N16_RA3 (insn16), - N16_IMM3U (insn16)); + case 0x13: /* lbi333 */ + insn = N32_TYPE2 (LBI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); goto done; - case 0x11: /* lwi333.bi */ - insn = N32_TYPE2 (LWI_BI, N16_RT3 (insn16), N16_RA3 (insn16), - N16_IMM3U (insn16)); + case 0x11: /* lwi333.bi */ + insn = N32_TYPE2 (LWI_BI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); goto done; - case 0x14: /* swi333 */ - insn = N32_TYPE2 (SWI, N16_RT3 (insn16), N16_RA3 (insn16), - N16_IMM3U (insn16)); + case 0x14: /* swi333 */ + insn = N32_TYPE2 (SWI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); goto done; - case 0x16: /* shi333 */ - insn = N32_TYPE2 (SHI, N16_RT3 (insn16), N16_RA3 (insn16), - N16_IMM3U (insn16)); + case 0x16: /* shi333 */ + insn = N32_TYPE2 (SHI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); goto done; - case 0x17: /* sbi333 */ - insn = N32_TYPE2 (SBI, N16_RT3 (insn16), N16_RA3 (insn16), - N16_IMM3U (insn16)); + case 0x17: /* sbi333 */ + insn = N32_TYPE2 (SBI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); goto done; - case 0x15: /* swi333.bi */ - insn = N32_TYPE2 (SWI_BI, N16_RT3 (insn16), N16_RA3 (insn16), - N16_IMM3U (insn16)); + case 0x15: /* swi333.bi */ + insn = N32_TYPE2 (SWI_BI, N16_RT3 (insn16), N16_RA3 (insn16), N16_IMM3U (insn16)); goto done; - case 0x18: /* addri36.sp */ - insn = N32_TYPE2 (ADDI, N16_RT3 (insn16), REG_SP, - N16_IMM6U (insn16) << 2); + + case 0x18: /* addri36.sp */ + insn = N32_TYPE2 (ADDI, N16_RT3 (insn16), REG_SP, N16_IMM6U (insn16) << 2); goto done; - case 0x19: /* lwi45.fe */ - insn = N32_TYPE2 (LWI, N16_RT4 (insn16), REG_R8, - (N16_IMM5U (insn16) - 32)); + + case 0x19: /* lwi45.fe */ + insn = N32_TYPE2 (LWI, N16_RT4 (insn16), REG_R8, (N16_IMM5U (insn16) - 32)); goto done; - case 0x1a: /* lwi450 */ + case 0x1a: /* lwi450 */ insn = N32_TYPE2 (LWI, N16_RT4 (insn16), N16_RA5 (insn16), 0); goto done; - case 0x1b: /* swi450 */ + case 0x1b: /* swi450 */ insn = N32_TYPE2 (SWI, N16_RT4 (insn16), N16_RA5 (insn16), 0); goto done; - /* These are r15 implied instructions. */ - case 0x30: /* slts45 */ + /* These are r15 implied instructions. */ + case 0x30: /* slts45 */ insn = N32_ALU1 (SLTS, REG_TA, N16_RT4 (insn16), N16_RA5 (insn16)); goto done; - case 0x31: /* slt45 */ + case 0x31: /* slt45 */ insn = N32_ALU1 (SLT, REG_TA, N16_RT4 (insn16), N16_RA5 (insn16)); goto done; - case 0x32: /* sltsi45 */ + case 0x32: /* sltsi45 */ insn = N32_TYPE2 (SLTSI, REG_TA, N16_RT4 (insn16), N16_IMM5U (insn16)); goto done; - case 0x33: /* slti45 */ + case 0x33: /* slti45 */ insn = N32_TYPE2 (SLTI, REG_TA, N16_RT4 (insn16), N16_IMM5U (insn16)); goto done; - case 0x34: /* beqzs8, bnezs8 */ + case 0x34: /* beqzs8, bnezs8 */ if (insn16 & N32_BIT (8)) insn = N32_BR2 (BNEZ, REG_TA, N16_IMM8S (insn16)); else insn = N32_BR2 (BEQZ, REG_TA, N16_IMM8S (insn16)); goto done; - case 0x35: /* break16, ex9.it */ + case 0x35: /* break16, ex9.it */ /* Only consider range of v3 break16. */ insn = N32_TYPE0 (MISC, (N16_IMM5U (insn16) << 5) | N32_MISC_BREAK); goto done; - case 0x3c: /* ifcall9 */ - insn = N32_BR2 (IFCALL, 0, N16_IMM9U (insn16)); + case 0x3c: /* ifcall9 */ + insn = N32_BR2 (SOP0, 0, N16_IMM9U (insn16)); goto done; - case 0x3d: /* movpi45 */ + case 0x3d: /* movpi45 */ insn = N32_TYPE1 (MOVI, N16_RT4 (insn16), N16_IMM5U (insn16) + 16); goto done; - case 0x3f: /* MISC33 */ + case 0x3f: /* MISC33 */ switch (insn16 & 0x7) { - case 2: /* neg33 */ + case 2: /* neg33 */ insn = N32_TYPE2 (SUBRI, N16_RT3 (insn16), N16_RA3 (insn16), 0); break; - case 3: /* not33 */ - insn = N32_ALU1 (NOR, N16_RT3 (insn16), N16_RA3 (insn16), - N16_RA3 (insn16)); + case 3: /* not33 */ + insn = N32_ALU1 (NOR, N16_RT3 (insn16), N16_RA3 (insn16), N16_RA3 (insn16)); break; - case 4: /* mul33 */ - insn = N32_ALU2 (MUL, N16_RT3 (insn16), N16_RT3 (insn16), - N16_RA3 (insn16)); + case 4: /* mul33 */ + insn = N32_ALU2 (MUL, N16_RT3 (insn16), N16_RT3 (insn16), N16_RA3 (insn16)); break; - case 5: /* xor33 */ - insn = N32_ALU1 (XOR, N16_RT3 (insn16), N16_RT3 (insn16), - N16_RA3 (insn16)); + case 5: /* xor33 */ + insn = N32_ALU1 (XOR, N16_RT3 (insn16), N16_RT3 (insn16), N16_RA3 (insn16)); break; - case 6: /* and33 */ - insn = N32_ALU1 (AND, N16_RT3 (insn16), N16_RT3 (insn16), - N16_RA3 (insn16)); + case 6: /* and33 */ + insn = N32_ALU1 (AND, N16_RT3 (insn16), N16_RT3 (insn16), N16_RA3 (insn16)); break; - case 7: /* or33 */ - insn = N32_ALU1 (OR, N16_RT3 (insn16), N16_RT3 (insn16), - N16_RA3 (insn16)); + case 7: /* or33 */ + insn = N32_ALU1 (OR, N16_RT3 (insn16), N16_RT3 (insn16), N16_RA3 (insn16)); break; } goto done; - case 0xb: + case 0xb: /* ... */ switch (insn16 & 0x7) { - case 0: /* zeb33 */ + case 0: /* zeb33 */ insn = N32_TYPE2 (ANDI, N16_RT3 (insn16), N16_RA3 (insn16), 0xff); break; - case 1: /* zeh33 */ + case 1: /* zeh33 */ insn = N32_ALU1 (ZEH, N16_RT3 (insn16), N16_RA3 (insn16), 0); break; - case 2: /* seb33 */ + case 2: /* seb33 */ insn = N32_ALU1 (SEB, N16_RT3 (insn16), N16_RA3 (insn16), 0); break; - case 3: /* seh33 */ + case 3: /* seh33 */ insn = N32_ALU1 (SEH, N16_RT3 (insn16), N16_RA3 (insn16), 0); break; - case 4: /* xlsb33 */ + case 4: /* xlsb33 */ insn = N32_TYPE2 (ANDI, N16_RT3 (insn16), N16_RA3 (insn16), 1); break; - case 5: /* x11b33 */ + case 5: /* x11b33 */ insn = N32_TYPE2 (ANDI, N16_RT3 (insn16), N16_RA3 (insn16), 0x7ff); break; - case 6: /* bmski33 */ + case 6: /* bmski33 */ insn = N32_TYPE2 (ANDI, N16_RT3 (insn16), N16_RT3 (insn16), 1 << __GF (insn16, 3, 3)); break; - case 7: /* fexti33 */ + case 7: /* fexti33 */ insn = N32_TYPE2 (ANDI, N16_RT3 (insn16), N16_RT3 (insn16), (1 << (__GF (insn16, 3, 3) + 1)) - 1); break; @@ -7534,70 +9005,70 @@ nds32_convert_16_to_32 (bfd *abfd, uint16_t insn16, uint32_t *pinsn) switch (__GF (insn16, 10, 5)) { - case 0x0: /* mov55 or ifret16 */ + case 0x0: /* mov55 or ifret16 */ if (mach >= MACH_V3 && N16_RT5 (insn16) == REG_SP && N16_RT5 (insn16) == N16_RA5 (insn16)) - insn = N32_JREG (JR, 0, 0, 0, 3); + insn = N32_JREG (JR, 0, 0, 0, 3); else - insn = N32_TYPE2 (ADDI, N16_RT5 (insn16), N16_RA5 (insn16), 0); + insn = N32_TYPE2 (ADDI, N16_RT5 (insn16), N16_RA5 (insn16), 0); goto done; - case 0x1: /* movi55 */ + case 0x1: /* movi55 */ insn = N32_TYPE1 (MOVI, N16_RT5 (insn16), N16_IMM5S (insn16)); goto done; - case 0x1b: /* addi10s (V2) */ + case 0x1b: /* addi10s (V2) */ insn = N32_TYPE2 (ADDI, REG_SP, REG_SP, N16_IMM10S (insn16)); goto done; } switch (__GF (insn16, 11, 4)) { - case 0x7: /* lwi37.fp/swi37.fp */ - if (insn16 & N32_BIT (7)) /* swi37.fp */ + case 0x7: /* lwi37.fp/swi37.fp */ + if (insn16 & N32_BIT (7)) /* swi37.fp */ insn = N32_TYPE2 (SWI, N16_RT38 (insn16), REG_FP, N16_IMM7U (insn16)); - else /* lwi37.fp */ + else /* lwi37.fp */ insn = N32_TYPE2 (LWI, N16_RT38 (insn16), REG_FP, N16_IMM7U (insn16)); goto done; - case 0x8: /* beqz38 */ + case 0x8: /* beqz38 */ insn = N32_BR2 (BEQZ, N16_RT38 (insn16), N16_IMM8S (insn16)); goto done; - case 0x9: /* bnez38 */ + case 0x9: /* bnez38 */ insn = N32_BR2 (BNEZ, N16_RT38 (insn16), N16_IMM8S (insn16)); goto done; - case 0xa: /* beqs38/j8, implied r5 */ + case 0xa: /* beqs38/j8, implied r5 */ if (N16_RT38 (insn16) == 5) insn = N32_JI (J, N16_IMM8S (insn16)); else insn = N32_BR1 (BEQ, N16_RT38 (insn16), REG_R5, N16_IMM8S (insn16)); goto done; - case 0xb: /* bnes38 and others */ + case 0xb: /* bnes38 and others */ if (N16_RT38 (insn16) == 5) { switch (__GF (insn16, 5, 3)) { - case 0: /* jr5 */ + case 0: /* jr5 */ insn = N32_JREG (JR, 0, N16_RA5 (insn16), 0, 0); break; - case 4: /* ret5 */ + case 4: /* ret5 */ insn = N32_JREG (JR, 0, N16_RA5 (insn16), 0, 1); break; - case 1: /* jral5 */ + case 1: /* jral5 */ insn = N32_JREG (JRAL, REG_LP, N16_RA5 (insn16), 0, 0); break; - case 2: /* ex9.it imm5 */ + case 2: /* ex9.it imm5 */ /* ex9.it had no 32-bit variantl. */ break; - case 5: /* add5.pc */ + case 5: /* add5.pc */ /* add5.pc had no 32-bit variantl. */ break; } } - else /* bnes38 */ + else /* bnes38 */ insn = N32_BR1 (BNE, N16_RT38 (insn16), REG_R5, N16_IMM8S (insn16)); goto done; - case 0xe: /* lwi37/swi37 */ - if (insn16 & (1 << 7)) /* swi37.sp */ + case 0xe: /* lwi37/swi37 */ + if (insn16 & (1 << 7)) /* swi37.sp */ insn = N32_TYPE2 (SWI, N16_RT38 (insn16), REG_SP, N16_IMM7U (insn16)); - else /* lwi37.sp */ + else /* lwi37.sp */ insn = N32_TYPE2 (LWI, N16_RT38 (insn16), REG_SP, N16_IMM7U (insn16)); goto done; } @@ -7650,19 +9121,19 @@ turn_insn_to_sda_access (uint32_t insn, bfd_signed_vma type, uint32_t *pinsn) switch (N32_OP6 (insn)) { case N32_OP6_LBI: - /* lbi.gp */ + /* lbi.gp */ oinsn = N32_TYPE1 (LBGP, N32_RT5 (insn), 0); break; case N32_OP6_LBSI: - /* lbsi.gp */ + /* lbsi.gp */ oinsn = N32_TYPE1 (LBGP, N32_RT5 (insn), N32_BIT (19)); break; case N32_OP6_SBI: - /* sbi.gp */ + /* sbi.gp */ oinsn = N32_TYPE1 (SBGP, N32_RT5 (insn), 0); break; case N32_OP6_ORI: - /* addi.gp */ + /* addi.gp */ oinsn = N32_TYPE1 (SBGP, N32_RT5 (insn), N32_BIT (19)); break; } @@ -7672,15 +9143,15 @@ turn_insn_to_sda_access (uint32_t insn, bfd_signed_vma type, uint32_t *pinsn) switch (N32_OP6 (insn)) { case N32_OP6_LHI: - /* lhi.gp */ + /* lhi.gp */ oinsn = N32_TYPE1 (HWGP, N32_RT5 (insn), 0); break; case N32_OP6_LHSI: - /* lhsi.gp */ + /* lhsi.gp */ oinsn = N32_TYPE1 (HWGP, N32_RT5 (insn), N32_BIT (18)); break; case N32_OP6_SHI: - /* shi.gp */ + /* shi.gp */ oinsn = N32_TYPE1 (HWGP, N32_RT5 (insn), N32_BIT (19)); break; } @@ -7690,11 +9161,11 @@ turn_insn_to_sda_access (uint32_t insn, bfd_signed_vma type, uint32_t *pinsn) switch (N32_OP6 (insn)) { case N32_OP6_LWI: - /* lwi.gp */ + /* lwi.gp */ oinsn = N32_TYPE1 (HWGP, N32_RT5 (insn), __MF (6, 17, 3)); break; case N32_OP6_SWI: - /* swi.gp */ + /* swi.gp */ oinsn = N32_TYPE1 (HWGP, N32_RT5 (insn), __MF (7, 17, 3)); break; } @@ -7835,7 +9306,7 @@ calculate_got_memory_address (bfd *abfd, struct bfd_link_info *link_info, bfd_vma *local_got_offsets; /* Get the value of the symbol referred to by the reloc. */ struct elf_link_hash_entry *h; - struct elf_nds32_link_hash_table *htab = nds32_elf_hash_table (link_info); + struct elf_link_hash_table *ehtab = elf_hash_table (link_info); /* An external symbol. */ symndx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; @@ -7847,18 +9318,13 @@ calculate_got_memory_address (bfd *abfd, struct bfd_link_info *link_info, if (symndx >= 0) { BFD_ASSERT (h != NULL); - return (htab->root.sgot->output_section->vma - + htab->root.sgot->output_offset - + h->got.offset); - } - else - { - local_got_offsets = elf_local_got_offsets (abfd); - BFD_ASSERT (local_got_offsets != NULL); - return (htab->root.sgot->output_section->vma - + htab->root.sgot->output_offset - + local_got_offsets[ELF32_R_SYM (irel->r_info)]); + return ehtab->sgot->output_section->vma + ehtab->sgot->output_offset + + h->got.offset; } + local_got_offsets = elf_local_got_offsets (abfd); + BFD_ASSERT (local_got_offsets != NULL); + return ehtab->sgot->output_section->vma + ehtab->sgot->output_offset + + local_got_offsets[ELF32_R_SYM (irel->r_info)]; /* The _GLOBAL_OFFSET_TABLE_ may be undefweak(or should be?). */ /* The check of h->root.type is passed. */ @@ -7899,7 +9365,6 @@ is_convert_32_to_16 (bfd *abfd, asection *sec, bfd_vma mem_addr; uint32_t insn = 0; Elf_Internal_Rela *pc_rel; - int pic_ext_target = 0; Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Sym *isymbuf = NULL; int convert_type; @@ -7938,8 +9403,7 @@ is_convert_32_to_16 (bfd *abfd, asection *sec, || ELF32_R_TYPE (pc_rel->r_info) == R_NDS32_25_PCREL_RELA || ELF32_R_TYPE (pc_rel->r_info) == R_NDS32_25_PLTREL) { - off = calculate_offset (abfd, sec, pc_rel, isymbuf, symtab_hdr, - &pic_ext_target); + off = calculate_offset (abfd, sec, pc_rel, isymbuf, symtab_hdr); if (off >= ACCURATE_8BIT_S1 || off < -ACCURATE_8BIT_S1 || off == 0) return FALSE; @@ -7948,10 +9412,8 @@ is_convert_32_to_16 (bfd *abfd, asection *sec, else if (ELF32_R_TYPE (pc_rel->r_info) == R_NDS32_20_RELA) { /* movi => movi55 */ - mem_addr = calculate_memory_address (abfd, pc_rel, isymbuf, - symtab_hdr); - /* mem_addr is unsigned, but the value should - be between [-16, 15]. */ + mem_addr = calculate_memory_address (abfd, pc_rel, isymbuf, symtab_hdr); + /* mem_addr is unsigned, but the value should be between [-16, 15]. */ if ((mem_addr + 0x10) >> 5) return FALSE; break; @@ -7980,14 +9442,12 @@ is_convert_32_to_16 (bfd *abfd, asection *sec, || ((ELF32_R_TYPE (pc_rel->r_info) > R_NDS32_LOADSTORE) && (ELF32_R_TYPE (pc_rel->r_info) < R_NDS32_DWARF2_OP1_RELA))) { - /* Prevent unresolved addi instruction translate - to addi45 or addi333. */ + /* Prevent unresolved addi instruction translate to addi45 or addi333. */ return FALSE; } else if ((ELF32_R_TYPE (pc_rel->r_info) == R_NDS32_17IFC_PCREL_RELA)) { - off = calculate_offset (abfd, sec, pc_rel, isymbuf, symtab_hdr, - &pic_ext_target); + off = calculate_offset (abfd, sec, pc_rel, isymbuf, symtab_hdr); if (off >= ACCURATE_U9BIT_S1 || off <= 0) return FALSE; break; @@ -8085,7 +9545,7 @@ static Elf_Internal_Rela * find_relocs_at_address_addr (Elf_Internal_Rela *reloc, Elf_Internal_Rela *relocs, Elf_Internal_Rela *irelend, - enum elf_nds32_reloc_type reloc_type, + unsigned char reloc_type, bfd_vma offset_p) { Elf_Internal_Rela *rel_t = NULL; @@ -8281,8 +9741,9 @@ insert_nds32_elf_blank (nds32_elf_blank_t **blank_p, bfd_vma addr, bfd_vma len) if (addr < blank_t->offset + blank_t->size) { - if (addr > blank_t->offset + blank_t->size) - blank_t->size = addr - blank_t->offset; + /* Extend the origin blank. */ + if (addr + len > blank_t->offset + blank_t->size) + blank_t->size = addr + len - blank_t->offset; } else { @@ -8414,7 +9875,7 @@ nds32_elf_relax_delete_blanks (bfd *abfd, asection *sec, /* Relocations MUST be kept in memory, because relaxation adjust them. */ internal_relocs = _bfd_elf_link_read_relocs (abfd, sect, NULL, NULL, - TRUE /* keep_memory */); + TRUE /* keep_memory */); irelend = internal_relocs + sect->reloc_count; blank_t = blank_head; @@ -8436,7 +9897,7 @@ nds32_elf_relax_delete_blanks (bfd *abfd, asection *sec, unsigned long val = 0; unsigned long mask; long before, between; - long offset = 0; + long offset; switch (ELF32_R_TYPE (irel->r_info)) { @@ -8468,28 +9929,23 @@ nds32_elf_relax_delete_blanks (bfd *abfd, asection *sec, -- before ---| ***************** --------------------- between ---| - We only care how much data are relax between DIFF, - marked as ***. */ + We only care how much data are relax between DIFF, marked as ***. */ before = get_nds32_elf_blank_total (&blank_t, irel->r_addend, 0); - between = get_nds32_elf_blank_total (&blank_t, - irel->r_addend + offset, 0); + between = get_nds32_elf_blank_total (&blank_t, irel->r_addend + offset, 0); if (between == before) goto done_adjust_diff; switch (ELF32_R_TYPE (irel->r_info)) { case R_NDS32_DIFF8: - bfd_put_8 (abfd, offset - (between - before), - contents + irel->r_offset); + bfd_put_8 (abfd, offset - (between - before), contents + irel->r_offset); break; case R_NDS32_DIFF16: - bfd_put_16 (abfd, offset - (between - before), - contents + irel->r_offset); + bfd_put_16 (abfd, offset - (between - before), contents + irel->r_offset); break; case R_NDS32_DIFF32: - bfd_put_32 (abfd, offset - (between - before), - contents + irel->r_offset); + bfd_put_32 (abfd, offset - (between - before), contents + irel->r_offset); break; } } @@ -8501,12 +9957,10 @@ nds32_elf_relax_delete_blanks (bfd *abfd, asection *sec, unsigned long before, between; bfd_byte *endp, *p; - val = _bfd_read_unsigned_leb128 (abfd, contents + irel->r_offset, - &len); + val = _bfd_read_unsigned_leb128 (abfd, contents + irel->r_offset, &len); before = get_nds32_elf_blank_total (&blank_t, irel->r_addend, 0); - between = get_nds32_elf_blank_total (&blank_t, - irel->r_addend + val, 0); + between = get_nds32_elf_blank_total (&blank_t, irel->r_addend + val, 0); if (between == before) goto done_adjust_diff; @@ -8523,16 +9977,14 @@ done_adjust_diff: if (sec == sect) { raddr = irel->r_offset; - irel->r_offset -= get_nds32_elf_blank_total (&blank_t2, - irel->r_offset, 1); + irel->r_offset -= get_nds32_elf_blank_total (&blank_t2, irel->r_offset, 1); if (ELF32_R_TYPE (irel->r_info) == R_NDS32_NONE) continue; if (blank_t2 && blank_t2->next - && (blank_t2->offset > raddr - || blank_t2->next->offset <= raddr)) - _bfd_error_handler - (_("%B: Error: search_nds32_elf_blank reports wrong node\n"), abfd); + && (blank_t2->offset > raddr || blank_t2->next->offset <= raddr)) + _bfd_error_handler (_("%B: %s\n"), abfd, + "Error: search_nds32_elf_blank reports wrong node"); /* Mark reloc in deleted portion as NONE. For some relocs like R_NDS32_LABEL that doesn't modify the @@ -8584,11 +10036,9 @@ done_adjust_diff: isym->st_value -= ahead; /* Adjust function size. */ - if (ELF32_ST_TYPE (isym->st_info) == STT_FUNC - && isym->st_size > 0) - isym->st_size -= - get_nds32_elf_blank_total - (&blank_t, orig_addr + isym->st_size, 0) - ahead; + if (ELF32_ST_TYPE (isym->st_info) == STT_FUNC && isym->st_size > 0) + isym->st_size -= get_nds32_elf_blank_total + (&blank_t, orig_addr + isym->st_size, 0) - ahead; } } } @@ -8617,9 +10067,8 @@ done_adjust_diff: /* Adjust function size. */ if (sym_hash->type == STT_FUNC) - sym_hash->size -= - get_nds32_elf_blank_total - (&blank_t, orig_addr + sym_hash->size, 0) - ahead; + sym_hash->size -= get_nds32_elf_blank_total + (&blank_t, orig_addr + sym_hash->size, 0) - ahead; } } @@ -8743,7 +10192,7 @@ relax_range_measurement (bfd *abfd) bfd_vma align; static int decide_relax_range = 0; int i; - int range_number = sizeof (sdata_init_range) / sizeof (sdata_init_range[0]); + int range_number = ARRAY_SIZE (sdata_init_range); if (decide_relax_range) return; @@ -8789,11 +10238,7 @@ relax_range_measurement (bfd *abfd) #define IS_OPTIMIZE(addend) ((addend) & 0x40000000) #define IS_16BIT_ON(addend) ((addend) & 0x20000000) -static const char * unrecognized_reloc_msg = - /* xgettext:c-format */ - N_("%B: warning: %s points to unrecognized reloc at %#Lx"); - -/* Relax LONGCALL1 relocation for nds32_elf_relax_section. */ +/* Relax LONGCALL1 relocation for nds32_elf_relax_section.*/ static bfd_boolean nds32_elf_relax_longcall1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, @@ -8803,19 +10248,19 @@ nds32_elf_relax_longcall1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, { /* There are 3 variations for LONGCALL1 case 4-4-2; 16-bit on, optimize off or optimize for space - sethi ta, hi20(symbol) ; LONGCALL1/HI20 + sethi ta, hi20(symbol) ; LONGCALL1/HI20 ori ta, ta, lo12(symbol) ; LO12S0 - jral5 ta ; + jral5 ta ; case 4-4-4; 16-bit off, optimize don't care - sethi ta, hi20(symbol) ; LONGCALL1/HI20 + sethi ta, hi20(symbol) ; LONGCALL1/HI20 ori ta, ta, lo12(symbol) ; LO12S0 - jral ta ; + jral ta ; case 4-4-4; 16-bit on, optimize for speed - sethi ta, hi20(symbol) ; LONGCALL1/HI20 + sethi ta, hi20(symbol) ; LONGCALL1/HI20 ori ta, ta, lo12(symbol) ; LO12S0 - jral ta ; + jral ta ; Check code for -mlong-calls output. */ /* Get the reloc for the address from which the register is @@ -8826,7 +10271,6 @@ nds32_elf_relax_longcall1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, int seq_len; /* Original length of instruction sequence. */ uint32_t insn; Elf_Internal_Rela *hi_irelfn, *lo_irelfn, *irelend; - int pic_ext_target = 0; bfd_signed_vma foff; uint16_t insn16; @@ -8843,21 +10287,21 @@ nds32_elf_relax_longcall1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, if (hi_irelfn == irelend || lo_irelfn == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGCALL1", - irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGCALL1 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } /* Get the value of the symbol referred to by the reloc. */ - foff = calculate_offset (abfd, sec, hi_irelfn, isymbuf, symtab_hdr, - &pic_ext_target); + foff = calculate_offset (abfd, sec, hi_irelfn, isymbuf, symtab_hdr); /* This condition only happened when symbol is undefined. */ - if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_24BIT_S1 + if (foff == 0 || foff < -CONSERVATIVE_24BIT_S1 || foff >= CONSERVATIVE_24BIT_S1) return FALSE; - /* Relax to: jal symbol; 25_PCREL */ + /* Relax to: jal symbol; 25_PCREL */ /* For simplicity of coding, we are going to modify the section contents, the section relocs, and the BFD symbol table. We must tell the rest of the code not to free up this @@ -8894,7 +10338,7 @@ nds32_elf_relax_longcall1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, } #define CONVERT_CONDITION_CALL(insn) (((insn) & 0xffff0000) ^ 0x90000) -/* Relax LONGCALL2 relocation for nds32_elf_relax_section. */ +/* Relax LONGCALL2 relocation for nds32_elf_relax_section.*/ static bfd_boolean nds32_elf_relax_longcall2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, @@ -8904,7 +10348,7 @@ nds32_elf_relax_longcall2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, { /* bltz rt, .L1 ; LONGCALL2 jal symbol ; 25_PCREL - .L1: */ + .L1: */ /* Get the reloc for the address from which the register is being loaded. This reloc will tell us which function is @@ -8913,7 +10357,6 @@ nds32_elf_relax_longcall2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, bfd_vma laddr; uint32_t insn; Elf_Internal_Rela *i1_irelfn, *cond_irelfn, *irelend; - int pic_ext_target = 0; bfd_signed_vma foff; irelend = internal_relocs + sec->reloc_count; @@ -8924,23 +10367,23 @@ nds32_elf_relax_longcall2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, if (i1_irelfn == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGCALL2", - irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGCALL2 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } insn = bfd_getb32 (contents + laddr); /* Get the value of the symbol referred to by the reloc. */ - foff = calculate_offset (abfd, sec, i1_irelfn, isymbuf, symtab_hdr, - &pic_ext_target); + foff = calculate_offset (abfd, sec, i1_irelfn, isymbuf, symtab_hdr); if (foff == 0 || foff < -CONSERVATIVE_16BIT_S1 || foff >= CONSERVATIVE_16BIT_S1) return FALSE; /* Relax to bgezal rt, label ; 17_PCREL - or bltzal rt, label ; 17_PCREL */ + or bltzal rt, label ; 17_PCREL */ /* Convert to complimentary conditional call. */ insn = CONVERT_CONDITION_CALL (insn); @@ -8974,7 +10417,7 @@ nds32_elf_relax_longcall2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, return TRUE; } -/* Relax LONGCALL3 relocation for nds32_elf_relax_section. */ +/* Relax LONGCALL3 relocation for nds32_elf_relax_section.*/ static bfd_boolean nds32_elf_relax_longcall3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, @@ -8984,25 +10427,25 @@ nds32_elf_relax_longcall3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, { /* There are 3 variations for LONGCALL3 case 4-4-4-2; 16-bit on, optimize off or optimize for space - bltz rt, $1 ; LONGCALL3 - sethi ta, hi20(symbol) ; HI20 + bltz rt, $1 ; LONGCALL3 + sethi ta, hi20(symbol) ; HI20 ori ta, ta, lo12(symbol) ; LO12S0 - jral5 ta ; + jral5 ta ; $1 case 4-4-4-4; 16-bit off, optimize don't care - bltz rt, $1 ; LONGCALL3 - sethi ta, hi20(symbol) ; HI20 + bltz rt, $1 ; LONGCALL3 + sethi ta, hi20(symbol) ; HI20 ori ta, ta, lo12(symbol) ; LO12S0 - jral ta ; + jral ta ; $1 case 4-4-4-4; 16-bit on, optimize for speed - bltz rt, $1 ; LONGCALL3 - sethi ta, hi20(symbol) ; HI20 + bltz rt, $1 ; LONGCALL3 + sethi ta, hi20(symbol) ; HI20 ori ta, ta, lo12(symbol) ; LO12S0 - jral ta ; - $1 */ + jral ta ; + $1 */ /* Get the reloc for the address from which the register is being loaded. This reloc will tell us which function is @@ -9012,7 +10455,6 @@ nds32_elf_relax_longcall3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, int seq_len; /* Original length of instruction sequence. */ uint32_t insn; Elf_Internal_Rela *hi_irelfn, *lo_irelfn, *cond_irelfn, *irelend; - int pic_ext_target = 0; bfd_signed_vma foff; uint16_t insn16; @@ -9030,16 +10472,16 @@ nds32_elf_relax_longcall3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, if (hi_irelfn == irelend || lo_irelfn == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGCALL3", - irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGCALL3 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } /* Get the value of the symbol referred to by the reloc. */ - foff = calculate_offset (abfd, sec, hi_irelfn, isymbuf, symtab_hdr, - &pic_ext_target); + foff = calculate_offset (abfd, sec, hi_irelfn, isymbuf, symtab_hdr); - if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_24BIT_S1 + if (foff == 0 || foff < -CONSERVATIVE_24BIT_S1 || foff >= CONSERVATIVE_24BIT_S1) return FALSE; @@ -9047,7 +10489,7 @@ nds32_elf_relax_longcall3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, if (foff >= -CONSERVATIVE_16BIT_S1 && foff < CONSERVATIVE_16BIT_S1) { /* Relax to bgezal rt, label ; 17_PCREL - or bltzal rt, label ; 17_PCREL */ + or bltzal rt, label ; 17_PCREL */ /* Convert to complimentary conditional call. */ insn = CONVERT_CONDITION_CALL (insn); @@ -9112,7 +10554,7 @@ nds32_elf_relax_longcall3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, return TRUE; } -/* Relax LONGJUMP1 relocation for nds32_elf_relax_section. */ +/* Relax LONGJUMP1 relocation for nds32_elf_relax_section.*/ static bfd_boolean nds32_elf_relax_longjump1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, @@ -9122,19 +10564,19 @@ nds32_elf_relax_longjump1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, { /* There are 3 variations for LONGJUMP1 case 4-4-2; 16-bit bit on, optimize off or optimize for space - sethi ta, hi20(symbol) ; LONGJUMP1/HI20 - ori ta, ta, lo12(symbol) ; LO12S0 - jr5 ta ; + sethi ta, hi20(symbol) ; LONGJUMP1/HI20 + ori ta, ta, lo12(symbol) ; LO12S0 + jr5 ta ; case 4-4-4; 16-bit off, optimize don't care - sethi ta, hi20(symbol) ; LONGJUMP1/HI20 - ori ta, ta, lo12(symbol) ; LO12S0 - jr ta ; + sethi ta, hi20(symbol) ; LONGJUMP1/HI20 + ori ta, ta, lo12(symbol) ; LO12S0 + jr ta ; case 4-4-4; 16-bit on, optimize for speed - sethi ta, hi20(symbol) ; LONGJUMP1/HI20 - ori ta, ta, lo12(symbol) ; LO12S0 - jr ta ; */ + sethi ta, hi20(symbol) ; LONGJUMP1/HI20 + ori ta, ta, lo12(symbol) ; LO12S0 + jr ta ; */ /* Get the reloc for the address from which the register is being loaded. This reloc will tell us which function is @@ -9145,7 +10587,6 @@ nds32_elf_relax_longjump1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, int insn16_on; /* 16-bit on/off. */ uint32_t insn; Elf_Internal_Rela *hi_irelfn, *lo_irelfn, *irelend; - int pic_ext_target = 0; bfd_signed_vma foff; uint16_t insn16; unsigned long reloc; @@ -9164,23 +10605,23 @@ nds32_elf_relax_longjump1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, R_NDS32_LO12S0_ORI_RELA, laddr + 4); if (hi_irelfn == irelend || lo_irelfn == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP1", - irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGJUMP1 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } /* Get the value of the symbol referred to by the reloc. */ - foff = calculate_offset (abfd, sec, hi_irelfn, isymbuf, symtab_hdr, - &pic_ext_target); + foff = calculate_offset (abfd, sec, hi_irelfn, isymbuf, symtab_hdr); - if (pic_ext_target || foff == 0 || foff >= CONSERVATIVE_24BIT_S1 + if (foff == 0 || foff >= CONSERVATIVE_24BIT_S1 || foff < -CONSERVATIVE_24BIT_S1) return FALSE; if (insn16_on && foff >= -ACCURATE_8BIT_S1 && foff < ACCURATE_8BIT_S1 && (seq_len & 0x2)) { - /* j8 label */ + /* j8 label */ /* 16-bit on, but not optimized for speed. */ reloc = R_NDS32_9_PCREL_RELA; insn16 = INSN_J8; @@ -9191,7 +10632,7 @@ nds32_elf_relax_longjump1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, } else { - /* j label */ + /* j label */ reloc = R_NDS32_25_PCREL_RELA; insn = INSN_J; bfd_putb32 (insn, contents + irel->r_offset); @@ -9275,14 +10716,14 @@ nds32_elf_convert_branch (uint16_t insn16, uint32_t insn, switch ((insn16 & 0xf000) >> 12) { case 0xc: - /* beqz38 or bnez38 */ + /* beqz38 or bnez38 */ comp_insn16 = (insn16 ^ 0x0800) & 0xff00; comp_insn = (comp_insn16 & 0x0800) ? INSN_BNEZ : INSN_BEQZ; comp_insn |= ((comp_insn16 & 0x0700) >> 8) << 20; break; case 0xd: - /* beqs38 or bnes38 */ + /* beqs38 or bnes38 */ comp_insn16 = (insn16 ^ 0x0800) & 0xff00; comp_insn = (comp_insn16 & 0x0800) ? INSN_BNE : INSN_BEQ; comp_insn |= (((comp_insn16 & 0x0700) >> 8) << 20) @@ -9290,7 +10731,7 @@ nds32_elf_convert_branch (uint16_t insn16, uint32_t insn, break; case 0xe: - /* beqzS8 or bnezS8 */ + /* beqzS8 or bnezS8 */ comp_insn16 = (insn16 ^ 0x0100) & 0xff00; comp_insn = (comp_insn16 & 0x0100) ? INSN_BNEZ : INSN_BEQZ; comp_insn |= REG_R15 << 20; @@ -9306,7 +10747,7 @@ nds32_elf_convert_branch (uint16_t insn16, uint32_t insn, *re_insn16 = comp_insn16; } -/* Relax LONGJUMP2 relocation for nds32_elf_relax_section. */ +/* Relax LONGJUMP2 relocation for nds32_elf_relax_section.*/ static bfd_boolean nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, @@ -9329,7 +10770,7 @@ nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, case 4-4; 1st insn convertible, 16-bit on, optimize for speed bne rt, ra, $1 ; LONGJUMP2 j label ; 25_PCREL - $1: */ + $1: */ /* Get the reloc for the address from which the register is being loaded. This reloc will tell us which function is @@ -9338,7 +10779,7 @@ nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, bfd_vma laddr; int seq_len; /* Original length of instruction sequence. */ Elf_Internal_Rela *i2_irelfn, *cond_irelfn, *irelend; - int pic_ext_target = 0, first_size; + int first_size; unsigned int i; bfd_signed_vma foff; uint32_t insn, re_insn = 0; @@ -9359,7 +10800,7 @@ nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, irelend, R_NDS32_25_PCREL_RELA, laddr + first_size); - for (i = 0; i < sizeof (checked_types) / sizeof(checked_types[0]); i++) + for (i = 0; i < ARRAY_SIZE (checked_types); i++) { cond_irelfn = find_relocs_at_address_addr (irel, internal_relocs, irelend, @@ -9370,16 +10811,16 @@ nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, if (i2_irelfn == irelend || cond_irelfn == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP2", - irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGJUMP2 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } /* Get the value of the symbol referred to by the reloc. */ foff = - calculate_offset (abfd, sec, i2_irelfn, isymbuf, symtab_hdr, - &pic_ext_target); - if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_16BIT_S1 + calculate_offset (abfd, sec, i2_irelfn, isymbuf, symtab_hdr); + if (foff == 0 || foff < -CONSERVATIVE_16BIT_S1 || foff >= CONSERVATIVE_16BIT_S1) return FALSE; @@ -9422,7 +10863,7 @@ nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, && (foff >= -(ACCURATE_14BIT_S1 - first_size) && foff < ACCURATE_14BIT_S1 - first_size)) { - /* beqs label ; 15_PCREL */ + /* beqs label ; 15_PCREL */ bfd_putb32 (re_insn, contents + irel->r_offset); *insn_len = 4; reloc = R_NDS32_15_PCREL_RELA; @@ -9432,7 +10873,7 @@ nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, && foff >= -CONSERVATIVE_16BIT_S1 && foff < CONSERVATIVE_16BIT_S1) { - /* beqz label ; 17_PCREL */ + /* beqz label ; 17_PCREL */ bfd_putb32 (re_insn, contents + irel->r_offset); *insn_len = 4; reloc = R_NDS32_17_PCREL_RELA; @@ -9465,7 +10906,7 @@ nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, return TRUE; } -/* Relax LONGJUMP3 relocation for nds32_elf_relax_section. */ +/* Relax LONGJUMP3 relocation for nds32_elf_relax_section.*/ static bfd_boolean nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, @@ -9476,42 +10917,42 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, /* There are 5 variations for LONGJUMP3 case 1: 2-4-4-2; 1st insn convertible, 16-bit on, optimize off or optimize for space - bnes38 rt, ra, $1 ; LONGJUMP3 - sethi ta, hi20(symbol) ; HI20 + bnes38 rt, ra, $1 ; LONGJUMP3 + sethi ta, hi20(symbol) ; HI20 ori ta, ta, lo12(symbol) ; LO12S0 - jr5 ta ; - $1: ; + jr5 ta ; + $1: ; case 2: 2-4-4-2; 1st insn convertible, 16-bit on, optimize for speed - bnes38 rt, ra, $1 ; LONGJUMP3 - sethi ta, hi20(symbol) ; HI20 + bnes38 rt, ra, $1 ; LONGJUMP3 + sethi ta, hi20(symbol) ; HI20 ori ta, ta, lo12(symbol) ; LO12S0 - jr5 ta ; - $1: ; LABEL + jr5 ta ; + $1: ; LABEL case 3: 4-4-4-2; 1st insn not convertible, 16-bit on, optimize off or optimize for space - bne rt, ra, $1 ; LONGJUMP3 - sethi ta, hi20(symbol) ; HI20 + bne rt, ra, $1 ; LONGJUMP3 + sethi ta, hi20(symbol) ; HI20 ori ta, ta, lo12(symbol) ; LO12S0 - jr5 ta ; - $1: ; + jr5 ta ; + $1: ; case 4: 4-4-4-4; 1st insn don't care, 16-bit off, optimize don't care 16-bit off if no INSN16 - bne rt, ra, $1 ; LONGJUMP3 - sethi ta, hi20(symbol) ; HI20 + bne rt, ra, $1 ; LONGJUMP3 + sethi ta, hi20(symbol) ; HI20 ori ta, ta, lo12(symbol) ; LO12S0 - jr ta ; - $1: ; + jr ta ; + $1: ; case 5: 4-4-4-4; 1st insn not convertible, 16-bit on, optimize for speed 16-bit off if no INSN16 - bne rt, ra, $1 ; LONGJUMP3 - sethi ta, hi20(symbol) ; HI20 + bne rt, ra, $1 ; LONGJUMP3 + sethi ta, hi20(symbol) ; HI20 ori ta, ta, lo12(symbol) ; LO12S0 - jr ta ; - $1: ; LABEL */ + jr ta ; + $1: ; LABEL */ /* Get the reloc for the address from which the register is being loaded. This reloc will tell us which function is @@ -9523,7 +10964,7 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, bfd_vma laddr; int seq_len; /* Original length of instruction sequence. */ Elf_Internal_Rela *hi_irelfn, *lo_irelfn, *cond_irelfn, *irelend; - int pic_ext_target = 0, first_size; + int first_size; unsigned int i; bfd_signed_vma foff; uint32_t insn, re_insn = 0; @@ -9551,7 +10992,7 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, R_NDS32_LO12S0_ORI_RELA, laddr + first_size + 4); - for (i = 0; i < sizeof (checked_types) / sizeof (checked_types[0]); i++) + for (i = 0; i < ARRAY_SIZE (checked_types); i++) { cond_irelfn = find_relocs_at_address_addr (irel, internal_relocs, irelend, @@ -9562,16 +11003,16 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, if (hi_irelfn == irelend || lo_irelfn == irelend || cond_irelfn == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP3", - irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGJUMP3 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } /* Get the value of the symbol referred to by the reloc. */ - foff = calculate_offset (abfd, sec, hi_irelfn, isymbuf, symtab_hdr, - &pic_ext_target); + foff = calculate_offset (abfd, sec, hi_irelfn, isymbuf, symtab_hdr); - if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_24BIT_S1 + if (foff == 0 || foff < -CONSERVATIVE_24BIT_S1 || foff >= CONSERVATIVE_24BIT_S1) return FALSE; @@ -9624,7 +11065,7 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, && (foff >= -(ACCURATE_14BIT_S1 - first_size) && foff < ACCURATE_14BIT_S1 - first_size)) { - /* beqs label ; 15_PCREL */ + /* beqs label ; 15_PCREL */ bfd_putb32 (re_insn, contents + irel->r_offset); *insn_len = 4; reloc = R_NDS32_15_PCREL_RELA; @@ -9635,7 +11076,7 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, && foff >= -CONSERVATIVE_16BIT_S1 && foff < CONSERVATIVE_16BIT_S1) { - /* beqz label ; 17_PCREL */ + /* beqz label ; 17_PCREL */ bfd_putb32 (re_insn, contents + irel->r_offset); *insn_len = 4; reloc = R_NDS32_17_PCREL_RELA; @@ -9661,7 +11102,7 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, case 4-4; 1st insn convertible, 16-bit on, optimize for speed bne rt, ra, $1 ; LONGJUMP2 j label ; 25_PCREL - $1 */ + $1 */ /* Offset for first instruction. */ @@ -9711,7 +11152,7 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, return TRUE; } -/* Relax LONGCALL4 relocation for nds32_elf_relax_section. */ +/* Relax LONGCALL4 relocation for nds32_elf_relax_section.*/ static bfd_boolean nds32_elf_relax_longcall4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, @@ -9728,7 +11169,6 @@ nds32_elf_relax_longcall4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, uint32_t insn; Elf_Internal_Rela *hi_irel, *ptr_irel, *insn_irel, *em_irel, *call_irel; Elf_Internal_Rela *irelend; - int pic_ext_target = 0; bfd_signed_vma foff; irelend = internal_relocs + sec->reloc_count; @@ -9742,21 +11182,21 @@ nds32_elf_relax_longcall4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, if (hi_irel == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGCALL4", - irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGCALL4 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } /* Get the value of the symbol referred to by the reloc. */ - foff = calculate_offset (abfd, sec, hi_irel, isymbuf, symtab_hdr, - &pic_ext_target); + foff = calculate_offset (abfd, sec, hi_irel, isymbuf, symtab_hdr); /* This condition only happened when symbol is undefined. */ - if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_24BIT_S1 + if (foff == 0 || foff < -CONSERVATIVE_24BIT_S1 || foff >= CONSERVATIVE_24BIT_S1) return FALSE; - /* Relax to: jal symbol; 25_PCREL */ + /* Relax to: jal symbol; 25_PCREL */ /* For simplicity of coding, we are going to modify the section contents, the section relocs, and the BFD symbol table. We must tell the rest of the code not to free up this @@ -9772,8 +11212,9 @@ nds32_elf_relax_longcall4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, if (ptr_irel == irelend || em_irel == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGCALL4", - irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGCALL4 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } /* Check these is enough space to insert jal in R_NDS32_EMPTY. */ @@ -9812,7 +11253,7 @@ nds32_elf_relax_longcall4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, return TRUE; } -/* Relax LONGCALL5 relocation for nds32_elf_relax_section. */ +/* Relax LONGCALL5 relocation for nds32_elf_relax_section.*/ static bfd_boolean nds32_elf_relax_longcall5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, @@ -9828,7 +11269,6 @@ nds32_elf_relax_longcall5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, bfd_vma laddr; uint32_t insn; Elf_Internal_Rela *cond_irel, *irelend; - int pic_ext_target = 0; bfd_signed_vma foff; irelend = internal_relocs + sec->reloc_count; @@ -9843,21 +11283,21 @@ nds32_elf_relax_longcall5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, R_NDS32_25_PCREL_RELA, irel->r_addend); if (cond_irel == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGCALL5", - irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGCALL5 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } /* Get the value of the symbol referred to by the reloc. */ - foff = calculate_offset (abfd, sec, cond_irel, isymbuf, symtab_hdr, - &pic_ext_target); + foff = calculate_offset (abfd, sec, cond_irel, isymbuf, symtab_hdr); if (foff == 0 || foff < -CONSERVATIVE_16BIT_S1 || foff >= CONSERVATIVE_16BIT_S1) return FALSE; /* Relax to bgezal rt, label ; 17_PCREL - or bltzal rt, label ; 17_PCREL */ + or bltzal rt, label ; 17_PCREL */ /* Convert to complimentary conditional call. */ insn = CONVERT_CONDITION_CALL (insn); @@ -9889,7 +11329,7 @@ nds32_elf_relax_longcall5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, return TRUE; } -/* Relax LONGCALL6 relocation for nds32_elf_relax_section. */ +/* Relax LONGCALL6 relocation for nds32_elf_relax_section.*/ static bfd_boolean nds32_elf_relax_longcall6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, @@ -9907,7 +11347,6 @@ nds32_elf_relax_longcall6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, bfd_vma laddr; uint32_t insn; Elf_Internal_Rela *em_irel, *cond_irel, *irelend; - int pic_ext_target = 0; bfd_signed_vma foff; irelend = internal_relocs + sec->reloc_count; @@ -9921,16 +11360,16 @@ nds32_elf_relax_longcall6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, if (em_irel == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGCALL6", - irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGCALL6 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } /* Get the value of the symbol referred to by the reloc. */ - foff = calculate_offset (abfd, sec, em_irel, isymbuf, symtab_hdr, - &pic_ext_target); + foff = calculate_offset (abfd, sec, em_irel, isymbuf, symtab_hdr); - if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_24BIT_S1 + if (foff == 0 || foff < -CONSERVATIVE_24BIT_S1 || foff >= CONSERVATIVE_24BIT_S1) return FALSE; @@ -9943,7 +11382,7 @@ nds32_elf_relax_longcall6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, if (foff >= -CONSERVATIVE_16BIT_S1 && foff < CONSERVATIVE_16BIT_S1) { /* Relax to bgezal rt, label ; 17_PCREL - or bltzal rt, label ; 17_PCREL */ + or bltzal rt, label ; 17_PCREL */ /* Convert to complimentary conditional call. */ *insn_len = 0; @@ -9959,8 +11398,9 @@ nds32_elf_relax_longcall6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, R_NDS32_PTR_RESOLVED, irel->r_addend); if (cond_irel == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, - "R_NDS32_LONGCALL6", irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGCALL6 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } cond_irel->r_addend = 1; @@ -10008,8 +11448,9 @@ nds32_elf_relax_longcall6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, R_NDS32_PTR_RESOLVED, irel->r_addend); if (cond_irel == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, - "R_NDS32_LONGCALL6", irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGCALL6 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } cond_irel->r_addend = 1; @@ -10024,7 +11465,7 @@ nds32_elf_relax_longcall6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, return TRUE; } -/* Relax LONGJUMP4 relocation for nds32_elf_relax_section. */ +/* Relax LONGJUMP4 relocation for nds32_elf_relax_section.*/ static bfd_boolean nds32_elf_relax_longjump4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, @@ -10041,7 +11482,6 @@ nds32_elf_relax_longjump4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, int seq_len; /* Original length of instruction sequence. */ uint32_t insn; Elf_Internal_Rela *hi_irel, *ptr_irel, *em_irel, *call_irel, *irelend; - int pic_ext_target = 0; bfd_signed_vma foff; irelend = internal_relocs + sec->reloc_count; @@ -10058,21 +11498,21 @@ nds32_elf_relax_longjump4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, if (hi_irel == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP4", - irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGJUMP4 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } /* Get the value of the symbol referred to by the reloc. */ - foff = calculate_offset (abfd, sec, hi_irel, isymbuf, symtab_hdr, - &pic_ext_target); + foff = calculate_offset (abfd, sec, hi_irel, isymbuf, symtab_hdr); - if (pic_ext_target || foff == 0 || foff >= CONSERVATIVE_24BIT_S1 + if (foff == 0 || foff >= CONSERVATIVE_24BIT_S1 || foff < -CONSERVATIVE_24BIT_S1) return FALSE; /* Convert it to "j label", it may be converted to j8 in the final - pass of relaxation. Therefore, we do not consider this currently. */ + pass of relaxation. Therefore, we do not consider this currently.*/ ptr_irel = find_relocs_at_address_addr (irel, internal_relocs, irelend, R_NDS32_PTR_RESOLVED, irel->r_addend); em_irel = find_relocs_at_address_addr (irel, internal_relocs, irelend, @@ -10080,8 +11520,9 @@ nds32_elf_relax_longjump4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, if (ptr_irel == irelend || em_irel == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP4", - irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGJUMP4 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } @@ -10109,7 +11550,7 @@ nds32_elf_relax_longjump4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, return TRUE; } -/* Relax LONGJUMP5 relocation for nds32_elf_relax_section. */ +/* Relax LONGJUMP5 relocation for nds32_elf_relax_section.*/ static bfd_boolean nds32_elf_relax_longjump5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, @@ -10131,7 +11572,6 @@ nds32_elf_relax_longjump5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, bfd_vma laddr; Elf_Internal_Rela *cond_irel, *irelend; - int pic_ext_target = 0; unsigned int i; bfd_signed_vma foff; uint32_t insn, re_insn = 0; @@ -10154,16 +11594,16 @@ nds32_elf_relax_longjump5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, R_NDS32_25_PCREL_RELA, irel->r_addend); if (cond_irel == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP5", - irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGJUMP5 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } /* Get the value of the symbol referred to by the reloc. */ - foff = calculate_offset (abfd, sec, cond_irel, isymbuf, symtab_hdr, - &pic_ext_target); + foff = calculate_offset (abfd, sec, cond_irel, isymbuf, symtab_hdr); - if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_16BIT_S1 + if (foff == 0 || foff < -CONSERVATIVE_16BIT_S1 || foff >= CONSERVATIVE_16BIT_S1) return FALSE; @@ -10208,7 +11648,7 @@ nds32_elf_relax_longjump5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, /* Clean relocations. */ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_NONE); - for (i = 0; i < sizeof (checked_types) / sizeof (checked_types[0]); i++) + for (i = 0; i < ARRAY_SIZE (checked_types); i++) { cond_irel = find_relocs_at_address_addr (irel, internal_relocs, irelend, checked_types[i], laddr); @@ -10234,7 +11674,7 @@ nds32_elf_relax_longjump5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, return TRUE; } -/* Relax LONGJUMP6 relocation for nds32_elf_relax_section. */ +/* Relax LONGJUMP6 relocation for nds32_elf_relax_section.*/ static bfd_boolean nds32_elf_relax_longjump6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, @@ -10265,7 +11705,6 @@ nds32_elf_relax_longjump6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, int reloc_off = 0, cond_removed = 0; bfd_vma laddr; Elf_Internal_Rela *cond_irel, *em_irel, *irelend, *insn_irel; - int pic_ext_target = 0; unsigned int i; bfd_signed_vma foff; uint32_t insn, re_insn = 0; @@ -10283,16 +11722,16 @@ nds32_elf_relax_longjump6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, if (em_irel == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP6", - irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGJUMP6 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } /* Get the value of the symbol referred to by the reloc. */ - foff = calculate_offset (abfd, sec, em_irel, isymbuf, symtab_hdr, - &pic_ext_target); + foff = calculate_offset (abfd, sec, em_irel, isymbuf, symtab_hdr); - if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_24BIT_S1 + if (foff == 0 || foff < -CONSERVATIVE_24BIT_S1 || foff >= CONSERVATIVE_24BIT_S1) return FALSE; @@ -10318,7 +11757,7 @@ nds32_elf_relax_longjump6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, if (N32_OP6 (re_insn) == N32_OP6_BR1 && (foff >= -CONSERVATIVE_14BIT_S1 && foff < CONSERVATIVE_14BIT_S1)) { - /* beqs label ; 15_PCREL */ + /* beqs label ; 15_PCREL */ bfd_putb32 (re_insn, contents + em_irel->r_offset); reloc = R_NDS32_15_PCREL_RELA; cond_removed = 1; @@ -10326,7 +11765,7 @@ nds32_elf_relax_longjump6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, else if (N32_OP6 (re_insn) == N32_OP6_BR2 && foff >= -CONSERVATIVE_16BIT_S1 && foff < CONSERVATIVE_16BIT_S1) { - /* beqz label ; 17_PCREL */ + /* beqz label ; 17_PCREL */ bfd_putb32 (re_insn, contents + em_irel->r_offset); reloc = R_NDS32_17_PCREL_RELA; cond_removed = 1; @@ -10383,7 +11822,7 @@ nds32_elf_relax_longjump6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, /* Clear relocations. */ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_NONE); - for (i = 0; i < sizeof (checked_types) / sizeof (checked_types[0]); i++) + for (i = 0; i < ARRAY_SIZE (checked_types); i++) { cond_irel = find_relocs_at_address_addr (irel, internal_relocs, irelend, @@ -10415,7 +11854,7 @@ nds32_elf_relax_longjump6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, return TRUE; } -/* Relax LONGJUMP7 relocation for nds32_elf_relax_section. */ +/* Relax LONGJUMP7 relocation for nds32_elf_relax_section.*/ static bfd_boolean nds32_elf_relax_longjump7 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, @@ -10435,7 +11874,6 @@ nds32_elf_relax_longjump7 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, bfd_vma laddr; Elf_Internal_Rela *cond_irel, *irelend, *insn_irel; - int pic_ext_target = 0; bfd_signed_vma foff; uint32_t insn, re_insn = 0; uint16_t insn16; @@ -10453,16 +11891,16 @@ nds32_elf_relax_longjump7 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, R_NDS32_15_PCREL_RELA, irel->r_addend); if (cond_irel == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP7", - irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_LONGJUMP7 points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); return FALSE; } /* Get the value of the symbol referred to by the reloc. */ - foff = calculate_offset (abfd, sec, cond_irel, isymbuf, symtab_hdr, - &pic_ext_target); + foff = calculate_offset (abfd, sec, cond_irel, isymbuf, symtab_hdr); - if (pic_ext_target || foff == 0 || foff < -CONSERVATIVE_8BIT_S1 + if (foff == 0 || foff < -CONSERVATIVE_8BIT_S1 || foff >= CONSERVATIVE_8BIT_S1) return FALSE; @@ -10516,6 +11954,123 @@ nds32_elf_relax_longjump7 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, return TRUE; } +/* Record the offset to gp, and check if it changed after relaxing. + If the offset is fixed or the offset is near enough, try to relax + the pattern. This is avoid truncated to fit when relaxing fixed + address symbol. Ex: _stack. */ +static bfd_boolean +nds32_elf_relax_guard (bfd_vma *access_addr, bfd_vma local_sda, asection *sec, + Elf_Internal_Rela *irel, bfd_boolean *again, + bfd_boolean init, + struct elf_nds32_link_hash_table *table, + Elf_Internal_Sym *isymbuf, Elf_Internal_Shdr *symtab_hdr) + +{ + /* The default linker script value. */ + int offset_to_gp; + static bfd_boolean sec_pass = FALSE; + static asection *first_sec = NULL, *sym_sec; + /* Record the number of instructions which may be removed. */ + static int count = 0, record_count; + Elf_Internal_Sym *isym; + struct elf_link_hash_entry *h = NULL; + int indx; + unsigned long r_symndx; + bfd *abfd = sec->owner; + static bfd_vma record_sda = 0; + int sda_offset = 0; + + /* Force doing relaxation when hyper-relax is high. */ + if (table->hyper_relax == 2) + return TRUE; + + /* Record the first section to get the round. */ + if (init) + { + if (!first_sec) + first_sec = sec; + else if (first_sec == sec) + { + record_count = count; + count = 0; + sec_pass = TRUE; + } + + if (!sec_pass) + *again = TRUE; + + return TRUE; + } + + if (record_sda == 0) + record_sda = local_sda; + else if (local_sda > record_sda) + /* In normal case, SDA is fixed or smaller except there is + DATA_SEGMENT_ALIGN in linker script.*/ + sda_offset = local_sda - record_sda; + + /* Although we doesn't delete all instructions here, counting all of + them to be conservative. */ + count++; + + r_symndx = ELF32_R_SYM (irel->r_info); + /* Global symbols. */ + if (r_symndx >= symtab_hdr->sh_info) + { + indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; + h = elf_sym_hashes (abfd)[indx]; + sym_sec = h->root.u.def.section; + if (NDS32_GUARD_SEC_P (sym_sec->flags) + || bfd_is_abs_section (sym_sec)) + { + /* Forbid doing relaxation when hyper-relax is low. */ + if (table->hyper_relax == 0) + return FALSE; + + offset_to_gp = *access_addr - local_sda; + if (elf32_nds32_hash_entry (h)->offset_to_gp == 0) + elf32_nds32_hash_entry (h)->offset_to_gp = offset_to_gp; + else if (abs (elf32_nds32_hash_entry (h)->offset_to_gp) + < abs (offset_to_gp) - sda_offset) + { + if (*access_addr >= local_sda) + *access_addr += (record_count * 4); + else + *access_addr -= (record_count * 4); + } + return sec_pass; + } + } + else + { + if (!elf32_nds32_allocate_local_sym_info (abfd)) + return FALSE; + isym = isymbuf + r_symndx; + + sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); + if (NDS32_GUARD_SEC_P (sym_sec->flags)) + { + /* Forbid doing relaxation when hyper-relax is low. */ + if (table->hyper_relax == 0) + return FALSE; + + offset_to_gp = *access_addr - local_sda; + if (elf32_nds32_local_gp_offset (abfd)[r_symndx] == 0) + elf32_nds32_local_gp_offset (abfd)[r_symndx] = offset_to_gp; + else if (abs (elf32_nds32_local_gp_offset (abfd)[r_symndx]) + < abs (offset_to_gp) - sda_offset) + { + if (*access_addr >= local_sda) + *access_addr += (record_count * 4); + else + *access_addr -= (record_count * 4); + } + return sec_pass; + } + } + + return TRUE; +} #define GET_LOADSTORE_RANGE(addend) (((addend) >> 8) & 0x3f) /* Relax LOADSTORE relocation for nds32_elf_relax_section. */ @@ -10525,21 +12080,24 @@ nds32_elf_relax_loadstore (struct bfd_link_info *link_info, bfd *abfd, asection *sec, Elf_Internal_Rela *irel, Elf_Internal_Rela *internal_relocs, int *insn_len, bfd_byte *contents, Elf_Internal_Sym *isymbuf, - Elf_Internal_Shdr *symtab_hdr, int load_store_relax) + Elf_Internal_Shdr *symtab_hdr, int load_store_relax, + struct elf_nds32_link_hash_table *table) { - int eliminate_sethi = 0, range_type; - unsigned int i; + int eliminate_sethi = 0, range_type, i; bfd_vma local_sda, laddr; int seq_len; /* Original length of instruction sequence. */ uint32_t insn; Elf_Internal_Rela *hi_irelfn = NULL, *irelend; bfd_vma access_addr = 0; bfd_vma range_l = 0, range_h = 0; /* Upper/lower bound. */ + struct elf_link_hash_entry *h = NULL; + int indx; enum elf_nds32_reloc_type checked_types[] = { R_NDS32_HI20_RELA, R_NDS32_GOT_HI20, R_NDS32_GOTPC_HI20, R_NDS32_GOTOFF_HI20, R_NDS32_PLTREL_HI20, R_NDS32_PLT_GOTREL_HI20, - R_NDS32_TLS_LE_HI20 + R_NDS32_TLS_LE_HI20, R_NDS32_TLS_IE_HI20, + R_NDS32_TLS_IEGP_HI20, R_NDS32_TLS_DESC_HI20 }; irelend = internal_relocs + sec->reloc_count; @@ -10548,7 +12106,7 @@ nds32_elf_relax_loadstore (struct bfd_link_info *link_info, bfd *abfd, *insn_len = seq_len; /* Get the high part relocation. */ - for (i = 0; i < ARRAY_SIZE (checked_types); i++) + for (i = 0; (unsigned) i < ARRAY_SIZE (checked_types); i++) { hi_irelfn = find_relocs_at_address_addr (irel, internal_relocs, irelend, checked_types[i], laddr); @@ -10558,9 +12116,12 @@ nds32_elf_relax_loadstore (struct bfd_link_info *link_info, bfd *abfd, if (hi_irelfn == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LOADSTORE", - irel->r_offset); - return FALSE; + /* Not R_NDS32_HI20_RELA. */ + if (i != 0) + _bfd_error_handler + ("%B: warning: R_NDS32_LOADSTORE points to unrecognized " + "reloc at 0x%lx.", abfd, (long) irel->r_offset); + return FALSE; } range_type = GET_LOADSTORE_RANGE (irel->r_addend); @@ -10574,39 +12135,41 @@ nds32_elf_relax_loadstore (struct bfd_link_info *link_info, bfd *abfd, access_addr = calculate_memory_address (abfd, hi_irelfn, isymbuf, symtab_hdr); - if (range_type == NDS32_LOADSTORE_IMM) + if (ELF32_R_SYM (hi_irelfn->r_info) >= symtab_hdr->sh_info) { - struct elf_link_hash_entry *h = NULL; - int indx; - - if (ELF32_R_SYM (hi_irelfn->r_info) >= symtab_hdr->sh_info) - { - indx = ELF32_R_SYM (hi_irelfn->r_info) - symtab_hdr->sh_info; - h = elf_sym_hashes (abfd)[indx]; - } + indx = ELF32_R_SYM (hi_irelfn->r_info) - symtab_hdr->sh_info; + h = elf_sym_hashes (abfd)[indx]; + } + /* Try movi. */ + if (range_type == NDS32_LOADSTORE_IMM) + { if ((access_addr < CONSERVATIVE_20BIT) && (!h || (h && strcmp (h->root.root.string, FP_BASE_NAME) != 0))) { eliminate_sethi = 1; break; } + } - /* This is avoid to relax symbol address which is fixed - relocations. Ex: _stack. */ - if (h && bfd_is_abs_section (h->root.u.def.section)) - return FALSE; + if (h && strcmp (h->root.root.string, FP_BASE_NAME) == 0) + { + eliminate_sethi = 1; + break; } + else if (!nds32_elf_relax_guard (&access_addr, local_sda, sec, hi_irelfn, + NULL, FALSE, table, isymbuf, symtab_hdr)) + return FALSE; if (!load_store_relax) return FALSE; /* Case for set gp register. */ if (N32_RT5 (insn) == REG_GP) - break; + return FALSE; if (range_type == NDS32_LOADSTORE_FLOAT_S - || range_type == NDS32_LOADSTORE_FLOAT_D) + || range_type == NDS32_LOADSTORE_FLOAT_S) { range_l = sdata_range[0][0]; range_h = sdata_range[0][1]; @@ -10618,57 +12181,6 @@ nds32_elf_relax_loadstore (struct bfd_link_info *link_info, bfd *abfd, } break; - case R_NDS32_GOT_HI20: - access_addr = - calculate_got_memory_address (abfd, link_info, hi_irelfn, symtab_hdr); - - /* If this symbol is not in .got, the return value will be -1. - Since the gp value is set to SDA_BASE but not GLOBAL_OFFSET_TABLE, - a negative offset is allowed. */ - if ((bfd_signed_vma) (access_addr - local_sda) < CONSERVATIVE_20BIT - && (bfd_signed_vma) (access_addr - local_sda) >= -CONSERVATIVE_20BIT) - eliminate_sethi = 1; - break; - - case R_NDS32_PLT_GOTREL_HI20: - access_addr = calculate_plt_memory_address (abfd, link_info, isymbuf, - hi_irelfn, symtab_hdr); - - if ((bfd_signed_vma) (access_addr - local_sda) < CONSERVATIVE_20BIT - && (bfd_signed_vma) (access_addr - local_sda) >= -CONSERVATIVE_20BIT) - eliminate_sethi = 1; - break; - - case R_NDS32_GOTOFF_HI20: - access_addr = - calculate_memory_address (abfd, hi_irelfn, isymbuf, symtab_hdr); - - if ((bfd_signed_vma) (access_addr - local_sda) < CONSERVATIVE_20BIT - && (bfd_signed_vma) (access_addr - local_sda) >= -CONSERVATIVE_20BIT) - eliminate_sethi = 1; - break; - - case R_NDS32_GOTPC_HI20: - /* The access_addr must consider r_addend of hi_irel. */ - access_addr = sec->output_section->vma + sec->output_offset - + irel->r_offset + hi_irelfn->r_addend; - - if ((bfd_signed_vma) (local_sda - access_addr) < CONSERVATIVE_20BIT - && (bfd_signed_vma) (local_sda - access_addr) >= -CONSERVATIVE_20BIT) - eliminate_sethi = 1; - break; - - case R_NDS32_TLS_LE_HI20: - access_addr = - calculate_memory_address (abfd, hi_irelfn, isymbuf, symtab_hdr); - BFD_ASSERT (elf_hash_table (link_info)->tls_sec != NULL); - access_addr -= (elf_hash_table (link_info)->tls_sec->vma + TP_OFFSET); - if ((range_type == NDS32_LOADSTORE_IMM) - && (bfd_signed_vma) (access_addr) < CONSERVATIVE_20BIT - && (bfd_signed_vma) (access_addr) >= -CONSERVATIVE_20BIT) - eliminate_sethi = 1; - break; - default: return FALSE; } @@ -10683,17 +12195,20 @@ nds32_elf_relax_loadstore (struct bfd_link_info *link_info, bfd *abfd, irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_NONE); *insn_len = 0; + return TRUE; } - return TRUE; + + return FALSE; } -/* Relax LO12 relocation for nds32_elf_relax_section. */ +/* Relax LO12 relocation for nds32_elf_relax_section.*/ static void nds32_elf_relax_lo12 (struct bfd_link_info *link_info, bfd *abfd, asection *sec, Elf_Internal_Rela *irel, Elf_Internal_Rela *internal_relocs, bfd_byte *contents, - Elf_Internal_Sym *isymbuf, Elf_Internal_Shdr *symtab_hdr) + Elf_Internal_Sym *isymbuf, Elf_Internal_Shdr *symtab_hdr, + struct elf_nds32_link_hash_table *table) { uint32_t insn; bfd_vma local_sda, laddr; @@ -10723,6 +12238,7 @@ nds32_elf_relax_lo12 (struct bfd_link_info *link_info, bfd *abfd, h = elf_sym_hashes (abfd)[indx]; } + /* Try movi. */ if (N32_OP6 (insn) == N32_OP6_ORI && access_addr < CONSERVATIVE_20BIT && (!h || (h && strcmp (h->root.root.string, FP_BASE_NAME) != 0))) { @@ -10731,13 +12247,14 @@ nds32_elf_relax_lo12 (struct bfd_link_info *link_info, bfd *abfd, insn = N32_TYPE1 (MOVI, N32_RT5 (insn), 0); bfd_putb32 (insn, contents + laddr); } - /* This is avoid to relax symbol address which is fixed - relocations. Ex: _stack. */ - else if (N32_OP6 (insn) == N32_OP6_ORI - && h && bfd_is_abs_section (h->root.u.def.section)) - return; else { + if (h && strcmp (h->root.root.string, FP_BASE_NAME) == 0) + { /* Fall through. */ } + else if (!nds32_elf_relax_guard (&access_addr, local_sda, sec, irel, NULL, + FALSE, table, isymbuf, symtab_hdr)) + return; + range_l = sdata_range[1][0]; range_h = sdata_range[1][1]; switch (ELF32_R_TYPE (irel->r_info)) @@ -10768,7 +12285,8 @@ nds32_elf_relax_lo12 (struct bfd_link_info *link_info, bfd *abfd, /* There are range_h and range_l because linker has to promise all sections move cross one page together. */ if ((local_sda <= access_addr && (access_addr - local_sda) < range_h) - || (local_sda > access_addr && (local_sda - access_addr) <= range_l)) + || (local_sda > access_addr && (local_sda - access_addr) <= range_l) + || (h && strcmp (h->root.root.string, FP_BASE_NAME) == 0)) { if (N32_OP6 (insn) == N32_OP6_ORI && N32_RT5 (insn) == REG_GP) { @@ -10790,7 +12308,6 @@ nds32_elf_relax_lo12 (struct bfd_link_info *link_info, bfd *abfd, if (irelfn != irelend && reloc != R_NDS32_SDA17S2_RELA) irelfn->r_info = ELF32_R_INFO (ELF32_R_SYM (irelfn->r_info), R_NDS32_NONE); - } } return; @@ -10798,7 +12315,7 @@ nds32_elf_relax_lo12 (struct bfd_link_info *link_info, bfd *abfd, /* Relax low part of PIC instruction pattern. */ -static void +ATTRIBUTE_UNUSED static void nds32_elf_relax_piclo12 (struct bfd_link_info *link_info, bfd *abfd, asection *sec, Elf_Internal_Rela *irel, bfd_byte *contents, Elf_Internal_Sym *isymbuf, @@ -10855,7 +12372,7 @@ nds32_elf_relax_piclo12 (struct bfd_link_info *link_info, bfd *abfd, /* Relax low part of LE TLS instruction pattern. */ -static void +ATTRIBUTE_UNUSED static void nds32_elf_relax_letlslo12 (struct bfd_link_info *link_info, bfd *abfd, Elf_Internal_Rela *irel, bfd_byte *contents, Elf_Internal_Sym *isymbuf, @@ -10885,7 +12402,7 @@ nds32_elf_relax_letlslo12 (struct bfd_link_info *link_info, bfd *abfd, /* Relax LE TLS calculate address instruction pattern. */ -static void +ATTRIBUTE_UNUSED static void nds32_elf_relax_letlsadd (struct bfd_link_info *link_info, bfd *abfd, asection *sec, Elf_Internal_Rela *irel, Elf_Internal_Rela *internal_relocs, @@ -10893,9 +12410,9 @@ nds32_elf_relax_letlsadd (struct bfd_link_info *link_info, bfd *abfd, Elf_Internal_Shdr *symtab_hdr, bfd_boolean *again) { /* Local TLS non-pic - sethi ta, hi20(symbol@tpoff) ; TLS_LE_HI20 + sethi ta, hi20(symbol@tpoff) ; TLS_LE_HI20 ori ta, ta, lo12(symbol@tpoff) ; TLS_LE_LO12 - add ra, ta, tp ; TLS_LE_ADD */ + add ra, ta, tp ; TLS_LE_ADD */ uint32_t insn; bfd_vma laddr; @@ -10931,14 +12448,13 @@ nds32_elf_relax_letlsadd (struct bfd_link_info *link_info, bfd *abfd, /* Relax LE TLS load store instruction pattern. */ -static void +ATTRIBUTE_UNUSED static void nds32_elf_relax_letlsls (struct bfd_link_info *link_info, bfd *abfd, asection *sec, Elf_Internal_Rela *irel, Elf_Internal_Rela *internal_relocs, bfd_byte *contents, Elf_Internal_Sym *isymbuf, Elf_Internal_Shdr *symtab_hdr, bfd_boolean *again) { - uint32_t insn; bfd_vma laddr; bfd_signed_vma foff; @@ -10970,7 +12486,6 @@ nds32_elf_relax_letlsls (struct bfd_link_info *link_info, bfd *abfd, success = 1; break; } - /* Fall through. */ case (N32_OP6_MEM << 8) | N32_MEM_LH: case (N32_OP6_MEM << 8) | N32_MEM_SH: case (N32_OP6_MEM << 8) | N32_MEM_LHS: @@ -10985,7 +12500,6 @@ nds32_elf_relax_letlsls (struct bfd_link_info *link_info, bfd *abfd, success = 1; break; } - /* Fall through. */ case (N32_OP6_MEM << 8) | N32_MEM_LW: case (N32_OP6_MEM << 8) | N32_MEM_SW: /* The range is +/-64k. */ @@ -10999,7 +12513,6 @@ nds32_elf_relax_letlsls (struct bfd_link_info *link_info, bfd *abfd, success = 1; break; } - /* Fall through. */ default: break; } @@ -11032,8 +12545,9 @@ nds32_elf_relax_ptr (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, if (re_irel == irelend) { - _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_PTR", - irel->r_offset); + _bfd_error_handler + ("%B: warning: R_NDS32_PTR points to unrecognized reloc at 0x%lx.", + abfd, (long) irel->r_offset); return FALSE; } @@ -11068,7 +12582,7 @@ nds32_elf_relax_ptr (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, /* Relax PLT_GOT_SUFF relocation for nds32_elf_relax_section. */ -static void +ATTRIBUTE_UNUSED static void nds32_elf_relax_pltgot_suff (struct bfd_link_info *link_info, bfd *abfd, asection *sec, Elf_Internal_Rela *irel, Elf_Internal_Rela *internal_relocs, @@ -11123,7 +12637,7 @@ nds32_elf_relax_pltgot_suff (struct bfd_link_info *link_info, bfd *abfd, return; irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_PLT_GOTREL_LO19); - /* addi.gp */ + /* addi.gp */ insn = N32_TYPE1 (SBGP, N32_RT5 (insn), N32_BIT (19)); } else if (N32_OP6 (insn) == N32_OP6_JREG @@ -11153,7 +12667,7 @@ nds32_elf_relax_pltgot_suff (struct bfd_link_info *link_info, bfd *abfd, /* Relax GOT_SUFF relocation for nds32_elf_relax_section. */ -static void +ATTRIBUTE_UNUSED static void nds32_elf_relax_got_suff (struct bfd_link_info *link_info, bfd *abfd, asection *sec, Elf_Internal_Rela *irel, Elf_Internal_Rela *internal_relocs, @@ -11200,7 +12714,7 @@ nds32_elf_relax_got_suff (struct bfd_link_info *link_info, bfd *abfd, /* Relax PLT_GOT_SUFF relocation for nds32_elf_relax_section. */ -static void +ATTRIBUTE_UNUSED static void nds32_elf_relax_gotoff_suff (struct bfd_link_info *link_info, bfd *abfd, asection *sec, Elf_Internal_Rela *irel, Elf_Internal_Rela *internal_relocs, @@ -11303,6 +12817,85 @@ nds32_elf_relax_gotoff_suff (struct bfd_link_info *link_info, bfd *abfd, } +/* Relax LWC relocation for nds32_elf_relax_section. */ + +static void +nds32_elf_relax_flsi (struct bfd_link_info *link_info, bfd *abfd, + asection *sec, Elf_Internal_Rela *irel, + Elf_Internal_Rela *internal_relocs, + bfd_byte *contents, Elf_Internal_Sym *isymbuf, + Elf_Internal_Shdr *symtab_hdr, bfd_boolean *again) +{ + /* Pattern for bug-12566 + sethi ra, hi20(symbol) ; HI20/LOADSTORE + ori ra, ra, lo12(symbol) ; LO12S0/PTR/PTR/.../INSN16 + flsi fsa, [ra + offset1] ; LSI/PTR_RESOLVED/INSN16 + flsi fsb, [ra + offset2] ; LSI/PTR_RESOLVED/INSN16 + ... */ + + uint32_t insn; + bfd_vma local_sda, laddr; + unsigned long reloc; + bfd_vma access_addr, flsi_offset; + bfd_vma range_l = 0, range_h = 0; /* Upper/lower bound. */ + Elf_Internal_Rela *irelend, *re_irel; + unsigned int opcode; + + irelend = internal_relocs + sec->reloc_count; + laddr = irel->r_offset; + insn = bfd_getb32 (contents + laddr); + + if ((insn & 0x80000000) || !is_sda_access_insn (insn)) + return; + + /* Can not do relaxation for bi format. */ + if ((insn & 0x1000)) + return; + + /* Only deal with flsi, fssi, fldi, fsdi, so far. */ + opcode = N32_OP6 (insn); + if ((opcode == N32_OP6_LWC) || (opcode == N32_OP6_SWC)) + reloc = R_NDS32_SDA12S2_SP_RELA; + else if ((opcode == N32_OP6_LDC) || (opcode == N32_OP6_SDC)) + reloc = R_NDS32_SDA12S2_DP_RELA; + else + return; + + re_irel = find_relocs_at_address (irel, internal_relocs, irelend, + R_NDS32_PTR_RESOLVED); + if (re_irel == irelend) + { + _bfd_error_handler + ("%pB: warning: R_NDS32_LSI has no R_NDS32_PTR_RESOLVED at 0x%lx.", + abfd, (long) irel->r_offset); + return; + } + + /* For SDA base relative relaxation. */ + nds32_elf_final_sda_base (sec->output_section->owner, link_info, + &local_sda, FALSE); + access_addr = calculate_memory_address (abfd, irel, isymbuf, symtab_hdr); + flsi_offset = (insn & 0xfff) << 2; + access_addr += flsi_offset; + range_l = sdata_range[0][0]; + range_h = sdata_range[0][1]; + + if ((local_sda <= access_addr && (access_addr - local_sda) < range_h) + || (local_sda > access_addr && (local_sda - access_addr) <= range_l)) + { + /* Turn flsi instruction into sda access format. */ + insn = (insn & 0x7ff07000) | (REG_GP << 15); + + /* Add relocation type to flsi. */ + irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), reloc); + irel->r_addend += flsi_offset; + bfd_putb32 (insn, contents + re_irel->r_offset); + + re_irel->r_addend |= 1; + *again = TRUE; + } +} + static bfd_boolean nds32_relax_adjust_label (bfd *abfd, asection *sec, Elf_Internal_Rela *internal_relocs, @@ -11387,9 +12980,11 @@ nds32_relax_adjust_label (bfd *abfd, asection *sec, { /* Remove all LABEL relocation from label_rel to tmp_rel including relocations with same offset as tmp_rel. */ - for (tmp2_rel = label_rel; tmp2_rel < tmp_rel - || tmp2_rel->r_offset == tmp_rel->r_offset; tmp2_rel++) + for (tmp2_rel = label_rel; tmp2_rel < tmp_rel; tmp2_rel++) { + if (tmp2_rel->r_offset == tmp_rel->r_offset) + break; + if (ELF32_R_TYPE (tmp2_rel->r_info) == R_NDS32_LABEL && tmp2_rel->r_addend < 2) tmp2_rel->r_info = @@ -11416,7 +13011,8 @@ nds32_relax_adjust_label (bfd *abfd, asection *sec, We may convert a 16-bit instruction right before a label to 32-bit, in order to align the label if necessary all reloc entries has been sorted by r_offset. */ - for (irel = internal_relocs; irel < irelend; irel++) + for (irel = internal_relocs; + irel < irelend && irel->r_offset < sec->size; irel++) { if (ELF32_R_TYPE (irel->r_info) != R_NDS32_INSN16 && ELF32_R_TYPE (irel->r_info) != R_NDS32_LABEL) @@ -11568,118 +13164,6 @@ nds32_relax_adjust_label (bfd *abfd, asection *sec, return TRUE; } -/* Pick relaxation round. */ - -static int -nds32_elf_pick_relax (bfd_boolean init, asection *sec, bfd_boolean *again, - struct elf_nds32_link_hash_table *table, - struct bfd_link_info *link_info) -{ - static asection *final_sec, *first_sec = NULL; - static bfd_boolean normal_again = FALSE; - static bfd_boolean set = FALSE; - static bfd_boolean first = TRUE; - int round_table[] = { - NDS32_RELAX_NORMAL_ROUND, - NDS32_RELAX_JUMP_IFC_ROUND, - NDS32_RELAX_EX9_BUILD_ROUND, - NDS32_RELAX_EX9_REPLACE_ROUND, - }; - static int pass = 0; - static int relax_round; - - /* The new round. */ - if (init && first_sec == sec) - { - set = TRUE; - normal_again = FALSE; - } - - if (first) - { - /* Run an empty run to get the final section. */ - relax_round = NDS32_RELAX_EMPTY_ROUND; - - /* It has to enter relax again because we can - not make sure what the final turn is. */ - *again = TRUE; - - first = FALSE; - first_sec = sec; - } - - if (!set) - { - /* Not reenter yet. */ - final_sec = sec; - return relax_round; - } - - relax_round = round_table[pass]; - - if (!init && relax_round == NDS32_RELAX_NORMAL_ROUND && *again) - normal_again = TRUE; - - if (!init && final_sec == sec) - { - switch (relax_round) - { - case NDS32_RELAX_NORMAL_ROUND: - if (!normal_again) - { - /* Normal relaxation done. */ - if (table->target_optimize & NDS32_RELAX_JUMP_IFC_ON) - { - pass++; - *again = TRUE; - } - else if (table->target_optimize & NDS32_RELAX_EX9_ON) - { - pass += 2; /* NDS32_RELAX_EX9_BUILD_ROUND */ - *again = TRUE; - } - else if (table->ex9_import_file) - { - /* Import ex9 table. */ - if (table->update_ex9_table) - pass += 2; /* NDS32_RELAX_EX9_BUILD_ROUND */ - else - pass += 3; /* NDS32_RELAX_EX9_REPLACE_ROUND */ - nds32_elf_ex9_import_table (link_info); - *again = TRUE; - } - } - break; - case NDS32_RELAX_JUMP_IFC_ROUND: - if (!nds32_elf_ifc_finish (link_info)) - _bfd_error_handler (_("error: Jump IFC Fail.")); - if (table->target_optimize & NDS32_RELAX_EX9_ON) - { - pass++; - *again = TRUE; - } - break; - case NDS32_RELAX_EX9_BUILD_ROUND: - nds32_elf_ex9_finish (link_info); - pass++; - *again = TRUE; - break; - case NDS32_RELAX_EX9_REPLACE_ROUND: - if (table->target_optimize & NDS32_RELAX_JUMP_IFC_ON) - { - /* Do jump IFC optimization again. */ - if (!nds32_elf_ifc_finish (link_info)) - _bfd_error_handler (_("error: Jump IFC Fail.")); - } - break; - default: - break; - } - } - - return relax_round; -} - static bfd_boolean nds32_elf_relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info, bfd_boolean *again) @@ -11697,26 +13181,25 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, uint32_t insn; uint16_t insn16; - /* Target dependnet option. */ + /* Target dependent option. */ struct elf_nds32_link_hash_table *table; int load_store_relax; - int relax_round; relax_blank_list = NULL; - *again = FALSE; /* Nothing to do for - * relocatable link or - * non-relocatable section or - * non-code section or - * empty content or - * no reloc entry. */ + relocatable link or + non-relocatable section or + non-code section or + empty content or + no reloc entry. */ if (bfd_link_relocatable (link_info) || (sec->flags & SEC_RELOC) == 0 - || (sec->flags & SEC_EXCLUDE) != 0 + || (sec->flags & SEC_EXCLUDE) == 1 || (sec->flags & SEC_CODE) == 0 - || sec->size == 0) + || sec->size == 0 + || sec->reloc_count == 0) return TRUE; /* 09.12.11 Workaround. */ @@ -11725,44 +13208,14 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, if (sec->alignment_power > 2) return TRUE; +#ifdef NDS32_LINUX_TOOLCHAIN + /* Do TLS model conversion once at first. */ + nds32_elf_unify_tls_model (abfd, sec, contents, link_info); +#endif + /* The optimization type to do. */ table = nds32_elf_hash_table (link_info); - relax_round = nds32_elf_pick_relax (TRUE, sec, again, table, link_info); - switch (relax_round) - { - case NDS32_RELAX_JUMP_IFC_ROUND: - /* Here is the entrance of ifc jump relaxation. */ - if (!nds32_elf_ifc_calc (link_info, abfd, sec)) - return FALSE; - nds32_elf_pick_relax (FALSE, sec, again, table, link_info); - return TRUE; - - case NDS32_RELAX_EX9_BUILD_ROUND: - /* Here is the entrance of ex9 relaxation. There are two pass of - ex9 relaxation. The one is to traverse all instructions and build - the hash table. The other one is to compare instructions and replace - it by ex9.it. */ - if (!nds32_elf_ex9_build_hash_table (abfd, sec, link_info)) - return FALSE; - nds32_elf_pick_relax (FALSE, sec, again, table, link_info); - return TRUE; - - case NDS32_RELAX_EX9_REPLACE_ROUND: - if (!nds32_elf_ex9_replace_instruction (link_info, abfd, sec)) - return FALSE; - return TRUE; - - case NDS32_RELAX_EMPTY_ROUND: - nds32_elf_pick_relax (FALSE, sec, again, table, link_info); - return TRUE; - - case NDS32_RELAX_NORMAL_ROUND: - default: - if (sec->reloc_count == 0) - return TRUE; - break; - } /* The begining of general relaxation. */ @@ -11775,20 +13228,10 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, relax_range_measurement (abfd); } - if (is_ITB_BASE_set == 0) - { - /* Set the _ITB_BASE_. */ - if (!nds32_elf_ex9_itb_base (link_info)) - { - _bfd_error_handler (_("%B: error: Cannot set _ITB_BASE_"), abfd); - bfd_set_error (bfd_error_bad_value); - } - } - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; /* Relocations MUST be kept in memory, because relaxation adjust them. */ internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, - TRUE /* keep_memory */); + TRUE /* keep_memory */); if (internal_relocs == NULL) goto error_return; @@ -11802,10 +13245,7 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, if (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_ENTRY) { if (irel->r_addend & R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG) - { - nds32_elf_pick_relax (FALSE, sec, again, table, link_info); - return TRUE; - } + return TRUE; if (irel->r_addend & R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG) optimize = 1; @@ -11888,7 +13328,8 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, || ELF32_R_TYPE (irel->r_info) == R_NDS32_17IFC_PCREL_RELA || ELF32_R_TYPE (irel->r_info) == R_NDS32_TLS_LE_LO12 || ELF32_R_TYPE (irel->r_info) == R_NDS32_TLS_LE_ADD - || ELF32_R_TYPE (irel->r_info) == R_NDS32_TLS_LE_LS) + || ELF32_R_TYPE (irel->r_info) == R_NDS32_TLS_LE_LS + || ELF32_R_TYPE (irel->r_info) == R_NDS32_LSI) seq_len = 0; else continue; @@ -11967,71 +13408,41 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, removed = nds32_elf_relax_loadstore (link_info, abfd, sec, irel, internal_relocs, &insn_len, contents, isymbuf, symtab_hdr, - load_store_relax); + load_store_relax, table); break; case R_NDS32_LO12S0_RELA: case R_NDS32_LO12S1_RELA: + case R_NDS32_LO12S2_RELA: case R_NDS32_LO12S2_DP_RELA: case R_NDS32_LO12S2_SP_RELA: - case R_NDS32_LO12S2_RELA: /* Relax for low part. */ nds32_elf_relax_lo12 (link_info, abfd, sec, irel, internal_relocs, - contents, isymbuf, symtab_hdr); + contents, isymbuf, symtab_hdr, table); /* It is impossible to delete blank, so just continue. */ continue; + case R_NDS32_PTR: + removed = nds32_elf_relax_ptr (abfd, sec, irel, internal_relocs, + &insn_len, &seq_len, contents); + break; + case R_NDS32_LSI: + nds32_elf_relax_flsi (link_info, abfd, sec, irel, internal_relocs, + contents, isymbuf, symtab_hdr, again); + continue; case R_NDS32_GOT_LO12: case R_NDS32_GOTOFF_LO12: case R_NDS32_PLTREL_LO12: case R_NDS32_PLT_GOTREL_LO12: case R_NDS32_GOTPC_LO12: - /* Relax for PIC gp-relative low part. */ - nds32_elf_relax_piclo12 (link_info, abfd, sec, irel, contents, - isymbuf, symtab_hdr); - - /* It is impossible to delete blank, so just continue. */ - continue; case R_NDS32_TLS_LE_LO12: - /* Relax for LE TLS low part. */ - nds32_elf_relax_letlslo12 (link_info, abfd, irel, contents, - isymbuf, symtab_hdr); - - /* It is impossible to delete blank, so just continue. */ - continue; case R_NDS32_TLS_LE_ADD: - nds32_elf_relax_letlsadd (link_info, abfd, sec, irel, internal_relocs, - contents, isymbuf, symtab_hdr, again); - /* It is impossible to delete blank, so just continue. */ - continue; case R_NDS32_TLS_LE_LS: - nds32_elf_relax_letlsls (link_info, abfd, sec, irel, internal_relocs, - contents, isymbuf, symtab_hdr, again); - continue; - case R_NDS32_PTR: - removed = nds32_elf_relax_ptr (abfd, sec, irel, internal_relocs, - &insn_len, &seq_len, contents); - break; case R_NDS32_PLT_GOT_SUFF: - nds32_elf_relax_pltgot_suff (link_info, abfd, sec, irel, - internal_relocs, contents, - isymbuf, symtab_hdr, again); - /* It is impossible to delete blank, so just continue. */ - continue; case R_NDS32_GOT_SUFF: - nds32_elf_relax_got_suff (link_info, abfd, sec, irel, - internal_relocs, contents, - symtab_hdr, again); - /* It is impossible to delete blank, so just continue. */ - continue; case R_NDS32_GOTOFF_SUFF: - nds32_elf_relax_gotoff_suff (link_info, abfd, sec, irel, - internal_relocs, contents, - isymbuf, symtab_hdr, again); - /* It is impossible to delete blank, so just continue. */ continue; default: continue; - } if (removed && seq_len - insn_len > 0) { @@ -12051,7 +13462,7 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, irelend, isymbuf)) goto error_return; - if (!*again) + if (*again == FALSE) { if (!nds32_fag_remove_unused_fpbase (abfd, sec, internal_relocs, irelend)) @@ -12059,9 +13470,7 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, } } - nds32_elf_pick_relax (FALSE, sec, again, table, link_info); - - if (!*again) + if (*again == FALSE) { if (!nds32_relax_adjust_label (abfd, sec, internal_relocs, contents, &relax_blank_list, optimize, opt_size)) @@ -12078,15 +13487,15 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, relax_blank_list = NULL; } - if (!*again) + if (*again == FALSE) { /* Closing the section, so we don't relax it anymore. */ bfd_vma sec_size_align; Elf_Internal_Rela *tmp_rel; /* Pad to alignment boundary. Only handle current section alignment. */ - sec_size_align = (sec->size + (~((-1U) << sec->alignment_power))) - & ((-1U) << sec->alignment_power); + sec_size_align = (sec->size + (~((bfd_vma)(-1) << sec->alignment_power))) + & ((bfd_vma)(-1) << sec->alignment_power); if ((sec_size_align - sec->size) & 0x2) { insn16 = NDS32_NOP16; @@ -12128,8 +13537,7 @@ error_return: goto finish; } -static struct bfd_elf_special_section const nds32_elf_special_sections[] = -{ +static struct bfd_elf_special_section const nds32_elf_special_sections[] = { {".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE}, {".sbss", 5, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE}, {NULL, 0, 0, 0, 0} @@ -12182,14 +13590,14 @@ bfd_elf32_nds32_set_target_option (struct bfd_link_info *link_info, int eliminate_gc_relocs, FILE * sym_ld_script, int load_store_relax, int target_optimize, int relax_status, - int relax_round, FILE * ex9_export_file, - FILE * ex9_import_file, - int update_ex9_table, int ex9_limit, - bfd_boolean ex9_loop_aware, - bfd_boolean ifc_loop_aware) + int relax_round, int hyper_relax, + int tls_desc_trampoline, char *abi) { struct elf_nds32_link_hash_table *table; + /* Initialize indirect call hash table. */ + nds32_elf_ict_hash_init (); + table = nds32_elf_hash_table (link_info); if (table == NULL) return; @@ -12201,12 +13609,81 @@ bfd_elf32_nds32_set_target_option (struct bfd_link_info *link_info, table->target_optimize = target_optimize; table->relax_status = relax_status; table->relax_round = relax_round; - table->ex9_export_file = ex9_export_file; - table->ex9_import_file = ex9_import_file; - table->update_ex9_table = update_ex9_table; - table->ex9_limit = ex9_limit; - table->ex9_loop_aware = ex9_loop_aware; - table->ifc_loop_aware = ifc_loop_aware; + table->hyper_relax = hyper_relax; + table->tls_desc_trampoline = tls_desc_trampoline; + output_abi = abi; +} + +void +bfd_elf32_nds32_append_section (struct bfd_link_info *link_info, bfd *abfd) +{ + asection *itable; + struct bfd_link_hash_entry *h; + unsigned int i, count = 0; + + /* Count number of indirect call function. */ + indirect_call_table.frozen = 1; + for (i = 0; i < indirect_call_table.size; i++) + { + struct bfd_hash_entry *p; + struct elf_nds32_ict_hash_entry *entry; + + for (p = indirect_call_table.table[i]; p != NULL; p = p->next) + { + entry = (struct elf_nds32_ict_hash_entry *) p; + entry->order = count; + count++; + } + } + indirect_call_table.frozen = 0; + + if (count) + { + h = bfd_link_hash_lookup (link_info->hash, "_INDIRECT_CALL_TABLE_BASE_", + FALSE, FALSE, FALSE); + if (h && (h->type == bfd_link_hash_defined + || h->type == bfd_link_hash_defweak + || h->type == bfd_link_hash_common)) + { + _bfd_error_handler (_("Warning: _INDIRECT_CALL_TABLE_BASE_ has already" + "be defined. All ICT suffix is ignored.")); + ignore_indirect_call = TRUE; + return; + } + + if (ict_model == R_NDS32_RELAX_ENTRY_ICT_LARGE) + itable = bfd_make_section_with_flags (abfd, NDS32_ICT_SECTION, + SEC_DATA | SEC_ALLOC | SEC_LOAD + | SEC_HAS_CONTENTS | SEC_READONLY + | SEC_IN_MEMORY | SEC_KEEP + | SEC_RELOC); + else + itable = bfd_make_section_with_flags (abfd, NDS32_ICT_SECTION, + SEC_CODE | SEC_ALLOC | SEC_LOAD + | SEC_HAS_CONTENTS | SEC_READONLY + | SEC_IN_MEMORY | SEC_KEEP + | SEC_RELOC); + if (itable) + { + itable->gc_mark = 1; + itable->alignment_power = 2; + itable->size = count * 4; + itable->contents = bfd_zalloc (abfd, itable->size); + + /* Add a symbol in the head of .nds32.ict to objdump clearly. */ + h = bfd_link_hash_lookup (link_info->hash, + "_INDIRECT_CALL_TABLE_BASE_", + FALSE, FALSE, FALSE); + _bfd_generic_link_add_one_symbol + (link_info, link_info->output_bfd, "_INDIRECT_CALL_TABLE_BASE_", + BSF_GLOBAL | BSF_WEAK, itable, 0, (const char *) NULL, FALSE, + get_elf_backend_data (link_info->output_bfd)->collect, &h); + } + + ict_file = fopen ("nds32_ict.s", FOPEN_WT); + if(ict_file == NULL) + _bfd_error_handler (_("Warning: Fail to build nds32_ict.s.")); + } } /* These functions and data-structures are used for fp-as-gp @@ -12394,7 +13871,7 @@ nds32_fag_find_base (struct nds32_fag *head, struct nds32_fag **bestpp) static bfd_boolean nds32_fag_mark_relax (struct bfd_link_info *link_info, - bfd *abfd, struct nds32_fag *best_fag, + asection *sec, struct nds32_fag *best_fag, Elf_Internal_Rela *internal_relocs, Elf_Internal_Rela *irelend) { @@ -12402,7 +13879,7 @@ nds32_fag_mark_relax (struct bfd_link_info *link_info, bfd_vma best_fpbase, gp; bfd *output_bfd; - output_bfd = abfd->sections->output_section->owner; + output_bfd = sec->output_section->owner; nds32_elf_final_sda_base (output_bfd, link_info, &gp, FALSE); best_fpbase = best_fag->addr; @@ -12525,7 +14002,6 @@ nds32_relax_fp_as_gp (struct bfd_link_info *link_info, { /* Begin of the region. */ if (begin_rel) - /* xgettext:c-format */ _bfd_error_handler (_("%B: Nested OMIT_FP in %A."), abfd, sec); begin_rel = irel; @@ -12544,7 +14020,6 @@ nds32_relax_fp_as_gp (struct bfd_link_info *link_info, if (begin_rel == NULL) { - /* xgettext:c-format */ _bfd_error_handler (_("%B: Unmatched OMIT_FP in %A."), abfd, sec); continue; } @@ -12557,7 +14032,7 @@ nds32_relax_fp_as_gp (struct bfd_link_info *link_info, /* Check if it is worth, and FP_BASE is near enough to SDA_BASE. */ if (accu < FAG_THRESHOLD - || !nds32_fag_mark_relax (link_info, abfd, best_fag, + || !nds32_fag_mark_relax (link_info, sec, best_fag, internal_relocs, irelend)) { /* Not worth to do fp-as-gp. */ @@ -12811,9 +14286,9 @@ nds32_elf_get_relocated_section_contents (bfd *abfd, case bfd_reloc_dangerous: BFD_ASSERT (error_message != NULL); (*link_info->callbacks->reloc_dangerous) - (link_info, error_message, - input_bfd, input_section, (*parent)->address); - break; + (link_info, error_message, input_bfd, input_section, + (*parent)->address); + break; case bfd_reloc_overflow: (*link_info->callbacks->reloc_overflow) (link_info, NULL, @@ -12827,9 +14302,8 @@ nds32_elf_get_relocated_section_contents (bfd *abfd, complete binaries. Do not abort, but issue an error message instead. */ link_info->callbacks->einfo - /* xgettext:c-format */ (_("%X%P: %B(%A): relocation \"%R\" goes out of range\n"), - abfd, input_section, * parent); + abfd, input_section, *parent); goto error_return; default: @@ -12847,745 +14321,807 @@ error_return: free (reloc_vector); return NULL; } - -/* Link-time IFC relaxation. - In this optimization, we chains jump instructions - of the same destination with ifcall. */ +/* Check target symbol. */ -/* List to save jal and j relocation. */ -struct elf_nds32_ifc_symbol_entry +static bfd_boolean +nds32_elf_is_target_special_symbol (bfd *abfd ATTRIBUTE_UNUSED, asymbol *sym) { - asection *sec; - struct elf_link_hash_entry *h; - struct elf_nds32_ifc_irel_list *irel_head; - unsigned long insn; - int times; - int enable; /* Apply ifc. */ - int ex9_enable; /* Apply ifc after ex9. */ - struct elf_nds32_ifc_symbol_entry *next; -}; + if (!sym || !sym->name || sym->name[0] != '$') + return FALSE; + return TRUE; +} -struct elf_nds32_ifc_irel_list +/* nds32 find maybe function sym. Ignore target special symbol + first, and then go the general function. */ + +static bfd_size_type +nds32_elf_maybe_function_sym (const asymbol *sym, asection *sec, + bfd_vma *code_off) { - Elf_Internal_Rela *irel; - asection *sec; - bfd_vma addr; - /* If this is set, then it is the last instruction for - ifc-chain, so it must be keep for the actual branching. */ - int keep; - struct elf_nds32_ifc_irel_list *next; -}; + if (nds32_elf_is_target_special_symbol (NULL, (asymbol *) sym)) + return 0; -static struct elf_nds32_ifc_symbol_entry *ifc_symbol_head = NULL; + return _bfd_elf_maybe_function_sym (sym, sec, code_off); +} -/* Insert symbol of jal and j for ifc. */ + +/* Do TLS model conversion. */ -static void -nds32_elf_ifc_insert_symbol (asection *sec, - struct elf_link_hash_entry *h, - Elf_Internal_Rela *irel, - unsigned long insn) +typedef struct relax_group_list_t { - struct elf_nds32_ifc_symbol_entry *ptr = ifc_symbol_head; + Elf_Internal_Rela *relo; + struct relax_group_list_t *next; + struct relax_group_list_t *next_sibling; + int id; +} relax_group_list_t; - /* Check there is target of existing entry the same as the new one. */ - while (ptr != NULL) - { - if (((h == NULL && ptr->sec == sec - && ELF32_R_SYM (ptr->irel_head->irel->r_info) == ELF32_R_SYM (irel->r_info) - && ptr->irel_head->irel->r_addend == irel->r_addend) - || h != NULL) - && ptr->h == h - && ptr->insn == insn) - { - /* The same target exist, so insert into list. */ - struct elf_nds32_ifc_irel_list *irel_list = ptr->irel_head; +int +list_insert (relax_group_list_t *pHead, Elf_Internal_Rela *pElem); - while (irel_list->next != NULL) - irel_list = irel_list->next; - irel_list->next = bfd_malloc (sizeof (struct elf_nds32_ifc_irel_list)); - irel_list = irel_list->next; - irel_list->irel = irel; - irel_list->keep = 1; +int +list_insert_sibling (relax_group_list_t *pNode, Elf_Internal_Rela *pElem); - if (h == NULL) - irel_list->sec = NULL; - else - irel_list->sec = sec; - irel_list->next = NULL; - return; - } - if (ptr->next == NULL) - break; - ptr = ptr->next; - } +void +dump_chain (relax_group_list_t *pHead); - /* There is no same target entry, so build a new one. */ - if (ifc_symbol_head == NULL) - { - ifc_symbol_head = bfd_malloc (sizeof (struct elf_nds32_ifc_symbol_entry)); - ptr = ifc_symbol_head; - } - else +int +list_insert (relax_group_list_t *pHead, Elf_Internal_Rela *pElem) +{ + relax_group_list_t *pNext = pHead; + + /* find place */ + while (pNext->next) { - ptr->next = bfd_malloc (sizeof (struct elf_nds32_ifc_symbol_entry)); - ptr = ptr->next; + if (pNext->next->id > (int) pElem->r_addend) + break; + + pNext = pNext->next; } - ptr->h = h; - ptr->irel_head = bfd_malloc (sizeof (struct elf_nds32_ifc_irel_list)); - ptr->irel_head->irel = irel; - ptr->insn = insn; - ptr->irel_head->keep = 1; + /* insert node */ + relax_group_list_t *pNew = bfd_malloc (sizeof (relax_group_list_t)); + if (!pNew) + return FALSE; + + relax_group_list_t *tmp = pNext->next; + pNext->next = pNew; - if (h == NULL) - { - /* Local symbols. */ - ptr->sec = sec; - ptr->irel_head->sec = NULL; - } - else - { - /* Global symbol. */ - ptr->sec = NULL; - ptr->irel_head->sec = sec; - } + pNew->id = pElem->r_addend; + pNew->relo = pElem; + pNew->next = tmp; + pNew->next_sibling = NULL; - ptr->irel_head->next = NULL; - ptr->times = 0; - ptr->enable = 0; - ptr->ex9_enable = 0; - ptr->next = NULL; + return TRUE; } -/* Gather all jal and j instructions. */ - -static bfd_boolean -nds32_elf_ifc_calc (struct bfd_link_info *info, - bfd *abfd, asection *sec) +int +list_insert_sibling (relax_group_list_t *pNode, Elf_Internal_Rela *pElem) { - Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *irelend; - Elf_Internal_Rela *irel; - Elf_Internal_Shdr *symtab_hdr; - bfd_byte *contents = NULL; - uint32_t insn, insn_with_reg; - unsigned long r_symndx; - struct elf_link_hash_entry *h; - struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (abfd); - struct elf_nds32_link_hash_table *table; - bfd_boolean ifc_loop_aware; + relax_group_list_t *pNext = pNode; - internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, - TRUE /* keep_memory */); - irelend = internal_relocs + sec->reloc_count; - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + /* find place */ + while (pNext->next_sibling) + { + pNext = pNext->next_sibling; + } + + /* insert node */ + relax_group_list_t *pNew = bfd_malloc (sizeof (relax_group_list_t)); + if (!pNew) + return FALSE; - /* Check if the object enable ifc. */ - irel = find_relocs_at_address (internal_relocs, internal_relocs, irelend, - R_NDS32_RELAX_ENTRY); + relax_group_list_t *tmp = pNext->next_sibling; + pNext->next_sibling = pNew; - if (irel == NULL - || irel >= irelend - || ELF32_R_TYPE (irel->r_info) != R_NDS32_RELAX_ENTRY - || (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_ENTRY - && !(irel->r_addend & R_NDS32_RELAX_ENTRY_IFC_FLAG))) - return TRUE; + pNew->id = -1; + pNew->relo = pElem; + pNew->next = NULL; + pNew->next_sibling = tmp; - if (!nds32_get_section_contents (abfd, sec, &contents, TRUE)) - return FALSE; + return TRUE; +} - table = nds32_elf_hash_table (info); - ifc_loop_aware = table->ifc_loop_aware; - while (irel != NULL && irel < irelend) +void +dump_chain (relax_group_list_t *pHead) +{ + relax_group_list_t *pNext = pHead->next; + while (pNext) { - /* Traverse all relocation and gather all of them to build the list. */ - - if (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_REGION_BEGIN) + printf("group %d @ 0x%08x", pNext->id, (unsigned)pNext->relo->r_offset); + relax_group_list_t *pNextSib = pNext->next_sibling; + while (pNextSib) { - if (ifc_loop_aware == 1 - && (irel->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG) != 0) - { - /* Check the region if loop or not. If it is true and - ifc-loop-aware is true, ignore the region till region end. */ - while (irel != NULL - && irel < irelend - && (ELF32_R_TYPE (irel->r_info) != R_NDS32_RELAX_REGION_END - || (irel->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG) != 0)) - irel++; - } + printf(", %d", (unsigned) ELF32_R_TYPE (pNextSib->relo->r_info)); + pNextSib = pNextSib->next_sibling; } + pNext = pNext->next; + printf("\n"); + } +} + +/* check R_NDS32_RELAX_GROUP of each section. + there might be multiple sections in one object file. */ +int +elf32_nds32_check_relax_group (bfd *abfd, asection *asec) +{ + elf32_nds32_relax_group_t *relax_group_ptr = + elf32_nds32_relax_group_ptr (abfd); + + int min_id = relax_group_ptr->min_id; + int max_id = relax_group_ptr->max_id; + + Elf_Internal_Rela *rel; + Elf_Internal_Rela *relend; + Elf_Internal_Rela *relocs; + enum elf_nds32_reloc_type rtype; + + do + { + /* Relocations MUST be kept in memory, because relaxation adjust them. */ + relocs = _bfd_elf_link_read_relocs (abfd, asec, NULL, NULL, + TRUE /* keep_memory */); + if (relocs == NULL) + break; - if (ELF32_R_TYPE (irel->r_info) == R_NDS32_25_PCREL_RELA) + /* check R_NDS32_RELAX_GROUP */ + relend = relocs + asec->reloc_count; + for (rel = relocs; rel < relend; rel++) { - insn = bfd_getb32 (contents + irel->r_offset); - nds32_elf_get_insn_with_reg (irel, insn, &insn_with_reg); - r_symndx = ELF32_R_SYM (irel->r_info); - if (r_symndx < symtab_hdr->sh_info) - { - /* Local symbol. */ - nds32_elf_ifc_insert_symbol (sec, NULL, irel, insn_with_reg); - } - else - { - /* External symbol. */ - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - nds32_elf_ifc_insert_symbol (sec, h, irel, insn_with_reg); - } + int id; + rtype = ELF32_R_TYPE (rel->r_info); + if (rtype != R_NDS32_RELAX_GROUP) + continue; + + id = rel->r_addend; + if (id < min_id) + min_id = id; + else if (id > max_id) + max_id = id; } - irel++; } - return TRUE; + while (FALSE); + + if ((relocs != NULL) && (elf_section_data (asec)->relocs != relocs)) + free (relocs); + + if ((min_id != relax_group_ptr->min_id) + || (max_id != relax_group_ptr->max_id)) + { + relax_group_ptr->count = max_id - min_id + 1; + BFD_ASSERT(min_id <= relax_group_ptr->min_id); + relax_group_ptr->min_id = min_id; + BFD_ASSERT(max_id >= relax_group_ptr->max_id); + relax_group_ptr->max_id = max_id; + } + + return relax_group_ptr->count; } -/* Determine whether j and jal should be substituted. */ +/* Reorder RELAX_GROUP ID when command line option '-r' is applied. */ +/* TODO: find a way to free me. */ +struct section_id_list_t *relax_group_section_id_list = NULL; -static void -nds32_elf_ifc_filter (struct bfd_link_info *info) +struct section_id_list_t * +elf32_nds32_lookup_section_id (int id, struct section_id_list_t **lst_ptr) { - struct elf_nds32_ifc_symbol_entry *ptr = ifc_symbol_head; - struct elf_nds32_ifc_irel_list *irel_ptr = NULL; - struct elf_nds32_ifc_irel_list *irel_keeper = NULL; - struct elf_nds32_link_hash_table *table; - int target_optimize; - bfd_vma address; + struct section_id_list_t *result = NULL; + struct section_id_list_t *lst = *lst_ptr; - table = nds32_elf_hash_table (info); - target_optimize = table->target_optimize; - while (ptr) + if (NULL == lst) + { + result = (struct section_id_list_t *) calloc ( + 1, sizeof (struct section_id_list_t)); + BFD_ASSERT (result); /* feed me */ + result->id = id; + *lst_ptr = result; + } + else { - irel_ptr = ptr->irel_head; - if (ptr->h == NULL) + struct section_id_list_t *cur = lst; + struct section_id_list_t *prv = NULL; + struct section_id_list_t *sec = NULL; + while (cur) { - /* Local symbol. */ - irel_keeper = irel_ptr; - while (irel_ptr && irel_ptr->next) + if (cur->id < id) { - /* Check there is jump target can be used. */ - if ((irel_ptr->next->irel->r_offset - - irel_keeper->irel->r_offset) > 1022) - irel_keeper = irel_ptr->next; - else - { - ptr->enable = 1; - irel_ptr->keep = 0; - } - irel_ptr = irel_ptr->next; + prv = cur; + cur = cur->next; + continue; } - } - else - { - /* Global symbol. */ - /* We have to get the absolute address and decide - whether to keep it or not. */ - while (irel_ptr) + + if (cur->id > id) { - address = (irel_ptr->irel->r_offset - + irel_ptr->sec->output_section->vma - + irel_ptr->sec->output_offset); - irel_ptr->addr = address; - irel_ptr = irel_ptr->next; + cur = NULL; /* to insert after prv */ + sec = cur; /* in case prv == NULL */ } - irel_ptr = ptr->irel_head; - while (irel_ptr) - { - /* Sort by address. */ - struct elf_nds32_ifc_irel_list *irel_dest = irel_ptr; - struct elf_nds32_ifc_irel_list *irel_temp = irel_ptr; - struct elf_nds32_ifc_irel_list *irel_ptr_prev = NULL; - struct elf_nds32_ifc_irel_list *irel_dest_prev = NULL; - - /* Get the smallest one. */ - while (irel_temp->next) - { - if (irel_temp->next->addr < irel_dest->addr) - { - irel_dest_prev = irel_temp; - irel_dest = irel_temp->next; - } - irel_temp = irel_temp->next; - } + break; + } - if (irel_dest != irel_ptr) - { - if (irel_ptr_prev) - irel_ptr_prev->next = irel_dest; - if (irel_dest_prev) - irel_dest_prev->next = irel_ptr; - irel_temp = irel_ptr->next; - irel_ptr->next = irel_dest->next; - irel_dest->next = irel_temp; - } - irel_ptr_prev = irel_ptr; - irel_ptr = irel_ptr->next; + if (NULL == cur) + { + /* insert after prv */ + result = (struct section_id_list_t *) calloc ( + 1, sizeof (struct section_id_list_t)); + BFD_ASSERT (result); /* feed me */ + result->id = id; + if (NULL != prv) + { + result->next = prv->next; + prv->next = result; } - - irel_ptr = ptr->irel_head; - irel_keeper = irel_ptr; - while (irel_ptr && irel_ptr->next) + else { - if ((irel_ptr->next->addr - irel_keeper->addr) > 1022) - irel_keeper = irel_ptr->next; - else - { - ptr->enable = 1; - irel_ptr->keep = 0; - } - irel_ptr = irel_ptr->next; + *lst_ptr = result; + result->next = sec; } } - - /* Ex9 enable. Reserve it for ex9. */ - if ((target_optimize & NDS32_RELAX_EX9_ON) - && ptr->irel_head != irel_keeper) - ptr->enable = 0; - ptr = ptr->next; } -} -/* Determine whether j and jal should be substituted after ex9 done. */ + return result; +} -static void -nds32_elf_ifc_filter_after_ex9 (void) +int +elf32_nds32_unify_relax_group (bfd *abfd, asection *asec) { - struct elf_nds32_ifc_symbol_entry *ptr = ifc_symbol_head; - struct elf_nds32_ifc_irel_list *irel_ptr = NULL; + static int next_relax_group_bias = 0; - while (ptr) + elf32_nds32_relax_group_t *relax_group_ptr = + elf32_nds32_relax_group_ptr (abfd); + + bfd_boolean result = TRUE; + Elf_Internal_Rela *rel; + Elf_Internal_Rela *relend; + Elf_Internal_Rela *relocs = NULL; + enum elf_nds32_reloc_type rtype; + struct section_id_list_t *node = NULL; + int count = 0; + + do { - if (ptr->enable == 0) + if (0 == relax_group_ptr->count) + break; + + /* check if this section has handled */ + node = elf32_nds32_lookup_section_id (asec->id, &relax_group_section_id_list); + if (NULL == node) + break; /* hit, the section id has handled. */ + + /* Relocations MUST be kept in memory, because relaxation adjust them. */ + relocs = _bfd_elf_link_read_relocs (abfd, asec, NULL, NULL, + TRUE /* keep_memory */); + if (relocs == NULL) { - /* Check whether ifc is applied or not. */ - irel_ptr = ptr->irel_head; - ptr->ex9_enable = 1; - while (irel_ptr) - { - if (ELF32_R_TYPE (irel_ptr->irel->r_info) == R_NDS32_TRAN) - { - /* Ex9 already. */ - ptr->ex9_enable = 0; - break; - } - irel_ptr = irel_ptr->next; - } + BFD_ASSERT (0); /* feed me */ + break; } - ptr = ptr->next; - } -} - -/* Wrapper to do ifc relaxation. */ -bfd_boolean -nds32_elf_ifc_finish (struct bfd_link_info *info) -{ - int relax_status; - struct elf_nds32_link_hash_table *table; + /* allocate group id bias for this bfd! */ + if (0 == relax_group_ptr->init) + { + relax_group_ptr->bias = next_relax_group_bias; + next_relax_group_bias += relax_group_ptr->count; + relax_group_ptr->init = 1; + } - table = nds32_elf_hash_table (info); - relax_status = table->relax_status; + /* reorder relax group groups */ + relend = relocs + asec->reloc_count; + for (rel = relocs; rel < relend; rel++) + { + rtype = ELF32_R_TYPE(rel->r_info); + if (rtype != R_NDS32_RELAX_GROUP) + continue; - if (!(relax_status & NDS32_RELAX_JUMP_IFC_DONE)) - nds32_elf_ifc_filter (info); - else - nds32_elf_ifc_filter_after_ex9 (); + /* change it */ + rel->r_addend += relax_group_ptr->bias; + /* debugging count */ + count++; + } + } + while (FALSE); - if (!nds32_elf_ifc_replace (info)) - return FALSE; + if (relocs != NULL && elf_section_data (asec)->relocs != relocs) + free (relocs); - if (table) - table->relax_status |= NDS32_RELAX_JUMP_IFC_DONE; - return TRUE; + return result; } -/* Traverse the result of ifc filter and replace it with ifcall9. */ - -static bfd_boolean -nds32_elf_ifc_replace (struct bfd_link_info *info) +int +nds32_elf_unify_tls_model (bfd *inbfd, asection *insec, bfd_byte *incontents, + struct bfd_link_info *lnkinfo) { - struct elf_nds32_ifc_symbol_entry *ptr = ifc_symbol_head; - struct elf_nds32_ifc_irel_list *irel_ptr = NULL; - nds32_elf_blank_t *relax_blank_list = NULL; - bfd_byte *contents = NULL; - Elf_Internal_Rela *internal_relocs; + bfd_boolean result = TRUE; Elf_Internal_Rela *irel; Elf_Internal_Rela *irelend; - unsigned short insn16 = INSN_IFCALL9; - struct elf_nds32_link_hash_table *table; - int relax_status; + Elf_Internal_Rela *internal_relocs; + unsigned long r_symndx; + enum elf_nds32_reloc_type r_type; - table = nds32_elf_hash_table (info); - relax_status = table->relax_status; + Elf_Internal_Sym *local_syms = NULL; + bfd_byte *contents = NULL; + + relax_group_list_t chain = { .id = -1, .next = NULL, .next_sibling = NULL }; + + Elf_Internal_Shdr *symtab_hdr = &elf_tdata (inbfd)->symtab_hdr; + struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; + sym_hashes = elf_sym_hashes (inbfd); + sym_hashes_end = + sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym); + if (!elf_bad_symtab (inbfd)) + sym_hashes_end -= symtab_hdr->sh_info; + + /* reorder RELAX_GROUP when command line option '-r' is applied */ + if (bfd_link_relocatable (lnkinfo)) + { + elf32_nds32_unify_relax_group (inbfd, insec); + /* goto finish; */ + return result; + } + + /* Relocations MUST be kept in memory, because relaxation adjust them. */ + internal_relocs = _bfd_elf_link_read_relocs (inbfd, insec, NULL, NULL, + TRUE /* keep_memory */); + if (internal_relocs == NULL) + goto error_return; + + irelend = internal_relocs + insec->reloc_count; + irel = find_relocs_at_address (internal_relocs, internal_relocs, + irelend, R_NDS32_RELAX_ENTRY); + if (irel == irelend) + goto finish; + + /* chain/remove groups */ + for (irel = internal_relocs; irel < irelend; irel++) + { + r_symndx = ELF32_R_SYM (irel->r_info); + r_type = ELF32_R_TYPE (irel->r_info); + if (r_type != R_NDS32_RELAX_GROUP) + continue; + + /* remove it */ + irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_NONE); + /* chain it now */ + if (!list_insert (&chain, irel)) + goto error_return; + } - while (ptr) + /* collect group relocations */ + /* presume relocations are sorted */ + relax_group_list_t *pNext = chain.next; + while (pNext) { - /* Traverse the ifc gather list, and replace the - filter entries by ifcall9. */ - if ((!(relax_status & NDS32_RELAX_JUMP_IFC_DONE) && ptr->enable == 1) - || ((relax_status & NDS32_RELAX_JUMP_IFC_DONE) - && ptr->ex9_enable == 1)) + for (irel = internal_relocs; irel < irelend; irel++) { - irel_ptr = ptr->irel_head; - if (ptr->h == NULL) + if (irel->r_offset == pNext->relo->r_offset) { - /* Local symbol. */ - internal_relocs = _bfd_elf_link_read_relocs - (ptr->sec->owner, ptr->sec, NULL, NULL, TRUE /* keep_memory */); - irelend = internal_relocs + ptr->sec->reloc_count; - - if (!nds32_get_section_contents (ptr->sec->owner, ptr->sec, - &contents, TRUE)) - return FALSE; + /* ignore Non-TLS relocation types */ + r_type = ELF32_R_TYPE (irel->r_info); + if ((R_NDS32_TLS_LE_HI20 > r_type) + || (R_NDS32_RELAX_ENTRY == r_type)) + continue; - while (irel_ptr) - { - if (irel_ptr->keep == 0 && irel_ptr->next) - { - /* The one can be replaced. We have to check whether - there is any alignment point in the region. */ - irel = irel_ptr->irel; - while (((irel_ptr->next->keep == 0 - && irel < irel_ptr->next->irel) - || (irel_ptr->next->keep == 1 && irel < irelend)) - && !(ELF32_R_TYPE (irel->r_info) == R_NDS32_LABEL - && (irel->r_addend & 0x1f) == 2)) - irel++; - if (irel >= irelend - || !(ELF32_R_TYPE (irel->r_info) == R_NDS32_LABEL - && (irel->r_addend & 0x1f) == 2 - && ((irel->r_offset - get_nds32_elf_blank_total - (&relax_blank_list, irel->r_offset, 1)) - & 0x02) == 0)) - { - /* Replace by ifcall9. */ - bfd_putb16 (insn16, contents + irel_ptr->irel->r_offset); - if (!insert_nds32_elf_blank_recalc_total - (&relax_blank_list, irel_ptr->irel->r_offset + 2, 2)) - return FALSE; - irel_ptr->irel->r_info = - ELF32_R_INFO (ELF32_R_SYM (irel_ptr->irel->r_info), - R_NDS32_10IFCU_PCREL_RELA); - } - } - irel_ptr = irel_ptr->next; - } + if (!list_insert_sibling (pNext, irel)) + goto error_return; + } + else if (irel->r_offset > pNext->relo->r_offset) + { + pNext = pNext->next; + if (!pNext) + break; - /* Delete the redundant code. */ - if (relax_blank_list) - { - nds32_elf_relax_delete_blanks (ptr->sec->owner, ptr->sec, - relax_blank_list); - relax_blank_list = NULL; - } + bfd_vma current_offset = pNext->relo->r_offset; + if (irel->r_offset > current_offset) + irel = internal_relocs; /* restart from head */ + else + --irel; /* check current irel again */ + continue; } else { - /* Global symbol. */ - while (irel_ptr) - { - if (irel_ptr->keep == 0 && irel_ptr->next) - { - /* The one can be replaced, and we have to check - whether there is any alignment point in the region. */ - internal_relocs = _bfd_elf_link_read_relocs - (irel_ptr->sec->owner, irel_ptr->sec, NULL, NULL, - TRUE /* keep_memory */); - irelend = internal_relocs + irel_ptr->sec->reloc_count; - if (!nds32_get_section_contents (irel_ptr->sec->owner, - irel_ptr->sec, &contents, - TRUE)) - return FALSE; - - irel = irel_ptr->irel; - while (((irel_ptr->sec == irel_ptr->next->sec - && irel_ptr->next->keep == 0 - && irel < irel_ptr->next->irel) - || ((irel_ptr->sec != irel_ptr->next->sec - || irel_ptr->next->keep == 1) - && irel < irelend)) - && !(ELF32_R_TYPE (irel->r_info) == R_NDS32_LABEL - && (irel->r_addend & 0x1f) == 2)) - irel++; - if (irel >= irelend - || !(ELF32_R_TYPE (irel->r_info) == R_NDS32_LABEL - && (irel->r_addend & 0x1f) == 2 - && ((irel->r_offset - - get_nds32_elf_blank_total (&relax_blank_list, - irel->r_offset, 1)) & 0x02) == 0)) - { - /* Replace by ifcall9. */ - bfd_putb16 (insn16, contents + irel_ptr->irel->r_offset); - if (!insert_nds32_elf_blank_recalc_total - (&relax_blank_list, irel_ptr->irel->r_offset + 2, 2)) - return FALSE; - - /* Delete the redundant code, and clear the relocation. */ - nds32_elf_relax_delete_blanks (irel_ptr->sec->owner, - irel_ptr->sec, - relax_blank_list); - irel_ptr->irel->r_info = - ELF32_R_INFO (ELF32_R_SYM (irel_ptr->irel->r_info), - R_NDS32_10IFCU_PCREL_RELA); - relax_blank_list = NULL; - } - } - - irel_ptr = irel_ptr->next; - } + //printf("irel->off = 0x%08x, pNext->relo->off = 0x%08x (0x%08x)\n", (unsigned)irel->r_offset, (unsigned)pNext->relo->r_offset, (unsigned)first_offset); } } - ptr = ptr->next; + if (pNext) + pNext = pNext->next; } - return TRUE; -} - -/* Relocate ifcall. */ - -static bfd_boolean -nds32_elf_ifc_reloc (void) -{ - struct elf_nds32_ifc_symbol_entry *ptr = ifc_symbol_head; - struct elf_nds32_ifc_irel_list *irel_ptr = NULL; - struct elf_nds32_ifc_irel_list *irel_keeper = NULL; - bfd_vma relocation, address; - unsigned short insn16; - bfd_byte *contents = NULL; - static bfd_boolean done = FALSE; +#ifdef DUBUG_VERBOSE + dump_chain(&chain); +#endif - if (done) - return TRUE; + /* Get symbol table and section content. */ + if (incontents) + contents = incontents; + else if (!nds32_get_section_contents (inbfd, insec, &contents, TRUE) + || !nds32_get_local_syms (inbfd, insec, &local_syms)) + goto error_return; - done = TRUE; + char *local_got_tls_type = elf32_nds32_local_got_tls_type (inbfd); - while (ptr) + /* convert TLS model each group if necessary */ + pNext = chain.next; + int cur_grp_id = -1; + int sethi_rt = -1; + int add_rt = -1; + enum elf_nds32_tls_type tls_type, org_tls_type, eff_tls_type; + tls_type = org_tls_type = eff_tls_type = 0; + while (pNext) { - /* Check the entry is enable ifcall. */ - if (ptr->enable == 1 || ptr->ex9_enable == 1) + relax_group_list_t *pNextSig = pNext->next_sibling; + while (pNextSig) { - /* Get the reserve jump. */ - irel_ptr = ptr->irel_head; - while (irel_ptr) + struct elf_link_hash_entry *h = NULL; + irel = pNextSig->relo; + r_symndx = ELF32_R_SYM(irel->r_info); + r_type = ELF32_R_TYPE(irel->r_info); + + if (pNext->id != cur_grp_id) { - if (irel_ptr->keep == 1) + cur_grp_id = pNext->id; + org_tls_type = get_tls_type (r_type, NULL); + if (r_symndx >= symtab_hdr->sh_info) { - irel_keeper = irel_ptr; - break; + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + tls_type = ((struct elf_nds32_link_hash_entry *) h)->tls_type; + } + else + { + /* TODO: find local symbol hash if necessary? */ + tls_type = local_got_tls_type ? local_got_tls_type[r_symndx] : GOT_NORMAL; } - irel_ptr = irel_ptr->next; + + eff_tls_type = 1 << (fls (tls_type) - 1); + sethi_rt = N32_RT5(bfd_getb32 (contents + irel->r_offset)); } - irel_ptr = ptr->irel_head; - if (ptr->h == NULL) + if (eff_tls_type != org_tls_type) { - /* Local symbol. */ - if (!nds32_get_section_contents (ptr->sec->owner, ptr->sec, - &contents, TRUE)) - return FALSE; - - while (irel_ptr) + switch (org_tls_type) { - if (irel_ptr->keep == 0 - && ELF32_R_TYPE (irel_ptr->irel->r_info) == R_NDS32_10IFCU_PCREL_RELA) + /* DESC to IEGP/IE/LE. */ + case GOT_TLS_DESC: + switch (eff_tls_type) { - relocation = irel_keeper->irel->r_offset; - relocation = relocation - irel_ptr->irel->r_offset; - while (irel_keeper && relocation > 1022) + case GOT_TLS_IE: + switch (r_type) { - irel_keeper = irel_keeper->next; - if (irel_keeper && irel_keeper->keep == 1) - { - relocation = irel_keeper->irel->r_offset; - relocation = relocation - irel_ptr->irel->r_offset; - } + case R_NDS32_TLS_DESC_HI20: + irel->r_info = ELF32_R_INFO(r_symndx, + R_NDS32_TLS_IE_HI20); + break; + case R_NDS32_TLS_DESC_LO12: + irel->r_info = ELF32_R_INFO(r_symndx, + R_NDS32_TLS_IE_LO12); + break; + case R_NDS32_TLS_DESC_ADD: + { + uint32_t insn = bfd_getb32 ( + contents + irel->r_offset); + add_rt = N32_RT5 (insn); + insn = N32_TYPE2 (LWI, add_rt, sethi_rt, 0); + bfd_putb32 (insn, contents + irel->r_offset); + + irel->r_info = ELF32_R_INFO(r_symndx, R_NDS32_NONE); +/* irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_IE_LW); +*/ + } + break; + case R_NDS32_TLS_DESC_FUNC: + bfd_putb32 (INSN_NOP, contents + irel->r_offset); + irel->r_info = ELF32_R_INFO(r_symndx, + R_NDS32_RELAX_REMOVE); + break; + case R_NDS32_TLS_DESC_CALL: + { + uint32_t insn = N32_ALU1(ADD, REG_R0, add_rt, + REG_TP); + bfd_putb32 (insn, contents + irel->r_offset); + + irel->r_info = ELF32_R_INFO(r_symndx, R_NDS32_NONE); + } + break; + case R_NDS32_LOADSTORE: + case R_NDS32_PTR: + case R_NDS32_PTR_RESOLVED: + case R_NDS32_NONE: + case R_NDS32_LABEL: + break; + default: + BFD_ASSERT(0); + break; } - if (relocation > 1022) + break; + case GOT_TLS_IEGP: + switch (r_type) { - /* Double check. */ - irel_keeper = ptr->irel_head; - while (irel_keeper) - { - if (irel_keeper->keep == 1) - { - relocation = irel_keeper->irel->r_offset; - relocation = relocation - irel_ptr->irel->r_offset; - } - if (relocation <= 1022) - break; - irel_keeper = irel_keeper->next; - } - if (!irel_keeper) - return FALSE; + case R_NDS32_TLS_DESC_HI20: + irel->r_info = ELF32_R_INFO(r_symndx, + R_NDS32_TLS_IEGP_HI20); + break; + case R_NDS32_TLS_DESC_LO12: + irel->r_info = ELF32_R_INFO(r_symndx, + R_NDS32_TLS_IEGP_LO12); + break; + case R_NDS32_TLS_DESC_ADD: + { + uint32_t insn = bfd_getb32 ( + contents + irel->r_offset); + add_rt = N32_RT5 (insn); + insn = N32_MEM(LW, add_rt, sethi_rt, REG_GP, 0); + bfd_putb32 (insn, contents + irel->r_offset); + + irel->r_info = ELF32_R_INFO(r_symndx, R_NDS32_NONE); +/* irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_IEGP_LW); +*/ + } + break; + case R_NDS32_TLS_DESC_FUNC: + bfd_putb32 (INSN_NOP, contents + irel->r_offset); + irel->r_info = ELF32_R_INFO(r_symndx, + R_NDS32_RELAX_REMOVE); + break; + case R_NDS32_TLS_DESC_CALL: + { + uint32_t insn = N32_ALU1(ADD, REG_R0, add_rt, + REG_TP); + bfd_putb32 (insn, contents + irel->r_offset); + + irel->r_info = ELF32_R_INFO(r_symndx, R_NDS32_NONE); + } + break; + case R_NDS32_LOADSTORE: + case R_NDS32_PTR: + case R_NDS32_PTR_RESOLVED: + case R_NDS32_NONE: + case R_NDS32_LABEL: + break; + default: + BFD_ASSERT(0); + break; } - irel_ptr->irel->r_info = - ELF32_R_INFO (ELF32_R_SYM (irel_ptr->irel->r_info), - R_NDS32_NONE); - insn16 = INSN_IFCALL9 | (relocation >> 1); - bfd_putb16 (insn16, contents + irel_ptr->irel->r_offset); + break; + case GOT_TLS_LE: + switch (r_type) + { + case R_NDS32_TLS_DESC_HI20: + irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_LE_HI20); + break; + case R_NDS32_TLS_DESC_LO12: + irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_LE_LO12); + break; + case R_NDS32_TLS_DESC_ADD: + { + uint32_t insn = bfd_getb32 (contents + irel->r_offset); + add_rt = N32_RT5 (insn); + insn = N32_ALU1 (ADD, REG_R0, sethi_rt, REG_TP); + bfd_putb32 (insn, contents + irel->r_offset); + + irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_LE_ADD); + } + break; + case R_NDS32_TLS_DESC_FUNC: + bfd_putb32 (INSN_NOP, contents + irel->r_offset); + irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_RELAX_REMOVE); + break; + case R_NDS32_TLS_DESC_CALL: + bfd_putb32 (INSN_NOP, contents + irel->r_offset); + irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_RELAX_REMOVE); + break; + case R_NDS32_LOADSTORE: + case R_NDS32_PTR: + case R_NDS32_PTR_RESOLVED: + case R_NDS32_NONE: + case R_NDS32_LABEL: + break; + default: + BFD_ASSERT(0); + break; + } + break; + default: +#ifdef DEBUG_VERBOSE + printf ( + "SKIP: %s: %s @ 0x%08x tls_type = 0x%08x, eff_tls_type = 0x%08x, org_tls_type = 0x%08x\n", + inbfd->filename, h ? h->root.root.string : "local", + (unsigned) irel->r_offset, tls_type, eff_tls_type, + org_tls_type); +#endif + break; } - irel_ptr = irel_ptr->next; - } - } - else - { - /* Global symbol. */ - while (irel_ptr) - { - if (irel_ptr->keep == 0 - && ELF32_R_TYPE (irel_ptr->irel->r_info) == R_NDS32_10IFCU_PCREL_RELA) + break; + /* IEGP to IE/LE. */ + case GOT_TLS_IEGP: + switch (eff_tls_type) { - /* Get the distance between ifcall and jump. */ - relocation = (irel_keeper->irel->r_offset - + irel_keeper->sec->output_section->vma - + irel_keeper->sec->output_offset); - address = (irel_ptr->irel->r_offset - + irel_ptr->sec->output_section->vma - + irel_ptr->sec->output_offset); - relocation = relocation - address; - - /* The distance is over ragne, find callee again. */ - while (irel_keeper && relocation > 1022) + case GOT_TLS_IE: + switch (r_type) { - irel_keeper = irel_keeper->next; - if (irel_keeper && irel_keeper->keep ==1) - { - relocation = (irel_keeper->irel->r_offset - + irel_keeper->sec->output_section->vma - + irel_keeper->sec->output_offset); - relocation = relocation - address; - } + case R_NDS32_TLS_IEGP_HI20: + irel->r_info = ELF32_R_INFO(r_symndx, + R_NDS32_TLS_IE_HI20); + break; + case R_NDS32_TLS_IEGP_LO12: + irel->r_info = ELF32_R_INFO(r_symndx, + R_NDS32_TLS_IE_LO12); + break; + case R_NDS32_PTR_RESOLVED: + { + uint32_t insn = bfd_getb32 ( + contents + irel->r_offset); + add_rt = N32_RT5 (insn); + insn = N32_TYPE2 (LWI, add_rt, sethi_rt, 0); + bfd_putb32 (insn, contents + irel->r_offset); + } + break; + case R_NDS32_TLS_IEGP_LW: + break; + case R_NDS32_LOADSTORE: + case R_NDS32_PTR: + case R_NDS32_NONE: + case R_NDS32_LABEL: + break; + default: + BFD_ASSERT(0); + break; } - - if (relocation > 1022) + break; + case GOT_TLS_LE: + switch (r_type) { - /* Double check. */ - irel_keeper = ptr->irel_head; - while (irel_keeper) - { - if (irel_keeper->keep == 1) - { - - relocation = (irel_keeper->irel->r_offset - + irel_keeper->sec->output_section->vma - + irel_keeper->sec->output_offset); - relocation = relocation - address; - } - if (relocation <= 1022) - break; - irel_keeper = irel_keeper->next; - } - if (!irel_keeper) - return FALSE; + case R_NDS32_TLS_IEGP_HI20: + irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_LE_HI20); + break; + case R_NDS32_TLS_IEGP_LO12: + irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_LE_LO12); + break; + case R_NDS32_TLS_IEGP_LW: + /* irel->r_info = ELF32_R_INFO(r_symndx, R_NDS32_TLS_LE_ADD); */ + bfd_putb32 (INSN_NOP, contents + irel->r_offset); + irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_RELAX_REMOVE); + break; + case R_NDS32_LOADSTORE: + case R_NDS32_PTR: + case R_NDS32_NONE: + case R_NDS32_LABEL: + case R_NDS32_PTR_RESOLVED: + break; + default: + BFD_ASSERT(0); + break; } - if (!nds32_get_section_contents - (irel_ptr->sec->owner, irel_ptr->sec, &contents, TRUE)) - return FALSE; - insn16 = INSN_IFCALL9 | (relocation >> 1); - bfd_putb16 (insn16, contents + irel_ptr->irel->r_offset); - irel_ptr->irel->r_info = - ELF32_R_INFO (ELF32_R_SYM (irel_ptr->irel->r_info), - R_NDS32_NONE); + break; + default: +#ifdef DEBUG_VERBOSE + printf ( + "SKIP: %s: %s @ 0x%08x tls_type = 0x%08x, eff_tls_type = 0x%08x, org_tls_type = 0x%08x\n", + inbfd->filename, h ? h->root.root.string : "local", + (unsigned) irel->r_offset, tls_type, eff_tls_type, + org_tls_type); +#endif + break; + } + break; + /* IE to LE. */ + case GOT_TLS_IE: + switch (eff_tls_type) + { + case GOT_TLS_LE: + switch (r_type) + { + case R_NDS32_TLS_IE_HI20: + irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_LE_HI20); + break; + case R_NDS32_TLS_IE_LO12S2: + { + uint32_t insn = bfd_getb32 (contents + irel->r_offset); + add_rt = N32_RT5 (insn); + insn = N32_TYPE2 (ORI, add_rt, sethi_rt, 0); + bfd_putb32 (insn, contents + irel->r_offset); + + irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_LE_LO12); + } + break; + /* + case R_NDS32_TLS_IE_ADD: + irel->r_info = ELF32_R_INFO (r_symndx, R_NDS32_TLS_LE_ADD); + break; + */ + case R_NDS32_LOADSTORE: + case R_NDS32_PTR: + case R_NDS32_NONE: + case R_NDS32_LABEL: + break; + default: + BFD_ASSERT(0); + break; + } + break; + default: +#ifdef DEBUG_VERBOSE + printf ( + "SKIP: %s: %s @ 0x%08x tls_type = 0x%08x, eff_tls_type = 0x%08x, org_tls_type = 0x%08x\n", + inbfd->filename, h ? h->root.root.string : "local", + (unsigned) irel->r_offset, tls_type, eff_tls_type, + org_tls_type); +#endif + break; } - irel_ptr =irel_ptr->next; + break; + default: +#ifdef DEBUG_VERBOSE + printf ( + "SKIP: %s: %s @ 0x%08x tls_type = 0x%08x, eff_tls_type = 0x%08x, org_tls_type = 0x%08x\n", + inbfd->filename, h ? h->root.root.string : "local", + (unsigned) irel->r_offset, tls_type, eff_tls_type, + org_tls_type); +#endif + break; } } + pNextSig = pNextSig->next_sibling; } - ptr = ptr->next; - } - - return TRUE; -} -/* End of IFC relaxation. */ - -/* EX9 Instruction Table Relaxation. */ +#if 1 + pNext = pNext->next; +#else + while (pNext) + { + if (pNext->id != cur_grp_id) + break; + pNext = pNext->next; + } +#endif + } -/* Global hash list. */ -struct elf_link_hash_entry_list -{ - struct elf_link_hash_entry *h; - struct elf_link_hash_entry_list *next; -}; +finish: + if (incontents) + contents = NULL; -/* Save different destination but same insn. */ -struct elf_link_hash_entry_mul_list -{ - /* Global symbol times. */ - int times; - /* Save relocation for each global symbol but useful?? */ - Elf_Internal_Rela *irel; - /* For sethi, two sethi may have the same high-part but different low-parts. */ - Elf_Internal_Rela rel_backup; - struct elf_link_hash_entry_list *h_list; - struct elf_link_hash_entry_mul_list *next; -}; + if (internal_relocs != NULL + && elf_section_data (insec)->relocs != internal_relocs) + free (internal_relocs); -/* Instruction hash table. */ -struct elf_nds32_code_hash_entry -{ - struct bfd_hash_entry root; - int times; - /* For insn that can use relocation or constant ex: sethi. */ - int const_insn; - asection *sec; - struct elf_link_hash_entry_mul_list *m_list; - /* Using r_addend. */ - Elf_Internal_Rela *irel; - /* Using r_info. */ - Elf_Internal_Rela rel_backup; -}; + if (contents != NULL + && elf_section_data (insec)->this_hdr.contents != contents) + free (contents); -/* Instruction count list. */ -struct elf_nds32_insn_times_entry -{ - const char *string; - int times; - int order; - asection *sec; - struct elf_link_hash_entry_mul_list *m_list; - Elf_Internal_Rela *irel; - Elf_Internal_Rela rel_backup; - struct elf_nds32_insn_times_entry *next; -}; + if (local_syms != NULL && symtab_hdr->contents != (bfd_byte *) local_syms) + free (local_syms); -/* J and JAL symbol list. */ -struct elf_nds32_symbol_entry -{ - char *string; - unsigned long insn; - struct elf_nds32_symbol_entry *next; -}; + if (chain.next) + { + pNext = chain.next; + relax_group_list_t *pDel; + while (pNext) + { + pDel = pNext; + pNext = pNext->next; + free (pDel); + } + } -/* Relocation list. */ -struct elf_nds32_irel_entry -{ - Elf_Internal_Rela *irel; - struct elf_nds32_irel_entry *next; -}; + return result; -/* ex9.it insn need to be fixed. */ -struct elf_nds32_ex9_refix -{ - Elf_Internal_Rela *irel; - asection *sec; - struct elf_link_hash_entry *h; - int order; - struct elf_nds32_ex9_refix *next; -}; +error_return: + result = FALSE; + goto finish; +} -static struct bfd_hash_table ex9_code_table; -static struct elf_nds32_insn_times_entry *ex9_insn_head = NULL; -static struct elf_nds32_ex9_refix *ex9_refix_head = NULL; +/* End TLS model conversion. */ + -/* EX9 hash function. */ +/* Rom-patch table hash function. */ static struct bfd_hash_entry * -nds32_elf_code_hash_newfunc (struct bfd_hash_entry *entry, - struct bfd_hash_table *table, - const char *string) +nds32_elf_ict_hash_newfunc (struct bfd_hash_entry *entry, + struct bfd_hash_table *table, + const char *string) { - struct elf_nds32_code_hash_entry *ret; + struct elf_nds32_ict_hash_entry *ret; /* Allocate the structure if it has not already been allocated by a subclass. */ @@ -13602,1837 +15138,118 @@ nds32_elf_code_hash_newfunc (struct bfd_hash_entry *entry, if (entry == NULL) return entry; - ret = (struct elf_nds32_code_hash_entry*) entry; - ret->times = 0; - ret->const_insn = 0; - ret->m_list = NULL; - ret->sec = NULL; - ret->irel = NULL; + ret = (struct elf_nds32_ict_hash_entry*) entry; + ret->order = 0; return &ret->root; } -/* Insert ex9 entry - this insert must be stable sorted by times. */ +static void +nds32_elf_ict_hash_init (void) +{ + if (!bfd_hash_table_init_n (&indirect_call_table, nds32_elf_ict_hash_newfunc, + sizeof (struct elf_nds32_ict_hash_entry), + 1023)) + _bfd_error_handler (_("ld error: cannot init rom patch hash table\n")); + return; +} +/* Relocate for NDS32_ICT_SECTION. */ static void -nds32_elf_ex9_insert_entry (struct elf_nds32_insn_times_entry *ptr) +nds32_elf_ict_relocate (bfd *output_bfd, struct bfd_link_info *info) { - struct elf_nds32_insn_times_entry *temp; - struct elf_nds32_insn_times_entry *temp2; + static bfd_boolean done = FALSE; + asection *sec; + bfd_byte *contents = NULL; + uint32_t insn; + unsigned int i; + struct elf_link_hash_entry *h; + struct bfd_link_hash_entry *h2; + bfd_vma relocation, base; - if (ex9_insn_head == NULL) - { - ex9_insn_head = ptr; - ptr->next = NULL; - } - else + if (done) + return; + + done = TRUE; + + sec = nds32_elf_get_target_section (info, NDS32_ICT_SECTION); + h2 = bfd_link_hash_lookup (info->hash, "_INDIRECT_CALL_TABLE_BASE_", + FALSE, FALSE, FALSE); + base = ((h2->u.def.value + + h2->u.def.section->output_section->vma + + h2->u.def.section->output_offset)); + + if (!nds32_get_section_contents (sec->owner, sec, &contents, TRUE)) + return; + + indirect_call_table.frozen = 1; + for (i = 0; i < indirect_call_table.size; i++) { - temp = ex9_insn_head; - temp2 = ex9_insn_head; - while (temp->next && - (temp->next->times >= ptr->times - || temp->times == -1)) - { - if (temp->times == -1) - temp2 = temp; - temp = temp->next; - } - if (ptr->times > temp->times && temp->times != -1) + struct bfd_hash_entry *p; + struct elf_nds32_ict_hash_entry *entry; + + for (p = indirect_call_table.table[i]; p != NULL; p = p->next) { - ptr->next = temp; - if (temp2->times == -1) - temp2->next = ptr; + entry = (struct elf_nds32_ict_hash_entry *) p; + insn = INSN_J; + h = entry->h; + if ((h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && h->root.u.def.section != NULL + && h->root.u.def.section->output_section != NULL) + { + if (ict_model == R_NDS32_RELAX_ENTRY_ICT_LARGE) + { + insn = h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset; + bfd_put_32 (output_bfd, insn, contents + (entry->order) * 4); + } + else + { + relocation = h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset; + insn |= ((relocation - base - entry->order * 4) >> 1) + & 0xffffff; + bfd_putb32 (insn, contents + (entry->order) * 4); + } + } else - ex9_insn_head = ptr; - } - else if (temp->next == NULL) - { - temp->next = ptr; - ptr->next = NULL; - } - else - { - ptr->next = temp->next; - temp->next = ptr; + { + if (ict_model == R_NDS32_RELAX_ENTRY_ICT_LARGE) + { + insn = 0; + bfd_put_32 (output_bfd, insn, contents + (entry->order) * 4); + } + else + bfd_putb32 (insn, contents + (entry->order) * 4); + } } } + indirect_call_table.frozen = 0; } -/* Examine each insn times in hash table. - Handle multi-link hash entry. - - TODO: This function doesn't assign so much info since it is fake. */ - -static int -nds32_elf_examine_insn_times (struct elf_nds32_code_hash_entry *h) +static asection* +nds32_elf_get_target_section (struct bfd_link_info *info, char *name) { - struct elf_nds32_insn_times_entry *ptr; - int times; + asection *sec = NULL; + bfd *abfd; - if (h->m_list == NULL) + for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next) { - /* Local symbol insn or insn without relocation. */ - if (h->times < 3) - return TRUE; - - ptr = (struct elf_nds32_insn_times_entry *) - bfd_malloc (sizeof (struct elf_nds32_insn_times_entry)); - ptr->times = h->times; - ptr->string = h->root.string; - ptr->m_list = NULL; - ptr->sec = h->sec; - ptr->irel = h->irel; - ptr->rel_backup = h->rel_backup; - nds32_elf_ex9_insert_entry (ptr); + sec = bfd_get_section_by_name (abfd, name); + if (sec != NULL) + break; } - else - { - /* Global symbol insn. */ - /* Only sethi insn has multiple m_list. */ - struct elf_link_hash_entry_mul_list *m_list = h->m_list; - times = 0; - while (m_list) - { - times += m_list->times; - m_list = m_list->next; - } - if (times >= 3) - { - m_list = h->m_list; - ptr = (struct elf_nds32_insn_times_entry *) - bfd_malloc (sizeof (struct elf_nds32_insn_times_entry)); - ptr->times = times; /* Use the total times. */ - ptr->string = h->root.string; - ptr->m_list = m_list; - ptr->sec = h->sec; - ptr->irel = m_list->irel; - ptr->rel_backup = m_list->rel_backup; - nds32_elf_ex9_insert_entry (ptr); - } - if (h->const_insn == 1) - { - /* sethi with constant value. */ - if (h->times < 3) - return TRUE; - - ptr = (struct elf_nds32_insn_times_entry *) - bfd_malloc (sizeof (struct elf_nds32_insn_times_entry)); - ptr->times = h->times; - ptr->string = h->root.string; - ptr->m_list = NULL; - ptr->sec = NULL; - ptr->irel = NULL; - ptr->rel_backup = h->rel_backup; - nds32_elf_ex9_insert_entry (ptr); - } - } - return TRUE; -} - -/* Count each insn times in hash table. - Handle multi-link hash entry. */ - -static int -nds32_elf_count_insn_times (struct elf_nds32_code_hash_entry *h) -{ - int reservation, times; - unsigned long relocation, min_relocation; - struct elf_nds32_insn_times_entry *ptr; - - if (h->m_list == NULL) - { - /* Local symbol insn or insn without relocation. */ - if (h->times < 3) - return TRUE; - ptr = (struct elf_nds32_insn_times_entry *) - bfd_malloc (sizeof (struct elf_nds32_insn_times_entry)); - ptr->times = h->times; - ptr->string = h->root.string; - ptr->m_list = NULL; - ptr->sec = h->sec; - ptr->irel = h->irel; - ptr->rel_backup = h->rel_backup; - nds32_elf_ex9_insert_entry (ptr); - } - else - { - /* Global symbol insn. */ - /* Only sethi insn has multiple m_list. */ - struct elf_link_hash_entry_mul_list *m_list = h->m_list; - - if (ELF32_R_TYPE (m_list->rel_backup.r_info) == R_NDS32_HI20_RELA - && m_list->next != NULL) - { - /* Sethi insn has different symbol or addend but has same hi20. */ - times = 0; - reservation = 1; - relocation = 0; - min_relocation = 0xffffffff; - while (m_list) - { - /* Get the minimum sethi address - and calculate how many entry the sethi-list have to use. */ - if ((m_list->h_list->h->root.type == bfd_link_hash_defined - || m_list->h_list->h->root.type == bfd_link_hash_defweak) - && (m_list->h_list->h->root.u.def.section != NULL - && m_list->h_list->h->root.u.def.section->output_section != NULL)) - { - relocation = (m_list->h_list->h->root.u.def.value + - m_list->h_list->h->root.u.def.section->output_section->vma + - m_list->h_list->h->root.u.def.section->output_offset); - relocation += m_list->irel->r_addend; - } - else - relocation = 0; - if (relocation < min_relocation) - min_relocation = relocation; - times += m_list->times; - m_list = m_list->next; - } - if (min_relocation < ex9_relax_size) - reservation = (min_relocation >> 12) + 1; - else - reservation = (min_relocation >> 12) - - ((min_relocation - ex9_relax_size) >> 12) + 1; - if (reservation < (times / 3)) - { - /* Efficient enough to use ex9. */ - int i; - - for (i = reservation ; i > 0; i--) - { - /* Allocate number of reservation ex9 entry. */ - ptr = (struct elf_nds32_insn_times_entry *) - bfd_malloc (sizeof (struct elf_nds32_insn_times_entry)); - ptr->times = h->m_list->times / reservation; - ptr->string = h->root.string; - ptr->m_list = h->m_list; - ptr->sec = h->sec; - ptr->irel = h->m_list->irel; - ptr->rel_backup = h->m_list->rel_backup; - nds32_elf_ex9_insert_entry (ptr); - } - } - } - else - { - /* Normal global symbol that means no different address symbol - using same ex9 entry. */ - if (m_list->times >= 3) - { - ptr = (struct elf_nds32_insn_times_entry *) - bfd_malloc (sizeof (struct elf_nds32_insn_times_entry)); - ptr->times = m_list->times; - ptr->string = h->root.string; - ptr->m_list = h->m_list; - ptr->sec = h->sec; - ptr->irel = h->m_list->irel; - ptr->rel_backup = h->m_list->rel_backup; - nds32_elf_ex9_insert_entry (ptr); - } - } - - if (h->const_insn == 1) - { - /* sethi with constant value. */ - if (h->times < 3) - return TRUE; - - ptr = (struct elf_nds32_insn_times_entry *) - bfd_malloc (sizeof (struct elf_nds32_insn_times_entry)); - ptr->times = h->times; - ptr->string = h->root.string; - ptr->m_list = NULL; - ptr->sec = NULL; - ptr->irel = NULL; - ptr->rel_backup = h->rel_backup; - nds32_elf_ex9_insert_entry (ptr); - } - } - - return TRUE; -} - -/* Hash table traverse function. */ - -static void -nds32_elf_code_hash_traverse (int (*func) (struct elf_nds32_code_hash_entry*)) -{ - unsigned int i; - - ex9_code_table.frozen = 1; - for (i = 0; i < ex9_code_table.size; i++) - { - struct bfd_hash_entry *p; - - for (p = ex9_code_table.table[i]; p != NULL; p = p->next) - if (!func ((struct elf_nds32_code_hash_entry *) p)) - goto out; - } -out: - ex9_code_table.frozen = 0; -} - - -/* Give order number to insn list. */ - -static void -nds32_elf_order_insn_times (struct bfd_link_info *info) -{ - struct elf_nds32_insn_times_entry *ex9_insn; - struct elf_nds32_insn_times_entry *temp = NULL; - struct elf_nds32_link_hash_table *table; - int ex9_limit; - int number = 0; - - if (ex9_insn_head == NULL) - return; - -/* The max number of entries is 512. */ - ex9_insn = ex9_insn_head; - table = nds32_elf_hash_table (info); - ex9_limit = table->ex9_limit; - - ex9_insn = ex9_insn_head; - - while (ex9_insn != NULL && number < ex9_limit) - { - ex9_insn->order = number; - number++; - temp = ex9_insn; - ex9_insn = ex9_insn->next; - } - - if (ex9_insn && temp) - temp->next = NULL; - - while (ex9_insn != NULL) - { - /* Free useless entry. */ - temp = ex9_insn; - ex9_insn = ex9_insn->next; - free (temp); - } -} - -/* Build .ex9.itable section. */ - -static void -nds32_elf_ex9_build_itable (struct bfd_link_info *link_info) -{ - asection *table_sec; - struct elf_nds32_insn_times_entry *ptr; - bfd *it_abfd; - int number = 0; - bfd_byte *contents = NULL; - - for (it_abfd = link_info->input_bfds; it_abfd != NULL; - it_abfd = it_abfd->link.next) - { - /* Find the section .ex9.itable, and put all entries into it. */ - table_sec = bfd_get_section_by_name (it_abfd, ".ex9.itable"); - if (table_sec != NULL) - { - if (!nds32_get_section_contents (it_abfd, table_sec, &contents, TRUE)) - return; - - for (ptr = ex9_insn_head; ptr !=NULL ; ptr = ptr->next) - number++; - - table_sec->size = number * 4; - - if (number == 0) - return; - - elf_elfheader (link_info->output_bfd)->e_flags |= E_NDS32_HAS_EX9_INST; - number = 0; - for (ptr = ex9_insn_head; ptr !=NULL ; ptr = ptr->next) - { - long val; - - val = strtol (ptr->string, NULL, 16); - bfd_putb32 ((bfd_vma) val, (char *) contents + (number * 4)); - number++; - } - break; - } - } -} - -/* Get insn with regs according to relocation type. */ - -static void -nds32_elf_get_insn_with_reg (Elf_Internal_Rela *irel, - uint32_t insn, uint32_t *insn_with_reg) -{ - reloc_howto_type *howto = NULL; - - if (irel == NULL - || (ELF32_R_TYPE (irel->r_info) >= (int) ARRAY_SIZE (nds32_elf_howto_table) - && (ELF32_R_TYPE (irel->r_info) - R_NDS32_RELAX_ENTRY) - >= (int) ARRAY_SIZE (nds32_elf_relax_howto_table))) - { - *insn_with_reg = insn; - return; - } - - howto = bfd_elf32_bfd_reloc_type_table_lookup (ELF32_R_TYPE (irel->r_info)); - *insn_with_reg = insn & (0xffffffff ^ howto->dst_mask); -} - -/* Mask number of address bits according to relocation. */ - -static unsigned long -nds32_elf_irel_mask (Elf_Internal_Rela *irel) -{ - reloc_howto_type *howto = NULL; - - if (irel == NULL - || (ELF32_R_TYPE (irel->r_info) >= (int) ARRAY_SIZE (nds32_elf_howto_table) - && (ELF32_R_TYPE (irel->r_info) - R_NDS32_RELAX_ENTRY) - >= (int) ARRAY_SIZE (nds32_elf_relax_howto_table))) - return 0; - - howto = bfd_elf32_bfd_reloc_type_table_lookup (ELF32_R_TYPE (irel->r_info)); - return howto->dst_mask; -} - -static void -nds32_elf_insert_irel_entry (struct elf_nds32_irel_entry **irel_list, - struct elf_nds32_irel_entry *irel_ptr) -{ - if (*irel_list == NULL) - { - *irel_list = irel_ptr; - irel_ptr->next = NULL; - } - else - { - irel_ptr->next = *irel_list; - *irel_list = irel_ptr; - } -} - -static void -nds32_elf_ex9_insert_fix (asection * sec, Elf_Internal_Rela * irel, - struct elf_link_hash_entry *h, int order) -{ - struct elf_nds32_ex9_refix *ptr; - - ptr = bfd_malloc (sizeof (struct elf_nds32_ex9_refix)); - ptr->sec = sec; - ptr->irel = irel; - ptr->h = h; - ptr->order = order; - ptr->next = NULL; - - if (ex9_refix_head == NULL) - ex9_refix_head = ptr; - else - { - struct elf_nds32_ex9_refix *temp = ex9_refix_head; - - while (temp->next != NULL) - temp = temp->next; - temp->next = ptr; - } -} - -enum -{ - DATA_EXIST = 1, - CLEAN_PRE = 1 << 1, - PUSH_PRE = 1 << 2 -}; - -/* Check relocation type if supporting for ex9. */ - -static int -nds32_elf_ex9_relocation_check (struct bfd_link_info *info, - Elf_Internal_Rela **irel, - Elf_Internal_Rela *irelend, - nds32_elf_blank_t *relax_blank_list, - asection *sec,bfd_vma *off, - bfd_byte *contents) -{ - /* Suppress ex9 if `.no_relax ex9' or inner loop. */ - bfd_boolean nested_ex9, nested_loop; - bfd_boolean ex9_loop_aware; - /* We use the highest 1 byte of result to record - how many bytes location counter has to move. */ - int result = 0; - Elf_Internal_Rela *irel_save = NULL; - struct elf_nds32_link_hash_table *table; - - table = nds32_elf_hash_table (info); - ex9_loop_aware = table->ex9_loop_aware; - - while ((*irel) != NULL && (*irel) < irelend && *off == (*irel)->r_offset) - { - switch (ELF32_R_TYPE ((*irel)->r_info)) - { - case R_NDS32_RELAX_REGION_BEGIN: - /* Ignore code block. */ - nested_ex9 = FALSE; - nested_loop = FALSE; - if (((*irel)->r_addend & R_NDS32_RELAX_REGION_NO_EX9_FLAG) - || (ex9_loop_aware - && ((*irel)->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG))) - { - /* Check the region if loop or not. If it is true and - ex9-loop-aware is true, ignore the region till region end. */ - /* To save the status for in .no_relax ex9 region and - loop region to conform the block can do ex9 relaxation. */ - nested_ex9 = ((*irel)->r_addend & R_NDS32_RELAX_REGION_NO_EX9_FLAG); - nested_loop = (ex9_loop_aware - && ((*irel)->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG)); - while ((*irel) && (*irel) < irelend && (nested_ex9 || nested_loop)) - { - (*irel)++; - if (ELF32_R_TYPE ((*irel)->r_info) == R_NDS32_RELAX_REGION_BEGIN) - { - /* There may be nested region. */ - if (((*irel)->r_addend & R_NDS32_RELAX_REGION_NO_EX9_FLAG) != 0) - nested_ex9 = TRUE; - else if (ex9_loop_aware - && ((*irel)->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG)) - nested_loop = TRUE; - } - else if (ELF32_R_TYPE ((*irel)->r_info) == R_NDS32_RELAX_REGION_END) - { - /* The end of region. */ - if (((*irel)->r_addend & R_NDS32_RELAX_REGION_NO_EX9_FLAG) != 0) - nested_ex9 = FALSE; - else if (ex9_loop_aware - && ((*irel)->r_addend & R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG)) - nested_loop = FALSE; - } - else if (ELF32_R_TYPE ((*irel)->r_info) == R_NDS32_LABEL - && ((*irel)->r_addend & 0x1f) == 2) - { - /* Alignment exist in the region. */ - result |= CLEAN_PRE; - if (((*irel)->r_offset - - get_nds32_elf_blank_total (&relax_blank_list, - (*irel)->r_offset, 0)) & 0x02) - result |= PUSH_PRE; - } - } - if ((*irel) >= irelend) - *off = sec->size; - else - *off = (*irel)->r_offset; - - /* The final instruction in the region, regard this one as data to ignore it. */ - result |= DATA_EXIST; - return result; - } - break; - - case R_NDS32_LABEL: - if (((*irel)->r_addend & 0x1f) == 2) - { - /* Check this point is align and decide to do ex9 or not. */ - result |= CLEAN_PRE; - if (((*irel)->r_offset - - get_nds32_elf_blank_total (&relax_blank_list, - (*irel)->r_offset, 0)) & 0x02) - result |= PUSH_PRE; - } - break; - case R_NDS32_32_RELA: - /* Data. */ - result |= (4 << 24); - result |= DATA_EXIST; - break; - case R_NDS32_16_RELA: - /* Data. */ - result |= (2 << 24); - result |= DATA_EXIST; - break; - case R_NDS32_DATA: - /* Data. */ - /* The least code alignment is 2. If the data is only one byte, - we have to shift one more byte. */ - if ((*irel)->r_addend == 1) - result |= ((*irel)->r_addend << 25) ; - else - result |= ((*irel)->r_addend << 24) ; - - result |= DATA_EXIST; - break; - - case R_NDS32_25_PCREL_RELA: - case R_NDS32_SDA16S3_RELA: - case R_NDS32_SDA15S3_RELA: - case R_NDS32_SDA15S3: - case R_NDS32_SDA17S2_RELA: - case R_NDS32_SDA15S2_RELA: - case R_NDS32_SDA12S2_SP_RELA: - case R_NDS32_SDA12S2_DP_RELA: - case R_NDS32_SDA15S2: - case R_NDS32_SDA18S1_RELA: - case R_NDS32_SDA15S1_RELA: - case R_NDS32_SDA15S1: - case R_NDS32_SDA19S0_RELA: - case R_NDS32_SDA15S0_RELA: - case R_NDS32_SDA15S0: - case R_NDS32_HI20_RELA: - case R_NDS32_LO12S0_ORI_RELA: - case R_NDS32_LO12S0_RELA: - case R_NDS32_LO12S1_RELA: - case R_NDS32_LO12S2_RELA: - /* These relocation is supported ex9 relaxation currently. */ - /* We have to save the relocation for using later, since we have - to check there is any alignment in the same address. */ - irel_save = *irel; - break; - default: - /* Not support relocations. */ - if (ELF32_R_TYPE ((*irel)->r_info) < ARRAY_SIZE (nds32_elf_howto_table) - && ELF32_R_TYPE ((*irel)->r_info) != R_NDS32_NONE - && ELF32_R_TYPE ((*irel)->r_info) != R_NDS32_INSN16) - { - /* Note: To optimize aggressively, it maybe can ignore R_NDS32_INSN16 here. - But we have to consider if there is any side-effect. */ - if (!(result & DATA_EXIST)) - { - /* We have to confirm there is no data relocation in the - same address. In general case, this won't happen. */ - /* We have to do ex9 conservative, for those relocation not - considerd we ignore instruction. */ - result |= DATA_EXIST; - if (*(contents + *off) & 0x80) - result |= (2 << 24); - else - result |= (4 << 24); - break; - } - } - } - if ((*irel) < irelend - && ((*irel) + 1) < irelend - && (*irel)->r_offset == ((*irel) + 1)->r_offset) - /* There are relocations pointing to the same address, we have to - check all of them. */ - (*irel)++; - else - { - if (irel_save) - *irel = irel_save; - return result; - } - } - return result; -} - -/* Replace with ex9 instruction. */ - -static bfd_boolean -nds32_elf_ex9_push_insn (uint16_t insn16, bfd_byte *contents, bfd_vma pre_off, - nds32_elf_blank_t **relax_blank_list, - struct elf_nds32_irel_entry *pre_irel_ptr, - struct elf_nds32_irel_entry **irel_list) -{ - if (insn16 != 0) - { - /* Implement the ex9 relaxation. */ - bfd_putb16 (insn16, contents + pre_off); - if (!insert_nds32_elf_blank_recalc_total (relax_blank_list, - pre_off + 2, 2)) - return FALSE; - if (pre_irel_ptr != NULL) - nds32_elf_insert_irel_entry (irel_list, pre_irel_ptr); - } - return TRUE; -} - -/* Replace input file instruction which is in ex9 itable. */ - -static bfd_boolean -nds32_elf_ex9_replace_instruction (struct bfd_link_info *info, bfd *abfd, asection *sec) -{ - struct elf_nds32_insn_times_entry *ex9_insn = ex9_insn_head; - bfd_byte *contents = NULL; - bfd_vma off; - uint16_t insn16, insn_ex9; - /* `pre_*' are used to track previous instruction that can use ex9.it. */ - bfd_vma pre_off = -1; - uint16_t pre_insn16 = 0; - struct elf_nds32_irel_entry *pre_irel_ptr = NULL; - Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *irel; - Elf_Internal_Rela *irelend; - Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Sym *isym = NULL; - nds32_elf_blank_t *relax_blank_list = NULL; - uint32_t insn = 0; - uint32_t insn_with_reg = 0; - uint32_t it_insn; - uint32_t it_insn_with_reg; - unsigned long r_symndx; - asection *isec; - struct elf_nds32_irel_entry *irel_list = NULL; - struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (abfd); - int data_flag, do_replace, save_irel; - struct elf_link_hash_entry_list *h_list; - - - /* Load section instructions, relocations, and symbol table. */ - if (!nds32_get_section_contents (abfd, sec, &contents, TRUE) - || !nds32_get_local_syms (abfd, sec, &isym)) - return FALSE; - internal_relocs = - _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, TRUE /* keep_memory */); - irelend = internal_relocs + sec->reloc_count; - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - - off = 0; - - /* Check if the object enable ex9. */ - irel = find_relocs_at_address (internal_relocs, internal_relocs, - irelend, R_NDS32_RELAX_ENTRY); - - /* Check this section trigger ex9 relaxation. */ - if (irel == NULL - || irel >= irelend - || ELF32_R_TYPE (irel->r_info) != R_NDS32_RELAX_ENTRY - || (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_ENTRY - && !(irel->r_addend & R_NDS32_RELAX_ENTRY_EX9_FLAG))) - return TRUE; - - irel = internal_relocs; - - /* Check alignment and fetch proper relocation. */ - while (off < sec->size) - { - struct elf_link_hash_entry *h = NULL; - struct elf_nds32_irel_entry *irel_ptr = NULL; - - /* Syn the instruction and the relocation. */ - while (irel != NULL && irel < irelend && irel->r_offset < off) - irel++; - - data_flag = nds32_elf_ex9_relocation_check (info, &irel, irelend, - relax_blank_list, sec, - &off, contents); - if (data_flag & PUSH_PRE) - if (!nds32_elf_ex9_push_insn (pre_insn16, contents, pre_off, - &relax_blank_list, pre_irel_ptr, - &irel_list)) - return FALSE; - - if (data_flag & CLEAN_PRE) - { - pre_off = 0; - pre_insn16 = 0; - pre_irel_ptr = NULL; - } - if (data_flag & DATA_EXIST) - { - /* We save the move offset in the highest byte. */ - off += (data_flag >> 24); - continue; - } - - if (*(contents + off) & 0x80) - { - /* 2-byte instruction. */ - off += 2; - continue; - } - - /* Load the instruction and its opcode with register for comparing. */ - ex9_insn = ex9_insn_head; - insn = bfd_getb32 (contents + off); - insn_with_reg = 0; - while (ex9_insn) - { - it_insn = strtol (ex9_insn->string, NULL, 16); - it_insn_with_reg = 0; - do_replace = 0; - save_irel = 0; - - if (irel != NULL && irel < irelend && irel->r_offset == off) - { - /* Insn with relocation. */ - nds32_elf_get_insn_with_reg (irel, insn, &insn_with_reg); - - if (ex9_insn->irel != NULL) - nds32_elf_get_insn_with_reg (ex9_insn->irel, it_insn, - &it_insn_with_reg); - - if (ex9_insn->irel != NULL - && (ELF32_R_TYPE (irel->r_info) == - ELF32_R_TYPE (ex9_insn->irel->r_info)) - && (insn_with_reg == it_insn_with_reg)) - { - /* Insn relocation and format is the same as table entry. */ - - if (ELF32_R_TYPE (irel->r_info) == R_NDS32_25_PCREL_RELA - || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S0_ORI_RELA - || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S0_RELA - || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S1_RELA - || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S2_RELA - || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3 - && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0) - || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3_RELA - && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0_RELA) - || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA12S2_DP_RELA - && ELF32_R_TYPE (irel->r_info) <= - R_NDS32_SDA12S2_SP_RELA) - || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA16S3_RELA - && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA19S0_RELA)) - { - r_symndx = ELF32_R_SYM (irel->r_info); - if (r_symndx < symtab_hdr->sh_info) - { - /* Local symbol. */ - int shndx = isym[r_symndx].st_shndx; - - isec = elf_elfsections (abfd)[shndx]->bfd_section; - if (ex9_insn->sec == isec - && ex9_insn->irel->r_addend == irel->r_addend - && ex9_insn->irel->r_info == irel->r_info) - { - do_replace = 1; - save_irel = 1; - } - } - else - { - /* External symbol. */ - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if (ex9_insn->m_list) - { - h_list = ex9_insn->m_list->h_list; - while (h_list) - { - if (h == h_list->h - && (ex9_insn->m_list->irel->r_addend == - irel->r_addend)) - { - do_replace = 1; - save_irel = 1; - break; - } - h_list = h_list->next; - } - } - } - } - else if (ELF32_R_TYPE (irel->r_info) == R_NDS32_HI20_RELA) - { - r_symndx = ELF32_R_SYM (irel->r_info); - if (r_symndx < symtab_hdr->sh_info) - { - /* Local symbols. Compare its base symbol and offset. */ - int shndx = isym[r_symndx].st_shndx; - - isec = elf_elfsections (abfd)[shndx]->bfd_section; - if (ex9_insn->sec == isec - && ex9_insn->irel->r_addend == irel->r_addend - && ex9_insn->irel->r_info == irel->r_info) - { - do_replace = 1; - save_irel = 1; - } - } - else - { - /* External symbol. */ - struct elf_link_hash_entry_mul_list *m_list; - - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - m_list = ex9_insn->m_list; - - while (m_list) - { - h_list = m_list->h_list; - - while (h_list) - { - if (h == h_list->h - && (m_list->irel->r_addend - == irel->r_addend)) - { - do_replace = 1; - save_irel = 1; - if (ex9_insn->next - && ex9_insn->m_list - && ex9_insn->m_list == ex9_insn->next->m_list) - { - /* sethi multiple entry must be fixed */ - nds32_elf_ex9_insert_fix (sec, irel, - h, ex9_insn->order); - } - break; - } - h_list = h_list->next; - } - m_list = m_list->next; - } - } - } - } - - /* Import table: Check the symbol hash table and the - jump target. Only R_NDS32_25_PCREL_RELA now. */ - else if (ex9_insn->times == -1 - && ELF32_R_TYPE (irel->r_info) == R_NDS32_25_PCREL_RELA) - { - nds32_elf_get_insn_with_reg (irel, it_insn, &it_insn_with_reg); - if (insn_with_reg == it_insn_with_reg) - { - char code[10]; - bfd_vma relocation; - - r_symndx = ELF32_R_SYM (irel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if ((h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - && h->root.u.def.section != NULL - && h->root.u.def.section->output_section != NULL - && h->root.u.def.section->gc_mark == 1 - && bfd_is_abs_section (h->root.u.def.section) - && h->root.u.def.value > sec->size) - { - relocation = h->root.u.def.value + - h->root.u.def.section->output_section->vma + - h->root.u.def.section->output_offset; - relocation += irel->r_addend; - insn = insn_with_reg - | ((relocation >> 1) & 0xffffff); - snprintf (code, sizeof (code), "%08x", insn); - if (strcmp (code, ex9_insn->string) == 0) - { - do_replace = 1; - save_irel = 1; - } - } - } - } - } - else if (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_REGION_BEGIN - || ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_REGION_END - || ELF32_R_TYPE (irel->r_info) == R_NDS32_NONE) - { - /* These relocations do not have to relocate contens, so it can - be regard as instruction without relocation. */ - if (insn == it_insn && ex9_insn->irel == NULL) - do_replace = 1; - } - } - else - { - /* Instruction without relocation, we only - have to compare their byte code. */ - if (insn == it_insn && ex9_insn->irel == NULL) - do_replace = 1; - } - - /* Insntruction match so replacing the code here. */ - if (do_replace == 1) - { - /* There are two formats of ex9 instruction. */ - if (ex9_insn->order < 32) - insn_ex9 = INSN_EX9_IT_2; - else - insn_ex9 = INSN_EX9_IT_1; - insn16 = insn_ex9 | ex9_insn->order; - - /* Insert ex9 instruction. */ - nds32_elf_ex9_push_insn (pre_insn16, contents, pre_off, - &relax_blank_list, pre_irel_ptr, - &irel_list); - pre_off = off; - pre_insn16 = insn16; - - if (save_irel) - { - /* For instuction with relocation do relax. */ - irel_ptr = (struct elf_nds32_irel_entry *) - bfd_malloc (sizeof (struct elf_nds32_irel_entry)); - irel_ptr->irel = irel; - irel_ptr->next = NULL; - pre_irel_ptr = irel_ptr; - } - else - pre_irel_ptr = NULL; - break; - } - ex9_insn = ex9_insn->next; - } - off += 4; - } - - /* Insert ex9 instruction. */ - nds32_elf_ex9_push_insn (pre_insn16, contents, pre_off, - &relax_blank_list, pre_irel_ptr, - &irel_list); - - /* Delete the redundant code. */ - if (relax_blank_list) - { - nds32_elf_relax_delete_blanks (abfd, sec, relax_blank_list); - relax_blank_list = NULL; - } - - /* Clear the relocation that is replaced by ex9. */ - while (irel_list) - { - struct elf_nds32_irel_entry *irel_ptr; - - irel_ptr = irel_list; - irel_list = irel_ptr->next; - irel_ptr->irel->r_info = - ELF32_R_INFO (ELF32_R_SYM (irel_ptr->irel->r_info), R_NDS32_TRAN); - free (irel_ptr); - } - return TRUE; -} - -/* Initialize ex9 hash table. */ - -int -nds32_elf_ex9_init (void) -{ - if (!bfd_hash_table_init_n (&ex9_code_table, nds32_elf_code_hash_newfunc, - sizeof (struct elf_nds32_code_hash_entry), - 1023)) - { - _bfd_error_handler (_("Linker: cannot init ex9 hash table error \n")); - return FALSE; - } - return TRUE; -} - -/* Predict how many bytes will be relaxed with ex9 and ifc. */ - -static void -nds32_elf_ex9_total_relax (struct bfd_link_info *info) -{ - struct elf_nds32_insn_times_entry *ex9_insn; - struct elf_nds32_insn_times_entry *temp; - int target_optimize; - struct elf_nds32_link_hash_table *table; - - if (ex9_insn_head == NULL) - return; - - table = nds32_elf_hash_table (info); - target_optimize = table->target_optimize; - ex9_insn = ex9_insn_head; - while (ex9_insn) - { - ex9_relax_size = ex9_insn->times * 2 + ex9_relax_size; - temp = ex9_insn; - ex9_insn = ex9_insn->next; - free (temp); - } - ex9_insn_head = NULL; - - if ((target_optimize & NDS32_RELAX_JUMP_IFC_ON)) - { - /* Examine ifc reduce size. */ - struct elf_nds32_ifc_symbol_entry *ifc_ent = ifc_symbol_head; - struct elf_nds32_ifc_irel_list *irel_ptr = NULL; - int size = 0; - - while (ifc_ent) - { - if (ifc_ent->enable == 0) - { - /* Not ifc yet. */ - irel_ptr = ifc_ent->irel_head; - while (irel_ptr) - { - size += 2; - irel_ptr = irel_ptr->next; - } - } - size -= 2; - ifc_ent = ifc_ent->next; - } - ex9_relax_size += size; - } -} - -/* Finish ex9 table. */ - -void -nds32_elf_ex9_finish (struct bfd_link_info *link_info) -{ - nds32_elf_code_hash_traverse (nds32_elf_examine_insn_times); - nds32_elf_order_insn_times (link_info); - nds32_elf_ex9_total_relax (link_info); - /* Traverse the hash table and count its times. */ - nds32_elf_code_hash_traverse (nds32_elf_count_insn_times); - nds32_elf_order_insn_times (link_info); - nds32_elf_ex9_build_itable (link_info); -} - -/* Relocate the entries in ex9 table. */ - -static bfd_vma -nds32_elf_ex9_reloc_insn (struct elf_nds32_insn_times_entry *ptr, - struct bfd_link_info *link_info) -{ - Elf_Internal_Sym *isym = NULL; - bfd_vma relocation = -1; - struct elf_link_hash_entry *h; - - if (ptr->m_list != NULL) - { - /* Global symbol. */ - h = ptr->m_list->h_list->h; - if ((h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - && h->root.u.def.section != NULL - && h->root.u.def.section->output_section != NULL) - { - - relocation = h->root.u.def.value + - h->root.u.def.section->output_section->vma + - h->root.u.def.section->output_offset; - relocation += ptr->m_list->irel->r_addend; - } - else - relocation = 0; - } - else if (ptr->sec !=NULL) - { - /* Local symbol. */ - Elf_Internal_Sym sym; - asection *sec = NULL; - asection isec; - asection *isec_ptr = &isec; - Elf_Internal_Rela irel_backup = *(ptr->irel); - asection *sec_backup = ptr->sec; - bfd *abfd = ptr->sec->owner; - - if (!nds32_get_local_syms (abfd, sec, &isym)) - return FALSE; - isym = isym + ELF32_R_SYM (ptr->irel->r_info); - - sec = bfd_section_from_elf_index (abfd, isym->st_shndx); - if (sec != NULL) - *isec_ptr = *sec; - sym = *isym; - - /* The purpose is same as elf_link_input_bfd. */ - if (isec_ptr != NULL - && isec_ptr->sec_info_type == SEC_INFO_TYPE_MERGE - && ELF_ST_TYPE (isym->st_info) != STT_SECTION) - { - sym.st_value = - _bfd_merged_section_offset (ptr->sec->output_section->owner, &isec_ptr, - elf_section_data (isec_ptr)->sec_info, - isym->st_value); - } - relocation = _bfd_elf_rela_local_sym (link_info->output_bfd, &sym, - &ptr->sec, ptr->irel); - if (ptr->irel != NULL) - relocation += ptr->irel->r_addend; - - /* Restore origin value since there may be some insntructions that - could not be replaced with ex9.it. */ - *(ptr->irel) = irel_backup; - ptr->sec = sec_backup; - } - - return relocation; -} - -/* Import ex9 table and build list. */ - -void -nds32_elf_ex9_import_table (struct bfd_link_info *info) -{ - int num = 0; - bfd_byte *contents; - FILE *ex9_import_file; - int update_ex9_table; - struct elf_nds32_link_hash_table *table; - - table = nds32_elf_hash_table (info); - ex9_import_file = table->ex9_import_file; - rewind (table->ex9_import_file); - - contents = bfd_malloc (sizeof (bfd_byte) * 4); - - /* Read instructions from the input file and build the list. */ - while (!feof (ex9_import_file)) - { - unsigned long insn; - char *code; - struct elf_nds32_insn_times_entry *ptr; - size_t nread; - - nread = fread (contents, sizeof (bfd_byte) * 4, 1, ex9_import_file); - /* Ignore the final byte 0x0a. */ - if (nread < 1) - break; - insn = bfd_getb32 (contents); - code = bfd_malloc (sizeof (char) * 9); - snprintf (code, 9, "%08lx", (insn & 0xffffffff)); - ptr = bfd_malloc (sizeof (struct elf_nds32_insn_times_entry)); - ptr->string = code; - ptr->order = num; - ptr->times = -1; - ptr->sec = NULL; - ptr->m_list = NULL; - ptr->rel_backup.r_offset = 0; - ptr->rel_backup.r_info = 0; - ptr->rel_backup.r_addend = 0; - ptr->irel = NULL; - ptr->next = NULL; - nds32_elf_ex9_insert_entry (ptr); - num++; - } - - update_ex9_table = table->update_ex9_table; - if (update_ex9_table == 1) - { - /* It has to consider of sethi need to use multiple page - but it not be done yet. */ - nds32_elf_code_hash_traverse (nds32_elf_examine_insn_times); - nds32_elf_order_insn_times (info); - } -} - -/* Export ex9 table. */ - -static void -nds32_elf_ex9_export (struct bfd_link_info *info, - bfd_byte *contents, int size) -{ - FILE *ex9_export_file; - struct elf_nds32_link_hash_table *table; - - table = nds32_elf_hash_table (info); - ex9_export_file = table->ex9_export_file; - fwrite (contents, sizeof (bfd_byte), size, ex9_export_file); - fclose (ex9_export_file); -} - -/* Adjust relocations of J and JAL in ex9.itable. - Export ex9 table. */ - -static void -nds32_elf_ex9_reloc_jmp (struct bfd_link_info *link_info) -{ - asection *table_sec = NULL; - struct elf_nds32_insn_times_entry *ex9_insn = ex9_insn_head; - struct elf_nds32_insn_times_entry *temp_ptr, *temp_ptr2; - bfd *it_abfd; - uint32_t insn, insn_with_reg, source_insn; - bfd_byte *contents = NULL, *source_contents = NULL; - int size = 0; - bfd_vma gp; - int shift, update_ex9_table, offset = 0; - reloc_howto_type *howto = NULL; - Elf_Internal_Rela rel_backup; - unsigned short insn_ex9; - struct elf_nds32_link_hash_table *table; - FILE *ex9_export_file; - static bfd_boolean done = FALSE; - - if (done) - return; - - done = TRUE; - - table = nds32_elf_hash_table (link_info); - if (table) - table->relax_status |= NDS32_RELAX_EX9_DONE; - - - update_ex9_table = table->update_ex9_table; - /* Generated ex9.itable exactly. */ - if (update_ex9_table == 0) - { - for (it_abfd = link_info->input_bfds; it_abfd != NULL; - it_abfd = it_abfd->link.next) - { - table_sec = bfd_get_section_by_name (it_abfd, ".ex9.itable"); - if (table_sec != NULL) - break; - } - - if (table_sec != NULL) - { - bfd *output_bfd; - - output_bfd = table_sec->output_section->owner; - nds32_elf_final_sda_base (output_bfd, link_info, &gp, FALSE); - if (table_sec->size == 0) - return; - - if (!nds32_get_section_contents (it_abfd, table_sec, &contents, TRUE)) - return; - } - } - else - { - /* Set gp. */ - bfd *output_bfd; - - output_bfd = link_info->input_bfds->sections->output_section->owner; - nds32_elf_final_sda_base (output_bfd, link_info, &gp, FALSE); - contents = bfd_malloc (sizeof (bfd_byte) * 2048); - } - - /* Relocate instruction. */ - while (ex9_insn) - { - bfd_vma relocation, min_relocation = 0xffffffff; - - insn = strtol (ex9_insn->string, NULL, 16); - insn_with_reg = 0; - if (ex9_insn->m_list != NULL || ex9_insn->sec != NULL) - { - if (ex9_insn->m_list) - rel_backup = ex9_insn->m_list->rel_backup; - else - rel_backup = ex9_insn->rel_backup; - - nds32_elf_get_insn_with_reg (&rel_backup, insn, &insn_with_reg); - howto = - bfd_elf32_bfd_reloc_type_table_lookup (ELF32_R_TYPE - (rel_backup.r_info)); - shift = howto->rightshift; - if (ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_25_PCREL_RELA - || ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_LO12S0_ORI_RELA - || ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_LO12S0_RELA - || ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_LO12S1_RELA - || ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_LO12S2_RELA) - { - relocation = nds32_elf_ex9_reloc_insn (ex9_insn, link_info); - insn = - insn_with_reg | ((relocation >> shift) & - nds32_elf_irel_mask (&rel_backup)); - bfd_putb32 (insn, contents + (ex9_insn->order) * 4); - } - else if ((ELF32_R_TYPE (rel_backup.r_info) >= R_NDS32_SDA15S3 - && ELF32_R_TYPE (rel_backup.r_info) <= R_NDS32_SDA15S0) - || (ELF32_R_TYPE (rel_backup.r_info) >= R_NDS32_SDA15S3_RELA - && ELF32_R_TYPE (rel_backup.r_info) <= R_NDS32_SDA15S0_RELA) - || (ELF32_R_TYPE (rel_backup.r_info) >= R_NDS32_SDA12S2_DP_RELA - && ELF32_R_TYPE (rel_backup.r_info) <= R_NDS32_SDA12S2_SP_RELA) - || (ELF32_R_TYPE (rel_backup.r_info) >= R_NDS32_SDA16S3_RELA - && ELF32_R_TYPE (rel_backup.r_info) <= R_NDS32_SDA19S0_RELA)) - { - relocation = nds32_elf_ex9_reloc_insn (ex9_insn, link_info); - insn = - insn_with_reg | (((relocation - gp) >> shift) & - nds32_elf_irel_mask (&rel_backup)); - bfd_putb32 (insn, contents + (ex9_insn->order) * 4); - } - else if (ELF32_R_TYPE (rel_backup.r_info) == R_NDS32_HI20_RELA) - { - /* Sethi may be multiple entry for one insn. */ - if (ex9_insn->next && ex9_insn->m_list - && ex9_insn->m_list == ex9_insn->next->m_list) - { - struct elf_link_hash_entry_mul_list *m_list; - struct elf_nds32_ex9_refix *fix_ptr; - struct elf_link_hash_entry *h; - - temp_ptr = ex9_insn; - temp_ptr2 = ex9_insn; - m_list = ex9_insn->m_list; - while (m_list) - { - h = m_list->h_list->h; - relocation = h->root.u.def.value + - h->root.u.def.section->output_section->vma + - h->root.u.def.section->output_offset; - relocation += m_list->irel->r_addend; - - if (relocation < min_relocation) - min_relocation = relocation; - m_list = m_list->next; - } - relocation = min_relocation; - - /* Put insntruction into ex9 table. */ - insn = insn_with_reg - | ((relocation >> shift) & nds32_elf_irel_mask (&rel_backup)); - bfd_putb32 (insn, contents + (ex9_insn->order) * 4); - relocation = relocation + 0x1000; /* hi20 */ - - while (ex9_insn->next && ex9_insn->m_list - && ex9_insn->m_list == ex9_insn->next->m_list) - { - /* Multiple sethi. */ - ex9_insn = ex9_insn->next; - size += 4; - insn = - insn_with_reg | ((relocation >> shift) & - nds32_elf_irel_mask (&rel_backup)); - bfd_putb32 (insn, contents + (ex9_insn->order) * 4); - relocation = relocation + 0x1000; /* hi20 */ - } - - fix_ptr = ex9_refix_head; - while (fix_ptr) - { - /* Fix ex9 insn. */ - /* temp_ptr2 points to the head of multiple sethi. */ - temp_ptr = temp_ptr2; - while (fix_ptr->order != temp_ptr->order && fix_ptr->next) - { - fix_ptr = fix_ptr->next; - } - if (fix_ptr->order != temp_ptr->order) - break; - - /* Set source insn. */ - relocation = - fix_ptr->h->root.u.def.value + - fix_ptr->h->root.u.def.section->output_section->vma + - fix_ptr->h->root.u.def.section->output_offset; - relocation += fix_ptr->irel->r_addend; - /* sethi imm is imm20s. */ - source_insn = insn_with_reg | ((relocation >> shift) & 0xfffff); - - while (temp_ptr) - { - /* Match entry and source code. */ - insn = bfd_getb32 (contents + (temp_ptr->order) * 4 + offset); - if (insn == source_insn) - { - /* Fix the ex9 insn. */ - if (temp_ptr->order != fix_ptr->order) - { - if (!nds32_get_section_contents - (fix_ptr->sec->owner, fix_ptr->sec, - &source_contents, TRUE)) - _bfd_error_handler - (_("Linker: error cannot fixed ex9 relocation \n")); - if (temp_ptr->order < 32) - insn_ex9 = INSN_EX9_IT_2; - else - insn_ex9 = INSN_EX9_IT_1; - insn_ex9 = insn_ex9 | temp_ptr->order; - bfd_putb16 (insn_ex9, source_contents + fix_ptr->irel->r_offset); - } - break; - } - else - { - if (!temp_ptr->next || temp_ptr->m_list != temp_ptr->next->m_list) - _bfd_error_handler - (_("Linker: error cannot fixed ex9 relocation \n")); - else - temp_ptr = temp_ptr->next; - } - } - fix_ptr = fix_ptr->next; - } - } - else - { - relocation = nds32_elf_ex9_reloc_insn (ex9_insn, link_info); - insn = insn_with_reg - | ((relocation >> shift) & nds32_elf_irel_mask (&rel_backup)); - bfd_putb32 (insn, contents + (ex9_insn->order) * 4); - } - } - } - else - { - /* Insn without relocation does not have to be fixed - if need to update export table. */ - if (update_ex9_table == 1) - bfd_putb32 (insn, contents + (ex9_insn->order) * 4); - } - ex9_insn = ex9_insn->next; - size += 4; - } - - ex9_export_file = table->ex9_export_file; - if (ex9_export_file != NULL) - nds32_elf_ex9_export (link_info, contents, table_sec->size); - else if (update_ex9_table == 1) - { - table->ex9_export_file = table->ex9_import_file; - rewind (table->ex9_export_file); - nds32_elf_ex9_export (link_info, contents, size); - } -} - -/* Generate ex9 hash table. */ - -static bfd_boolean -nds32_elf_ex9_build_hash_table (bfd *abfd, asection *sec, - struct bfd_link_info *link_info) -{ - Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *irelend; - Elf_Internal_Rela *irel; - Elf_Internal_Rela *jrel; - Elf_Internal_Rela rel_backup; - Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Sym *isym = NULL; - asection *isec; - struct elf_link_hash_entry **sym_hashes; - bfd_byte *contents = NULL; - bfd_vma off = 0; - unsigned long r_symndx; - uint32_t insn, insn_with_reg; - struct elf_link_hash_entry *h; - int data_flag, shift, align; - bfd_vma relocation; - /* Suppress ex9 if `.no_relax ex9' or inner loop. */ - reloc_howto_type *howto = NULL; - - sym_hashes = elf_sym_hashes (abfd); - /* Load section instructions, relocations, and symbol table. */ - if (!nds32_get_section_contents (abfd, sec, &contents, TRUE)) - return FALSE; - - internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, - TRUE /* keep_memory */); - irelend = internal_relocs + sec->reloc_count; - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - if (!nds32_get_local_syms (abfd, sec, &isym)) - return FALSE; - - /* Check the object if enable ex9. */ - irel = find_relocs_at_address (internal_relocs, internal_relocs, irelend, - R_NDS32_RELAX_ENTRY); - - /* Check this section trigger ex9 relaxation. */ - if (irel == NULL - || irel >= irelend - || ELF32_R_TYPE (irel->r_info) != R_NDS32_RELAX_ENTRY - || (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_ENTRY - && !(irel->r_addend & R_NDS32_RELAX_ENTRY_EX9_FLAG))) - return TRUE; - - irel = internal_relocs; - - /* Push each insn into hash table. */ - while (off < sec->size) - { - char code[10]; - struct elf_nds32_code_hash_entry *entry; - - while (irel != NULL && irel < irelend && irel->r_offset < off) - irel++; - - data_flag = nds32_elf_ex9_relocation_check (link_info, &irel, irelend, - NULL, sec, &off, contents); - if (data_flag & DATA_EXIST) - { - /* We save the move offset in the highest byte. */ - off += (data_flag >> 24); - continue; - } - - if (*(contents + off) & 0x80) - { - off += 2; - } - else - { - h = NULL; - isec = NULL; - jrel = NULL; - rel_backup.r_info = 0; - rel_backup.r_offset = 0; - rel_backup.r_addend = 0; - /* Load the instruction and its opcode with register for comparing. */ - insn = bfd_getb32 (contents + off); - insn_with_reg = 0; - if (irel != NULL && irel < irelend && irel->r_offset == off) - { - nds32_elf_get_insn_with_reg (irel, insn, &insn_with_reg); - howto = bfd_elf32_bfd_reloc_type_table_lookup (ELF32_R_TYPE (irel->r_info)); - shift = howto->rightshift; - align = (1 << shift) - 1; - if (ELF32_R_TYPE (irel->r_info) == R_NDS32_25_PCREL_RELA - || ELF32_R_TYPE (irel->r_info) == R_NDS32_HI20_RELA - || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S0_ORI_RELA - || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S0_RELA - || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S1_RELA - || ELF32_R_TYPE (irel->r_info) == R_NDS32_LO12S2_RELA - ||(ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3 - && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0) - || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3_RELA - && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0_RELA) - || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA12S2_DP_RELA - && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA12S2_SP_RELA) - || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA16S3_RELA - && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA19S0_RELA)) - { - r_symndx = ELF32_R_SYM (irel->r_info); - jrel = irel; - rel_backup = *irel; - if (r_symndx < symtab_hdr->sh_info) - { - /* Local symbol. */ - int shndx = isym[r_symndx].st_shndx; - - bfd_vma st_value = (isym + r_symndx)->st_value; - isec = elf_elfsections (abfd)[shndx]->bfd_section; - relocation = (isec->output_section->vma + isec->output_offset - + st_value + irel->r_addend); - } - else - { - /* External symbol. */ - bfd_boolean warned ATTRIBUTE_UNUSED; - bfd_boolean ignored ATTRIBUTE_UNUSED; - bfd_boolean unresolved_reloc ATTRIBUTE_UNUSED; - asection *sym_sec; - - /* Maybe there is a better way to get h and relocation */ - RELOC_FOR_GLOBAL_SYMBOL (link_info, abfd, sec, irel, - r_symndx, symtab_hdr, sym_hashes, - h, sym_sec, relocation, - unresolved_reloc, warned, ignored); - relocation += irel->r_addend; - if ((h->root.type != bfd_link_hash_defined - && h->root.type != bfd_link_hash_defweak) - || strcmp (h->root.root.string, "_FP_BASE_") == 0) - { - off += 4; - continue; - } - } - - /* Check for gp relative instruction alignment. */ - if ((ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3 - && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0) - || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA15S3_RELA - && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA15S0_RELA) - || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA12S2_DP_RELA - && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA12S2_SP_RELA) - || (ELF32_R_TYPE (irel->r_info) >= R_NDS32_SDA16S3_RELA - && ELF32_R_TYPE (irel->r_info) <= R_NDS32_SDA19S0_RELA)) - { - bfd_vma gp; - bfd *output_bfd = sec->output_section->owner; - bfd_reloc_status_type r; - - /* If the symbol is in the abs section, the out_bfd will be null. - This happens when the relocation has a symbol@GOTOFF. */ - r = nds32_elf_final_sda_base (output_bfd, link_info, &gp, FALSE); - if (r != bfd_reloc_ok) - { - off += 4; - continue; - } - - relocation -= gp; - - /* Make sure alignment is correct. */ - if (relocation & align) - { - /* Incorrect alignment. */ - _bfd_error_handler - /* xgettext:c-format */ - (_("%B: warning: unaligned small data access " - "for entry: {%Ld, %Ld, %Ld}, addr = %#Lx, align = %#x"), - abfd, irel->r_offset, - irel->r_info, irel->r_addend, relocation, align); - off += 4; - continue; - } - } - - insn = insn_with_reg - | ((relocation >> shift) & nds32_elf_irel_mask (irel)); - } - else if (ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_REGION_BEGIN - || ELF32_R_TYPE (irel->r_info) == R_NDS32_RELAX_REGION_END - || ELF32_R_TYPE (irel->r_info) == R_NDS32_NONE) - { - /* These relocations do not have to relocate contens, so it can - be regard as instruction without relocation. */ - } - else - { - off += 4; - continue; - } - } - - snprintf (code, sizeof (code), "%08x", insn); - /* Copy "code". */ - entry = (struct elf_nds32_code_hash_entry*) - bfd_hash_lookup (&ex9_code_table, code, TRUE, TRUE); - if (entry == NULL) - { - _bfd_error_handler - (_("failed creating ex9.it %s hash table entry"), code); - return FALSE; - } - if (h) - { - if (h->root.type == bfd_link_hash_undefined) - return TRUE; - /* Global symbol. */ - /* In order to do sethi with different symbol but same value. */ - if (entry->m_list == NULL) - { - struct elf_link_hash_entry_mul_list *m_list_new; - struct elf_link_hash_entry_list *h_list_new; - - m_list_new = (struct elf_link_hash_entry_mul_list *) - bfd_malloc (sizeof (struct elf_link_hash_entry_mul_list)); - h_list_new = (struct elf_link_hash_entry_list *) - bfd_malloc (sizeof (struct elf_link_hash_entry_list)); - entry->m_list = m_list_new; - m_list_new->h_list = h_list_new; - m_list_new->rel_backup = rel_backup; - m_list_new->times = 1; - m_list_new->irel = jrel; - m_list_new->next = NULL; - h_list_new->h = h; - h_list_new->next = NULL; - } - else - { - struct elf_link_hash_entry_mul_list *m_list = entry->m_list; - struct elf_link_hash_entry_list *h_list; - - while (m_list) - { - /* Build the different symbols that point to the same address. */ - h_list = m_list->h_list; - if (h_list->h->root.u.def.value == h->root.u.def.value - && h_list->h->root.u.def.section->output_section->vma - == h->root.u.def.section->output_section->vma - && h_list->h->root.u.def.section->output_offset - == h->root.u.def.section->output_offset - && m_list->rel_backup.r_addend == rel_backup.r_addend) - { - m_list->times++; - m_list->irel = jrel; - while (h_list->h != h && h_list->next) - h_list = h_list->next; - if (h_list->h != h) - { - struct elf_link_hash_entry_list *h_list_new; - - h_list_new = (struct elf_link_hash_entry_list *) - bfd_malloc (sizeof (struct elf_link_hash_entry_list)); - h_list->next = h_list_new; - h_list_new->h = h; - h_list_new->next = NULL; - } - break; - } - /* The sethi case may have different address but the - hi20 is the same. */ - else if (ELF32_R_TYPE (jrel->r_info) == R_NDS32_HI20_RELA - && m_list->next == NULL) - { - struct elf_link_hash_entry_mul_list *m_list_new; - struct elf_link_hash_entry_list *h_list_new; - - m_list_new = (struct elf_link_hash_entry_mul_list *) - bfd_malloc (sizeof (struct elf_link_hash_entry_mul_list)); - h_list_new = (struct elf_link_hash_entry_list *) - bfd_malloc (sizeof (struct elf_link_hash_entry_list)); - m_list->next = m_list_new; - m_list_new->h_list = h_list_new; - m_list_new->rel_backup = rel_backup; - m_list_new->times = 1; - m_list_new->irel = jrel; - m_list_new->next = NULL; - h_list_new->h = h; - h_list_new->next = NULL; - break; - } - m_list = m_list->next; - } - if (!m_list) - { - off += 4; - continue; - } - } - } - else - { - /* Local symbol and insn without relocation*/ - entry->times++; - entry->rel_backup = rel_backup; - } - - /* Use in sethi insn with constant and global symbol in same format. */ - if (!jrel) - entry->const_insn = 1; - else - entry->irel = jrel; - entry->sec = isec; - off += 4; - } - } - return TRUE; + return sec; } - -/* Set the _ITB_BASE, and point it to ex9 table. */ - -bfd_boolean -nds32_elf_ex9_itb_base (struct bfd_link_info *link_info) -{ - bfd *abfd; - asection *sec; - bfd *output_bfd = NULL; - struct bfd_link_hash_entry *bh = NULL; - - if (is_ITB_BASE_set == 1) - return TRUE; - - is_ITB_BASE_set = 1; - - bh = bfd_link_hash_lookup (link_info->hash, "_ITB_BASE_", FALSE, FALSE, TRUE); - - if (bh && (bh->type == bfd_link_hash_defined - || bh->type == bfd_link_hash_defweak)) - return TRUE; - - for (abfd = link_info->input_bfds; abfd != NULL; - abfd = abfd->link.next) - { - sec = bfd_get_section_by_name (abfd, ".ex9.itable"); - if (sec != NULL) - { - output_bfd = sec->output_section->owner; - break; - } - } - if (output_bfd == NULL) - { - output_bfd = link_info->output_bfd; - if (output_bfd->sections == NULL) - return TRUE; - else - sec = bfd_abs_section_ptr; - } - bh = bfd_link_hash_lookup (link_info->hash, "_ITB_BASE_", - FALSE, FALSE, TRUE); - return (_bfd_generic_link_add_one_symbol - (link_info, output_bfd, "_ITB_BASE_", - BSF_GLOBAL | BSF_WEAK, sec, 0, - (const char *) NULL, FALSE, get_elf_backend_data - (output_bfd)->collect, &bh)); -} /* End EX9.IT */ #define ELF_ARCH bfd_arch_nds32 #define ELF_MACHINE_CODE EM_NDS32 #define ELF_MAXPAGESIZE 0x1000 -#define ELF_TARGET_ID NDS32_ELF_DATA +#define ELF_TARGET_ID NDS32_ELF_DATA #define TARGET_BIG_SYM nds32_elf32_be_vec #define TARGET_BIG_NAME "elf32-nds32be" @@ -15448,7 +15265,7 @@ nds32_elf_ex9_itb_base (struct bfd_link_info *link_info) #define bfd_elf32_bfd_relax_section nds32_elf_relax_section #define bfd_elf32_bfd_set_private_flags nds32_elf_set_private_flags -#define bfd_elf32_mkobject nds32_elf_mkobject +#define bfd_elf32_mkobject nds32_elf_mkobject #define elf_backend_action_discarded nds32_elf_action_discarded #define elf_backend_add_symbol_hook nds32_elf_add_symbol_hook #define elf_backend_check_relocs nds32_elf_check_relocs @@ -15469,7 +15286,9 @@ nds32_elf_ex9_itb_base (struct bfd_link_info *link_info) #define elf_backend_final_write_processing nds32_elf_final_write_processing #define elf_backend_special_sections nds32_elf_special_sections #define bfd_elf32_bfd_get_relocated_section_contents \ - nds32_elf_get_relocated_section_contents + nds32_elf_get_relocated_section_contents +#define bfd_elf32_bfd_is_target_special_symbol nds32_elf_is_target_special_symbol +#define elf_backend_maybe_function_sym nds32_elf_maybe_function_sym #define elf_backend_can_gc_sections 1 #define elf_backend_can_refcount 1 @@ -15480,7 +15299,6 @@ nds32_elf_ex9_itb_base (struct bfd_link_info *link_info) #define elf_backend_may_use_rel_p 1 #define elf_backend_default_use_rela_p 1 #define elf_backend_may_use_rela_p 1 -#define elf_backend_dtrel_excludes_plt 1 #include "elf32-target.h" diff --git binutils-2.30/bfd/elf32-nds32.h binutils-2.30-nds32/bfd/elf32-nds32.h index 7e09e01a3f..fda4155ab3 100644 --- binutils-2.30/bfd/elf32-nds32.h +++ binutils-2.30-nds32/bfd/elf32-nds32.h @@ -22,6 +22,8 @@ #ifndef ELF32_NDS32_H #define ELF32_NDS32_H +#include "bfd_stdint.h" + #ifdef __cplusplus extern "C" { #endif @@ -46,6 +48,13 @@ extern "C" { #define R_NDS32_RELAX_ENTRY_EX9_FLAG (1 << 2) /* Enable IFC optimization for this section. */ #define R_NDS32_RELAX_ENTRY_IFC_FLAG (1 << 3) +/* Two bits for ICT to comply with files without directive. */ +/* ICT small model. */ +#define R_NDS32_RELAX_ENTRY_ICT_SMALL (0x2 << 4) +/* ICT large model. */ +#define R_NDS32_RELAX_ENTRY_ICT_LARGE (0x3 << 4) +/* Mask for get ict bits. */ +#define R_NDS32_RELAX_ENTRY_ICT_MASK (0x3 << 4) /* Relocation flags for R_NDS32_INSN16. */ @@ -66,8 +75,6 @@ extern "C" { /* NOT_OMIT_FP_FLAG is set if this region is not worth for fp-as-gp. */ #define R_NDS32_RELAX_REGION_NOT_OMIT_FP_FLAG (1 << 1) -/* Suppress EX9 optimization in the region. */ -#define R_NDS32_RELAX_REGION_NO_EX9_FLAG (1 << 2) /* A Innermost loop region. Some optimizations is suppressed in this region due to performance drop. */ #define R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG (1 << 4) @@ -91,35 +98,57 @@ enum NDS32_RELAX_NONE_ROUND = 0, NDS32_RELAX_NORMAL_ROUND, NDS32_RELAX_JUMP_IFC_ROUND, + NDS32_RELAX_IFC_ROUND, NDS32_RELAX_EX9_BUILD_ROUND, NDS32_RELAX_EX9_REPLACE_ROUND, NDS32_RELAX_EMPTY_ROUND }; -/* Optimization status mask. */ -#define NDS32_RELAX_JUMP_IFC_DONE (1 << 0) -#define NDS32_RELAX_EX9_DONE (1 << 1) +/* Security tag. */ +enum +{ + NDS32_SECURITY_NONE = 0, + NDS32_SECURITY_START, + NDS32_SECURITY_RESTART, + NDS32_SECURITY_END +}; /* Optimization turn on mask. */ -#define NDS32_RELAX_JUMP_IFC_ON (1 << 0) +#define NDS32_RELAX_IFC_ON (1 << 0) #define NDS32_RELAX_EX9_ON (1 << 1) extern void nds32_insertion_sort (void *, size_t, size_t, int (*) (const void *, const void *)); -extern int nds32_elf_ex9_init (void); -extern int nds32_convert_32_to_16 (bfd *, uint32_t, uint16_t *, int *); -extern int nds32_convert_16_to_32 (bfd *, uint16_t, uint32_t *); -extern void bfd_elf32_nds32_set_target_option (struct bfd_link_info *, - int, int, FILE *, int, - int, int, int, FILE *, - FILE *, int, int, - bfd_boolean, bfd_boolean); +struct section_id_list_t +{ + int id; + struct section_id_list_t *next; +}; + +extern struct section_id_list_t * +elf32_nds32_lookup_section_id (int, struct section_id_list_t **); +extern int elf32_nds32_check_relax_group (bfd *, asection *); +extern int elf32_nds32_unify_relax_group (bfd *, asection *); +extern int nds32_elf_unify_tls_model (bfd *, asection *, bfd_byte *, + struct bfd_link_info *); + +extern void bfd_elf32_nds32_set_target_option (struct bfd_link_info *, int, int, + FILE *, int, int, int, int, int, + int, char *); +extern void bfd_elf32_nds32_append_section (struct bfd_link_info*, bfd *); +extern int nds32_convert_32_to_16 (bfd *, uint32_t, uint16_t *, int *); +extern int nds32_convert_16_to_32 (bfd *, uint16_t, uint32_t *); #define nds32_elf_hash_table(info) \ (elf_hash_table_id ((struct elf_link_hash_table *) ((info)->hash)) \ - == NDS32_ELF_DATA ? \ - ((struct elf_nds32_link_hash_table *) ((info)->hash)) : NULL) + == NDS32_ELF_DATA ? ((struct elf_nds32_link_hash_table *) ((info)->hash)) : NULL) + +#define elf32_nds32_compute_jump_table_size(htab) \ + ((htab)->next_tls_desc_index * 4) + +#define elf32_nds32_local_tlsdesc_gotent(bfd) \ + (elf_nds32_tdata (bfd)->local_tlsdesc_gotent) /* Hash table structure for target nds32. There are some members to save target options passed from nds32elf.em to bfd. */ @@ -144,12 +173,34 @@ struct elf_nds32_link_hash_table int target_optimize; /* Switch optimization. */ int relax_status; /* Finished optimization. */ int relax_round; /* Going optimization. */ - FILE *ex9_export_file; /* --mexport-ex9= */ - FILE *ex9_import_file; /* --mimport-ex9= */ - int update_ex9_table; /* --mupdate-ex9. */ - int ex9_limit; - bfd_boolean ex9_loop_aware; /* Ignore ex9 if inside a loop. */ - bfd_boolean ifc_loop_aware; /* Ignore ifc if inside a loop. */ + bfd_boolean hyper_relax; /* Relax for symbol not in RW sections. */ + int tls_desc_trampoline; /* --m[no-]tlsdesc-trampoline. */ + + /* The offset into splt of the PLT entry for the TLS descriptor + resolver. Special values are 0, if not necessary (or not found + to be necessary yet), and -1 if needed but not determined + yet. */ + bfd_vma dt_tlsdesc_plt; + + /* The offset into sgot of the GOT entry used by the PLT entry + above. */ + bfd_vma dt_tlsdesc_got; + + /* Offset in .plt section of tls_nds32_trampoline. */ + bfd_vma tls_trampoline; + + /* The index of the next unused R_NDS32_TLS_DESC slot in .rel.plt. */ + bfd_vma next_tls_desc_index; + + /* How many R_NDS32_TLS_DESC relocations were generated so far. */ + bfd_vma num_tls_desc; + + /* The amount of space used by the reserved portion of the sgotplt + section, plus whatever space is used by the jump slots. */ + bfd_vma sgotplt_jump_table_size; + + /* True if the target uses REL relocations. */ + int use_rel; }; #ifdef __cplusplus diff --git binutils-2.30/bfd/libbfd.h binutils-2.30-nds32/bfd/libbfd.h index 2f5f16e776..ff89105086 100644 --- binutils-2.30/bfd/libbfd.h +++ binutils-2.30-nds32/bfd/libbfd.h @@ -1872,6 +1872,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_NDS32_SDA17S2", "BFD_RELOC_NDS32_SDA18S1", "BFD_RELOC_NDS32_SDA19S0", + "BFD_RELOC_NDS32_SECURITY_16", "BFD_RELOC_NDS32_GOT20", "BFD_RELOC_NDS32_9_PLTREL", "BFD_RELOC_NDS32_25_PLTREL", @@ -1955,18 +1956,39 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_NDS32_17IFC_PCREL", "BFD_RELOC_NDS32_10IFCU_PCREL", "BFD_RELOC_NDS32_TPOFF", + "BFD_RELOC_NDS32_GOTTPOFF", "BFD_RELOC_NDS32_TLS_LE_HI20", "BFD_RELOC_NDS32_TLS_LE_LO12", - "BFD_RELOC_NDS32_TLS_LE_ADD", - "BFD_RELOC_NDS32_TLS_LE_LS", - "BFD_RELOC_NDS32_GOTTPOFF", - "BFD_RELOC_NDS32_TLS_IE_HI20", - "BFD_RELOC_NDS32_TLS_IE_LO12S2", - "BFD_RELOC_NDS32_TLS_TPOFF", "BFD_RELOC_NDS32_TLS_LE_20", "BFD_RELOC_NDS32_TLS_LE_15S0", "BFD_RELOC_NDS32_TLS_LE_15S1", "BFD_RELOC_NDS32_TLS_LE_15S2", + "BFD_RELOC_NDS32_TLS_LE_ADD", + "BFD_RELOC_NDS32_TLS_LE_LS", + "BFD_RELOC_NDS32_TLS_IE_HI20", + "BFD_RELOC_NDS32_TLS_IE_LO12", + "BFD_RELOC_NDS32_TLS_IE_LO12S2", + "BFD_RELOC_NDS32_TLS_IEGP_HI20", + "BFD_RELOC_NDS32_TLS_IEGP_LO12", + "BFD_RELOC_NDS32_TLS_IEGP_LO12S2", + "BFD_RELOC_NDS32_TLS_IEGP_LW", + "BFD_RELOC_NDS32_TLS_DESC", + "BFD_RELOC_NDS32_TLS_DESC_HI20", + "BFD_RELOC_NDS32_TLS_DESC_LO12", + "BFD_RELOC_NDS32_TLS_DESC_20", + "BFD_RELOC_NDS32_TLS_DESC_SDA17S2", + "BFD_RELOC_NDS32_TLS_DESC_ADD", + "BFD_RELOC_NDS32_TLS_DESC_FUNC", + "BFD_RELOC_NDS32_TLS_DESC_CALL", + "BFD_RELOC_NDS32_TLS_DESC_MEM", + "BFD_RELOC_NDS32_REMOVE", + "BFD_RELOC_NDS32_GROUP", + "BFD_RELOC_NDS32_ICT", + "BFD_RELOC_NDS32_ICT_HI20", + "BFD_RELOC_NDS32_ICT_LO12", + "BFD_RELOC_NDS32_ICT_25PC", + "BFD_RELOC_NDS32_ICT_LO12S2", + "BFD_RELOC_NDS32_LSI", "BFD_RELOC_V850_9_PCREL", "BFD_RELOC_V850_22_PCREL", "BFD_RELOC_V850_SDA_16_16_OFFSET", diff --git binutils-2.30/bfd/reloc.c binutils-2.30-nds32/bfd/reloc.c index a1353a281b..0d96e13027 100644 --- binutils-2.30/bfd/reloc.c +++ binutils-2.30-nds32/bfd/reloc.c @@ -4182,6 +4182,10 @@ ENUMDOC This is a 19-bit reloc containing the small data area 19-bit signed offset and shift left by 0 for use in lbi.gp, sbi.gp... ENUM + BFD_RELOC_NDS32_SECURITY_16 +ENUMDOC + This is a 24-bit reloc for security check sum. +ENUM BFD_RELOC_NDS32_GOT20 ENUMX BFD_RELOC_NDS32_9_PLTREL @@ -4375,33 +4379,62 @@ ENUMDOC ENUM BFD_RELOC_NDS32_TPOFF ENUMX + BFD_RELOC_NDS32_GOTTPOFF +ENUMX BFD_RELOC_NDS32_TLS_LE_HI20 ENUMX BFD_RELOC_NDS32_TLS_LE_LO12 ENUMX + BFD_RELOC_NDS32_TLS_LE_20 +ENUMX + BFD_RELOC_NDS32_TLS_LE_15S0 +ENUMX + BFD_RELOC_NDS32_TLS_LE_15S1 +ENUMX + BFD_RELOC_NDS32_TLS_LE_15S2 +ENUMX BFD_RELOC_NDS32_TLS_LE_ADD ENUMX BFD_RELOC_NDS32_TLS_LE_LS ENUMX - BFD_RELOC_NDS32_GOTTPOFF -ENUMX BFD_RELOC_NDS32_TLS_IE_HI20 ENUMX + BFD_RELOC_NDS32_TLS_IE_LO12 +ENUMX BFD_RELOC_NDS32_TLS_IE_LO12S2 ENUMX - BFD_RELOC_NDS32_TLS_TPOFF + BFD_RELOC_NDS32_TLS_IEGP_HI20 ENUMX - BFD_RELOC_NDS32_TLS_LE_20 + BFD_RELOC_NDS32_TLS_IEGP_LO12 ENUMX - BFD_RELOC_NDS32_TLS_LE_15S0 + BFD_RELOC_NDS32_TLS_IEGP_LO12S2 ENUMX - BFD_RELOC_NDS32_TLS_LE_15S1 + BFD_RELOC_NDS32_TLS_IEGP_LW ENUMX - BFD_RELOC_NDS32_TLS_LE_15S2 + BFD_RELOC_NDS32_TLS_DESC +ENUMX + BFD_RELOC_NDS32_TLS_DESC_HI20 +ENUMX + BFD_RELOC_NDS32_TLS_DESC_LO12 +ENUMX + BFD_RELOC_NDS32_TLS_DESC_20 +ENUMX + BFD_RELOC_NDS32_TLS_DESC_SDA17S2 +ENUMX + BFD_RELOC_NDS32_TLS_DESC_ADD +ENUMX + BFD_RELOC_NDS32_TLS_DESC_FUNC +ENUMX + BFD_RELOC_NDS32_TLS_DESC_CALL +ENUMX + BFD_RELOC_NDS32_TLS_DESC_MEM +ENUMX + BFD_RELOC_NDS32_REMOVE +ENUMX + BFD_RELOC_NDS32_GROUP ENUMDOC For TLS. - ENUM BFD_RELOC_V850_9_PCREL ENUMDOC diff --git binutils-2.30/gas/config.in binutils-2.30-nds32/gas/config.in index 0855179696..551434a45b 100644 --- binutils-2.30/gas/config.in +++ binutils-2.30-nds32/gas/config.in @@ -202,6 +202,9 @@ /* Define default value for nds32_audio_ext */ #undef NDS32_DEFAULT_AUDIO_EXT +/* Define default value for nds32_dsp_ext */ +#undef NDS32_DEFAULT_DSP_EXT + /* Define default value for nds32_dx_regs */ #undef NDS32_DEFAULT_DX_REGS @@ -214,6 +217,12 @@ /* Define default value for nds32_string_ext */ #undef NDS32_DEFAULT_STRING_EXT +/* Define default value for nds32_zol_ext */ +#undef NDS32_DEFAULT_ZOL_EXT + +/* Defined for linux toolchain */ +#undef NDS32_LINUX_TOOLCHAIN + /* Define if environ is not declared in system header files. */ #undef NEED_DECLARATION_ENVIRON diff --git binutils-2.30/gas/config/tc-nds32.c binutils-2.30-nds32/gas/config/tc-nds32.c index b2741b8213..f8cbd80edc 100644 --- binutils-2.30/gas/config/tc-nds32.c +++ binutils-2.30-nds32/gas/config/tc-nds32.c @@ -19,6 +19,8 @@ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ +#pragma GCC diagnostic ignored "-Wstack-usage=" + #include "as.h" #include "safe-ctype.h" #include "subsegs.h" @@ -35,6 +37,8 @@ #include "opcode/nds32.h" #include +#include +#include /* GAS definitions. */ @@ -66,6 +70,8 @@ struct nds32_relocs_pattern struct nds32_opcode *opcode; char *where; struct nds32_relocs_pattern *next; + /* Assembled instruction bytes. */ + uint32_t insn; }; /* Suffix name and relocation. */ @@ -73,7 +79,6 @@ struct suffix_name { const char *suffix; short unsigned int reloc; - int pic; }; static int vec_size = 0; /* If the assembly code is generated by compiler, it is supposed to have @@ -87,11 +92,7 @@ static struct hash_control *nds32_hint_hash; /* Generate relocation for relax or not, and the default is true. */ static int enable_relax_relocs = 1; -/* The value will be used in RELAX_ENTRY. */ -static int enable_relax_ex9 = 0; -/* The value will be used in RELAX_ENTRY. */ -static int enable_relax_ifc = 0; -/* Save option -O for performance. */ +/* Save option -O for perfomance. */ static int optimize = 0; /* Save option -Os for code size. */ static int optimize_for_space = 0; @@ -99,1768 +100,1798 @@ static int optimize_for_space = 0; static int label_exist = 0; /* Flag to save state in omit_fp region. */ static int in_omit_fp = 0; -extern struct nds32_keyword keyword_gpr[]; +extern keyword_t keyword_gpr[]; /* Tag there is relax relocation having to link. */ static bfd_boolean relaxing = FALSE; +/* Save security status. */ +static bfd_boolean crcing = FALSE; +/* Inline asm status. */ +static bfd_boolean inline_asm = FALSE; +/* v3 is compatiable with v3f/v3s. */ +static bfd_boolean compatible_abi = FALSE; +/* ICT model. */ +enum ict_option { + ICT_NONE = 0, + ICT_SMALL, + ICT_LARGE +}; +static enum ict_option ict_flag = ICT_NONE; +/* True if ICT existed. */ +static bfd_boolean ict_exist = FALSE; static struct hash_control *nds32_relax_info_hash; +/* Branch pattern. */ static relax_info_t relax_table[] = { - { - "jal", /* opcode */ - BR_RANGE_S16M, /* br_range */ - {{0, 0, 0, FALSE}}, /* cond_field */ - { - { - INSN_JAL /* jal label */ - }, /* BR_RANGE_S256 */ - { - INSN_JAL /* jal label */ - }, /* BR_RANGE_S16K */ - { - INSN_JAL /* jal label */ - }, /* BR_RANGE_S64K */ - { - INSN_JAL /* jal label */ - }, /* BR_RANGE_S16M */ - { - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JRAL_TA - }, /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ - {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ - {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ - {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ - {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 4, 4, 12}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ - { - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, 0, BFD_RELOC_NDS32_HI20}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL4}, - {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "bltzal", /* opcode */ - BR_RANGE_S64K, /* br_range */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* cond_field */ - { - { - INSN_BLTZAL /* bltzal $rt, label */ - }, /* BR_RANGE_S256 */ - { - INSN_BLTZAL /* bltzal $rt, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BLTZAL /* bltzal $rt, label */ - }, /* BR_RANGE_S64K */ - { - INSN_BGEZ, /* bgez $rt, $1 */ - INSN_JAL /* jal label */ - }, /* BR_RANGE_S16M */ - { - INSN_BGEZ, /* bgez $rt, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JRAL_TA /* jral $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S256 */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S64K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16M */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 4, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ - { - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "bgezal", /* opcode */ - BR_RANGE_S64K, /* br_range */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* cond_field */ - { - { - INSN_BGEZAL /* bgezal $rt, label */ - }, /* BR_RANGE_S256 */ - { - INSN_BGEZAL /* bgezal $rt, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BGEZAL /* bgezal $rt, label */ - }, /* BR_RANGE_S64K */ - { - INSN_BLTZ, /* bltz $rt, $1 */ - INSN_JAL /* jal label */ - }, /* BR_RANGE_S16M */ - { - INSN_BLTZ, /* bltz $rt, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JRAL_TA /* jral $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S256 */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S64K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16M */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 4, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ - { - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "j", /* opcode */ - BR_RANGE_S16M, /* br_range */ - {{0, 0, 0, FALSE}}, /* cond_field */ - { - { - (INSN_J8 << 16) /* j8 label */ - }, /* BR_RANGE_S256 */ - { - INSN_J /* j label */ - }, /* BR_RANGE_S16K */ - { - INSN_J /* j label */ - }, /* BR_RANGE_S64K */ - { - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - }, /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ - {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ - {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ - {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ - {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {2, 4, 4, 4, 12}, /* relax_code_size */ - {2, 4, 4, 4, 4}, /* relax_branch_isize */ - { - { - {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, 0, BFD_RELOC_NDS32_HI20}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4}, - {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "j8", /* opcode */ - BR_RANGE_S256, /* br_range */ - {{0, 0, 0, FALSE}}, /* cond_field */ - { - { - (INSN_J8 << 16) /* j8 label */ - }, /* BR_RANGE_S256 */ - { - INSN_J /* j label */ - }, /* BR_RANGE_S16K */ - { - INSN_J /* j label */ - }, /* BR_RANGE_S64K */ - { - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - }, /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ - {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ - {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ - {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ - {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {2, 4, 4, 4, 12}, /* relax_code_size */ - {2, 4, 4, 4, 4}, /* relax_branch_isize */ - { - { - {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, 0, BFD_RELOC_NDS32_HI20}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4}, - {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "beqz", /* opcode */ - BR_RANGE_S64K, /* br_range */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* cond_field */ - { - { - INSN_BEQZ /* beqz $rt, label */ - }, /* BR_RANGE_S256 */ - { - INSN_BEQZ /* beqz $rt, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BEQZ /* beqz $rt, label */ - }, /* BR_RANGE_S64K */ - { - INSN_BNEZ, /* bnez $rt, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_BNEZ, /* bnez $rt, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S256 */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S64K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16M */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 4, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ - { - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "bgez", /* opcode */ - BR_RANGE_S64K, /* br_range */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* cond_field */ - { - { - INSN_BGEZ /* bgez $rt, label */ - }, /* BR_RANGE_S256 */ - { - INSN_BGEZ /* bgez $rt, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BGEZ /* bgez $rt, label */ - }, /* BR_RANGE_S64K */ - { - INSN_BLTZ, /* bltz $rt, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_BLTZ, /* bltz $rt, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S256 */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S64K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16M */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 4, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ - { - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "bnez", /* opcode */ - BR_RANGE_S64K, /* br_range */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* cond_field */ - { - { - INSN_BNEZ /* bnez $rt, label */ - }, /* BR_RANGE_S256 */ - { - INSN_BNEZ /* bnez $rt, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BNEZ /* bnez $rt, label */ - }, /* BR_RANGE_S64K */ - { - INSN_BEQZ, /* beqz $rt, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_BEQZ, /* beqz $rt, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S256 */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S64K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16M */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 4, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ - { - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "bgtz", /* opcode */ - BR_RANGE_S64K, /* br_range */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* cond_field */ - { - { - INSN_BGTZ /* bgtz $rt, label */ - }, /* BR_RANGE_S256 */ - { - INSN_BGTZ /* bgtz $rt, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BGTZ /* bgtz $rt, label */ - }, /* BR_RANGE_S64K */ - { - INSN_BLEZ, /* blez $rt, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_BLEZ, /* blez $rt, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S256 */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S64K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16M */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 4, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ - { - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "blez", /* opcode */ - BR_RANGE_S64K, /* br_range */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* cond_field */ - { - { - INSN_BLEZ /* blez $rt, label */ - }, /* BR_RANGE_S256 */ - { - INSN_BLEZ /* blez $rt, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BLEZ /* blez $rt, label */ - }, /* BR_RANGE_S64K */ - { - INSN_BGTZ, /* bgtz $rt, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_BGTZ, /* bgtz $rt, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S256 */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S64K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16M */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 4, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ - { - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "bltz", /* opcode */ - BR_RANGE_S64K, /* br_range */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* cond_field */ - { - { - INSN_BLTZ /* bltz $rt, label */ - }, /* BR_RANGE_S256 */ - { - INSN_BLTZ /* bltz $rt, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BLTZ /* bltz $rt, label */ - }, /* BR_RANGE_S64K */ - { - INSN_BGEZ, /* bgez $rt, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_BGEZ, /* bgez $rt, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S256 */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S64K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16M */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 4, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ - { - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "beq", /* opcode */ - BR_RANGE_S16K, /* br_range */ - { - {0, 20, 0x1F, FALSE}, - {0, 15, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* cond_field */ - { - { - INSN_BEQ /* beq $rt, $ra, label */ - }, /* BR_RANGE_S256 */ - { - INSN_BEQ /* beq $rt, $ra, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BNE, /* bne $rt, $ra, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S64K */ - { - INSN_BNE, /* bne $rt, $ra, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_BNE, /* bne $rt, $ra, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - { - {0, 20, 0x1F, FALSE}, - {0, 15, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S256 */ - { - {0, 20, 0x1F, FALSE}, - {0, 15, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16K */ - { - {0, 20, 0x1F, FALSE}, - {0, 15, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S64K */ - { - {0, 20, 0x1F, FALSE}, - {0, 15, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16M */ - { - {0, 20, 0x1F, FALSE}, - {0, 15, 0x1F, FALSE}, - {0, 0, 0, FALSE} - } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 8, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ - { - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {4, 4, NDS32_ABS, BFD_RELOC_NDS32_EMPTY}, - {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "bne", /* opcode */ - BR_RANGE_S16K, /* br_range */ - { - {0, 20, 0x1F, FALSE}, - {0, 15, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* cond_field */ - { - { - INSN_BNE /* bne $rt, $ra, label */ - }, /* BR_RANGE_S256 */ - { - INSN_BNE /* bne $rt, $ra, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BEQ, /* beq $rt, $ra, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S64K */ - { - INSN_BEQ, /* beq $rt, $ra, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_BEQ, /* beq $rt, $ra, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - { - {0, 20, 0x1F, FALSE}, - {0, 15, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S256 */ - { - {0, 20, 0x1F, FALSE}, - {0, 15, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16K */ - { - {0, 20, 0x1F, FALSE}, - {0, 15, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S64K */ - { - {0, 20, 0x1F, FALSE}, - {0, 15, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16M */ - { - {0, 20, 0x1F, FALSE}, - {0, 15, 0x1F, FALSE}, - {0, 0, 0, FALSE} - } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 8, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ - { - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "beqz38", /* opcode */ - BR_RANGE_S256, /* br_range */ - { - {0, 8, 0x7, FALSE}, - {0, 0, 0, FALSE} - }, /* cond_field */ - { - { - INSN_BEQZ38 << 16 /* beqz $rt, label */ - }, /* BR_RANGE_S256 */ - { - INSN_BEQZ /* beqz $rt, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BEQZ /* beqz $rt, label */ - }, /* BR_RANGE_S64K */ - { - INSN_BNEZ, /* bnez $rt, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_BNEZ, /* bnez $rt, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - { - {0, 8, 0x7, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S256 */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S64K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16M */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {2, 4, 4, 8, 16}, /* relax_code_size */ - {2, 4, 4, 4, 4}, /* relax_branch_isize */ - { - { - {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "bnez38", /* opcode */ - BR_RANGE_S256, /* br_range */ - { - {0, 8, 0x7, FALSE}, - {0, 0, 0, FALSE} - }, /* cond_field */ - { - { - INSN_BNEZ38 << 16 /* bnez $rt, label */ - }, /* BR_RANGE_S256 */ - { - INSN_BNEZ /* bnez $rt, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BNEZ /* bnez $rt, label */ - }, /* BR_RANGE_S64K */ - { - INSN_BEQZ, /* beqz $rt, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_BEQZ, /* beqz $rt, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ { - { - {0, 8, 0x7, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S256 */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S64K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16M */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {2, 4, 4, 8, 16}, /* relax_code_size */ - {2, 4, 4, 4, 4}, /* relax_branch_isize */ + .opcode = "jal", + .br_range = BR_RANGE_S16M, + .cond_field = { + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_JAL}, /* jal label */ + .relax_code_size[BR_RANGE_S256] = 4, + .relax_branch_isize[BR_RANGE_S256] = 4, + .relax_fixup[BR_RANGE_S256] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_JAL}, /* jal label */ + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_JAL}, /* jal label */ + .relax_code_size[BR_RANGE_S64K] = 4, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_JAL}, /* jal label */ + .relax_code_size[BR_RANGE_S16M] = 4, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JRAL_TA}, /* jral $ta */ + .relax_code_size[BR_RANGE_U4G] = 12, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, 0, BFD_RELOC_NDS32_HI20}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL4}, + {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "beqzs8", /* opcode */ - BR_RANGE_S256, /* br_range */ - {{0, 0, 0, FALSE}}, /* cond_field */ + .opcode = "bgezal", + .br_range = BR_RANGE_S64K, + .cond_field = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BGEZAL}, /* bgezal $rt, label */ + .relax_code_condition[BR_RANGE_S256] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S256] = 4, + .relax_branch_isize[BR_RANGE_S256] = 4, + .relax_fixup[BR_RANGE_S256] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_BGEZAL}, /* bgezal $rt, label */ + .relax_code_condition[BR_RANGE_S16K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BGEZAL}, /* bgezal $rt, label */ + .relax_code_condition[BR_RANGE_S64K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S64K] = 4, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BLTZ, /* bltz $rt, $1 */ + INSN_JAL}, /* jal label */ + .relax_code_condition[BR_RANGE_S16M] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BLTZ, /* bltz $rt, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JRAL_TA}, /* jral $ta */ + .relax_code_condition[BR_RANGE_U4G] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - INSN_BEQZS8 << 16 /* beqz $r15, label */ - }, /* BR_RANGE_S256 */ - { - INSN_BEQZ_TA /* bnez $rt, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BEQZ_TA /* bnez $rt, label */ - }, /* BR_RANGE_S64K */ - { - INSN_BNEZ_TA, /* bnez $r15, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_BNEZ_TA, /* bnez $r15, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ - {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ - {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ - {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ - {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {2, 4, 4, 8, 16}, /* relax_code_size */ - {2, 4, 4, 4, 4}, /* relax_branch_isize */ + .opcode = "bltzal", + .br_range = BR_RANGE_S64K, + .cond_field = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BLTZAL}, /* bltzal $rt, label */ + .relax_code_condition[BR_RANGE_S256] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S256] = 4, + .relax_branch_isize[BR_RANGE_S256] = 4, + .relax_fixup[BR_RANGE_S256] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_BLTZAL}, /* bltzal $rt, label */ + .relax_code_condition[BR_RANGE_S16K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BLTZAL}, /* bltzal $rt, label */ + .relax_code_condition[BR_RANGE_S64K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S64K] = 4, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BGEZ, /* bgez $rt, $1 */ + INSN_JAL}, /* jal label */ + .relax_code_condition[BR_RANGE_S16M] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BGEZ, /* bgez $rt, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JRAL_TA}, /* jral $ta */ + .relax_code_condition[BR_RANGE_U4G] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "bnezs8", /* opcode */ - BR_RANGE_S256, /* br_range */ - {{0, 0, 0, FALSE}}, /* cond_field */ + .opcode = "j", + .br_range = BR_RANGE_S16M, + .cond_field = { + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + (INSN_J8 << 16)}, /* j8 label */ + .relax_code_size[BR_RANGE_S256] = 2, + .relax_branch_isize[BR_RANGE_S256] = 2, + .relax_fixup[BR_RANGE_S256] = { + {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_J}, /* j label */ + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_J}, /* j label */ + .relax_code_size[BR_RANGE_S64K] = 4, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_J}, /* j label */ + .relax_code_size[BR_RANGE_S16M] = 4, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ta */ + .relax_code_size[BR_RANGE_U4G] = 12, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, 0, BFD_RELOC_NDS32_HI20}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4}, + {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - INSN_BNEZS8 << 16 /* bnez $r15, label */ - }, /* BR_RANGE_S256 */ - { - INSN_BNEZ_TA /* bnez $r15, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BNEZ_TA /* bnez $r15, label */ - }, /* BR_RANGE_S64K */ - { - INSN_BEQZ_TA, /* beqz $r15, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_BEQZ_TA, /* beqz $r15, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ - {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ - {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ - {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ - {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {2, 4, 4, 8, 16}, /* relax_code_size */ - {2, 4, 4, 4, 4}, /* relax_branch_isize */ + .opcode = "j8", + .br_range = BR_RANGE_S256, + .cond_field = { + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + (INSN_J8 << 16)}, /* j8 label */ + .relax_code_size[BR_RANGE_S256] = 2, + .relax_branch_isize[BR_RANGE_S256] = 2, + .relax_fixup[BR_RANGE_S256] = { + {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_J}, /* j label */ + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_J}, /* j label */ + .relax_code_size[BR_RANGE_S64K] = 4, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_J}, /* j label */ + .relax_code_size[BR_RANGE_S16M] = 4, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ta */ + .relax_code_size[BR_RANGE_U4G] = 12, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, 0, BFD_RELOC_NDS32_HI20}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4}, + {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "bnes38", /* opcode */ - BR_RANGE_S256, /* br_range */ + .opcode = "beqz", + .br_range = BR_RANGE_S64K, + .cond_field = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + /* We do not use beqz38 and beqzs8 here directly because we + don't want to check register number for specail condition. */ + .relax_code_seq[BR_RANGE_S256] = { + INSN_BEQZ}, /* beqz $rt, label */ + .relax_code_condition[BR_RANGE_S256] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S256] = 4, + .relax_branch_isize[BR_RANGE_S256] = 4, + .relax_fixup[BR_RANGE_S256] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_BEQZ}, /* beqz $rt, label */ + .relax_code_condition[BR_RANGE_S16K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BEQZ}, /* beqz $rt, label */ + .relax_code_condition[BR_RANGE_S64K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S64K] = 4, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BNEZ, /* bnez $rt, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S16M] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + /* bnez range is 17 pcrel, but it use 15 pcrel here since link time + relaxtion. If 17 pcrel can reach, it do not have to + use S16M. Therefore, 15 pcrel is just for linker to + distinguish LONGJUMP5 and LONGJUMP6. */ + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BNEZ, /* bnez $rt, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ta */ + .relax_code_condition[BR_RANGE_U4G] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - {0, 8, 0x7, FALSE}, - {0, 0, 0, FALSE} - }, /* cond_field */ + .opcode = "bgez", + .br_range = BR_RANGE_S64K, + .cond_field = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BGEZ}, /* bgez $rt, label */ + .relax_code_condition[BR_RANGE_S256] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S256] = 4, + .relax_branch_isize[BR_RANGE_S256] = 4, + .relax_fixup[BR_RANGE_S256] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_BGEZ}, /* bgez $rt, label */ + .relax_code_condition[BR_RANGE_S16K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BGEZ}, /* bgez $rt, label */ + .relax_code_condition[BR_RANGE_S64K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S64K] = 4, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BLTZ, /* bltz $rt, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S16M] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BLTZ, /* bltz $rt, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ta */ + .relax_code_condition[BR_RANGE_U4G] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - INSN_BNES38 << 16 /* bne $rt, $R5, label */ - }, /* BR_RANGE_S256 */ - { - INSN_BNE_R5 /* bne $rt, $R5, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BEQ_R5, /* beq $rt, $R5, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S64K */ - { - INSN_BEQ_R5, /* beq $rt, $R5, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_BEQ_R5, /* beq $rt, $R5, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + .opcode = "bnez", + .br_range = BR_RANGE_S64K, + .cond_field = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BNEZ}, /* bnez $rt, label */ + .relax_code_condition[BR_RANGE_S256] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S256] = 4, + .relax_branch_isize[BR_RANGE_S256] = 4, + .relax_fixup[BR_RANGE_S256] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_BNEZ}, /* bnez $rt, label */ + .relax_code_condition[BR_RANGE_S16K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BNEZ}, /* bnez $rt, label */ + .relax_code_condition[BR_RANGE_S64K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S64K] = 4, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BEQZ, /* beqz $rt, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S16M] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BEQZ, /* beqz $rt, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ta */ + .relax_code_condition[BR_RANGE_U4G] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - {0, 8, 0x7, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S256 */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S64K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16M */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {2, 4, 8, 8, 16}, /* relax_code_size */ - {2, 4, 4, 4, 4}, /* relax_branch_isize */ + .opcode = "bgtz", + .br_range = BR_RANGE_S64K, + .cond_field = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BGTZ}, /* bgtz $rt, label */ + .relax_code_condition[BR_RANGE_S256] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S256] = 4, + .relax_branch_isize[BR_RANGE_S256] = 4, + .relax_fixup[BR_RANGE_S256] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_BGTZ}, /* bgtz $rt, label */ + .relax_code_condition[BR_RANGE_S16K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BGTZ}, /* bgtz $rt, label */ + .relax_code_condition[BR_RANGE_S64K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S64K] = 4, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BLEZ, /* blez $rt, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S16M] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BLEZ, /* blez $rt, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ta */ + .relax_code_condition[BR_RANGE_U4G] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "beqs38", /* opcode */ - BR_RANGE_S256, /* br_range */ + .opcode = "blez", + .br_range = BR_RANGE_S64K, + .cond_field = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BLEZ}, /* blez $rt, label */ + .relax_code_condition[BR_RANGE_S256] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S256] = 4, + .relax_branch_isize[BR_RANGE_S256] = 4, + .relax_fixup[BR_RANGE_S256] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_BLEZ}, /* blez $rt, label */ + .relax_code_condition[BR_RANGE_S16K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BLEZ}, /* blez $rt, label */ + .relax_code_condition[BR_RANGE_S64K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S64K] = 4, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BGTZ, /* bgtz $rt, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S16M] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BGTZ, /* bgtz $rt, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ta */ + .relax_code_condition[BR_RANGE_U4G] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - {0, 8, 0x7, FALSE}, - {0, 0, 0, FALSE} - }, /* cond_field */ + .opcode = "bltz", + .br_range = BR_RANGE_S64K, + .cond_field = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BLTZ}, /* bltz $rt, label */ + .relax_code_condition[BR_RANGE_S256] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S256] = 4, + .relax_branch_isize[BR_RANGE_S256] = 4, + .relax_fixup[BR_RANGE_S256] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_BLTZ}, /* bltz $rt, label */ + .relax_code_condition[BR_RANGE_S16K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BLTZ}, /* bltz $rt, label */ + .relax_code_condition[BR_RANGE_S64K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S64K] = 4, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BGEZ, /* bgez $rt, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S16M] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BGEZ, /* bgez $rt, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ta */ + .relax_code_condition[BR_RANGE_U4G] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE}, + }, + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - INSN_BEQS38 << 16 /* beq $rt, $R5, label */ - }, /* BR_RANGE_S256 */ - { - INSN_BEQ_R5 /* beq $rt, $R5, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BNE_R5, /* bne $rt, $R5, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S64K */ - { - INSN_BNE_R5, /* bne $rt, $R5, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_BNE_R5, /* bne $rt, $R5, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + .opcode = "beq", + .br_range = BR_RANGE_S16K, + .cond_field = { + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BEQ}, /* beq $rt, $ra, label */ + .relax_code_condition[BR_RANGE_S256] = { + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S256] = 4, + .relax_branch_isize[BR_RANGE_S256] = 4, + .relax_fixup[BR_RANGE_S256] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_BEQ}, /* beq $rt, $ra, label */ + .relax_code_condition[BR_RANGE_S16K] = { + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BNE, /* bne $rt, $ra, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S64K] = { + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S64K] = 8, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BNE, /* bne $rt, $ra, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S16M] = { + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BNE, /* bne $rt, $ra, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ta */ + .relax_code_condition[BR_RANGE_U4G] = { + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - {0, 8, 0x7, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S256 */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S64K */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16M */ - { - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {2, 4, 8, 8, 16}, /* relax_code_size */ - {2, 4, 4, 4, 4}, /* relax_branch_isize */ + .opcode = "bne", + .br_range = BR_RANGE_S16K, + .cond_field = { + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BNE}, /* bne $rt, $ra, label */ + .relax_code_condition[BR_RANGE_S256] = { + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S256] = 4, + .relax_branch_isize[BR_RANGE_S256] = 4, + .relax_fixup[BR_RANGE_S256] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_BNE}, /* bne $rt, $ra, label */ + .relax_code_condition[BR_RANGE_S16K] = { + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BEQ, /* beq $rt, $ra, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S64K] = { + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S64K] = 8, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BEQ, /* beq $rt, $ra, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S16M] = { + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BEQ, /* beq $rt, $ra, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ta */ + .relax_code_condition[BR_RANGE_U4G] = { + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, - {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, - {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, - {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "beqc", /* opcode */ - BR_RANGE_S256, /* br_range */ + .opcode = "beqz38", + .br_range = BR_RANGE_S256, + .cond_field = { + {0, 8, 0x7, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BEQZ38 << 16}, /* beqz $rt, label */ + .relax_code_condition[BR_RANGE_S256] = { + {0, 8, 0x7, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S256] = 2, + .relax_branch_isize[BR_RANGE_S256] = 2, + .relax_fixup[BR_RANGE_S256] = { + {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_BEQZ}, /* beqz $rt, label */ + .relax_code_condition[BR_RANGE_S16K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BEQZ}, /* beqz $rt, label */ + .relax_code_condition[BR_RANGE_S64K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S64K] = 4, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BNEZ, /* bnez $rt, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S16M] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BNEZ, /* bnez $rt, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ta */ + .relax_code_condition[BR_RANGE_U4G] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - {0, 8, 0x7FF, TRUE}, - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* cond_field */ + .opcode = "bnez38", + .br_range = BR_RANGE_S256, + .cond_field = { + {0, 8, 0x7, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BNEZ38 << 16}, /* bnez $rt, label */ + .relax_code_condition[BR_RANGE_S256] = { + {0, 8, 0x7, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S256] = 2, + .relax_branch_isize[BR_RANGE_S256] = 2, + .relax_fixup[BR_RANGE_S256] = { + {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_BNEZ}, /* bnez $rt, label */ + .relax_code_condition[BR_RANGE_S16K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BNEZ}, /* bnez $rt, label */ + .relax_code_condition[BR_RANGE_S64K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S64K] = 4, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BEQZ, /* beqz $rt, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S16M] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BEQZ, /* beqz $rt, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ a */ + .relax_code_condition[BR_RANGE_U4G] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - INSN_BEQC /* beqc $rt, imm11s, label */ - }, /* BR_RANGE_S256 */ - { - INSN_MOVI_TA, /* movi $ta, imm11s */ - INSN_BEQ_TA /* beq $rt, $ta, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BNEC, /* bnec $rt, imm11s, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S64K */ - { - INSN_BNEC, /* bnec $rt, imm11s, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_BNEC, /* bnec $rt, imm11s, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + .opcode = "beqzs8", + .br_range = BR_RANGE_S256, + .cond_field = { + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BEQZS8 << 16}, /* beqz $r15, label */ + .relax_code_size[BR_RANGE_S256] = 2, + .relax_branch_isize[BR_RANGE_S256] = 2, + .relax_fixup[BR_RANGE_S256] = { + {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_BEQZ_TA}, /* beqz $r15, label */ + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BEQZ_TA}, /* beqz $r15, label */ + .relax_code_size[BR_RANGE_S64K] = 4, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BNEZ_TA, /* bnez $r15, $1 */ + INSN_J}, /* j label */ + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BNEZ_TA, /* bnez $r15, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ a */ + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - {0, 8, 0x7FF, TRUE}, - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S256 */ - { - {0, 0, 0xFFFFF, FALSE}, - {4, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16K */ - { - {0, 8, 0x7FF, FALSE}, - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S64K */ - { - {0, 8, 0x7FF, FALSE}, - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16M */ - { - {0, 8, 0x7FF, FALSE}, - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 8, 8, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ + .opcode = "bnezs8", + .br_range = BR_RANGE_S256, + .cond_field = { + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BNEZS8 << 16}, /* bnez $r15, label */ + .relax_code_size[BR_RANGE_S256] = 2, + .relax_branch_isize[BR_RANGE_S256] = 2, + .relax_fixup[BR_RANGE_S256] = { + {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_BNEZ_TA}, /* bnez $r15, label */ + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BNEZ_TA}, /* bnez $r15, label */ + .relax_code_size[BR_RANGE_S64K] = 4, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BEQZ_TA, /* beqz $r15, $1 */ + INSN_J}, /* j label */ + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BEQZ_TA, /* beqz $r15, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ a */ + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - }, - { - "bnec", /* opcode */ - BR_RANGE_S256, /* br_range */ + .opcode = "bnes38", + .br_range = BR_RANGE_S256, + .cond_field = { + {0, 8, 0x7, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BNES38 << 16}, /* bne $rt, $r5, label */ + .relax_code_condition[BR_RANGE_S256] = { + {0, 8, 0x7, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S256] = 2, + .relax_branch_isize[BR_RANGE_S256] = 2, + .relax_fixup[BR_RANGE_S256] = { + {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_BNE_R5}, /* bne $rt, $r5, label */ + .relax_code_condition[BR_RANGE_S16K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BEQ_R5, /* beq $rt, $r5, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S64K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S64K] = 8, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BEQ_R5, /* beq $rt, $r5, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S16M] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BEQ_R5, /* beq $rt, $r5, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ a */ + .relax_code_condition[BR_RANGE_U4G] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - {0, 8, 0x7FF, TRUE}, - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* cond_field */ + .opcode = "beqs38", + .br_range = BR_RANGE_S256, + .cond_field = { + {0, 8, 0x7, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BEQS38 << 16}, /* beq $rt, $r5, label */ + .relax_code_condition[BR_RANGE_S256] = { + {0, 8, 0x7, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S256] = 2, + .relax_branch_isize[BR_RANGE_S256] = 2, + .relax_fixup[BR_RANGE_S256] = { + {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_BEQ_R5}, /* beq $rt, $r5, label */ + .relax_code_condition[BR_RANGE_S16K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S16K] = 4, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BNE_R5, /* bne $rt, $r5, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S64K] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S64K] = 8, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BNE_R5, /* bne $rt, $r5, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S16M] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BNE_R5, /* bne $rt, $r5, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ a */ + .relax_code_condition[BR_RANGE_U4G] = { + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - INSN_BNEC /* bnec $rt, imm11s, label */ - }, /* BR_RANGE_S256 */ - { - INSN_MOVI_TA, /* movi $ta, imm11s */ - INSN_BNE_TA /* bne $rt, $ta, label */ - }, /* BR_RANGE_S16K */ - { - INSN_BEQC, /* beqc $rt, imm11s, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S64K */ - { - INSN_BEQC, /* beqc $rt, imm11s, $1 */ - INSN_J /* j label */ - }, /* BR_RANGE_S16M */ - { - INSN_BEQC, /* beqc $rt, imm11s, $1 */ - INSN_SETHI_TA, /* sethi $ta, label */ - INSN_ORI_TA, /* ori $ta, $ta, label */ - INSN_JR_TA /* jr $ta */ - } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + .opcode = "beqc", + .br_range = BR_RANGE_S256, + .cond_field = { + {0, 8, 0x7FF, TRUE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BEQC}, /* beqc $rt, imm11s, label */ + .relax_code_condition[BR_RANGE_S256] = { + {0, 8, 0x7FF, FALSE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S256] = 4, + .relax_branch_isize[BR_RANGE_S256] = 4, + .relax_fixup[BR_RANGE_S256] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_MOVI_TA, /* movi $ta, imm11s */ + INSN_BEQ_TA}, /* beq $rt, $ta, label */ + .relax_code_condition[BR_RANGE_S16K] = { + {0, 0, 0xFFFFF, FALSE}, + {4, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S16K] = 8, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BNEC, /* bnec $rt, imm11s, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S64K] = { + {0, 8, 0x7FF, FALSE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S64K] = 8, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BNEC, /* bnec $rt, imm11s, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S16M] = { + {0, 8, 0x7FF, FALSE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BNEC, /* bnec $rt, imm11s, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ a */ + .relax_code_condition[BR_RANGE_U4G] = { + {0, 8, 0x7FF, FALSE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, + {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - {0, 8, 0x7FF, TRUE}, - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S256 */ - { - {0, 0, 0xFFFFF, FALSE}, - {4, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16K */ - { - {0, 8, 0x7FF, FALSE}, - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S64K */ - { - {0, 8, 0x7FF, FALSE}, - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - }, /* BR_RANGE_S16M */ - { - {0, 8, 0x7FF, FALSE}, - {0, 20, 0x1F, FALSE}, - {0, 0, 0, FALSE} - } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 8, 8, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ + .opcode = "bnec", + .br_range = BR_RANGE_S256, + .cond_field = { + {0, 8, 0x7FF, TRUE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_seq[BR_RANGE_S256] = { + INSN_BNEC}, /* bnec $rt, imm11s, label */ + .relax_code_condition[BR_RANGE_S256] = { + {0, 8, 0x7FF, FALSE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S256] = 4, + .relax_branch_isize[BR_RANGE_S256] = 4, + .relax_fixup[BR_RANGE_S256] = { + {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16K] = { + INSN_MOVI_TA, /* movi $ta, imm11s */ + INSN_BNE_TA}, /* bne $rt, $ta, label */ + .relax_code_condition[BR_RANGE_S16K] = { + {0, 0, 0xFFFFF, FALSE}, + {4, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S16K] = 8, + .relax_branch_isize[BR_RANGE_S16K] = 4, + .relax_fixup[BR_RANGE_S16K] = { + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S64K] = { + INSN_BEQC, /* beqc $rt, imm11s, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S64K] = { + {0, 8, 0x7FF, FALSE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S64K] = 8, + .relax_branch_isize[BR_RANGE_S64K] = 4, + .relax_fixup[BR_RANGE_S64K] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_S16M] = { + INSN_BEQC, /* beqc $rt, imm11s, $1 */ + INSN_J}, /* j label */ + .relax_code_condition[BR_RANGE_S16M] = { + {0, 8, 0x7FF, FALSE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_S16M] = 8, + .relax_branch_isize[BR_RANGE_S16M] = 4, + .relax_fixup[BR_RANGE_S16M] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, + {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, + {0, 0, 0, 0} + }, + + .relax_code_seq[BR_RANGE_U4G] = { + INSN_BEQC, /* beqc $rt, imm11s, $1 */ + INSN_SETHI_TA, /* sethi $ta, label */ + INSN_ORI_TA, /* ori $ta, $ta, label */ + INSN_JR_TA}, /* jr $ a */ + .relax_code_condition[BR_RANGE_U4G] = { + {0, 8, 0x7FF, FALSE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, + .relax_code_size[BR_RANGE_U4G] = 16, + .relax_branch_isize[BR_RANGE_U4G] = 4, + .relax_fixup[BR_RANGE_U4G] = { + {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, + {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + }, + }, { - { - {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S256 */ - { - {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, - {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S64K */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, - {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} - }, /* BR_RANGE_S16M */ - { - {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, - {0, 0, 0, 0} - } /* BR_RANGE_U4G */ - } /* relax_fixup */ - } + .opcode = NULL, + }, }; + /* GAS definitions for command-line options. */ enum options @@ -1901,9 +1932,9 @@ size_t md_longopts_size = sizeof (md_longopts); struct nds32_parse_option_table { - const char *name; /* Option string. */ - const char *help; /* Help description. */ - int (*func) (const char *arg); /* How to parse it. */ + const char *name; /* Option string. */ + const char *help; /* Help description. */ + int (*func) (const char *arg); /* How to parse it. */ }; @@ -1920,7 +1951,7 @@ static int nds32_fpu_dp_ext = -1; static int nds32_freg = -1; static int nds32_abi = -1; -/* Record ELF flags */ +/* Record ELF flags. */ static int nds32_elf_flags = 0; static int nds32_fpu_com = 0; @@ -1929,34 +1960,49 @@ static int nds32_parse_baseline (const char *str); static int nds32_parse_freg (const char *str); static int nds32_parse_abi (const char *str); +static void add_mapping_symbol (enum mstate state, + unsigned int padding_byte, unsigned int align); + static struct nds32_parse_option_table parse_opts [] = { + {"ace=", N_("\t Support user defined instruction extension"), + nds32_parse_udi}, + {"cop0=", N_("\t Support coprocessor 0 extension"), + nds32_parse_cop0}, + {"cop1=", N_("\t Support coprocessor 1 extension"), + nds32_parse_cop1}, + {"cop2=", N_("\t Support coprocessor 2 extension"), + nds32_parse_cop2}, + {"cop3=", N_("\t Support coprocessor 3 extension"), + nds32_parse_cop3}, {"arch=", N_("\t Assemble for architecture \n\ could be\n\ - v3, v3j, v3m, v3f, v3s, "\ + v3, v3j, v3m, v3m+ v3f, v3s, "\ "v2, v2j, v2f, v2s"), nds32_parse_arch}, {"baseline=", N_("\t Assemble for baseline \n\ could be v2, v3, v3m"), nds32_parse_baseline}, {"fpu-freg=", N_("\t Specify a FPU configuration\n\ \n\ - 0: 8 SP / 4 DP registers\n\ - 1: 16 SP / 8 DP registers\n\ - 2: 32 SP / 16 DP registers\n\ - 3: 32 SP / 32 DP registers"), nds32_parse_freg}, + 0/4: 8 SP / 4 DP registers\n\ + 1/5: 16 SP / 8 DP registers\n\ + 2/6: 32 SP / 16 DP registers\n\ + 3/7: 32 SP / 32 DP registers"), nds32_parse_freg}, {"abi=", N_("\t Specify a abi version\n\ - could be v1, v2, v2fp, v2fpp"), nds32_parse_abi}, + could be v1, v2, v2fp, v2fp+"), nds32_parse_abi}, {NULL, NULL, NULL} }; static int nds32_mac = 1; static int nds32_div = 1; static int nds32_16bit_ext = 1; -static int nds32_dx_regs = 1; -static int nds32_perf_ext = 1; -static int nds32_perf_ext2 = 1; -static int nds32_string_ext = 1; -static int nds32_audio_ext = 1; +static int nds32_dx_regs = NDS32_DEFAULT_DX_REGS; +static int nds32_perf_ext = NDS32_DEFAULT_PERF_EXT; +static int nds32_perf_ext2 = NDS32_DEFAULT_PERF_EXT2; +static int nds32_string_ext = NDS32_DEFAULT_STRING_EXT; +static int nds32_audio_ext = NDS32_DEFAULT_AUDIO_EXT; +static int nds32_dsp_ext = NDS32_DEFAULT_DSP_EXT; +static int nds32_zol_ext = NDS32_DEFAULT_ZOL_EXT; static int nds32_fpu_fma = 0; static int nds32_pic = 0; static int nds32_relax_fp_as_gp = 1; @@ -1965,7 +2011,7 @@ static int nds32_relax_all = 1; struct nds32_set_option_table { const char *name; /* Option string. */ - const char *help; /* Help description. */ + const char *help; /* Help description. */ int *var; /* Variable to be set. */ int value; /* Value to set. */ }; @@ -1987,6 +2033,8 @@ static struct nds32_set_option_table toggle_opts [] = {"fpu-sp-ext", N_("FPU SP extension"), &nds32_fpu_sp_ext, 1}, {"fpu-dp-ext", N_("FPU DP extension"), &nds32_fpu_dp_ext, 1}, {"fpu-fma", N_("FPU fused-multiply-add instructions"), &nds32_fpu_fma, 1}, + {"dsp-ext", N_("DSP extension"), &nds32_dsp_ext, 1}, + {"zol-ext", N_("hardware loop extension"), &nds32_zol_ext, 1}, {NULL, NULL, NULL, 0} }; @@ -2000,7 +2048,7 @@ nds32_asm_parse_operand (struct nds32_asm_desc *pdesc, char **pstr, int64_t *value); -struct nds32_asm_desc asm_desc; +static struct nds32_asm_desc asm_desc; /* md_after_parse_args () @@ -2086,11 +2134,9 @@ nds32_start_line_hook (void) { } -/* - * Pseudo opcodes - */ +/* Pseudo opcodes. */ -typedef void (*nds32_pseudo_opcode_func) (int argc, char *argv[], unsigned int pv); +typedef void (*nds32_pseudo_opcode_func) (int argc, char *argv[], int pv); struct nds32_pseudo_opcode { const char *opcode; @@ -2183,13 +2229,12 @@ static void do_pseudo_li_internal (const char *rt, int imm32s); static void do_pseudo_move_reg_internal (char *dst, char *src); static void -do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { char *arg_label = argv[0]; relaxing = TRUE; /* b label */ - if (nds32_pic && strstr (arg_label, "@PLT")) + if (nds32_pic) { md_assemblef ("sethi $ta,hi20(%s)", arg_label); md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label); @@ -2204,18 +2249,16 @@ do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { char *arg_label = argv[0]; relaxing = TRUE; /* bal|call label */ - if (nds32_pic - && (strstr (arg_label, "@GOT") || strstr (arg_label, "@PLT"))) + if (nds32_pic) { md_assemblef ("sethi $ta,hi20(%s)", arg_label); md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label); - md_assemble ((char *) "add $ta,$ta,$gp"); + md_assemble ((char *) "add $ta,$ta,$gp"); md_assemble ((char *) "jral $ta"); } else @@ -2226,8 +2269,7 @@ do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { /* rt5, ra5, label */ md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]); @@ -2235,8 +2277,7 @@ do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { /* rt5, ra5, label */ md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]); @@ -2244,8 +2285,7 @@ do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { /* bgt rt5, ra5, label */ md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]); @@ -2253,8 +2293,7 @@ do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { /* bgt rt5, ra5, label */ md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]); @@ -2262,8 +2301,7 @@ do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { /* bgt rt5, ra5, label */ md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]); @@ -2271,8 +2309,7 @@ do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { /* bgt rt5, ra5, label */ md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]); @@ -2280,8 +2317,7 @@ do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { /* rt5, ra5, label */ md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]); @@ -2289,8 +2325,7 @@ do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { /* rt5, ra5, label */ md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]); @@ -2298,15 +2333,13 @@ do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_br (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_br (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { md_assemblef ("jr %s", argv[0]); } static void -do_pseudo_bral (int argc, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_bral (int argc, char *argv[], int pv ATTRIBUTE_UNUSED) { if (argc == 1) md_assemblef ("jral $lp,%s", argv[0]); @@ -2329,19 +2362,24 @@ do_pseudo_la_internal (const char *arg_reg, char *arg_label, relaxing = TRUE; /* rt, label */ - if (!nds32_pic && !strstr(arg_label, "@")) + if (!nds32_pic && !strstr (arg_label, "@")) + { + md_assemblef ("sethi %s,hi20(%s)", arg_reg, arg_label); + md_assemblef ("ori %s,%s,lo12(%s)", arg_reg, arg_reg, arg_label); + } + else if (strstr (arg_label, "@ICT")) { md_assemblef ("sethi %s,hi20(%s)", arg_reg, arg_label); md_assemblef ("ori %s,%s,lo12(%s)", arg_reg, arg_reg, arg_label); } else if (strstr (arg_label, "@TPOFF")) { - /* la $rt, sym@TPOFF */ + /* la $rt, sym@TPOFF */ md_assemblef ("sethi $ta,hi20(%s)", arg_label); md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label); md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG); } - else if (strstr(arg_label, "@GOTTPOFF")) + else if (strstr (arg_label, "@GOTTPOFF")) { /* la $rt, sym@GOTTPOFF*/ md_assemblef ("sethi $ta,hi20(%s)", arg_label); @@ -2381,8 +2419,7 @@ do_pseudo_la_internal (const char *arg_reg, char *arg_label, } static void -do_pseudo_la (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_la (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { do_pseudo_la_internal (argv[0], argv[1], argv[argc]); } @@ -2404,8 +2441,7 @@ do_pseudo_li_internal (const char *rt, int imm32s) } static void -do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { /* Validate argv[1] for constant expression. */ expressionS exp; @@ -2421,8 +2457,7 @@ do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv) +do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], int pv) { char ls = 'r'; char size = 'x'; @@ -2451,14 +2486,14 @@ do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], relaxing = TRUE; if (strstr (argv[1], "@TPOFF")) { - /* ls.w $rt, sym@TPOFF */ + /* ls.w $rt, sym@TPOFF */ md_assemblef ("sethi $ta,hi20(%s)", argv[1]); md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]); md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG); } else if (strstr (argv[1], "@GOTTPOFF")) { - /* ls.w $rt, sym@GOTTPOFF */ + /* ls.w $rt, sym@GOTTPOFF */ md_assemblef ("sethi $ta,hi20(%s)", argv[1]); md_assemblef ("lwi $ta,[$ta+lo12(%s)]", argv[1]); md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG); @@ -2509,8 +2544,7 @@ do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv) +do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[], int pv) { char *arg_rt = argv[0]; char *arg_label = argv[1]; @@ -2537,8 +2571,7 @@ do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv) +do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[], int pv) { char *arg_rt = argv[0]; char *arg_inc = argv[1]; @@ -2563,8 +2596,7 @@ do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv) +do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED, char *argv[], int pv) { char ls = 'r'; char size = 'x'; @@ -2597,8 +2629,7 @@ do_pseudo_move_reg_internal (char *dst, char *src) } static void -do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { expressionS exp; @@ -2617,23 +2648,20 @@ do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { /* Instead of "subri". */ md_assemblef ("subri %s,%s,0", argv[0], argv[1]); } static void -do_pseudo_not (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_not (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { md_assemblef ("nor %s,%s,%s", argv[0], argv[1], argv[1]); } static void -do_pseudo_pushpopm (int argc, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_pushpopm (int argc, char *argv[], int pv ATTRIBUTE_UNUSED) { /* posh/pop $ra, $rb */ /* SMW.{b | a}{i | d}{m?} Rb, [Ra], Re, Enable4 */ @@ -2683,11 +2711,11 @@ do_pseudo_pushpopm (int argc, char *argv[], /* Reduce register. */ if (nds32_gpr16 && re > 10 && !(rb == 31 && re == 31)) { - if (re >= 15 && strstr(opc, "smw") != NULL) + if (re >= 15 && strstr (opc, "smw") != NULL) md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4); if (rb <= 10) md_assemblef ("%s $r%d,[$sp],$r10, 0x0", opc, rb); - if (re >= 15 && strstr(opc, "lmw") != NULL) + if (re >= 15 && strstr (opc, "lmw") != NULL) md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4); } else @@ -2695,10 +2723,9 @@ do_pseudo_pushpopm (int argc, char *argv[], } static void -do_pseudo_pushpop (int argc, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_pushpop (int argc, char *argv[], int pv ATTRIBUTE_UNUSED) { - /* push/pop $ra5, $label=$sp */ + /* push/pop $ra5, $label=$sp */ char *argvm[3]; if (argc == 2) @@ -2712,15 +2739,13 @@ do_pseudo_pushpop (int argc, char *argv[], } static void -do_pseudo_v3push (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_v3push (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { md_assemblef ("push25 %s,%s", argv[0], argv[1]); } static void -do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { md_assemblef ("pop25 %s,%s", argv[0], argv[1]); } @@ -2729,11 +2754,10 @@ do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[], pv != 0, parsing "pop.s" pseudo instruction operands. */ static void -do_pseudo_pushpop_stack (int argc, char *argv[], - unsigned int pv) +do_pseudo_pushpop_stack (int argc, char *argv[], int pv) { - /* push.s Rb,Re,{$fp $gp $lp $sp} ==> smw.adm Rb,[$sp],Re,Eable4 */ - /* pop.s Rb,Re,{$fp $gp $lp $sp} ==> lmw.bim Rb,[$sp],Re,Eable4 */ + /* push.s Rb,Re,{$fp $gp $lp $sp} ==> smw.adm Rb,[$sp],Re,Eable4 */ + /* pop.s Rb,Re,{$fp $gp $lp $sp} ==> lmw.bim Rb,[$sp],Re,Eable4 */ int rb, re; int en4; @@ -2794,8 +2818,7 @@ do_pseudo_pushpop_stack (int argc, char *argv[], } static void -do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { char size = 'x'; /* If users omit push location, use $sp as default value. */ @@ -2818,7 +2841,7 @@ do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], md_assemblef ("l.%c $ta,%s", size, argv[0]); md_assemblef ("smw.adm $ta,[%s],$ta", location); - if ((pv & 0x3) == 0x3) /* double-word */ + if ((pv & 0x3) == 0x3) /* double-word */ { md_assemblef ("l.w $ta,%s+4", argv[0]); md_assemblef ("smw.adm $ta,[%s],$ta", location); @@ -2826,8 +2849,7 @@ do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { char size = 'x'; /* If users omit pop location, use $sp as default value. */ @@ -2847,7 +2869,7 @@ do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], location[7] = '\0'; } - if ((pv & 0x3) == 0x3) /* double-word */ + if ((pv & 0x3) == 0x3) /* double-word */ { md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]); md_assemblef ("s.w %s,%s+4", argv[1], argv[0]); @@ -2858,8 +2880,7 @@ do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { /* If users omit push location, use $sp as default value. */ char location[8] = "$sp"; /* 8 is enough for register name. */ @@ -2875,8 +2896,7 @@ do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[], } static void -do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[], - unsigned int pv ATTRIBUTE_UNUSED) +do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { /* If users omit push location, use $sp as default value. */ char location[8] = "$sp"; /* 8 is enough for register name. */ @@ -2891,8 +2911,7 @@ do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[], md_assemblef ("smw.adm $ta,[%s],$ta", location); } -struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] = -{ +static struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] = { {"b", 1, do_pseudo_b, 0, 0}, {"bal", 1, do_pseudo_bal, 0, 0}, @@ -2967,8 +2986,8 @@ struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] = {"v3pop", 2, do_pseudo_v3pop, 0, 0}, /* Support pseudo instructions of pushing/poping registers into/from stack - push.s Rb, Re, { $fp $gp $lp $sp } ==> smw.adm Rb,[$sp],Re,Enable4 - pop.s Rb, Re, { $fp $gp $lp $sp } ==> lmw.bim Rb,[$sp],Re,Enable4 */ + push.s Rb, Re, { $fp $gp $lp $sp } ==> smw.adm Rb,[$sp],Re,Enable4 + pop.s Rb, Re, { $fp $gp $lp $sp } ==> lmw.bim Rb,[$sp],Re,Enable4 */ { "push.s", 3, do_pseudo_pushpop_stack, 0, 0 }, { "pop.s", 3, do_pseudo_pushpop_stack, 1, 0 }, { "push.b", 2, do_pseudo_push_bhwd, 0, 0 }, @@ -3009,18 +3028,16 @@ static struct nds32_pseudo_opcode * nds32_lookup_pseudo_opcode (const char *str) { int i = 0; - /* Assume pseudo-opcode are less than 16-char in length. */ - char op[16] = {0}; + /* *op = first word of current source line (*str) */ + int maxlen = strlen (str); + char *op = alloca (maxlen + 1); - for (i = 0; i < (int)ARRAY_SIZE (op); i++) + for (i = 0; i < maxlen; i++) { if (ISSPACE (op[i] = str[i])) break; } - if (i >= (int)ARRAY_SIZE (op)) - return NULL; - op[i] = '\0'; return hash_find (nds32_pseudo_opcode_hash, op); @@ -3081,6 +3098,7 @@ nds32_parse_arch (const char *str) } archs[] = { {"v3m", ISA_V3M, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI}, + {"v3m+",ISA_V3M, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI}, {"v3j", ISA_V3, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI}, {"v3s", ISA_V3, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS}, {"v3f", ISA_V3, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS}, @@ -3119,11 +3137,11 @@ nds32_parse_arch (const char *str) static int nds32_parse_baseline (const char *str) { - if (strcmp (str, "v3") == 0) + if (strcasecmp (str, "v3") == 0) nds32_baseline = ISA_V3; - else if (strcmp (str, "v3m") == 0) + else if (strcasecmp (str, "v3m") == 0) nds32_baseline = ISA_V3M; - else if (strcmp (str, "v2") == 0) + else if (strcasecmp (str, "v2") == 0) nds32_baseline = ISA_V2; else { @@ -3140,13 +3158,13 @@ nds32_parse_baseline (const char *str) static int nds32_parse_freg (const char *str) { - if (strcmp (str, "2") == 0) + if (strcmp (str, "2") == 0 || strcmp (str, "6") == 0) nds32_freg = E_NDS32_FPU_REG_32SP_16DP; - else if (strcmp (str, "3") == 0) + else if (strcmp (str, "3") == 0 || strcmp (str, "7") == 0) nds32_freg = E_NDS32_FPU_REG_32SP_32DP; - else if (strcmp (str, "1") == 0) + else if (strcmp (str, "1") == 0 || strcmp (str, "5") == 0) nds32_freg = E_NDS32_FPU_REG_16SP_8DP; - else if (strcmp (str, "0") == 0) + else if (strcmp (str, "0") == 0 || strcmp (str, "4") == 0) nds32_freg = E_NDS32_FPU_REG_8SP_4DP; else { @@ -3170,13 +3188,19 @@ nds32_parse_abi (const char *str) nds32_abi = E_NDS_ABI_V2FP; else if (strcmp (str, "v1") == 0) nds32_abi = E_NDS_ABI_V1; - else if (strcmp (str,"v2fpp") == 0) + else if (strcmp (str,"v2fpp") == 0 || strcmp (str,"v2fp+") == 0) nds32_abi = E_NDS_ABI_V2FP_PLUS; else { - /* Logic here rejects the input abi version. */ - as_bad (_("unknown ABI version`%s'\n"), str); - return 0; + /* bug-10880, decided to accept any other versions but drop them. */ + if (TRUE) + return 1; + else + { + /* Logic here rejects the input abi version. */ + as_bad (_("unknown ABI version`%s'\n"), str); + return 0; + } } return 1; @@ -3198,6 +3222,10 @@ nds32_all_ext (void) nds32_fpu_fma = 1; nds32_fpu_sp_ext = 1; nds32_fpu_dp_ext = 1; + nds32_dsp_ext = 1; + nds32_zol_ext = 1; + /* Turn off reduced register. */ + nds32_gpr16 = 0; return 1; } @@ -3295,7 +3323,7 @@ nds32_parse_option (int c, const char *arg) return 1; } -/* tc_check_label */ +/* tc_check_label */ void nds32_check_label (symbolS *label ATTRIBUTE_UNUSED) @@ -3342,8 +3370,7 @@ typedef struct nds32_seg_entryT flagword flags; } nds32_seg_entry; -nds32_seg_entry nds32_seg_table[] = -{ +static nds32_seg_entry nds32_seg_table[] = { {NULL, ".sdata_f", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS | SEC_SMALL_DATA}, {NULL, ".sdata_b", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA @@ -3409,24 +3436,40 @@ nds32_seg (int i) } /* Set if label adjustment is needed. I should not adjust .xbyte in dwarf. */ -static symbolS *nds32_last_label; /* Last label for alignment. */ +static symbolS *nds32_last_label; /* Last label for aligment. */ + +static void +add_mapping_symbol_for_align (int shift, valueT addr, int is_data_align) +{ + if ((shift > 1) && (addr & 1)) + { + int n = (1 << shift) - 1; + if (!is_data_align) + add_mapping_symbol (MAP_CODE, 1, 0); + else if ((int) (addr & n) != n) + add_mapping_symbol (MAP_CODE, 1, 0); + } + else if ((shift > 1) && ((int) (addr & 1) == 0)) + add_mapping_symbol (MAP_CODE, 0, 0); -/* This code is referred from D30V for adjust label to be with pending - alignment. For example, +} + +/* This code is referred from D30V for adjust label to be with pedning + aligment. For example, LBYTE: .byte 0x12 LHALF: .half 0x12 LWORD: .word 0x12 - Without this, the above label will not attach to incoming data. */ + Without this, the above label will not attatch to incoming data. */ static void nds32_adjust_label (int n) { - /* FIXME: I think adjust label and alignment is - the programmer's obligation. Sadly, VLSI team doesn't + /* FIXME: I think adjust lable and alignment is + the programmer's obligation. Saddly, VLSI team doesn't properly use .align for their test cases. So I re-implement cons_align and auto adjust labels, again. - I think d30v's implementation is simple and good enough. */ + I think d30v's implmentation is simple and good enough. */ symbolS *label = nds32_last_label; nds32_last_label = NULL; @@ -3441,10 +3484,14 @@ nds32_adjust_label (int n) /* Only frag by alignment when needed. Otherwise, it will fail to optimize labels on 4-byte boundary. (bug8454) See md_convert_frag () and RELAX_SET_RELAXABLE (frag) for details. */ + if (frag_now_fix () & ((1 << n) -1 )) { if (subseg_text_p (now_seg)) - frag_align_code (n, 0); + { + add_mapping_symbol_for_align (n, frag_now_fix (), 1); + frag_align_code (n, 0); + } else frag_align (n, 0, 0); @@ -3474,7 +3521,7 @@ nds32_adjust_label (int n) if (symbol_get_frag (sym) == old_frag && S_GET_VALUE (sym) == old_value) { - /* Warning HERE! */ + /* Warning HERE! */ label_seen = TRUE; symbol_set_frag (sym, frag_now); S_SET_VALUE (sym, new_value); @@ -3493,7 +3540,7 @@ nds32_cons_align (int size ATTRIBUTE_UNUSED) There are two things should be done for auto-adjust-label. 1. Align data/instructions and adjust label to be attached to them. - 2. Clear auto-adjust state, so incoming data/instructions will not + 2. Clear auto-adjust state, so incommng data/instructions will not adjust the label. For example, @@ -3510,15 +3557,67 @@ nds32_cons_align (int size ATTRIBUTE_UNUSED) } static void +make_mapping_symbol (enum mstate state, valueT value, fragS * frag, unsigned int align) +{ + symbolS *symbol_p = NULL; + const char *symbol_name = NULL; + switch (state) + { + case MAP_DATA: + if (align == 0) { + symbol_name = "$d0"; + } + else if (align == 1) { + symbol_name = "$d1"; + } + else if (align == 2) + symbol_name = "$d2"; + else if (align == 3) + symbol_name = "$d3"; + else if (align == 4) + symbol_name = "$d4"; + break; + case MAP_CODE: + symbol_name = "$c"; + break; + default: + abort (); + } + + symbol_p = symbol_new (symbol_name, now_seg, value, frag); + /* local scope attribute */ + symbol_get_bfdsym (symbol_p)->flags |= BSF_NO_FLAGS | BSF_LOCAL; +} + +static void +add_mapping_symbol (enum mstate state, unsigned int padding_byte, unsigned int align) +{ + enum mstate current_mapping_state = + seg_info (now_seg)->tc_segment_info_data.mapstate; + + if (state == MAP_CODE && current_mapping_state == state) + return; + + if (!SEG_NORMAL (now_seg) || !subseg_text_p (now_seg)) + return; + + /* start adding mapping symbol */ + seg_info (now_seg)->tc_segment_info_data.mapstate = state; + make_mapping_symbol (state, (valueT) frag_now_fix () + padding_byte, + frag_now, align); +} + +static void nds32_aligned_cons (int idx) { nds32_adjust_label (idx); + add_mapping_symbol (MAP_DATA, 0, idx); /* Call default handler. */ cons (1 << idx); if (now_seg->flags & SEC_CODE && now_seg->flags & SEC_ALLOC && now_seg->flags & SEC_RELOC) { - /* Use BFD_RELOC_NDS32_DATA to avoid EX9 optimization replacing data. */ + /* Use BFD_RELOC_NDS32_DATA to avoid linker optimization replacing data. */ expressionS exp; exp.X_add_number = 0; @@ -3578,7 +3677,7 @@ nds32_relax_relocs (int relax) char *name; int i; const char *subtype_relax[] = - {"", "", "ex9", "ifc"}; + {"", "",}; name = input_line_pointer; while (*input_line_pointer && !ISSPACE (*input_line_pointer)) @@ -3595,14 +3694,6 @@ nds32_relax_relocs (int relax) case 0: case 1: enable_relax_relocs = relax & enable_relax_relocs; - enable_relax_ex9 = relax & enable_relax_ex9; - enable_relax_ifc = relax & enable_relax_ifc; - break; - case 2: - enable_relax_ex9 = relax; - break; - case 3: - enable_relax_ifc = relax; break; default: break; @@ -3652,51 +3743,36 @@ nds32_omit_fp_begin (int mode) } } -/* Insert relocations to mark the begin and end of ex9 region, - for further relaxation use. - bit[i] for $ri */ - static void -nds32_no_ex9_begin (int mode) +nds32_loop_begin (int mode) { + /* Insert loop region relocation here. */ expressionS exp; exp.X_op = O_symbol; exp.X_add_symbol = abs_section_sym; if (mode == 1) { - exp.X_add_number = R_NDS32_RELAX_REGION_NO_EX9_FLAG; + exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG; fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0, BFD_RELOC_NDS32_RELAX_REGION_BEGIN); } else { - exp.X_add_number = R_NDS32_RELAX_REGION_NO_EX9_FLAG; + exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG; fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0, BFD_RELOC_NDS32_RELAX_REGION_END); } } +/* Record if in the inline assembly code segment. */ static void -nds32_loop_begin (int mode) +nds32_inline_asm (int mode) { - /* Insert loop region relocation here. */ - expressionS exp; - - exp.X_op = O_symbol; - exp.X_add_symbol = abs_section_sym; - if (mode == 1) - { - exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG; - fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0, - BFD_RELOC_NDS32_RELAX_REGION_BEGIN); - } + if (mode) + inline_asm = TRUE; else - { - exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG; - fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0, - BFD_RELOC_NDS32_RELAX_REGION_END); - } + inline_asm = FALSE; } struct nds32_relocs_group @@ -3706,16 +3782,49 @@ struct nds32_relocs_group }; static struct nds32_relocs_group *nds32_relax_hint_current = NULL; +/* Used to reorder the id for ".relax_hint id". */ +static int relax_hint_bias = 0; +/* Record current relax hint id. */ +static int relax_hint_id_current = -1; +int reset_bias = 0; +/* If ".relax_hint begin" is triggered? */ +int relax_hint_begin = 0; + +/* Record the reordered relax hint id. */ + +struct relax_hint_id +{ + int old_id; + int new_id; + struct relax_hint_id *next; +}; + +/* FIXME: Need to find somewhere to free the list. */ +struct relax_hint_id *record_id_head = NULL; + +/* Is the buffer large enough? */ +#define MAX_BUFFER 12 + +static char *nds_itoa (int n); + +static char * +nds_itoa (int n) +{ + char *buf = xmalloc (MAX_BUFFER * sizeof (char)); + snprintf (buf, MAX_BUFFER, "%d", n); + return buf; +} /* Insert a relax hint. */ static void nds32_relax_hint (int mode ATTRIBUTE_UNUSED) { - char *name; + char *name = NULL; char saved_char; struct nds32_relocs_pattern *relocs = NULL; struct nds32_relocs_group *group, *new; + struct relax_hint_id *record_id; name = input_line_pointer; while (*input_line_pointer && !ISSPACE (*input_line_pointer)) @@ -3724,20 +3833,66 @@ nds32_relax_hint (int mode ATTRIBUTE_UNUSED) *input_line_pointer = 0; name = strdup (name); + if (name && strcmp (name, "begin") == 0) + { + if (relax_hint_id_current == -1) + reset_bias = 1; + relax_hint_bias++; + relax_hint_id_current++; + relax_hint_begin = 1; + } + + /* Original case ".relax_hint id". It's id may need to be reordered. */ + if (!relax_hint_begin) + { + int tmp = strtol (name, NULL, 10); + record_id = record_id_head; + while (record_id) + { + if (record_id->old_id == tmp) + { + name = nds_itoa (record_id->new_id); + goto reordered_id; + } + record_id = record_id->next; + } + if (reset_bias) + { + relax_hint_bias = relax_hint_id_current - atoi (name) + 1; + reset_bias = 0; + } + relax_hint_id_current = tmp + relax_hint_bias; + + /* Insert the element to the head of the link list. */ + struct relax_hint_id *tmp_id = malloc (sizeof (struct relax_hint_id)); + tmp_id->old_id = tmp; + tmp_id->new_id = relax_hint_id_current; + tmp_id->next = record_id_head; + record_id_head = tmp_id; + } + + if (name && strcmp (name, "end") == 0) + relax_hint_begin = 0; + name = nds_itoa (relax_hint_id_current); + +reordered_id: + /* Find relax hint entry for next instruction, and all member will be initialized at that time. */ relocs = hash_find (nds32_hint_hash, name); if (relocs == NULL) { - relocs = XNEW (struct nds32_relocs_pattern); + relocs = malloc (sizeof (struct nds32_relocs_pattern)); + memset (relocs, 0, sizeof (struct nds32_relocs_pattern)); hash_insert (nds32_hint_hash, name, relocs); } else { while (relocs->next) relocs=relocs->next; - relocs->next = XNEW (struct nds32_relocs_pattern); + relocs->next = malloc (sizeof (struct nds32_relocs_pattern)); relocs = relocs->next; + memset (relocs, 0, sizeof (struct nds32_relocs_pattern)); } relocs->next = NULL; @@ -3749,7 +3904,8 @@ nds32_relax_hint (int mode ATTRIBUTE_UNUSED) /* It has to build this list because there are maybe more than one instructions relative to the same instruction. It to connect to next instruction after md_assemble. */ - new = XNEW (struct nds32_relocs_group); + new = malloc (sizeof (struct nds32_relocs_group)); + memset (new, 0, sizeof (struct nds32_relocs_group)); new->pattern = relocs; new->next = NULL; group = nds32_relax_hint_current; @@ -3764,6 +3920,27 @@ nds32_relax_hint (int mode ATTRIBUTE_UNUSED) relaxing = TRUE; } +/* This is directive generated for compiler to estimate branch target + alignment. But assembler does not use the info currently. */ + +static void +nds32_maybe_align (int mode ATTRIBUTE_UNUSED) +{ + /* Ignore the reset of line. */ + ignore_rest_of_line (); +} + +/* The end of security. It must check if there is any branch + between begin and end. */ +static void +nds32_security_end (int mode ATTRIBUTE_UNUSED) +{ + if (crcing == FALSE) + as_bad (_("Found unexpected branches inside the " + "signature protected region.")); + +} + /* Decide the size of vector entries, only accepts 4 or 16 now. */ static void @@ -3819,7 +3996,7 @@ nds32_flag (int ignore ATTRIBUTE_UNUSED) switch (i) { case 0: - /* flag: verbatim */ + /* flag: verbatim */ verbatim = 1; break; default: @@ -3835,6 +4012,54 @@ nds32_flag (int ignore ATTRIBUTE_UNUSED) } static void +ict_model (int ignore ATTRIBUTE_UNUSED) +{ + char *name; + char saved_char; + int i; + const char *possible_flags[] = { "small", "large" }; + + /* Skip whitespaces. */ + name = input_line_pointer; + while (*input_line_pointer && !ISSPACE (*input_line_pointer)) + input_line_pointer++; + saved_char = *input_line_pointer; + *input_line_pointer = 0; + + for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++) + { + if (strcmp (name, possible_flags[i]) == 0) + { + switch (i) + { + case 0: + /* flag: verbatim */ + ict_flag = ICT_SMALL; + break; + case 1: + ict_flag = ICT_LARGE; + break; + default: + break; + } + /* Already found the flag, no need to continue next loop. */ + break; + } + } + + *input_line_pointer = saved_char; + ignore_rest_of_line (); +} + +/* Create .note.v2abi_compatible section if the object is compatible with v3f/v3s. + Do it at the md_end(). */ +static void +nds32_compatible_abi (int mode ATTRIBUTE_UNUSED) +{ + compatible_abi = TRUE; +} + +static void nds32_n12hc (int ignore ATTRIBUTE_UNUSED) { /* N1213HC core is used. */ @@ -3842,8 +4067,7 @@ nds32_n12hc (int ignore ATTRIBUTE_UNUSED) /* The target specific pseudo-ops which we support. */ -const pseudo_typeS md_pseudo_table[] = -{ +const pseudo_typeS md_pseudo_table[] = { /* Forced alignment if declared these ways. */ {"ascii", stringer, 8 + 0}, {"asciz", stringer, 8 + 1}, @@ -3894,13 +4118,17 @@ const pseudo_typeS md_pseudo_table[] = {"hint_func_args", nds32_set_hint_func_args, 0}, /* Abandon?? */ {"omit_fp_begin", nds32_omit_fp_begin, 1}, {"omit_fp_end", nds32_omit_fp_begin, 0}, - {"no_ex9_begin", nds32_no_ex9_begin, 1}, - {"no_ex9_end", nds32_no_ex9_begin, 0}, {"vec_size", nds32_vec_size, 0}, {"flag", nds32_flag, 0}, {"innermost_loop_begin", nds32_loop_begin, 1}, {"innermost_loop_end", nds32_loop_begin, 0}, {"relax_hint", nds32_relax_hint, 0}, + {"maybe_align", nds32_maybe_align, 0}, + {"signature_end", nds32_security_end, 0}, + {"inline_asm_begin", nds32_inline_asm, 1}, + {"inline_asm_end", nds32_inline_asm, 0}, + {"ict_model", ict_model, 0}, + {"v2abi_compatible", nds32_compatible_abi, 0}, {NULL, NULL, 0} }; @@ -3917,9 +4145,10 @@ nds32_pre_do_align (int n, char *fill, int len, int max) { dwarf2_emit_insn (0); fragP = frag_now; + add_mapping_symbol_for_align (n, frag_now_fix (), 0); frag_align_code (n, max); - /* Tag this alignment when there is a label before it. */ + /* Tag this alignment when there is a lable before it. */ if (label_exist) { fragP->tc_frag_data.flag = NDS32_FRAG_LABEL; @@ -4003,24 +4232,26 @@ void md_begin (void) { struct nds32_keyword *k; - unsigned int i; + relax_info_t *relax_info; + int flags = 0; bfd_set_arch_mach (stdoutput, TARGET_ARCH, nds32_baseline); nds32_init_nds32_pseudo_opcodes (); asm_desc.parse_operand = nds32_asm_parse_operand; - nds32_asm_init (&asm_desc, 0); + if (nds32_gpr16) + flags |= NASM_OPEN_REDUCED_REG; + nds32_asm_init (&asm_desc, flags); - /* Initial general purpose registers hash table. */ + /* Initial general pupose registers hash table. */ nds32_gprs_hash = hash_new (); for (k = keyword_gpr; k->name; k++) hash_insert (nds32_gprs_hash, k->name, k); /* Initial branch hash table. */ nds32_relax_info_hash = hash_new (); - for (i = 0; i < ARRAY_SIZE (relax_table); i++) - hash_insert (nds32_relax_info_hash, relax_table[i].opcode, - &relax_table[i]); + for (relax_info = relax_table; relax_info->opcode; relax_info++) + hash_insert (nds32_relax_info_hash, relax_info->opcode, relax_info); /* Initial relax hint hash table. */ nds32_hint_hash = hash_new (); @@ -4138,13 +4369,14 @@ get_range_type (const struct nds32_field *field) /* Save pseudo instruction relocation list. */ static struct nds32_relocs_pattern* -nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_opcode *opcode, +nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_asm_insn *insn, char *out, symbolS *sym, struct nds32_relocs_pattern *reloc_ptr, fragS *fragP) { + struct nds32_opcode *opcode = insn->opcode; if (!reloc_ptr) - reloc_ptr = XNEW (struct nds32_relocs_pattern); + reloc_ptr = malloc (sizeof (struct nds32_relocs_pattern)); reloc_ptr->seg = now_seg; reloc_ptr->sym = sym; reloc_ptr->frag = fragP; @@ -4152,6 +4384,7 @@ nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_opcode *opcode, reloc_ptr->fixP = fixP; reloc_ptr->opcode = opcode; reloc_ptr->where = out; + reloc_ptr->insn = insn->insn; reloc_ptr->next = NULL; return reloc_ptr; } @@ -4193,10 +4426,21 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, reloc = BFD_RELOC_NDS32_TLS_LE_HI20; break; case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */ - reloc = BFD_RELOC_NDS32_TLS_IE_HI20; + reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_HI20 : BFD_RELOC_NDS32_TLS_IE_HI20; + break; + case BFD_RELOC_NDS32_TLS_DESC: /* @TLSDESC */ + reloc = BFD_RELOC_NDS32_TLS_DESC_HI20; + break; + case BFD_RELOC_NDS32_ICT: + reloc = BFD_RELOC_NDS32_ICT_HI20; break; default: /* No suffix. */ - reloc = BFD_RELOC_NDS32_HI20; + if (nds32_pic) + /* When the file is pic, the address must be offset to gp. + It may define another relocation or use GOTOFF. */ + reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20; + else + reloc = BFD_RELOC_NDS32_HI20; break; } fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, @@ -4228,8 +4472,22 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */ reloc = BFD_RELOC_NDS32_TLS_LE_LO12; break; + case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */ + reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_LO12 : BFD_RELOC_NDS32_TLS_IE_LO12; + break; + case BFD_RELOC_NDS32_TLS_DESC: /* @TLSDESC */ + reloc = BFD_RELOC_NDS32_TLS_DESC_LO12; + break; + case BFD_RELOC_NDS32_ICT: + reloc = BFD_RELOC_NDS32_ICT_LO12; + break; default: /* No suffix. */ - reloc = BFD_RELOC_NDS32_LO12S0; + if (nds32_pic) + /* When the file is pic, the address must be offset to gp. + It may define another relocation or use GOTOFF. */ + reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12; + else + reloc = BFD_RELOC_NDS32_LO12S0; break; } } @@ -4237,11 +4495,14 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, reloc = BFD_RELOC_NDS32_LO12S1; /* [ls]hi */ else if (fld->bitsize == 15 && fld->shift == 2) { - /* [ls]wi */ + /* [ls]wi */ switch (pexp->X_md) { case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */ - reloc = BFD_RELOC_NDS32_TLS_IE_LO12S2; + reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_LO12S2 : BFD_RELOC_NDS32_TLS_IE_LO12S2; + break; + case BFD_RELOC_NDS32_ICT: + reloc = BFD_RELOC_NDS32_ICT_LO12S2; break; default: /* No suffix. */ reloc = BFD_RELOC_NDS32_LO12S2; @@ -4251,7 +4512,7 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, else if (fld->bitsize == 15 && fld->shift == 3) reloc = BFD_RELOC_NDS32_LO12S3; /* [ls]di */ else if (fld->bitsize == 12 && fld->shift == 2) - reloc = R_NDS32_LO12S2_SP_RELA; /* f[ls][sd]i */ + reloc = BFD_RELOC_NDS32_LO12S2_SP; /* f[ls][sd]i */ fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, insn->info, 0 /* pcrel */, reloc); @@ -4261,7 +4522,12 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, { /* Relocation for 32-bit branch instructions. */ if (fld->bitsize == 24 && fld->shift == 1) - reloc = BFD_RELOC_NDS32_25_PCREL; + { + if (pexp->X_md == BFD_RELOC_NDS32_ICT) + reloc = BFD_RELOC_NDS32_ICT_25PC; + else + reloc = BFD_RELOC_NDS32_25_PCREL; + } else if (fld->bitsize == 16 && fld->shift == 1) reloc = BFD_RELOC_NDS32_17_PCREL; else if (fld->bitsize == 14 && fld->shift == 1) @@ -4272,7 +4538,7 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, abort (); fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, - insn->info, 1 /* pcrel */, reloc); + insn->info, 1 /* pcrel */, reloc); } else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4 && (insn->attr & NASM_ATTR_GPREL)) @@ -4288,7 +4554,7 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, abort (); fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, - insn->info, 0 /* pcrel */, reloc); + insn->info, 0 /* pcrel */, reloc); /* Insert INSN16 for converting fp_as_gp. */ exp.X_op = O_symbol; exp.X_add_symbol = abs_section_sym; @@ -4310,20 +4576,6 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, insn->info, 1 /* pcrel */, reloc); } - else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_IFC_EXT)) - { - /* Relocation for ifcall instruction. */ - if (insn->opcode->isize == 2 && fld->bitsize == 9 && fld->shift == 1) - reloc = BFD_RELOC_NDS32_10IFCU_PCREL; - else if (insn->opcode->isize == 4 && fld->bitsize == 16 - && fld->shift == 1) - reloc = BFD_RELOC_NDS32_17IFC_PCREL; - else - abort (); - - fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, - insn->info, 1 /* pcrel */, reloc); - } else if (fld) as_bad (_("Don't know how to handle this field. %s"), str); @@ -4335,8 +4587,9 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str, static void nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out, - struct nds32_opcode *opcode, fragS *fragP, - const struct nds32_field *fld) + struct nds32_asm_insn *insn, fragS *fragP, + const struct nds32_field *fld, + bfd_boolean pseudo_hint) { struct nds32_relocs_pattern *reloc_ptr; struct nds32_relocs_group *group; @@ -4346,10 +4599,32 @@ nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out, if (fld) sym = pexp->X_add_symbol; - if (pseudo_opcode) + if (pseudo_hint) + { + /* We cannot know how many instructions will be expanded for + the pseudo instruction here. The first expanded instruction fills + the memory created by relax_hint. The follower will created and link + here. */ + group = nds32_relax_hint_current; + while (group) + { + if (group->pattern->opcode == NULL) + nds32_elf_save_pseudo_pattern (fixP, insn, out, sym, + group->pattern, fragP); + else + { + group->pattern->next = + nds32_elf_save_pseudo_pattern (fixP, insn, out, sym, + NULL, fragP); + group->pattern = group->pattern->next; + } + group = group->next; + } + } + else if (pseudo_opcode) { /* Save instruction relation for pseudo instruction expanding pattern. */ - reloc_ptr = nds32_elf_save_pseudo_pattern (fixP, opcode, out, sym, + reloc_ptr = nds32_elf_save_pseudo_pattern (fixP, insn, out, sym, NULL, fragP); if (!relocs_list) relocs_list = reloc_ptr; @@ -4367,7 +4642,7 @@ nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out, group = nds32_relax_hint_current; while (group) { - nds32_elf_save_pseudo_pattern (fixP, opcode, out, sym, + nds32_elf_save_pseudo_pattern (fixP, insn, out, sym, group->pattern, fragP); group = group->next; free (nds32_relax_hint_current); @@ -4383,40 +4658,214 @@ nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out, #define N32_MEM_EXT(insn) ((N32_OP6_MEM << 25) | insn) /* Relax pattern for link time relaxation. */ +/* relaxation types only! relocation types are not necessary */ +/* refer to nds32_elf_record_fixup_exp() */ static struct nds32_relax_hint_table relax_ls_table[] = { { - /* Set address: la -> sethi ori. */ - NDS32_RELAX_HINT_LA, /* main_type */ - 8, /* relax_code_size */ - { - OP6 (SETHI), - OP6 (ORI), - }, /* relax_code_seq */ - { - {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, - {4, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_INSN16} - } /* relax_fixup */ + /* For bug-12566, LA and Floating LSI. */ + .main_type = NDS32_RELAX_HINT_LA_FLSI, + .relax_code_size = 12, + .relax_code_seq = + { + OP6 (SETHI), + OP6 (ORI), + OP6 (LBI), + }, + .relax_fixup = + { + {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, + {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR}, + {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, + {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_LSI}, + {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, + {8, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + } }, { - /* Set address: l.w -> sethi ori. */ - NDS32_RELAX_HINT_LS, /* main_type */ - 8, /* relax_code_size */ - { - OP6 (SETHI), - OP6 (LBI), - }, /* relax_code_seq */ - { - {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, - {4, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_INSN16} - } /* relax_fixup */ + /* Load Address / Load-Store (LALS). */ + .main_type = NDS32_RELAX_HINT_LALS, + .relax_code_size = 12, + .relax_code_seq = + { + OP6 (SETHI), + OP6 (ORI), + OP6 (LBI), + }, + .relax_fixup = + { + {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, + {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, + {8, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + } }, { - 0, - 0, - {0}, - {{0, 0 , 0, 0}} + /* B(AL) symbol@PLT */ + .main_type = NDS32_RELAX_HINT_LA_PLT, + .relax_code_size = 16, + .relax_code_seq = + { + OP6 (SETHI), + OP6 (ORI), + OP6 (ALU1), + OP6 (JREG), + }, + .relax_fixup = + { + {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, + {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PLT_GOT_SUFF}, + {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + } + }, + { + /* LA (@GOT). */ + .main_type = NDS32_RELAX_HINT_LA_GOT, + .relax_code_size = 12, + .relax_code_seq = + { + OP6 (SETHI), + OP6 (ORI), + OP6 (MEM), + }, + .relax_fixup = + { + {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, + {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, + {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOT_SUFF}, + {0, 0, 0, 0} + } + }, + { + /* LA (@GOTOFF). */ + .main_type = NDS32_RELAX_HINT_LA_GOTOFF, + .relax_code_size = 16, + .relax_code_seq = + { + OP6 (SETHI), + OP6 (ORI), + OP6 (ALU1), + OP6 (MEM), + }, + .relax_fixup = + { + {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, + {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, + {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOTOFF_SUFF}, + {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOTOFF_SUFF}, + {0, 0, 0, 0} + } + }, + { + /* TLS LE LS|LA */ + .main_type = NDS32_RELAX_HINT_TLS_LE_LS, + .relax_code_size = 16, + .relax_code_seq = + { + OP6(SETHI), + OP6(ORI), + OP6(MEM), + OP6(ALU1), + }, + .relax_fixup = + { + {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, + {4, 4, NDS32_HINT | NDS32_PTR_MULTIPLE, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, + {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_LE_LS}, + {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_LE_ADD}, + {0, 0, 0, 0} + } + }, + { + /* TLS IE LA */ + .main_type = NDS32_RELAX_HINT_TLS_IE_LA, + .relax_code_size = 8, + .relax_code_seq = + { + OP6(SETHI), + OP6(LBI), + }, + .relax_fixup = + { + {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, + {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} + } + }, + { + /* TLS IEGP LA */ + .main_type = NDS32_RELAX_HINT_TLS_IEGP_LA, + .relax_code_size = 12, + .relax_code_seq = + { + OP6 (SETHI), + OP6 (ORI), + OP6 (MEM), + }, + .relax_fixup = + { + {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, + {4, 4, NDS32_HINT | NDS32_PTR_PATTERN, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, + {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_IEGP_LW}, + {0, 0, 0, 0} + } + }, + { + /* TLS DESC LS: */ + .main_type = NDS32_RELAX_HINT_TLS_DESC_LS, + .relax_code_size = 24, + .relax_code_seq = + { + OP6 (SETHI), + OP6 (ORI), + OP6 (ALU1), + OP6 (LBI), /* load argument */ + OP6 (JREG), + OP6 (MEM), /* load/store variable or load argument */ + }, + .relax_fixup = + { + {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, + {4, 4, NDS32_HINT | NDS32_PTR_PATTERN, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED}, + {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_ADD}, + {12, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_FUNC}, + {16, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_CALL}, + {20, 4, NDS32_HINT | NDS32_SYM_DESC_MEM, BFD_RELOC_NDS32_TLS_DESC_MEM}, + {0, 0, 0, 0} + } + }, + { + /* Load Address of ICT. */ + .main_type = NDS32_RELAX_HINT_ICT_LA, + .relax_code_size = 8, + .relax_code_seq = + { + OP6 (SETHI), + OP6 (ORI), + }, + .relax_fixup = + { + /* TODO: insert relocations to do relax. */ + {0, 0, 0, 0} + } + }, + { + .main_type = 0, + .relax_code_seq = {0}, + .relax_fixup = {{0, 0 , 0, 0}} } }; @@ -4481,118 +4930,189 @@ nds32_elf_sethi_range (struct nds32_relocs_pattern *pattern) (((size) & 0xff) | ((convertible) ? 1 << 31 : 0) \ | ((optimize) ? 1<< 30 : 0) | (insn16_on ? 1 << 29 : 0)) +#define MAC_COMBO (E_NDS32_HAS_FPU_MAC_INST|E_NDS32_HAS_MAC_DX_INST) static void nds32_set_elf_flags_by_insn (struct nds32_asm_insn * insn) { - /* Set E_NDS32_HAS_EXT_INST. */ - if (insn->opcode->attr & NASM_ATTR_PERF_EXT) - { - if (nds32_perf_ext) - nds32_elf_flags |= E_NDS32_HAS_EXT_INST; - else - as_bad (_("instruction %s requires enabling performance extension"), - insn->opcode->opcode); - } - else if (insn->opcode->attr & NASM_ATTR_PERF2_EXT) - { - if (nds32_perf_ext2) - nds32_elf_flags |= E_NDS32_HAS_EXT2_INST; - else - as_bad (_("instruction %s requires enabling performance extension II"), - insn->opcode->opcode); - } - else if (insn->opcode->attr & NASM_ATTR_AUDIO_ISAEXT) - { - if (nds32_audio_ext) - nds32_elf_flags |= E_NDS32_HAS_AUDIO_INST; - else - as_bad (_("instruction %s requires enabling AUDIO extension"), - insn->opcode->opcode); - } - else if (insn->opcode->attr & NASM_ATTR_STR_EXT) - { - if (nds32_string_ext) - nds32_elf_flags |= E_NDS32_HAS_STRING_INST; - else - as_bad (_("instruction %s requires enabling STRING extension"), - insn->opcode->opcode); - } - else if ((insn->opcode->attr & NASM_ATTR_DIV) - && (insn->opcode->attr & NASM_ATTR_DXREG)) - { - if (nds32_div && nds32_dx_regs) - nds32_elf_flags |= E_NDS32_HAS_DIV_DX_INST; - else - as_bad (_("instruction %s requires enabling DIV & DX_REGS extension"), - insn->opcode->opcode); - } - else if (insn->opcode->attr & NASM_ATTR_FPU) - { - if (nds32_fpu_sp_ext || nds32_fpu_dp_ext) - { - if (!(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))) - nds32_fpu_com = 1; - } - else - as_bad (_("instruction %s requires enabling FPU extension"), - insn->opcode->opcode); - } - else if (insn->opcode->attr & NASM_ATTR_FPU_SP_EXT) - { - if (nds32_fpu_sp_ext) - nds32_elf_flags |= E_NDS32_HAS_FPU_INST; - else - as_bad (_("instruction %s requires enabling FPU_SP extension"), - insn->opcode->opcode); - } - else if ((insn->opcode->attr & NASM_ATTR_FPU_SP_EXT) - && (insn->opcode->attr & NASM_ATTR_MAC)) - { - if (nds32_fpu_sp_ext && nds32_mac) - { - nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST; - nds32_elf_flags |= E_NDS32_HAS_FPU_INST; - } - else - as_bad (_("instruction %s requires enabling FPU_MAC extension"), - insn->opcode->opcode); - } - else if (insn->opcode->attr & NASM_ATTR_FPU_DP_EXT) - { - if (nds32_fpu_dp_ext) - nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST; - else - as_bad (_("instruction %s requires enabling FPU_DP extension"), - insn->opcode->opcode); - } - else if ((insn->opcode->attr & NASM_ATTR_FPU_DP_EXT) - && (insn->opcode->attr & NASM_ATTR_MAC)) + static int skip_flags = NASM_ATTR_EX9_EXT | NASM_ATTR_FPU_FMA + | NASM_ATTR_BRANCH | NASM_ATTR_SATURATION_EXT | NASM_ATTR_GPREL + | NASM_ATTR_DXREG | NASM_ATTR_ISA_V1 | NASM_ATTR_ISA_V2 | NASM_ATTR_ISA_V3 + | NASM_ATTR_ISA_V3M | NASM_ATTR_PCREL; + + int new_flags = insn->opcode->attr & ~skip_flags; + while (new_flags) { - if (nds32_fpu_dp_ext && nds32_mac) + int next = 1 << (ffs (new_flags) - 1); + new_flags &= ~next; + switch (next) { - nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST; - nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST; + case NASM_ATTR_PERF_EXT: + { + if (nds32_perf_ext) + { + nds32_elf_flags |= E_NDS32_HAS_EXT_INST; + skip_flags |= NASM_ATTR_PERF_EXT; + } + else + as_bad (_("instruction %s requires enabling performance " + "extension"), insn->opcode->opcode); + } + break; + case NASM_ATTR_PERF2_EXT: + { + if (nds32_perf_ext2) + { + nds32_elf_flags |= E_NDS32_HAS_EXT2_INST; + skip_flags |= NASM_ATTR_PERF2_EXT; + } + else + as_bad (_("instruction %s requires enabling performance " + "extension II"), insn->opcode->opcode); + } + break; + case NASM_ATTR_AUDIO_ISAEXT: + { + if (nds32_audio_ext) + { + nds32_elf_flags |= E_NDS32_HAS_AUDIO_INST; + skip_flags |= NASM_ATTR_AUDIO_ISAEXT; + } + else + as_bad (_("instruction %s requires enabling AUDIO extension"), + insn->opcode->opcode); + } + break; + case NASM_ATTR_STR_EXT: + { + if (nds32_string_ext) + { + nds32_elf_flags |= E_NDS32_HAS_STRING_INST; + skip_flags |= NASM_ATTR_STR_EXT; + } + else + as_bad (_("instruction %s requires enabling STRING extension"), + insn->opcode->opcode); + } + break; + case NASM_ATTR_DIV: + { + if (insn->opcode->attr & NASM_ATTR_DXREG) + { + if (nds32_div && nds32_dx_regs) + { + nds32_elf_flags |= E_NDS32_HAS_DIV_DX_INST; + skip_flags |= NASM_ATTR_DIV; + } + else + as_bad (_("instruction %s requires enabling DIV & DX_REGS " + "extension"), insn->opcode->opcode); + } + } + break; + case NASM_ATTR_FPU: + { + if (nds32_fpu_sp_ext || nds32_fpu_dp_ext) + { + if (!(nds32_elf_flags + & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))) + nds32_fpu_com = 1; + skip_flags |= NASM_ATTR_FPU; + } + else + as_bad (_("instruction %s requires enabling FPU extension"), + insn->opcode->opcode); + } + break; + case NASM_ATTR_FPU_SP_EXT: + { + if (nds32_fpu_sp_ext) + { + nds32_elf_flags |= E_NDS32_HAS_FPU_INST; + skip_flags |= NASM_ATTR_FPU_SP_EXT; + } + else + as_bad (_("instruction %s requires enabling FPU_SP extension"), + insn->opcode->opcode); + } + break; + case NASM_ATTR_FPU_DP_EXT: + { + if (nds32_fpu_dp_ext) + { + nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST; + skip_flags |= NASM_ATTR_FPU_DP_EXT; + } + else + as_bad (_("instruction %s requires enabling FPU_DP extension"), + insn->opcode->opcode); + } + break; + case NASM_ATTR_MAC: + { + if (insn->opcode->attr & NASM_ATTR_FPU_SP_EXT) + { + if (nds32_fpu_sp_ext && nds32_mac) + nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST; + else + as_bad (_("instruction %s requires enabling FPU_MAC " + "extension"), insn->opcode->opcode); + } + else if (insn->opcode->attr & NASM_ATTR_FPU_DP_EXT) + { + if (nds32_fpu_dp_ext && nds32_mac) + nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST; + else + as_bad (_("instruction %s requires enabling FPU_MAC " + "extension"), insn->opcode->opcode); + } + else if (insn->opcode->attr & NASM_ATTR_DXREG) + { + if (nds32_dx_regs && nds32_mac) + nds32_elf_flags |= E_NDS32_HAS_MAC_DX_INST; + else + as_bad (_("instruction %s requires enabling DX_REGS " + "extension"), insn->opcode->opcode); + } + + if (MAC_COMBO == (MAC_COMBO & nds32_elf_flags)) + skip_flags |= NASM_ATTR_MAC; + } + break; + case NASM_ATTR_IFC_EXT: + { + nds32_elf_flags |= E_NDS32_HAS_IFC_INST; + skip_flags |= NASM_ATTR_IFC_EXT; + } + break; + case NASM_ATTR_DSP_ISAEXT: + { + if (nds32_dsp_ext) + { + nds32_elf_flags |= E_NDS32_HAS_DSP_INST; + skip_flags |= NASM_ATTR_DSP_ISAEXT; + } + else + as_bad (_("instruction %s requires enabling dsp extension"), + insn->opcode->opcode); + } + break; + case NASM_ATTR_ZOL: + { + if (nds32_zol_ext) + { + nds32_elf_flags |= E_NDS32_HAS_ZOL; + skip_flags |= NASM_ATTR_ZOL; + } + else + as_bad (_("instruction %s requires enabling zol extension"), + insn->opcode->opcode); + } + break; + default: + as_bad (_("internal error: unknown instruction attribute: 0x%08x"), + next); } - else - as_bad (_("instruction %s requires enabling FPU_MAC extension"), - insn->opcode->opcode); - } - /* TODO: FPU_BOTH */ - else if ((insn->opcode->attr & NASM_ATTR_MAC) - && (insn->opcode->attr & NASM_ATTR_DXREG)) - { - if (nds32_mac && nds32_dx_regs) - nds32_elf_flags |= E_NDS32_HAS_MAC_DX_INST; - else - as_bad (_("instruction %s requires enabling DX_REGS extension"), - insn->opcode->opcode); - } - /* TODO: for DX_REG set but not for MAC, DIV, AUDIO */ - else if (insn->opcode->attr & NASM_ATTR_IFC_EXT) - { - nds32_elf_flags |= E_NDS32_HAS_IFC_INST; } - /* TODO: E_NDS32_HAS_SATURATION_INST */ } /* Flag for analysis relaxation type. */ @@ -4607,100 +5127,212 @@ enum nds32_insn_type N32_RELAX_ORI = (1 << 5), N32_RELAX_MEM = (1 << 6), N32_RELAX_MOVI = (1 << 7), + N32_RELAX_ALU1 = (1 << 8), + N32_RELAX_16BIT = (1 << 9), }; struct nds32_hint_map { + /* the preamble relocation */ bfd_reloc_code_real_type hi_type; + /* mnemonic */ const char *opc; + /* relax pattern ID */ enum nds32_relax_hint_type hint_type; + /* range */ enum nds32_br_range range; + /* pattern character flags */ enum nds32_insn_type insn_list; + /* optional pattern character flags */ + enum nds32_insn_type option_list; }; /* Table to match instructions with hint and relax pattern. */ static struct nds32_hint_map hint_map [] = { - { - /* LONGCALL4. */ - BFD_RELOC_NDS32_HI20, - "jal", - NDS32_RELAX_HINT_NONE, - BR_RANGE_U4G, - N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL - }, - { - /* LONGCALL5. */ - _dummy_first_bfd_reloc_code_real, - "bgezal", - NDS32_RELAX_HINT_NONE, - BR_RANGE_S16M, - N32_RELAX_BR | N32_RELAX_CALL - }, - { - /* LONGCALL6. */ - BFD_RELOC_NDS32_HI20, - "bgezal", - NDS32_RELAX_HINT_NONE, - BR_RANGE_U4G, - N32_RELAX_BR | N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL - }, - { - /* LONGJUMP4. */ - BFD_RELOC_NDS32_HI20, - "j", - NDS32_RELAX_HINT_NONE, - BR_RANGE_U4G, - N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_JUMP - }, - { - /* LONGJUMP5. */ - /* There is two kinds of variations of LONGJUMP5. One of them - generate EMPTY relocation for converted INSN16 if needed. - But we don't distinguish them here. */ - _dummy_first_bfd_reloc_code_real, - "beq", - NDS32_RELAX_HINT_NONE, - BR_RANGE_S16M, - N32_RELAX_BR | N32_RELAX_JUMP - }, - { - /* LONGJUMP6. */ - BFD_RELOC_NDS32_HI20, - "beq", - NDS32_RELAX_HINT_NONE, - BR_RANGE_U4G, - N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_BR | N32_RELAX_JUMP - }, - { - /* LONGJUMP7. */ - _dummy_first_bfd_reloc_code_real, - "beqc", - NDS32_RELAX_HINT_NONE, - BR_RANGE_S16K, - N32_RELAX_MOVI | N32_RELAX_BR - }, - { - /* LOADSTORE ADDRESS. */ - BFD_RELOC_NDS32_HI20, - NULL, - NDS32_RELAX_HINT_LA, - BR_RANGE_U4G, - N32_RELAX_SETHI | N32_RELAX_ORI - }, - { - /* LOADSTORE ADDRESS. */ - BFD_RELOC_NDS32_HI20, - NULL, - NDS32_RELAX_HINT_LS, - BR_RANGE_U4G, - N32_RELAX_SETHI | N32_RELAX_LSI - }, - {0, NULL, 0, 0 ,0} + { + /* LONGCALL4. */ + BFD_RELOC_NDS32_HI20, + "jal", + NDS32_RELAX_HINT_NONE, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL, + 0, + }, + { + /* LONGCALL5. */ + _dummy_first_bfd_reloc_code_real, + "bgezal", + NDS32_RELAX_HINT_NONE, + BR_RANGE_S16M, + N32_RELAX_BR | N32_RELAX_CALL, + 0, + }, + { + /* LONGCALL6. */ + BFD_RELOC_NDS32_HI20, + "bgezal", + NDS32_RELAX_HINT_NONE, + BR_RANGE_U4G, + N32_RELAX_BR | N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL, + 0, + }, + { + /* LONGJUMP4. */ + BFD_RELOC_NDS32_HI20, + "j", + NDS32_RELAX_HINT_NONE, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_JUMP, + 0, + }, + { + /* LONGJUMP5. */ + /* There is two kinds of variation of LONGJUMP5. One of them + generate EMPTY relocation for converted INSN16 if needed. + But we don't distinguish them here. */ + _dummy_first_bfd_reloc_code_real, + "beq", + NDS32_RELAX_HINT_NONE, + BR_RANGE_S16M, + N32_RELAX_BR | N32_RELAX_JUMP, + 0, + }, + { + /* LONGJUMP6. */ + BFD_RELOC_NDS32_HI20, + "beq", + NDS32_RELAX_HINT_NONE, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_BR | N32_RELAX_JUMP, + 0, + }, + { + /* LONGJUMP7. */ + _dummy_first_bfd_reloc_code_real, + "beqc", + NDS32_RELAX_HINT_NONE, + BR_RANGE_S16K, + N32_RELAX_MOVI | N32_RELAX_BR, + 0, + }, + { + /* LONGCALL (BAL|JR|LA symbol@PLT). */ + BFD_RELOC_NDS32_PLT_GOTREL_HI20, + NULL, + NDS32_RELAX_HINT_LA_PLT, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_ORI, + N32_RELAX_ALU1 | N32_RELAX_CALL | N32_RELAX_JUMP, + }, + /* relative issue: #12566 */ + { + /* LA and Floating LSI. */ + BFD_RELOC_NDS32_HI20, + NULL, + NDS32_RELAX_HINT_LA_FLSI, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_LSI, + 0, + }, + /* relative issue: #11685 #11602 */ + { + /* load address / load-store (LALS). */ + BFD_RELOC_NDS32_HI20, + NULL, + NDS32_RELAX_HINT_LALS, + BR_RANGE_U4G, + N32_RELAX_SETHI, + N32_RELAX_ORI | N32_RELAX_LSI, + }, + { + /* setup $GP (_GLOBAL_OFFSET_TABLE_) */ + BFD_RELOC_NDS32_GOTPC_HI20, + NULL, + NDS32_RELAX_HINT_LALS, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_ORI, + 0, + }, + { + /* GOT LA/LS (symbol@GOT) */ + BFD_RELOC_NDS32_GOT_HI20, + NULL, + NDS32_RELAX_HINT_LA_GOT, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_ORI, + N32_RELAX_MEM, + }, + { + /* GOTOFF LA/LS (symbol@GOTOFF) */ + BFD_RELOC_NDS32_GOTOFF_HI20, + NULL, + NDS32_RELAX_HINT_LA_GOTOFF, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_ORI, + N32_RELAX_ALU1 | N32_RELAX_MEM, /* | N32_RELAX_LSI, */ + }, + { + /* TLS LE LA|LS (@TPOFF) */ + BFD_RELOC_NDS32_TLS_LE_HI20, + NULL, + NDS32_RELAX_HINT_TLS_LE_LS, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_ORI, + N32_RELAX_ALU1 | N32_RELAX_MEM, + }, + { + /* TLS IE LA */ + BFD_RELOC_NDS32_TLS_IE_HI20, + NULL, + NDS32_RELAX_HINT_TLS_IE_LA, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_LSI, + 0, + }, + { + /* TLS IE LS */ + BFD_RELOC_NDS32_TLS_IE_HI20, + NULL, + NDS32_RELAX_HINT_TLS_IE_LS, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_LSI | N32_RELAX_MEM, + 0, + }, + { + /* TLS IEGP LA */ + BFD_RELOC_NDS32_TLS_IEGP_HI20, + NULL, + NDS32_RELAX_HINT_TLS_IEGP_LA, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_MEM, + 0, + }, + { + /* TLS DESC LS */ + BFD_RELOC_NDS32_TLS_DESC_HI20, + NULL, + NDS32_RELAX_HINT_TLS_DESC_LS, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_ALU1 | N32_RELAX_CALL, + N32_RELAX_LSI | N32_RELAX_MEM, + }, + { + /* Jump-patch load address (LA). */ + BFD_RELOC_NDS32_ICT_HI20, + NULL, + NDS32_RELAX_HINT_ICT_LA, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_ORI, + 0, + }, + /* last one */ + {0, NULL, 0, 0 ,0, 0} }; /* Find the relaxation pattern according to instructions. */ +/* TODO: refine this function with hash or so */ static bfd_boolean nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern, @@ -4739,6 +5371,9 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern, case N32_OP6_MEM: relax_type |= N32_RELAX_MEM; break; + case N32_OP6_ALU1: + relax_type |= N32_RELAX_ALU1; + break; case N32_OP6_ORI: relax_type |= N32_RELAX_ORI; break; @@ -4760,6 +5395,8 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern, case N32_OP6_SWI: case N32_OP6_LWC: case N32_OP6_SWC: + case N32_OP6_LDC: + case N32_OP6_SDC: relax_type |= N32_RELAX_LSI; break; case N32_OP6_JREG: @@ -4784,16 +5421,20 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern, { /* 2 byte instruction. Compare by opcode name because the opcode of 2byte instruction is not regular. */ - for (i = 0; i < sizeof (check_insn) / sizeof (check_insn[0]); i++) + int is_matched = 0; + for (i = 0; i < ARRAY_SIZE (check_insn); i++) { if (strcmp (pattern->opcode->opcode, check_insn[i]) == 0) { relax_type |= N32_RELAX_BR; + is_matched += 1; break; } } - if (strcmp (pattern->opcode->opcode, "movi55") == 0) - relax_type |= N32_RELAX_MOVI; + if (!is_matched) + { + relax_type |= N32_RELAX_16BIT; + } } pattern = pattern->next; } @@ -4801,23 +5442,35 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern, /* Analysis instruction flag to choose relaxation table. */ while (map_ptr->insn_list != 0) { - if (map_ptr->insn_list == relax_type - && (!hi_pattern - || (hi_pattern->fixP - && hi_pattern->fixP->fx_r_type == map_ptr->hi_type))) + struct nds32_hint_map *hint = map_ptr++; + enum nds32_insn_type must = hint->insn_list; + enum nds32_insn_type optional = hint->option_list; + enum nds32_insn_type extra; + + if (must != (must & relax_type)) + continue; + + extra = relax_type ^ must; + if (extra != (extra & optional)) + continue; + + if (!hi_pattern + || (hi_pattern->fixP + && hi_pattern->fixP->fx_r_type == hint->hi_type)) { - opc = map_ptr->opc; - hint_type = map_ptr->hint_type; - range = map_ptr->range; + opc = hint->opc; + hint_type = hint->hint_type; + range = hint->range; + map_ptr = hint; break; } - map_ptr++; } if (map_ptr->insn_list == 0) { - as_warn (_("Can not find match relax hint. Line: %d"), - relocs_pattern->frag->fr_line); + if (!nds32_pic) + as_warn (_("Can not find match relax hint. line : %d"), + relocs_pattern->fixP->fx_line); return FALSE; } @@ -4876,12 +5529,14 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern, /* Because there are a lot of variant of load-store, check all these type here. */ -#define CLEAN_REG(insn) ((insn) & 0xff0003ff) +#define CLEAN_REG(insn) ((insn) & 0xfe0003ff) +#define GET_OPCODE(insn) ((insn) & 0xfe000000) + static bfd_boolean nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq) { const char *check_insn[] = - { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" }; + { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8", "jral5" }; uint32_t insn = opcode->value; unsigned int i; @@ -4897,22 +5552,23 @@ nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq) if (insn == OP6 (LBI) || insn == OP6 (SBI) || insn == OP6 (LBSI) || insn == OP6 (LHI) || insn == OP6 (SHI) || insn == OP6 (LHSI) || insn == OP6 (LWI) || insn == OP6 (SWI) - || insn == OP6 (LWC) || insn == OP6 (SWC)) - return TRUE; + || insn == OP6 (LWC) || insn == OP6 (SWC) + || insn == OP6 (LDC) || insn == OP6 (SDC)) + return TRUE; break; case OP6 (BR2): /* This is for LONGCALL5 and LONGCALL6. */ if (insn == OP6 (BR2)) - return TRUE; + return TRUE; break; case OP6 (BR1): /* This is for LONGJUMP5 and LONGJUMP6. */ if (opcode->isize == 4 && (insn == OP6 (BR1) || insn == OP6 (BR2) || insn == OP6 (BR3))) - return TRUE; + return TRUE; else if (opcode->isize == 2) { - for (i = 0; i < sizeof (check_insn) / sizeof (check_insn[0]); i++) + for (i = 0; i < ARRAY_SIZE (check_insn); i++) if (strcmp (opcode->opcode, check_insn[i]) == 0) return TRUE; } @@ -4920,8 +5576,28 @@ nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq) case OP6 (MOVI): /* This is for LONGJUMP7. */ if (opcode->isize == 2 && strcmp (opcode->opcode, "movi55") == 0) - return TRUE; + return TRUE; + break; + case OP6 (MEM): + if (OP6 (MEM) == GET_OPCODE (insn)) + return TRUE; break; + case OP6 (JREG): + /* bit 24: N32_JI_JAL */ /* feed me! */ + if ((insn & ~(N32_BIT (24))) == JREG (JRAL)) + return TRUE; + break; + default: + if (opcode->isize == 2) + { + for (i = 0; i < ARRAY_SIZE (check_insn); i++) + if (strcmp (opcode->opcode, check_insn[i]) == 0) + return TRUE; + + if ((strcmp (opcode->opcode, "add5.pc") == 0) || + (strcmp (opcode->opcode, "add45") == 0)) + return TRUE; + } } return FALSE; } @@ -4929,7 +5605,7 @@ nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq) /* Append relax relocation for link time relaxing. */ static void -nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) +nds32_elf_append_relax_relocs (const char *key, void *value) { struct nds32_relocs_pattern *relocs_pattern = (struct nds32_relocs_pattern *) value; @@ -4942,7 +5618,7 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) struct nds32_relax_hint_table hint_info; nds32_relax_fixup_info_t *hint_fixup, *fixup_now; size_t fixup_size; - offsetT branch_offset; + offsetT branch_offset, hi_branch_offset = 0; fixS *fixP; int range, offset; unsigned int ptr_offset, hint_count, relax_code_size, count = 0; @@ -4963,6 +5639,7 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) if (pattern_now->opcode->value == OP6 (SETHI)) { hi_sym = pattern_now->sym; + hi_branch_offset = pattern_now->fixP->fx_offset; break; } pattern_now = pattern_now->next; @@ -4979,15 +5656,36 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) relax_code_size = hint_info.relax_code_size; pattern_now = relocs_pattern; +#ifdef NDS32_LINUX_TOOLCHAIN + /* prepare group relocation ID (number). */ + long group_id = 0; + if (key) + { + /* convert .relax_hint key to number */ + errno = 0; + group_id = strtol (key, NULL, 10); + if ((errno == ERANGE && (group_id == LONG_MAX || group_id == LONG_MIN)) + || (errno != 0 && group_id == 0)) + { + as_bad (_("Internal error: .relax_hint KEY is not a number!")); + goto restore; + } + } +#endif + /* Insert relaxation. */ exp.X_op = O_symbol; + /* for each instruction in the hint group */ while (pattern_now) { - /* Choose the match fixup by instruction. */ + if (count >= relax_code_size / 4) + count = 0; + /* Choose the match fix-up by instruction. */ code_insn = CLEAN_REG (*(code_seq + count)); if (!nds32_match_hint_insn (pattern_now->opcode, code_insn)) { + /* try search from head again */ count = 0; code_insn = CLEAN_REG (*(code_seq + count)); @@ -4996,8 +5694,11 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) count++; if (count >= relax_code_size / 4) { - as_bad (_("Internal error: Relax hint error. %s: %x"), - now_seg->name, pattern_now->opcode->value); + as_bad (_("Internal error: Relax hint (%s) error. %s: %s (%x)"), + key, + now_seg->name, + pattern_now->opcode->opcode, + pattern_now->opcode->value); goto restore; } code_insn = CLEAN_REG (*(code_seq + count)); @@ -5024,7 +5725,7 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) } fixup_size = fixup_now->size; - /* Insert all fixup. */ + /* Insert all fix-up. */ while (fixup_size != 0 && fixup_now->offset == offset) { /* Set the real instruction size in element. */ @@ -5093,7 +5794,108 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) { /* For EMPTY relocation save the true symbol. */ exp.X_add_symbol = hi_sym; - exp.X_add_number = branch_offset; + exp.X_add_number = hi_branch_offset; + } + else if (NDS32_SYM_DESC_MEM & fixup_now->ramp) + { + /* do the same as NDS32_SYM */ + exp.X_add_symbol = hi_sym; + exp.X_add_number = hi_branch_offset; + + /* extra to NDS32_SYM */ + /* detect if DESC_FUNC relax type do apply */ + if ((REG_GP == N32_RA5 (pattern_now->insn)) + || (REG_GP == N32_RB5 (pattern_now->insn))) + { + fixP = fix_new_exp (fragP, where - fragP->fr_literal, + fixup_size, &exp, pcrel, + BFD_RELOC_NDS32_TLS_DESC_FUNC); + fixP->fx_addnumber = fixP->fx_offset; + + fixup_size = 0; + } + /* else do as usual */ + } + else if (fixup_now->ramp & NDS32_PTR_PATTERN) + { + /* find out PTR_RESOLVED code pattern */ + nds32_relax_fixup_info_t *next_fixup = fixup_now + 1; + uint32_t resolved_pattern = 0; + while (next_fixup->offset) + { + if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED) + { + uint32_t new_pattern = code_seq[next_fixup->offset >> 2]; + if (!resolved_pattern) + resolved_pattern = new_pattern; + else if (new_pattern != resolved_pattern) + { + as_warn (_("Multiple BFD_RELOC_NDS32_PTR_RESOLVED patterns are not supported yet!")); + break; + } + } + ++next_fixup; + } + + /* find matched code and insert fix-ups */ + struct nds32_relocs_pattern *next_pattern = pattern_now->next; + /* This relocation has to point to another instruction. Make + sure each resolved relocation has to be pointed. */ + /* All instruction in relax_table should be 32-bit. */ + while (next_pattern) + { + uint32_t cur_pattern = GET_OPCODE (next_pattern->opcode->value); + if (cur_pattern == resolved_pattern) + { + ptr_offset = next_pattern->where + - next_pattern->frag->fr_literal; + exp.X_add_symbol = symbol_temp_new (now_seg, ptr_offset, + next_pattern->frag); + exp.X_add_number = 0; + fixP = fix_new_exp (fragP, where - fragP->fr_literal, + fixup_size, &exp, 0, + fixup_now->r_type); + fixP->fx_addnumber = fixP->fx_offset; + } + next_pattern = next_pattern->next; + } + + fixup_size = 0; + } + else if (fixup_now->ramp & NDS32_PTR_MULTIPLE) + { + /* find each PTR_RESOLVED pattern after PTR */ + nds32_relax_fixup_info_t *next_fixup = fixup_now + 1; + while (next_fixup->offset) + { + if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED) + { + uint32_t pattern = code_seq[next_fixup->offset >> 2]; + /* find matched code to insert fix-ups */ + struct nds32_relocs_pattern *next_insn = pattern_now->next; + while (next_insn) + { + uint32_t insn_pattern = GET_OPCODE( + next_insn->opcode->value); + if (insn_pattern == pattern) + { + ptr_offset = next_insn->where + - next_insn->frag->fr_literal; + exp.X_add_symbol = symbol_temp_new ( + now_seg, ptr_offset, next_insn->frag); + exp.X_add_number = 0; + fixP = fix_new_exp (fragP, + where - fragP->fr_literal, + fixup_size, &exp, 0, + fixup_now->r_type); + fixP->fx_addnumber = fixP->fx_offset; + } + next_insn = next_insn->next; + } + } + ++next_fixup; + } + fixup_size = 0; } else { @@ -5110,6 +5912,19 @@ nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) fixup_now++; fixup_size = fixup_now->size; } + +#ifdef NDS32_LINUX_TOOLCHAIN + /* Insert group relocation for each relax hint. */ + if (key) + { + exp.X_add_symbol = hi_sym; /* for eyes only */ + exp.X_add_number = group_id; + fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size, + &exp, pcrel, BFD_RELOC_NDS32_GROUP); + fixP->fx_addnumber = fixP->fx_offset; + } +#endif + if (count < relax_code_size / 4) count++; pattern_now = pattern_now->next; @@ -5120,6 +5935,19 @@ restore: frchain_now = frchain_bak; } +static void +nds32_str_tolower (const char *src, char *dest) +{ + unsigned int i, len; + + len = strlen (src); + + for (i = 0; i < len; i++) + *(dest + i) = TOLOWER (*(src + i)); + + *(dest + i) = '\0'; +} + /* Check instruction if it can be used for the baseline. */ static bfd_boolean @@ -5127,6 +5955,28 @@ nds32_check_insn_available (struct nds32_asm_insn insn, const char *str) { int attr = insn.attr & ATTR_ALL; static int baseline_isa = 0; + char *s; + + s = alloca (strlen (str) + 1); + nds32_str_tolower (str, s); + if (verbatim && inline_asm + && (((insn.opcode->value == ALU2 (MTUSR) + || insn.opcode->value == ALU2 (MFUSR)) + && (strstr (s, "lc") + || strstr (s, "le") + || strstr (s, "lb"))) + || (insn.attr & NASM_ATTR_ZOL))) + { + as_bad (_("Not support instruction %s in verbatim."), str); + return FALSE; + } + + if (!enable_16bit && insn.opcode->isize == 2) + { + as_bad (_("16-bit instruction is disabled: %s."), str); + return FALSE; + } + /* No isa setting or all isa can use. */ if (attr == 0 || attr == ATTR_ALL) return TRUE; @@ -5150,28 +6000,70 @@ nds32_check_insn_available (struct nds32_asm_insn insn, const char *str) if ((baseline_isa & attr) == 0) { - as_bad (_("Instruction %s not supported in the baseline."), str); + as_bad (_("Not support instruction %s in the baseline."), str); return FALSE; } return TRUE; } +/* Clear security and insert relocation. */ +static void +nds32_set_crc (fragS *fragP, struct nds32_asm_insn *insn, char *out) +{ + expressionS exp; + + /* The security region begin. */ + if (strcmp (insn->opcode->opcode, "isps") == 0) + { + exp.X_op = O_symbol; + exp.X_add_symbol = abs_section_sym; + /* Meet the new crc in previos crc region. */ + if (crcing == TRUE) + { + exp.X_add_number = NDS32_SECURITY_RESTART; + fix_new_exp (fragP, out - fragP->fr_literal, 0, &exp, + 0, BFD_RELOC_NDS32_SECURITY_16); + } + crcing = TRUE; + /* For security used only. */ + exp.X_add_number = NDS32_SECURITY_START; + fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, + &exp, 0 /* pcrel */, BFD_RELOC_NDS32_SECURITY_16); + } + /* Turn off security region when meeting branch. */ + else if (crcing && ((insn->attr & NASM_ATTR_BRANCH) + || insn->opcode->value == MISC (SYSCALL) + || insn->opcode->value == MISC (TRAP) + || insn->opcode->value == MISC (TEQZ) + || insn->opcode->value == MISC (TNEZ) + || insn->opcode->value == MISC (IRET) + || insn->attr & NASM_ATTR_IFC_EXT)) + { + crcing = FALSE; + exp.X_op = O_symbol; + exp.X_add_symbol = abs_section_sym; + exp.X_add_number = NDS32_SECURITY_END; + fix_new_exp (fragP, out - fragP->fr_literal, 0, &exp, + 0, BFD_RELOC_NDS32_SECURITY_16); + } +} + /* Stub of machine dependent. */ void md_assemble (char *str) { struct nds32_asm_insn insn; - expressionS expr; char *out; struct nds32_pseudo_opcode *popcode; const struct nds32_field *fld = NULL; fixS *fixP; uint16_t insn_16; struct nds32_relocs_pattern *relocs_temp; - expressionS *pexp; + struct nds32_relocs_group *group_temp; fragS *fragP; int label = label_exist; + static bfd_boolean pseudo_hint = FALSE; popcode = nds32_lookup_pseudo_opcode (str); /* Note that we need to check 'verbatim' and @@ -5180,11 +6072,23 @@ md_assemble (char *str) need to perform pseudo instruction expansion/transformation. */ if (popcode && !(verbatim && popcode->physical_op)) { + /* Pseudo instruction is with relax_hint. */ + if (relaxing) + pseudo_hint = TRUE; pseudo_opcode = TRUE; nds32_pseudo_opcode_wrapper (str, popcode); pseudo_opcode = FALSE; + pseudo_hint = FALSE; nds32_elf_append_relax_relocs (NULL, relocs_list); + /* Free relax_hint group list. */ + while (nds32_relax_hint_current) + { + group_temp = nds32_relax_hint_current->next; + free (nds32_relax_hint_current); + nds32_relax_hint_current = group_temp; + } + /* Free pseudo list. */ relocs_temp = relocs_list; while (relocs_temp) @@ -5193,12 +6097,11 @@ md_assemble (char *str) free (relocs_temp); relocs_temp = relocs_list; } - return; } label_exist = 0; - insn.info = & expr; + insn.info = (expressionS *) alloca (sizeof (expressionS)); asm_desc.result = NASM_OK; nds32_assemble (&asm_desc, &insn, str); @@ -5235,11 +6138,13 @@ md_assemble (char *str) /* Make sure the beginning of text being 2-byte align. */ nds32_adjust_label (1); + add_mapping_symbol (MAP_CODE, 0, 0); fld = insn.field; /* Try to allocate the max size to guarantee relaxable same branch instructions in the same fragment. */ frag_grow (NDS32_MAXCHAR); fragP = frag_now; + if (fld && (insn.attr & NASM_ATTR_BRANCH) && (pseudo_opcode || (insn.opcode->value != INSN_JAL && insn.opcode->value != INSN_J)) @@ -5247,7 +6152,7 @@ md_assemble (char *str) { /* User assembly code branch relax for it. */ /* If fld is not NULL, it is a symbol. */ - /* Branch must relax to proper pattern in user assembly code exclude + /* Branch msut relax to proper pattern in user assembly code exclude J and JAL. Keep these two in original type for users which wants to keep their size be fixed. In general, assembler does not convert instruction generated by compiler. But jump instruction may be @@ -5257,8 +6162,8 @@ md_assemble (char *str) /* Get branch range type. */ dwarf2_emit_insn (0); enum nds32_br_range range_type; + expressionS *pexp = insn.info; - pexp = insn.info; range_type = get_range_type (fld); out = frag_var (rs_machine_dependent, NDS32_MAXCHAR, @@ -5274,6 +6179,12 @@ md_assemble (char *str) else if (insn.opcode->isize == 2) bfd_putb16 (insn.insn, out); fragP->tc_frag_data.flag |= NDS32_FRAG_BRANCH; + + if (fld->bitsize == 24 && fld->shift == 1 + && pexp->X_md == BFD_RELOC_NDS32_ICT) + fragP->tc_frag_data.flag |= NDS32_FRAG_ICT_BRANCH; + + nds32_set_crc (fragP, &insn, out); return; /* md_convert_frag will insert relocations. */ } @@ -5284,7 +6195,7 @@ md_assemble (char *str) && nds32_convert_16_to_32 (stdoutput, insn.insn, NULL)))) { /* Record this one is relaxable. */ - pexp = insn.info; + expressionS *pexp = insn.info; dwarf2_emit_insn (0); if (fld) { @@ -5304,7 +6215,7 @@ md_assemble (char *str) fragP->tc_frag_data.insn = insn.insn; fragP->fr_fix += 2; - /* In original, we don't relax the instruction with label on it, + /* In original, we don't relax the instrucion with label on it, but this may cause some redundant nop16. Therefore, tag this relaxable instruction and relax it carefully. */ if (label) @@ -5314,6 +6225,7 @@ md_assemble (char *str) bfd_putb16 (insn_16, out); else if (insn.opcode->isize == 2) bfd_putb16 (insn.insn, out); + nds32_set_crc (fragP, &insn, out); return; } else if ((verbatim || !relaxing) && optimize && label) @@ -5322,7 +6234,7 @@ md_assemble (char *str) expressionS exp; out = frag_var (rs_machine_dependent, insn.opcode->isize, 0, 0, NULL, 0, NULL); - /* If this instruction is branch target, it is not relaxable. */ + /* If this insturction is branch target, it is not relaxable. */ fragP->tc_frag_data.flag = NDS32_FRAG_LABEL; fragP->tc_frag_data.opcode = insn.opcode; fragP->tc_frag_data.insn = insn.insn; @@ -5343,18 +6255,20 @@ md_assemble (char *str) if (insn.opcode->isize == 4) bfd_putb32 (insn.insn, out); - if (insn.opcode->isize == 2) + else if (insn.opcode->isize == 2) bfd_putb16 (insn.insn, out); dwarf2_emit_insn (insn.opcode->isize); /* Compiler generating code and user assembly pseudo load-store, insert fixup here. */ - pexp = insn.info; + expressionS *pexp = insn.info; fixP = nds32_elf_record_fixup_exp (fragP, str, fld, pexp, out, &insn); /* Build relaxation pattern when relaxing is enable. */ if (relaxing) - nds32_elf_build_relax_relation (fixP, pexp, out, insn.opcode, fragP, fld); + nds32_elf_build_relax_relation (fixP, pexp, out, &insn, fragP, fld, + pseudo_hint); + nds32_set_crc (fragP, &insn, out); } /* md_macro_start */ @@ -5402,7 +6316,7 @@ md_section_align (segT segment, valueT size) { int align = bfd_get_section_alignment (stdoutput, segment); - return ((size + (1 << align) - 1) & -(1 << align)); + return ((size + (1 << align) - 1) & ((valueT) -1 << align)); } /* GAS will call this function when a symbol table lookup fails, before it @@ -5441,6 +6355,7 @@ nds32_calc_branch_offset (segT segment, fragS *fragP, { /* Calculate symbol-to-instruction offset. */ branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset; + /* If the destination symbol is beyond current frag address, STRETCH will take effect to symbol's position. */ if (S_GET_VALUE (branch_symbol) > fragP->fr_address) @@ -5464,31 +6379,31 @@ nds32_convert_to_range_type (long offset) { enum nds32_br_range range_type; - if (-(0x100) <= offset && offset < 0x100) /* 256 bytes */ + if (-(0x100) <= offset && offset < 0x100) /* 256 bytes */ range_type = BR_RANGE_S256; - else if (-(0x4000) <= offset && offset < 0x4000) /* 16K bytes */ + else if (-(0x4000) <= offset && offset < 0x4000) /* 16K bytes */ range_type = BR_RANGE_S16K; - else if (-(0x10000) <= offset && offset < 0x10000) /* 64K bytes */ + else if (-(0x10000) <= offset && offset < 0x10000) /* 64K bytes */ range_type = BR_RANGE_S64K; - else if (-(0x1000000) <= offset && offset < 0x1000000) /* 16M bytes */ + else if (-(0x1000000) <= offset && offset < 0x1000000) /* 16M bytes */ range_type = BR_RANGE_S16M; - else /* 4G bytes */ + else /* 4G bytes */ range_type = BR_RANGE_U4G; return range_type; } -/* Set instruction register mask. */ +/* Set insntruction register mask. */ static void nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn, uint32_t ori_insn, int range) { - nds32_cond_field_t *cond_fields = relax_info->cond_field; + nds32_cond_field_t *cond_fields; + cond_fields = relax_info->cond_field; nds32_cond_field_t *code_seq_cond = relax_info->relax_code_condition[range]; uint32_t mask; int i = 0; - /* The instruction has conditions. Collect condition values. */ while (code_seq_cond[i].bitmask != 0) { @@ -5525,24 +6440,45 @@ nds32_relax_branch_instructions (segT segment, fragS *fragP, int insn_size; int code_seq_offset; - /* Replace with gas_assert (fragP->fr_symbol != NULL); */ + /* Replace with gas_assert (fragP->fr_symbol != NULL); */ if (fragP->fr_symbol == NULL) return adjust; - /* If frag_var is not enough room, the previous frag is fr_full and with + /* If frag_var is not enough room, the previos frag is fr_full and with opcode. The new one is rs_dependent but without opcode. */ if (opcode == NULL) return adjust; + /* Use U4G mode for b and bal in verbatim mode because lto may combine + functions into a file. And order the file in the last when linking. + Once there is multiple definition, the same function will be kicked. + This may cause relocation truncated error. */ + if (verbatim && !nds32_pic + && (strcmp (opcode->opcode, "j") == 0 + || strcmp (opcode->opcode, "jal") == 0)) + { + fragP->fr_subtype = BR_RANGE_U4G; + if (init) + return 8; + else + return 0; + } + relax_info = hash_find (nds32_relax_info_hash, opcode->opcode); if (relax_info == NULL) return adjust; if (init) - branch_range_type = relax_info->br_range; + { + branch_range_type = relax_info->br_range; + i = BR_RANGE_S256; + } else - branch_range_type = fragP->fr_subtype; + { + branch_range_type = fragP->fr_subtype; + i = branch_range_type; + } offset = nds32_calc_branch_offset (segment, fragP, stretch, relax_info, branch_range_type); @@ -5551,15 +6487,21 @@ nds32_relax_branch_instructions (segT segment, fragS *fragP, /* If actual range is equal to instruction jump range, do nothing. */ if (real_range_type == branch_range_type) - return adjust; + { + fragP->fr_subtype = real_range_type; + return adjust; + } /* Find out proper relaxation code sequence. */ - for (i = BR_RANGE_S256; i < BR_RANGE_NUM; i++) + for (; i < BR_RANGE_NUM; i++) { if (real_range_type <= (unsigned int) i) { if (init) diff = relax_info->relax_code_size[i] - opcode->isize; + else if (real_range_type < (unsigned int) i) + diff = relax_info->relax_code_size[real_range_type] + - relax_info->relax_code_size[branch_range_type]; else diff = relax_info->relax_code_size[i] - relax_info->relax_code_size[branch_range_type]; @@ -5592,7 +6534,7 @@ nds32_relax_branch_instructions (segT segment, fragS *fragP, } /* Update fr_subtype to new NDS32_BR_RANGE. */ - fragP->fr_subtype = i; + fragP->fr_subtype = real_range_type; break; } } @@ -5631,19 +6573,19 @@ nds32_get_align (addressT address, int align) { addressT mask, new_address; - mask = ~((~0U) << align); + mask = ~((addressT) (~0) << align); new_address = (address + mask) & (~mask); return (new_address - address); } /* Check the prev_frag is legal. */ static void -invalid_prev_frag (fragS * fragP, fragS **prev_frag) +invalid_prev_frag (fragS * fragP, fragS **prev_frag, bfd_boolean relax) { addressT address; fragS *frag_start = *prev_frag; - if (!frag_start) + if (!frag_start || !relax) return; if (frag_start->last_fr_address >= fragP->last_fr_address) @@ -5659,13 +6601,13 @@ invalid_prev_frag (fragS * fragP, fragS **prev_frag) || frag_t->fr_type == rs_align_code || frag_t->fr_type == rs_align_test) { - /* Relax instruction can not walk across label. */ + /* Relax instruction can not walk across lable. */ if (frag_t->tc_frag_data.flag & NDS32_FRAG_LABEL) { prev_frag = NULL; return; } - /* Relax previous relaxable to align rs_align frag. */ + /* Relax previos relaxable to align rs_align frag. */ address = frag_t->fr_address + frag_t->fr_fix; addressT offset = nds32_get_align (address, (int) frag_t->fr_offset); if (offset & 0x2) @@ -5711,7 +6653,7 @@ nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED) static fragS *prev_frag = NULL; int adjust = 0; - invalid_prev_frag (fragP, &prev_frag); + invalid_prev_frag (fragP, &prev_frag, TRUE); if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH) adjust = nds32_relax_branch_instructions (segment, fragP, stretch, 0); @@ -5720,8 +6662,8 @@ nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED) if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE && (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) == 0) /* Here is considered relaxed case originally. But it may cause - an endless loop when relaxing. Once the instruction is relaxed, - it can not be undone. */ + unendless loop when relaxing. Once the instruction is relaxed, + it can not be undo. */ prev_frag = fragP; return adjust; @@ -5744,11 +6686,11 @@ md_estimate_size_before_relax (fragS *fragP, segT segment) 1. relax for branch 2. relax for 32-bits to 16-bits */ - /* Save previous relaxable frag. */ + /* Save previos relaxable frag. */ static fragS *prev_frag = NULL; int adjust = 0; - invalid_prev_frag (fragP, &prev_frag); + invalid_prev_frag (fragP, &prev_frag, FALSE); if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH) adjust = nds32_relax_branch_instructions (segment, fragP, 0, 1); @@ -5798,12 +6740,14 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP) nds32_relax_fixup_info_t fixup_info[MAX_RELAX_FIX]; /* Save the 1st instruction is converted to 16 bit or not. */ unsigned int branch_size; + bfd_boolean is_ict_sym; + enum bfd_reloc_code_real final_r_type; - /* Replace with gas_assert (branch_symbol != NULL); */ + /* Replace with gas_assert (branch_symbol != NULL); */ if (branch_symbol == NULL && !(fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)) return; - /* If frag_var is not enough room, the previous frag is fr_full and with + /* If frag_var is not enough room, the previos frag is fr_full and with opcode. The new one is rs_dependent but without opcode. */ if (opcode == NULL) return; @@ -5872,6 +6816,8 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP) /* Branch instruction adjust and append relocations. */ relax_info = hash_find (nds32_relax_info_hash, opcode->opcode); + is_ict_sym = fragP->tc_frag_data.flag & NDS32_FRAG_ICT_BRANCH; + if (relax_info == NULL) return; @@ -5902,8 +6848,8 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP) /* Fill in frag. */ i = 0; k = 0; - offset = 0; /* code_seq offset */ - buf_offset = 0; /* fr_buffer offset */ + offset = 0; /* code_seq offset */ + buf_offset = 0; /* fr_buffer offset */ while (offset < code_size) { insn = code_seq[i]; @@ -5921,7 +6867,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP) origin_insn, branch_range_type); /* Try to convert to 16-bits instruction. Currently, only the first - instruction in pattern can be converted. EX: bnez sethi ori jr, + insntruction in pattern can be converted. EX: bnez sethi ori jr, only bnez can be converted to 16 bit and ori can't. */ while (fixup_info[k].size != 0 @@ -5978,9 +6924,20 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP) if (fixup_info[i].r_type != 0) { + final_r_type = fixup_info[i].r_type; + + /* Convert reloc type to ICT style if this frag is + handle for ICT symbol. */ + if (is_ict_sym && final_r_type == BFD_RELOC_NDS32_HI20) + final_r_type = BFD_RELOC_NDS32_ICT_HI20; + else if (is_ict_sym && final_r_type == BFD_RELOC_NDS32_LO12S0_ORI) + final_r_type = BFD_RELOC_NDS32_ICT_LO12; + else if (is_ict_sym && fixup_info[i].ramp & NDS32_HINT) + continue; + fixP = fix_new_exp (fragP, fr_where + fixup_info[i].offset, fixup_size, &exp, pcrel, - fixup_info[i].r_type); + final_r_type); fixP->fx_addnumber = fixP->fx_offset; } } @@ -6003,7 +6960,7 @@ nds32_relaxable_section (asection *sec) && strcmp (sec->name, ".eh_frame") != 0); } -/* TC_FORCE_RELOCATION */ +/* TC_FORCE_RELOCATION */ int nds32_force_relocation (fixS * fix) { @@ -6041,8 +6998,8 @@ nds32_force_relocation (fixS * fix) && nds32_relaxable_section (S_GET_SEGMENT (fix->fx_addsy)); case BFD_RELOC_64: if (fix->fx_subsy) - as_bad ("Double word for difference between two symbols " - "is not supported across relaxation."); + as_bad ("Double word for difference between two symbols is not " + "supported across relaxation."); default: ; } @@ -6202,14 +7159,16 @@ nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, fixS *fixp; seginfo = seg_info (sec); + if (symbol_find ("_INDIRECT_CALL_TABLE_BASE_")) + ict_exist = TRUE; if (!seginfo || !symbol_rootP || !subseg_text_p (sec) || sec->size == 0) return; - /* If there is no relocation and relax is disabled, it is not necessary to - insert R_NDS32_RELAX_ENTRY for linker do EX9 or IFC optimization. */ + for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next) if (!fixp->fx_done) break; - if (!fixp && !enable_relax_ex9 && !verbatim) + + if (!fixp && !verbatim && (!ict_exist || ict_flag == ICT_NONE)) return; subseg_change (sec, 0); @@ -6217,21 +7176,21 @@ nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, /* Set RELAX_ENTRY flags for linker. */ fragP = seginfo->frchainP->frch_root; exp.X_op = O_symbol; - exp.X_add_symbol = section_symbol (sec); + exp.X_add_symbol = abs_section_sym; exp.X_add_number = 0; if (!enable_relax_relocs) exp.X_add_number |= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG; else { /* These flags are only enabled when global relax is enabled. - Maybe we can check DISABLE_RELAX_FLAG at link-time, + Maybe we can check DISABLE_RELAX_FLAG at linke-time, so we set them anyway. */ - if (enable_relax_ex9) - exp.X_add_number |= R_NDS32_RELAX_ENTRY_EX9_FLAG; - if (enable_relax_ifc) - exp.X_add_number |= R_NDS32_RELAX_ENTRY_IFC_FLAG; if (verbatim) exp.X_add_number |= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG; + if (ict_exist && ict_flag == ICT_SMALL) + exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_SMALL; + else if (ict_exist && ict_flag == ICT_LARGE) + exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_LARGE; } if (optimize) exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG; @@ -6282,9 +7241,28 @@ nds32_elf_insert_final_frag (void) } } +static void +nds32_create_section_compatible_abi (void) +{ + segT comp_section = subseg_new (".note.v2abi_compatible", 0); + bfd_set_section_flags (stdoutput, comp_section, + SEC_READONLY | SEC_DATA | SEC_EXCLUDE); + + /* Set content to .v2abi_compatible section. */ + now_seg = comp_section; + frag_grow (NDS32_MAXCHAR); + char *out = frag_more (4); + if (compatible_abi) + bfd_putb32 ((bfd_vma) 1, out); + else + bfd_putb32 ((bfd_vma) 0, out); +} + void md_end (void) { + if (compatible_abi) + nds32_create_section_compatible_abi (); nds32_elf_insert_final_frag (); nds32_elf_analysis_relax_hint (); bfd_map_over_sections (stdoutput, nds32_insert_leb128_fixes, NULL); @@ -6390,6 +7368,8 @@ nds32_fix_adjustable (fixS *fixP) case BFD_RELOC_NDS32_LONGJUMP5: case BFD_RELOC_NDS32_LONGJUMP6: case BFD_RELOC_NDS32_LONGJUMP7: + case BFD_RELOC_NDS32_10IFCU_PCREL: + case BFD_RELOC_NDS32_17IFC_PCREL: return 1; default: return 0; @@ -6407,7 +7387,7 @@ elf_nds32_final_processing (void) && !(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))) { /* Since only FPU_COM instructions are used and no other FPU instructions - are used. The nds32_elf_flags will be decided by the enabled options + are used. The nds32_elf_flags will be decided by the enabled options by command line or default configuration. */ if (nds32_fpu_dp_ext || nds32_fpu_sp_ext) { @@ -6430,9 +7410,6 @@ elf_nds32_final_processing (void) nds32_elf_flags |= (nds32_freg << E_NDS32_FPU_REG_CONF_SHIFT); } - if (nds32_pic) - nds32_elf_flags |= E_NDS32_HAS_PIC; - if (nds32_gpr16) nds32_elf_flags |= E_NDS32_HAS_REDUCED_REGS; @@ -6440,7 +7417,7 @@ elf_nds32_final_processing (void) elf_elfheader (stdoutput)->e_flags |= nds32_elf_flags; } -/* Implement md_apply_fix. Apply the fix-up or transform the fix-up for +/* Implement md_apply_fix. Apply the fix-up or tranform the fix-up for later relocation generation. */ void @@ -6463,14 +7440,10 @@ nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) fixP->fx_addnumber = value; fixP->tc_fix_data = NULL; - /* Transform specific relocations here for later relocation generation. - Tag data here for ex9 relaxation and tag tls data for linker. */ + /* Tranform specific relocations here for later relocation generation. + Tag tls data here for linker. */ switch (fixP->fx_r_type) { - case BFD_RELOC_NDS32_DATA: - if (!enable_relax_ex9) - fixP->fx_done = 1; - break; case BFD_RELOC_NDS32_TPOFF: case BFD_RELOC_NDS32_TLS_LE_HI20: case BFD_RELOC_NDS32_TLS_LE_LO12: @@ -6479,6 +7452,12 @@ nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_NDS32_GOTTPOFF: case BFD_RELOC_NDS32_TLS_IE_HI20: case BFD_RELOC_NDS32_TLS_IE_LO12S2: + case BFD_RELOC_NDS32_TLS_DESC_HI20: + case BFD_RELOC_NDS32_TLS_DESC_LO12: + case BFD_RELOC_NDS32_TLS_IE_LO12: + case BFD_RELOC_NDS32_TLS_IEGP_HI20: + case BFD_RELOC_NDS32_TLS_IEGP_LO12: + case BFD_RELOC_NDS32_TLS_IEGP_LO12S2: S_SET_THREAD_LOCAL (fixP->fx_addsy); break; default: @@ -6519,7 +7498,7 @@ nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) ---- 8< ---- 8< ---- 8< ---- 8< ---- We use a single relocation entry for this expression. - * The initial distance value is stored directly in that location + * The initial distance value is stored direcly in that location specified by r_offset (i.e., foo in this example.) * The begin of the region, i.e., .LBEGIN, is specified by r_info/R_SYM and r_addend, e.g., .text + 0x32. @@ -6605,7 +7584,6 @@ nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) break; case BFD_RELOC_64: md_number_to_chars (where, value, 8); - break; default: as_bad_where (fixP->fx_file, fixP->fx_line, _("Internal error: Unknown fixup type %d (`%s')"), @@ -6624,9 +7602,9 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP) arelent *reloc; bfd_reloc_code_real_type code; - reloc = XNEW (arelent); + reloc = (arelent *) xmalloc (sizeof (arelent)); - reloc->sym_ptr_ptr = XNEW (asymbol *); + reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); reloc->address = fixP->fx_frag->fr_address + fixP->fx_where; @@ -6661,13 +7639,15 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP) return reloc; } -struct suffix_name suffix_table[] = +static struct suffix_name suffix_table[] = { - {"GOTOFF", BFD_RELOC_NDS32_GOTOFF, 1}, - {"GOT", BFD_RELOC_NDS32_GOT20, 1}, - {"TPOFF", BFD_RELOC_NDS32_TPOFF, 0}, - {"PLT", BFD_RELOC_NDS32_25_PLTREL, 1}, - {"GOTTPOFF", BFD_RELOC_NDS32_GOTTPOFF, 0} + {"GOTOFF", BFD_RELOC_NDS32_GOTOFF}, + {"GOT", BFD_RELOC_NDS32_GOT20}, + {"TPOFF", BFD_RELOC_NDS32_TPOFF}, + {"PLT", BFD_RELOC_NDS32_25_PLTREL}, + {"GOTTPOFF", BFD_RELOC_NDS32_GOTTPOFF}, + {"TLSDESC", BFD_RELOC_NDS32_TLS_DESC}, + {"ICT", BFD_RELOC_NDS32_ICT} }; /* Implement md_parse_name. */ @@ -6686,9 +7666,9 @@ nds32_parse_name (char const *name, expressionS *exprP, exprP->X_op = O_symbol; exprP->X_add_number = 0; - /* Check the special name if a symbol. */ + /* Check the specail name if a symbol. */ segment = S_GET_SEGMENT (exprP->X_add_symbol); - if (segment != undefined_section) + if ((segment != undefined_section) && (*nextcharP != '@')) return 0; if (strcmp (name, GOT_NAME) == 0 && *nextcharP != '@') @@ -6702,13 +7682,11 @@ nds32_parse_name (char const *name, expressionS *exprP, char *next; for (i = 0; i < ARRAY_SIZE (suffix_table); i++) { - next = input_line_pointer + 1 + strlen(suffix_table[i].suffix); + next = input_line_pointer + 1 + strlen (suffix_table[i].suffix); if (strncasecmp (input_line_pointer + 1, suffix_table[i].suffix, strlen (suffix_table[i].suffix)) == 0 && !is_part_of_name (*next)) { - if (!nds32_pic && suffix_table[i].pic) - as_bad (_("need PIC qualifier with symbol.")); exprP->X_md = suffix_table[i].reloc; *input_line_pointer = *nextcharP; input_line_pointer = next; @@ -6718,6 +7696,10 @@ nds32_parse_name (char const *name, expressionS *exprP, } } } + + if (exprP->X_md == BFD_RELOC_NDS32_ICT) + ict_exist = TRUE; + return 1; } diff --git binutils-2.30/gas/config/tc-nds32.h binutils-2.30-nds32/gas/config/tc-nds32.h index 178ca4ec33..bcea94afe0 100644 --- binutils-2.30/gas/config/tc-nds32.h +++ binutils-2.30-nds32/gas/config/tc-nds32.h @@ -24,13 +24,28 @@ #include "bfd_stdint.h" +/* Enum mapping symbol. */ +enum mstate +{ + MAP_UNDEFINED = 0, /* Must be zero, for seginfo in new sections. */ + MAP_DATA, + MAP_CODE, +}; +#define TC_SEGMENT_INFO_TYPE struct nds32_segment_info_type + +/* For mapping symbol. */ +struct nds32_segment_info_type +{ + enum mstate mapstate; +}; + #define LISTING_HEADER \ (target_big_endian ? "NDS32 GAS" : "NDS32 GAS Little Endian") /* The target BFD architecture. */ #define TARGET_ARCH bfd_arch_nds32 -/* mapping to mach_table[5] */ +/* mapping to mach_table[5] */ #define ISA_V1 bfd_mach_n1h #define ISA_V2 bfd_mach_n1h_v2 #define ISA_V3 bfd_mach_n1h_v3 @@ -42,29 +57,28 @@ #define TARGET_BYTES_BIG_ENDIAN 1 #endif -/* as.c. */ -/* Extend GAS command line option handling capability. */ +/* as.c */ +/* Extend GAS command line option handling capability */ extern int nds32_parse_option (int, const char *); extern void nds32_after_parse_args (void); /* The endianness of the target format may change based on command line arguments. */ -extern const char * nds32_target_format (void); - +extern const char *nds32_target_format (void); #define md_parse_option(optc, optarg) nds32_parse_option (optc, optarg) #define md_after_parse_args() nds32_after_parse_args () #define TARGET_FORMAT nds32_target_format() -/* expr.c */ +/* expr.c */ extern int nds32_parse_name (char const *, expressionS *, enum expr_mode, char *); extern bfd_boolean nds32_allow_local_subtract (expressionS *, expressionS *, segT); #define md_parse_name(name, exprP, mode, nextcharP) \ nds32_parse_name (name, exprP, mode, nextcharP) #define md_allow_local_subtract(lhs,rhs,sect) nds32_allow_local_subtract (lhs, rhs, sect) -/* dwarf2dbg.c. */ +/* dwarf2dbg.c */ #define DWARF2_USE_FIXED_ADVANCE_PC 1 -/* write.c. */ +/* write.c */ extern long nds32_pcrel_from_section (struct fix *, segT); extern bfd_boolean nds32_fix_adjustable (struct fix *); extern void nds32_frob_file (void); @@ -73,14 +87,13 @@ extern void nds32_frob_file_before_fix (void); extern void elf_nds32_final_processing (void); extern int nds32_validate_fix_sub (struct fix *, segT); extern int nds32_force_relocation (struct fix *); -extern void nds32_set_section_relocs (asection *, arelent ** , unsigned int); +extern void nds32_set_section_relocs (asection *, arelent **, unsigned int); /* Fill in rs_align_code fragments. TODO: Review this. */ extern void nds32_handle_align (fragS *); extern int nds32_relax_frag (segT, fragS *, long); extern int tc_nds32_regname_to_dw2regnum (char *); extern void tc_nds32_frame_initial_instructions (void); - #define MD_PCREL_FROM_SECTION(fix, sect) nds32_pcrel_from_section (fix, sect) #define TC_FINALIZE_SYMS_BEFORE_SIZE_SEG 0 #define tc_fix_adjustable(FIX) nds32_fix_adjustable (FIX) @@ -103,7 +116,7 @@ extern void tc_nds32_frame_initial_instructions (void); #define md_relax_frag(segment, fragP, stretch) nds32_relax_frag (segment, fragP, stretch) #define WORKING_DOT_WORD /* We don't need to handle .word strangely. */ /* Using to chain fixup with previous fixup. */ -#define TC_FIX_TYPE struct fix * +#define TC_FIX_TYPE struct fix* #define TC_INIT_FIX_DATA(fixP) \ do \ { \ @@ -111,8 +124,8 @@ extern void tc_nds32_frame_initial_instructions (void); } \ while (0) -/* read.c. */ -/* Extend GAS macro handling capability. */ +/* read.c */ +/* Extend GAS macro handling capability */ extern void nds32_macro_start (void); extern void nds32_macro_end (void); extern void nds32_macro_info (void *); @@ -128,7 +141,6 @@ extern void nds32_check_label (symbolS *); extern void nds32_frob_label (symbolS *); extern void nds32_pre_do_align (int, char *, int, int); extern void nds32_do_align (int); - #define md_macro_start() nds32_macro_start () #define md_macro_end() nds32_macro_end () #define md_macro_info(args) nds32_macro_info (args) @@ -143,7 +155,7 @@ extern void nds32_do_align (int); #define md_do_align(N, FILL, LEN, MAX, LABEL) \ nds32_pre_do_align (N, FILL, LEN, MAX); \ if ((N) > 1 && (subseg_text_p (now_seg) \ - || strncmp (now_seg->name, ".gcc_except_table", sizeof(".gcc_except_table") - 1) == 0)) \ + || strncmp (now_seg->name, ".gcc_except_table", sizeof (".gcc_except_table") - 1) == 0)) \ nds32_do_align (N); \ goto LABEL; #define md_elf_section_change_hook() nds32_elf_section_change_hook () @@ -151,7 +163,7 @@ extern void nds32_do_align (int); #define md_cleanup() nds32_cleanup () #define LOCAL_LABELS_FB 1 /* Permit temporary numeric labels. */ -/* frags.c. */ +/* frags.c */ enum FRAG_ATTR { @@ -161,7 +173,8 @@ enum FRAG_ATTR NDS32_FRAG_LABEL = 0x8, NDS32_FRAG_FINAL = 0x10, NDS32_FRAG_RELAXABLE_BRANCH = 0x20, - NDS32_FRAG_ALIGN = 0x40 + NDS32_FRAG_ALIGN = 0x40, + NDS32_FRAG_ICT_BRANCH = 0x80 }; struct nds32_frag_type @@ -231,7 +244,11 @@ enum nds32_ramp NDS32_FIX = (1 << 7), NDS32_ADDEND = (1 << 8), NDS32_SYM = (1 << 9), - NDS32_PCREL = (1 << 10) + NDS32_PCREL = (1 << 10), + NDS32_PTR_PATTERN = (1 << 11), + NDS32_PTR_MULTIPLE = (1 << 12), + NDS32_GROUP = (1 << 13), + NDS32_SYM_DESC_MEM = (1 << 14) }; typedef struct nds32_relax_fixup_info @@ -255,7 +272,7 @@ typedef struct nds32_cond_field #define NDS32_MAXCHAR 20 /* In current, the max extended number of instruction for one pseudo instruction is 4, but its number of relocation may be 12. */ -#define MAX_RELAX_NUM 4 +#define MAX_RELAX_NUM 6 #define MAX_RELAX_FIX 12 typedef struct nds32_relax_info @@ -275,8 +292,18 @@ typedef struct nds32_relax_info enum nds32_relax_hint_type { NDS32_RELAX_HINT_NONE = 0, - NDS32_RELAX_HINT_LA, - NDS32_RELAX_HINT_LS + NDS32_RELAX_HINT_LA_FLSI, + NDS32_RELAX_HINT_LALS, + NDS32_RELAX_HINT_LA_PLT, + NDS32_RELAX_HINT_LA_GOT, + NDS32_RELAX_HINT_LA_GOTOFF, + NDS32_RELAX_HINT_TLS_START = 0x100, + NDS32_RELAX_HINT_TLS_LE_LS, + NDS32_RELAX_HINT_TLS_IE_LS, + NDS32_RELAX_HINT_TLS_IE_LA, + NDS32_RELAX_HINT_TLS_IEGP_LA, + NDS32_RELAX_HINT_TLS_DESC_LS, + NDS32_RELAX_HINT_ICT_LA, }; struct nds32_relax_hint_table @@ -287,4 +314,4 @@ struct nds32_relax_hint_table nds32_relax_fixup_info_t relax_fixup[MAX_RELAX_FIX]; }; -#endif /* TC_NDS32 */ +#endif /* TC_NDS32 */ diff --git binutils-2.30/gas/configure binutils-2.30-nds32/gas/configure index 0d5422572f..41a83a2998 100755 --- binutils-2.30/gas/configure +++ binutils-2.30-nds32/gas/configure @@ -12491,6 +12491,11 @@ _ACEOF ;; nds32) + # setup NDS32_LINUX_TOOLCHAIN definition + if test "linux" = $em; then +$as_echo "#define NDS32_LINUX_TOOLCHAIN 1" >>confdefs.h + fi + # Decide BASELINE, REDUCED_REGS, FPU_DP_EXT, FPU_SP_EXT features # based on arch_name. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --with-arch" >&5 @@ -12582,6 +12587,34 @@ $as_echo "#define NDS32_DEFAULT_AUDIO_EXT 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_audio_ext" >&5 $as_echo "$enable_audio_ext" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --enable-dsp-ext" >&5 +$as_echo_n "checking for default configuration of --enable-dsp-ext... " >&6; } + if test "x${enable_dsp_ext}" == xno; then + +$as_echo "#define NDS32_DEFAULT_DSP_EXT 0" >>confdefs.h + + else + +$as_echo "#define NDS32_DEFAULT_DSP_EXT 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_dsp_ext" >&5 +$as_echo "$enable_dsp_ext" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --enable-zol-ext" >&5 +$as_echo_n "checking for default configuration of --enable-zol-ext... " >&6; } + if test "x${enable_zol_ext}" == xno; then + +$as_echo "#define NDS32_DEFAULT_ZOL_EXT 0" >>confdefs.h + + else + +$as_echo "#define NDS32_DEFAULT_ZOL_EXT 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_zol_ext" >&5 +$as_echo "$enable_zol_ext" >&6; } ;; aarch64 | i386 | riscv | s390 | sparc) diff --git binutils-2.30/include/dis-asm.h binutils-2.30-nds32/include/dis-asm.h index eebdaf874f..5cbe83aad7 100644 --- binutils-2.30/include/dis-asm.h +++ binutils-2.30-nds32/include/dis-asm.h @@ -261,11 +261,13 @@ extern void print_arm_disassembler_options (FILE *); extern void print_arc_disassembler_options (FILE *); extern void print_s390_disassembler_options (FILE *); extern void print_wasm32_disassembler_options (FILE *); +extern void print_nds32_disassembler_options (FILE *); extern bfd_boolean aarch64_symbol_is_valid (asymbol *, struct disassemble_info *); extern bfd_boolean arm_symbol_is_valid (asymbol *, struct disassemble_info *); extern void disassemble_init_powerpc (struct disassemble_info *); extern void disassemble_init_s390 (struct disassemble_info *); extern void disassemble_init_wasm32 (struct disassemble_info *); +extern void disassemble_init_nds32 (struct disassemble_info *); extern const disasm_options_t *disassembler_options_powerpc (void); extern const disasm_options_t *disassembler_options_arm (void); extern const disasm_options_t *disassembler_options_s390 (void); diff --git binutils-2.30/include/elf/nds32.h binutils-2.30-nds32/include/elf/nds32.h index 1b3a3219d0..7250f2bb0c 100644 --- binutils-2.30/include/elf/nds32.h +++ binutils-2.30-nds32/include/elf/nds32.h @@ -107,9 +107,9 @@ START_RELOC_NUMBERS (elf_nds32_reloc_type) RELOC_NUMBER (R_NDS32_SDA17S2_RELA, 74) RELOC_NUMBER (R_NDS32_SDA18S1_RELA, 75) RELOC_NUMBER (R_NDS32_SDA19S0_RELA, 76) - RELOC_NUMBER (R_NDS32_DWARF2_OP1_RELA, 77) - RELOC_NUMBER (R_NDS32_DWARF2_OP2_RELA, 78) - RELOC_NUMBER (R_NDS32_DWARF2_LEB_RELA, 79) + RELOC_NUMBER (R_NDS32_DWARF2_OP1_RELA, 77) /* This is obsoleted. */ + RELOC_NUMBER (R_NDS32_DWARF2_OP2_RELA, 78) /* This is obsoleted. */ + RELOC_NUMBER (R_NDS32_DWARF2_LEB_RELA, 79) /* This is obsoleted. */ RELOC_NUMBER (R_NDS32_UPDATE_TA_RELA, 80) /* This is obsoleted. */ RELOC_NUMBER (R_NDS32_9_PLTREL, 81) RELOC_NUMBER (R_NDS32_PLT_GOTREL_LO20, 82) @@ -128,15 +128,6 @@ START_RELOC_NUMBERS (elf_nds32_reloc_type) RELOC_NUMBER (R_NDS32_25_ABS_RELA, 95) RELOC_NUMBER (R_NDS32_17IFC_PCREL_RELA, 96) RELOC_NUMBER (R_NDS32_10IFCU_PCREL_RELA, 97) - RELOC_NUMBER (R_NDS32_TLS_LE_HI20, 98) - RELOC_NUMBER (R_NDS32_TLS_LE_LO12, 99) - RELOC_NUMBER (R_NDS32_TLS_IE_HI20, 100) - RELOC_NUMBER (R_NDS32_TLS_IE_LO12S2, 101) - RELOC_NUMBER (R_NDS32_TLS_TPOFF, 102) - RELOC_NUMBER (R_NDS32_TLS_LE_20, 103) - RELOC_NUMBER (R_NDS32_TLS_LE_15S0, 104) - RELOC_NUMBER (R_NDS32_TLS_LE_15S1, 105) - RELOC_NUMBER (R_NDS32_TLS_LE_15S2, 106) RELOC_NUMBER (R_NDS32_LONGCALL4, 107) RELOC_NUMBER (R_NDS32_LONGCALL5, 108) RELOC_NUMBER (R_NDS32_LONGCALL6, 109) @@ -144,7 +135,37 @@ START_RELOC_NUMBERS (elf_nds32_reloc_type) RELOC_NUMBER (R_NDS32_LONGJUMP5, 111) RELOC_NUMBER (R_NDS32_LONGJUMP6, 112) RELOC_NUMBER (R_NDS32_LONGJUMP7, 113) + RELOC_NUMBER (R_NDS32_SECURITY_16, 114) + /* TLS support { */ + RELOC_NUMBER (R_NDS32_TLS_TPOFF, 102) + RELOC_NUMBER (R_NDS32_TLS_LE_HI20, 98) + RELOC_NUMBER (R_NDS32_TLS_LE_LO12, 99) + RELOC_NUMBER (R_NDS32_TLS_LE_20, 103) + RELOC_NUMBER (R_NDS32_TLS_LE_15S0, 104) + RELOC_NUMBER (R_NDS32_TLS_LE_15S1, 105) + RELOC_NUMBER (R_NDS32_TLS_LE_15S2, 106) + RELOC_NUMBER (R_NDS32_TLS_IE_HI20, 100) + RELOC_NUMBER (R_NDS32_TLS_IE_LO12, 115) + RELOC_NUMBER (R_NDS32_TLS_IE_LO12S2, 101) + RELOC_NUMBER (R_NDS32_TLS_IEGP_HI20, 116) + RELOC_NUMBER (R_NDS32_TLS_IEGP_LO12, 117) + RELOC_NUMBER (R_NDS32_TLS_IEGP_LO12S2, 118) + RELOC_NUMBER (R_NDS32_TLS_DESC, 119) + RELOC_NUMBER (R_NDS32_TLS_DESC_HI20, 120) + RELOC_NUMBER (R_NDS32_TLS_DESC_LO12, 121) + RELOC_NUMBER (R_NDS32_TLS_DESC_20, 122) + RELOC_NUMBER (R_NDS32_TLS_DESC_SDA17S2, 123) + /* TLS support } */ + /* new relocation type add here. */ + RELOC_NUMBER (R_NDS32_RELOC_NEXT, 124) + + /* Jump-patch table relocations. */ + RELOC_NUMBER (R_NDS32_ICT_HI20, 125) + RELOC_NUMBER (R_NDS32_ICT_LO12, 126) + RELOC_NUMBER (R_NDS32_ICT_25PC, 127) + RELOC_NUMBER (R_NDS32_ICT_LO12S2, 128) + /* relax only following */ RELOC_NUMBER (R_NDS32_RELAX_ENTRY, 192) RELOC_NUMBER (R_NDS32_GOT_SUFF, 193) RELOC_NUMBER (R_NDS32_GOTOFF_SUFF, 194) @@ -164,9 +185,21 @@ START_RELOC_NUMBERS (elf_nds32_reloc_type) RELOC_NUMBER (R_NDS32_DIFF_ULEB128, 208) RELOC_NUMBER (R_NDS32_DATA, 209) RELOC_NUMBER (R_NDS32_TRAN, 210) + RELOC_NUMBER (R_NDS32_EMPTY, 213) + /* TLS support { */ RELOC_NUMBER (R_NDS32_TLS_LE_ADD, 211) RELOC_NUMBER (R_NDS32_TLS_LE_LS, 212) - RELOC_NUMBER (R_NDS32_EMPTY, 213) + RELOC_NUMBER (R_NDS32_TLS_IEGP_LW, 220) + RELOC_NUMBER (R_NDS32_TLS_DESC_ADD, 214) + RELOC_NUMBER (R_NDS32_TLS_DESC_FUNC, 215) + RELOC_NUMBER (R_NDS32_TLS_DESC_CALL, 216) + RELOC_NUMBER (R_NDS32_TLS_DESC_MEM, 217) + RELOC_NUMBER (R_NDS32_RELAX_REMOVE, 218) + RELOC_NUMBER (R_NDS32_RELAX_GROUP, 219) + /* TLS support } */ + /* new relaxation type add here. */ + RELOC_NUMBER (R_NDS32_LSI, 221) + RELOC_NUMBER (R_NDS32_RELAX_NEXT, 222) END_RELOC_NUMBERS (R_NDS32_max) @@ -259,10 +292,10 @@ END_RELOC_NUMBERS (R_NDS32_max) #define E_NDS32_FPU_REG_32SP_32DP 0x3 /* FPU MAC instruction used. */ #define E_NDS32_HAS_FPU_MAC_INST 0x01000000 -/* <<>>. */ -#define E_NDS32_NULL 0x02000000 -/* PIC enabled. */ -#define E_NDS32_HAS_PIC 0x04000000 +/* DSP extension. */ +#define E_NDS32_HAS_DSP_INST 0x02000000 +/* Hardware zero-overhead loop enabled. */ +#define E_NDS32_HAS_ZOL (1 << 26) /* Use custom section. */ #define E_NDS32_HAS_CUSTOM_SEC 0x08000000 diff --git binutils-2.30/include/opcode/nds32.h binutils-2.30-nds32/include/opcode/nds32.h index 4d113be8b8..04a02b5222 100644 --- binutils-2.30/include/opcode/nds32.h +++ binutils-2.30-nds32/include/opcode/nds32.h @@ -21,31 +21,32 @@ #define OPCODE_NDS32_H /* Registers. */ -#define REG_R5 5 -#define REG_R8 8 -#define REG_R10 10 -#define REG_R12 12 -#define REG_R15 15 -#define REG_R16 16 -#define REG_R20 20 -#define REG_TA 15 -#define REG_TP 27 -#define REG_FP 28 -#define REG_GP 29 -#define REG_LP 30 -#define REG_SP 31 +#define REG_R0 (0) +#define REG_R5 (5) +#define REG_R8 (8) +#define REG_R10 (10) +#define REG_R12 (12) +#define REG_R15 (15) +#define REG_R16 (16) +#define REG_R20 (20) +#define REG_TA (15) +#define REG_TP (25) +#define REG_FP (28) +#define REG_GP (29) +#define REG_LP (30) +#define REG_SP (31) /* Macros for extracting fields or making an instruction. */ static const int nds32_r45map[] ATTRIBUTE_UNUSED = { - 0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19 }; static const int nds32_r54map[] ATTRIBUTE_UNUSED = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, -1, -1, -1, -1, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; @@ -146,6 +147,7 @@ static const int nds32_r54map[] ATTRIBUTE_UNUSED = #define N32_RD5(insn) (((insn) >> 5) & 0x1f) #define N32_SH5(insn) (((insn) >> 5) & 0x1f) #define N32_SUB5(insn) (((insn) >> 0) & 0x1f) +#define N32_SUB6(insn) (((insn) >> 0) & 0x3f) #define N32_SWID(insn) (((insn) >> 5) & 0x3ff) #define N32_IMMU(insn, bs) ((insn) & __MASK (bs)) #define N32_IMMS(insn, bs) ((signed) __SEXT (((insn) & __MASK (bs)), bs)) @@ -275,7 +277,7 @@ enum n32_opcodes N32_BR1_BNE = 1, /* bit[16:19] */ - N32_BR2_IFCALL = 0, + N32_BR2_SOP0 = 0, N32_BR2_BEQZ = 2, N32_BR2_BNEZ = 3, N32_BR2_BGEZ = 4, @@ -365,7 +367,8 @@ enum n32_opcodes N32_ALU2_FFZMISM, N32_ALU2_KADD = 0x18, N32_ALU2_KSUB, - N32_ALU2_KSLRA, + N32_ALU2_KSLRAW, + N32_ALU2_KSLRAWu, N32_ALU2_MFUSR = 0x20, N32_ALU2_MTUSR, N32_ALU2_0x22, @@ -381,20 +384,173 @@ enum n32_opcodes N32_ALU2_MSUB64, N32_ALU2_DIVS, N32_ALU2_DIV, - N32_ALU2_0x30 = 0x30, + N32_ALU2_ADD64 = 0x30, N32_ALU2_MULT32, - N32_ALU2_0x32, + N32_ALU2_SMAL, N32_ALU2_MADD32, - N32_ALU2_0x34, + N32_ALU2_SUB64, N32_ALU2_MSUB32, - - /* bit[0:5], where bit[6:9] != 0 */ + N32_ALU2_0x36, + N32_ALU2_0x37, + N32_ALU2_RADD64 = 0x38, + N32_ALU2_URADD64, + N32_ALU2_KADD64, + N32_ALU2_UKADD64, + N32_ALU2_RSUB64, + N32_ALU2_URSUB64, + N32_ALU2_KSUB64, + N32_ALU2_UKSUB64, + + /* bit[0:5], where bit[6:9] = 0001 */ + N32_ALU2_SMAR64 = 0x0, + N32_ALU2_UMAR64, + N32_ALU2_SMSR64, + N32_ALU2_UMSR64, + N32_ALU2_KMAR64, + N32_ALU2_UKMAR64, + N32_ALU2_KMSR64, + N32_ALU2_UKMSR64, + N32_ALU2_SMALDA = 0x8, + N32_ALU2_SMSLDA, + N32_ALU2_SMALDS, + N32_ALU2_SMALBB, N32_ALU2_FFBI = 0xe, N32_ALU2_FLMISM = 0xf, + N32_ALU2_SMALXDA = 0x10, + N32_ALU2_SMSLXDA, + N32_ALU2_SMALXDS, + N32_ALU2_SMALBT, + N32_ALU2_SMALDRS = 0x1a, + N32_ALU2_SMALTT, + N32_ALU2_RDOV = 0x20, + N32_ALU2_CLROV, N32_ALU2_MULSR64 = 0x28, N32_ALU2_MULR64 = 0x29, - N32_ALU2_MADDR32 = 0x33, - N32_ALU2_MSUBR32 = 0x35, + N32_ALU2_SMDS = 0x30, + N32_ALU2_SMXDS, + N32_ALU2_SMDRS, + N32_ALU2_MADDR32, + N32_ALU2_KMADRS, + N32_ALU2_MSUBR32, + N32_ALU2_KMADS, + N32_ALU2_KMAXDS, + + /* bit[0:5], where bit[6:9] = 0010 */ + N32_ALU2_KADD16 = 0x0, + N32_ALU2_KSUB16, + N32_ALU2_KCRAS16, + N32_ALU2_KCRSA16, + N32_ALU2_KADD8, + N32_ALU2_KSUB8, + N32_ALU2_WEXT, + N32_ALU2_WEXTI, + N32_ALU2_UKADD16 = 0x8, + N32_ALU2_UKSUB16, + N32_ALU2_UKCRAS16, + N32_ALU2_UKCRSA16, + N32_ALU2_UKADD8, + N32_ALU2_UKSUB8, + N32_ALU2_ONEOP = 0xf, + N32_ALU2_SMBB = 0x10, + N32_ALU2_SMBT, + N32_ALU2_SMTT, + N32_ALU2_KMABB = 0x15, + N32_ALU2_KMABT, + N32_ALU2_KMATT, + N32_ALU2_KMDA = 0x18, + N32_ALU2_KMXDA, + N32_ALU2_KMADA, + N32_ALU2_KMAXDA, + N32_ALU2_KMSDA, + N32_ALU2_KMSXDA, + N32_ALU2_RADD16 = 0x20, + N32_ALU2_RSUB16, + N32_ALU2_RCRAS16, + N32_ALU2_RCRSA16, + N32_ALU2_RADD8, + N32_ALU2_RSUB8, + N32_ALU2_RADDW, + N32_ALU2_RSUBW, + N32_ALU2_URADD16 = 0x28, + N32_ALU2_URSUB16, + N32_ALU2_URCRAS16, + N32_ALU2_URCRSA16, + N32_ALU2_URADD8, + N32_ALU2_URSUB8, + N32_ALU2_URADDW, + N32_ALU2_URSUBW, + N32_ALU2_ADD16 = 0x30, + N32_ALU2_SUB16, + N32_ALU2_CRAS16, + N32_ALU2_CRSA16, + N32_ALU2_ADD8, + N32_ALU2_SUB8, + N32_ALU2_BITREV, + N32_ALU2_BITREVI, + N32_ALU2_SMMUL = 0x38, + N32_ALU2_SMMULu, + N32_ALU2_KMMAC, + N32_ALU2_KMMACu, + N32_ALU2_KMMSB, + N32_ALU2_KMMSBu, + N32_ALU2_KWMMUL, + N32_ALU2_KWMMULu, + + /* bit[0:5], where bit[6:9] = 0011 */ + N32_ALU2_SMMWB = 0x0, + N32_ALU2_SMMWBu, + N32_ALU2_SMMWT, + N32_ALU2_SMMWTu, + N32_ALU2_KMMAWB, + N32_ALU2_KMMAWBu, + N32_ALU2_KMMAWT, + N32_ALU2_KMMAWTu, + N32_ALU2_PKTT16 = 0x8, + N32_ALU2_PKTB16, + N32_ALU2_PKBT16, + N32_ALU2_PKBB16, + N32_ALU2_0x10 = 0x10, + N32_ALU2_SCLIP16, + N32_ALU2_0x12, + N32_ALU2_SMAX16, + N32_ALU2_SMAX8 = 0x17, + N32_ALU2_0x18 = 0x18, + N32_ALU2_UCLIP16, + N32_ALU2_0x1a, + N32_ALU2_UMAX16, + N32_ALU2_UMAX8 = 0x1f, + N32_ALU2_SRA16 = 0x20, + N32_ALU2_SRA16u, + N32_ALU2_SRL16, + N32_ALU2_SRL16u, + N32_ALU2_SLL16, + N32_ALU2_KSLRA16, + N32_ALU2_KSLRA16u, + N32_ALU2_SRAu, + N32_ALU2_SRAI16 = 0x28, + N32_ALU2_SRAI16u, + N32_ALU2_SRLI16, + N32_ALU2_SRLI16u, + N32_ALU2_SLLI16, + N32_ALU2_KSLLI16, + N32_ALU2_KSLLI, + N32_ALU2_SRAIu, + N32_ALU2_CMPEQ16 = 0x30, + N32_ALU2_SCMPLT16, + N32_ALU2_SCMPLE16, + N32_ALU2_SMIN16, + N32_ALU2_CMPEQ8, + N32_ALU2_SCMPLT8, + N32_ALU2_SCMPLE8, + N32_ALU2_SMIN8, + N32_ALU2_0x38, + N32_ALU2_UCMPLT16 = 0x39, + N32_ALU2_UCMPLE16, + N32_ALU2_UMIN16, + N32_ALU2_0x3c, + N32_ALU2_UCMPLT8, + N32_ALU2_UCMPLE8, + N32_ALU2_UMIN8, /* bit[0:5] */ N32_MEM_LB = 0, @@ -459,7 +615,8 @@ enum n32_opcodes N32_MISC_MSYNC, N32_MISC_ISYNC, N32_MISC_TLBOP, - N32_MISC_0xf, + N32_MISC_SPECL, + N32_MISC_BPICK = 0x10, /* bit[0:4] */ N32_SIMD_PBSAD = 0, @@ -582,7 +739,7 @@ enum n32_opcodes N32_FPU_MTCP_XR = 0xc, /* MTCP/XR b[14:10] */ - N32_FPU_MTCP_XR_FMTCSR = 0x1 + N32_FPU_MTCP_XR_FMTCSR = 0x1, }; enum n16_opcodes @@ -675,7 +832,7 @@ enum n16_opcodes N16_BFMI333_XLSB33 = 4, N16_BFMI333_X11B33 = 5, N16_BFMI333_BMSKI33 = 6, - N16_BFMI333_FEXTI33 = 7 + N16_BFMI333_FEXTI33 = 7, }; /* These macros a deprecated. DO NOT use them anymore. @@ -704,6 +861,7 @@ enum n16_opcodes #define INSN_ANDI 0x54000000 #define INSN_LDI 0x06000000 #define INSN_SDI 0x16000000 +#define INSN_LW 0x38000002 #define INSN_LWI 0x04000000 #define INSN_LWSI 0x24000000 #define INSN_LWIP 0x0c000000 diff --git binutils-2.30/ld/config.in binutils-2.30-nds32/ld/config.in index a846743da6..9cc2f6303a 100644 --- binutils-2.30/ld/config.in +++ binutils-2.30-nds32/ld/config.in @@ -63,9 +63,18 @@ */ #undef HAVE_DIRENT_H +/* Define to 1 if you have the `dlclose' function. */ +#undef HAVE_DLCLOSE + /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H +/* Define to 1 if you have the `dlopen' function. */ +#undef HAVE_DLOPEN + +/* Define to 1 if you have the `dlsym' function. */ +#undef HAVE_DLSYM + /* Define to 1 if you have the header file. */ #undef HAVE_ELF_HINTS_H @@ -168,6 +177,9 @@ */ #undef LT_OBJDIR +/* Define if linux toolchain is to be built. */ +#undef NDS32_LINUX_TOOLCHAIN + /* Name of package */ #undef PACKAGE diff --git binutils-2.30/ld/configure binutils-2.30-nds32/ld/configure index 48606ae36b..732630063d 100755 --- binutils-2.30/ld/configure +++ binutils-2.30-nds32/ld/configure @@ -17165,6 +17165,53 @@ do . ${srcdir}/configure.tgt + case ${target_cpu} in + nds32*) + case ${targ} in + *-*-linux*) + +$as_echo "#define NDS32_LINUX_TOOLCHAIN 1" >>confdefs.h + + ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --enable-ifc-ext" >&5 +$as_echo_n "checking for default configuration of --enable-ifc-ext... " >&6; } + if test "x${enable_ifc_ext}" == xyes; then + +$as_echo "#define NDS32_IFC_EXT 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_ifc_ext" >&5 +$as_echo "$enable_ifc_ext" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --enable-ex9-ext" >&5 +$as_echo_n "checking for default configuration of --enable-ex9-ext... " >&6; } + if test "x${enable_ex9_ext}" == xyes; then + +$as_echo "#define NDS32_EX9_EXT 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_ex9_ext" >&5 +$as_echo "$enable_ex9_ext" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --enable-16m-addr" >&5 +$as_echo_n "checking for default configuration of --enable-16m-addr... " >&6; } + if test "x${enable_16m_addr}" == xyes; then + case ${targ} in + nds32*le-*-elf*) + targ_emul=nds32elf16m + ;; + nds32*be-*-elf*) + targ_emul=nds32belf16m + ;; + esac + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_16m-addr" >&5 +$as_echo "$enable_16m-addr" >&6; } + ;; + esac + if test "$targ" = "$target"; then EMUL=$targ_emul fi diff --git binutils-2.30/ld/configure.tgt binutils-2.30-nds32/ld/configure.tgt index 6183a85b3d..b3d285faaa 100644 --- binutils-2.30/ld/configure.tgt +++ binutils-2.30-nds32/ld/configure.tgt @@ -583,8 +583,8 @@ nds32*le-*-elf*) targ_emul=nds32elf nds32*be-*-elf*) targ_emul=nds32belf targ_extra_emuls="nds32elf nds32elf16m nds32belf16m" ;; -nds32*le-*-linux-gnu*) targ_emul=nds32elf_linux ;; -nds32*be-*-linux-gnu*) targ_emul=nds32belf_linux ;; +nds32*le-*-linux*) targ_emul=nds32elf_linux ;; +nds32*be-*-linux*) targ_emul=nds32belf_linux ;; nios2*-*-linux*) targ_emul=nios2linux ;; nios2*-*-*) targ_emul=nios2elf ;; ns32k-pc532-mach* | ns32k-pc532-ux*) targ_emul=pc532macha ;; diff --git binutils-2.30/ld/emulparams/nds32elf.sh binutils-2.30-nds32/ld/emulparams/nds32elf.sh index f0a7c31329..e2fde5d0a2 100644 --- binutils-2.30/ld/emulparams/nds32elf.sh +++ binutils-2.30-nds32/ld/emulparams/nds32elf.sh @@ -14,5 +14,9 @@ MAXPAGESIZE=0x20 EMBEDDED=yes COMMONPAGESIZE=0x20 -# Use external linker script files. -COMPILE_IN=no +# Instruct genscripts.sh not to compile scripts in by COMPILE_IN +# in order to use external linker scripts files. +EMULATION_LIBPATH= + +GENERATE_SHLIB_SCRIPT=yes +GENERATE_PIE_SCRIPT=yes diff --git binutils-2.30/ld/emulparams/nds32elf16m.sh binutils-2.30-nds32/ld/emulparams/nds32elf16m.sh index deb8699004..7d3b063abd 100644 --- binutils-2.30/ld/emulparams/nds32elf16m.sh +++ binutils-2.30-nds32/ld/emulparams/nds32elf16m.sh @@ -14,5 +14,6 @@ MAXPAGESIZE=0x20 EMBEDDED=yes COMMONPAGESIZE=0x20 -# Use external linker script files. -COMPILE_IN=no +# Instruct genscripts.sh not to compile scripts in by COMPILE_IN +# in order to use external linker scripts files. +EMULATION_LIBPATH= diff --git binutils-2.30/ld/emulparams/nds32elf_linux.sh binutils-2.30-nds32/ld/emulparams/nds32elf_linux.sh index 1145c0eeea..6d89f7924f 100644 --- binutils-2.30/ld/emulparams/nds32elf_linux.sh +++ binutils-2.30-nds32/ld/emulparams/nds32elf_linux.sh @@ -31,5 +31,6 @@ fi GENERATE_SHLIB_SCRIPT=yes GENERATE_PIE_SCRIPT=yes -# Use external linker script files. -COMPILE_IN=no +# Instruct genscripts.sh not to compile scripts in by COMPILE_IN +# in order to use external linker scripts files. +EMULATION_LIBPATH= diff --git binutils-2.30/ld/emultempl/elf32.em binutils-2.30-nds32/ld/emultempl/elf32.em index c0925fc9b9..e5f109d3ce 100644 --- binutils-2.30/ld/emultempl/elf32.em +++ binutils-2.30-nds32/ld/emultempl/elf32.em @@ -114,7 +114,7 @@ fi if test x"$LDEMUL_AFTER_PARSE" != xgld"$EMULATION_NAME"_after_parse; then fragment < */ +static int hyper_relax = 1; /* --mhyper-relax */ /* Disable if linking a dynamically linked executable. */ static int load_store_relax = 1; static int target_optimize = 0; /* Switch optimization. */ static int relax_status = 0; /* Finished optimization. */ static int relax_round = 0; /* Going optimization. */ -static FILE *ex9_export_file = NULL; /* --mexport-ex9= */ -static FILE *ex9_import_file = NULL; /* --mimport-ex9= */ -static int update_ex9_table = 0; /* --mupdate-ex9. */ -static int ex9_limit = 511; -static bfd_boolean ex9_loop_aware = FALSE; /* Ignore ex9 if inside a loop. */ -static bfd_boolean ifc_loop_aware = FALSE; /* Ignore ifc if inside a loop. */ +static int tls_desc_trampoline = 0; /* --m[no]tlsdesc-trampoline. */ +static char *set_output_abi = NULL; /* --mabi. */ /* Save the target options into output bfd to avoid using to many global variables. Do this after the output has been created, but before @@ -61,39 +59,41 @@ nds32_elf_create_output_section_statements (void) sym_ld_script, load_store_relax, target_optimize, relax_status, relax_round, - ex9_export_file, ex9_import_file, - update_ex9_table, ex9_limit, - ex9_loop_aware, ifc_loop_aware); + hyper_relax, + tls_desc_trampoline, + set_output_abi); } static void nds32_elf_after_parse (void) { +#ifdef NDS32_LINUX_TOOLCHAIN + if (RELAXATION_ENABLED) + { + einfo ("%P: warning: The relaxation isn't supported yet.\n"); + DISABLE_RELAXATION; + } +#endif + if (bfd_link_relocatable (&link_info)) DISABLE_RELAXATION; if (!RELAXATION_ENABLED) { - target_optimize = target_optimize & (!NDS32_RELAX_JUMP_IFC_ON); - target_optimize = target_optimize & (!NDS32_RELAX_EX9_ON); + target_optimize &= ~(NDS32_RELAX_IFC_ON | NDS32_RELAX_EX9_ON); relax_fp_as_gp = 0; } - if (ex9_import_file != NULL) - { - ex9_export_file = NULL; - target_optimize = target_optimize & (!NDS32_RELAX_EX9_ON); - } - else - update_ex9_table = 0; - if (bfd_link_pic (&link_info)) { - target_optimize = target_optimize & (!NDS32_RELAX_JUMP_IFC_ON); - target_optimize = target_optimize & (!NDS32_RELAX_EX9_ON); + target_optimize &= ~(NDS32_RELAX_IFC_ON | NDS32_RELAX_EX9_ON); } - gld${EMULATION_NAME}_after_parse (); + after_parse_default (); + + /* Backward compatible for linker script output_format. */ + if (output_target && strcmp (output_target, "elf32-nds32") == 0) + output_target = default_target; } static void @@ -107,10 +107,15 @@ nds32_elf_after_open (void) We may try to merge object files with different architecture together. */ for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link.next) { - if (arch_ver == (unsigned int)-1 && E_N1_ARCH != (elf_elfheader (abfd)->e_flags & EF_NDS_ARCH)) + if (arch_ver == (unsigned int)-1 + && E_N1_ARCH != (elf_elfheader (abfd)->e_flags & EF_NDS_ARCH)) arch_ver = elf_elfheader (abfd)->e_flags & EF_NDS_ARCH ; - if (abi_ver == (unsigned int)-1) + if (set_output_abi != NULL) + { + /* do not check ABI. */ + } + else if (abi_ver == (unsigned int)-1) { /* Initialize ABI version, if not ABI0. (OS uses empty file to create empty ELF with ABI0). */ @@ -120,67 +125,34 @@ nds32_elf_after_open (void) else if ((elf_elfheader (abfd)->e_flags & EF_NDS_ABI) != 0 && abi_ver != (elf_elfheader (abfd)->e_flags & EF_NDS_ABI)) { + asection *section = NULL; + bfd_byte *contents = NULL; + section = bfd_get_section_by_name (abfd, ".note.v2abi_compatible"); + if (section) + bfd_get_full_section_contents (abfd, section, &contents); + /* Incompatible objects. */ - einfo (_("%F%B: ABI version of object files mismatched\n"), abfd); + if ((contents == NULL) + || bfd_getb32 (contents) != 1 + || abi_ver != E_NDS_ABI_V2FP_PLUS) + einfo (_("%F%B: ABI version of object files mismatched\n"), abfd); } -#if defined NDS32_EX9_EXT - /* Append .ex9.itable section in the last input object file. */ - if (abfd->link_next == NULL && (target_optimize & NDS32_RELAX_EX9_ON)) - { - asection *itable; - struct bfd_link_hash_entry *h; - itable = bfd_make_section_with_flags (abfd, ".ex9.itable", - SEC_CODE | SEC_ALLOC | SEC_LOAD - | SEC_HAS_CONTENTS | SEC_READONLY - | SEC_IN_MEMORY | SEC_KEEP); - if (itable) - { - itable->gc_mark = 1; - itable->alignment_power = 2; - itable->size = 0x1000; - itable->contents = bfd_zalloc (abfd, itable->size); - - /* Add a symbol in the head of ex9.itable to objdump clearly. */ - h = bfd_link_hash_lookup (link_info.hash, "_EX9_BASE_", - FALSE, FALSE, FALSE); - _bfd_generic_link_add_one_symbol - (&link_info, link_info.output_bfd, "_EX9_BASE_", - BSF_GLOBAL | BSF_WEAK, itable, 0, (const char *) NULL, FALSE, - get_elf_backend_data (link_info.output_bfd)->collect, &h); - } - } -#endif + /* Append target needed section in the last input object file. */ + if (abfd->link.next == NULL) + bfd_elf32_nds32_append_section (&link_info, abfd); } /* Check object files if the target is dynamic linked executable or shared object. */ if (elf_hash_table (&link_info)->dynamic_sections_created - || bfd_link_pic (&link_info)) + || bfd_link_pic (&link_info) || bfd_link_pie (&link_info)) { - for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link.next) - { - if (!(elf_elfheader (abfd)->e_flags & E_NDS32_HAS_PIC)) - { - /* Non-PIC object file is used. */ - if (bfd_link_pic (&link_info)) - { - /* For PIE or shared object, all input must be PIC. */ - einfo (_("%B: must use -fpic to compile this file " - "for shared object or PIE\n"), abfd); - } - else - { - /* Dynamic linked executable with SDA and non-PIC. - Turn off load/store relaxtion. */ - /* TODO: This may support in the future. */ - load_store_relax = 0 ; - relax_fp_as_gp = 0; - } - } - } - /* Turn off relax when building shared object or PIE - until we can support their relaxation. */ + /* Dynamic linked executable with SDA and non-PIC. + Turn off load/store relaxtion. */ + /* TODO: This may support in the future. */ + load_store_relax = 0 ; + relax_fp_as_gp = 0; } /* Call the standard elf routine. */ @@ -190,19 +162,26 @@ nds32_elf_after_open (void) static void nds32_elf_after_allocation (void) { - if (target_optimize & NDS32_RELAX_EX9_ON - || (ex9_import_file != NULL && update_ex9_table == 1)) - { - /* Initialize ex9 hash table. */ - if (!nds32_elf_ex9_init ()) - return; - } + struct bfd_link_hash_entry *h; /* Call default after allocation callback. 1. This is where relaxation is done. 2. It calls gld${EMULATION_NAME}_map_segments to build ELF segment table. 3. Any relaxation requires relax being done must be called after it. */ gld${EMULATION_NAME}_after_allocation (); + + /* Add a symbol for linker script check the max size. */ + if (link_info.output_bfd->sections) + { + h = bfd_link_hash_lookup (link_info.hash, "_RELAX_END_", + FALSE, FALSE, FALSE); + if (!h) + _bfd_generic_link_add_one_symbol + (&link_info, link_info.output_bfd, "_RELAX_END_", + BSF_GLOBAL | BSF_WEAK, link_info.output_bfd->sections, + 0, (const char *) NULL, FALSE, + get_elf_backend_data (link_info.output_bfd)->collect, &h); + } } EOF @@ -217,31 +196,19 @@ PARSE_AND_LIST_PROLOGUE=' #define OPTION_REDUCE_FP_UPDATE (OPTION_BASELINE + 4) #define OPTION_NO_REDUCE_FP_UPDATE (OPTION_BASELINE + 5) #define OPTION_EXPORT_SYMBOLS (OPTION_BASELINE + 6) - -/* These are only available to ex9. */ -#if defined NDS32_EX9_EXT -#define OPTION_EX9_BASELINE 320 -#define OPTION_EX9_TABLE (OPTION_EX9_BASELINE + 1) -#define OPTION_NO_EX9_TABLE (OPTION_EX9_BASELINE + 2) -#define OPTION_EXPORT_EX9 (OPTION_EX9_BASELINE + 3) -#define OPTION_IMPORT_EX9 (OPTION_EX9_BASELINE + 4) -#define OPTION_UPDATE_EX9 (OPTION_EX9_BASELINE + 5) -#define OPTION_EX9_LIMIT (OPTION_EX9_BASELINE + 6) -#define OPTION_EX9_LOOP (OPTION_EX9_BASELINE + 7) -#endif - -/* These are only available to link-time ifc. */ -#if defined NDS32_IFC_EXT -#define OPTION_IFC_BASELINE 340 -#define OPTION_JUMP_IFC (OPTION_IFC_BASELINE + 1) -#define OPTION_NO_JUMP_IFC (OPTION_IFC_BASELINE + 2) -#define OPTION_IFC_LOOP (OPTION_IFC_BASELINE + 3) -#endif +#define OPTION_HYPER_RELAX (OPTION_BASELINE + 7) +#define OPTION_TLSDESC_TRAMPOLINE (OPTION_BASELINE + 8) +#define OPTION_NO_TLSDESC_TRAMPOLINE (OPTION_BASELINE + 9) +#define OPTION_SET_ABI (OPTION_BASELINE + 10) ' PARSE_AND_LIST_LONGOPTS=' { "mfp-as-gp", no_argument, NULL, OPTION_FP_AS_GP}, { "mno-fp-as-gp", no_argument, NULL, OPTION_NO_FP_AS_GP}, { "mexport-symbols", required_argument, NULL, OPTION_EXPORT_SYMBOLS}, + { "mhyper-relax", required_argument, NULL, OPTION_HYPER_RELAX}, + { "mtlsdesc-trampoline", no_argument, NULL, OPTION_TLSDESC_TRAMPOLINE}, + { "mno-tlsdesc-trampoline", no_argument, NULL, OPTION_NO_TLSDESC_TRAMPOLINE}, + { "mabi", required_argument, NULL, OPTION_SET_ABI}, /* These are deprecated options. Remove them in the future. */ { "mrelax-reduce-fp-update", no_argument, NULL, OPTION_REDUCE_FP_UPDATE}, { "mrelax-no-reduce-fp-update", no_argument, NULL, OPTION_NO_REDUCE_FP_UPDATE}, @@ -250,46 +217,14 @@ PARSE_AND_LIST_LONGOPTS=' { "mrelax-omit-fp", no_argument, NULL, OPTION_FP_AS_GP}, { "mrelax-no-omit-fp", no_argument, NULL, OPTION_NO_FP_AS_GP}, { "mgen-symbol-ld-script", required_argument, NULL, OPTION_EXPORT_SYMBOLS}, - /* These are specific optioins for ex9-ext support. */ -#if defined NDS32_EX9_EXT - { "mex9", no_argument, NULL, OPTION_EX9_TABLE}, - { "mno-ex9", no_argument, NULL, OPTION_NO_EX9_TABLE}, - { "mexport-ex9", required_argument, NULL, OPTION_EXPORT_EX9}, - { "mimport-ex9", required_argument, NULL, OPTION_IMPORT_EX9}, - { "mupdate-ex9", no_argument, NULL, OPTION_UPDATE_EX9}, - { "mex9-limit", required_argument, NULL, OPTION_EX9_LIMIT}, - { "mex9-loop-aware", no_argument, NULL, OPTION_EX9_LOOP}, -#endif - /* These are specific optioins for ifc-ext support. */ -#if defined NDS32_IFC_EXT - { "mifc", no_argument, NULL, OPTION_JUMP_IFC}, - { "mno-ifc", no_argument, NULL, OPTION_NO_JUMP_IFC}, - { "mifc-loop-aware", no_argument, NULL, OPTION_IFC_LOOP}, -#endif ' PARSE_AND_LIST_OPTIONS=' fprintf (file, _("\ --m[no-]fp-as-gp Disable/enable fp-as-gp relaxation\n\ --mexport-symbols=FILE Exporting symbols in linker script\n\ + --mhyper-relax=level Adjust relax level (low|medium|high). default: medium\n\ + --m[no-]tlsdesc-trampoline Disable/enable TLS DESC trampoline\n\ ")); - -#if defined NDS32_EX9_EXT - fprintf (file, _("\ - --m[no-]ex9 Disable/enable link-time EX9 relaxation\n\ - --mexport-ex9=FILE Export EX9 table after linking\n\ - --mimport-ex9=FILE Import Ex9 table for EX9 relaxation\n\ - --mupdate-ex9 Update existing EX9 table\n\ - --mex9-limit=NUM Maximum number of entries in ex9 table\n\ - --mex9-loop-aware Avoid generate EX9 instruction inside loop\n\ -")); -#endif - -#if defined NDS32_IFC_EXT - fprintf (file, _("\ - --m[no-]ifc Disable/enable link-time IFC optimization\n\ - --mifc-loop-aware Avoid generate IFC instruction inside loop\n\ -")); -#endif ' PARSE_AND_LIST_ARGS_CASES=' case OPTION_BASELINE: @@ -319,65 +254,33 @@ PARSE_AND_LIST_ARGS_CASES=' einfo (_("%P%F: cannot open map file %s: %E.\n"), optarg); } break; -#if defined NDS32_EX9_EXT - case OPTION_EX9_TABLE: - target_optimize = target_optimize | NDS32_RELAX_EX9_ON; - break; - case OPTION_NO_EX9_TABLE: - target_optimize = target_optimize & (!NDS32_RELAX_EX9_ON); - break; - case OPTION_EXPORT_EX9: + case OPTION_HYPER_RELAX: if (!optarg) - einfo (_("Missing file for --mexport-ex9=.\n")); + einfo (_("Valid arguments to --mhyper-relax=(low|medium|high).\n")); - if(strcmp (optarg, "-") == 0) - ex9_export_file = stdout; + if (strcmp (optarg, "low") == 0) + hyper_relax = 0; + else if (strcmp (optarg, "medium") == 0) + hyper_relax = 1; + else if (strcmp (optarg, "high") == 0) + hyper_relax = 2; else - { - ex9_export_file = fopen (optarg, "wb"); - if(ex9_export_file == NULL) - einfo (_("ERROR %P%F: cannot open ex9 export file %s.\n"), optarg); - } - break; - case OPTION_IMPORT_EX9: - if (!optarg) - einfo (_("Missing file for --mimport-ex9=.\n")); + einfo (_("Valid arguments to --mhyper-relax=(low|medium|high).\n")); - ex9_import_file = fopen (optarg, "rb+"); - if(ex9_import_file == NULL) - einfo (_("ERROR %P%F: cannot open ex9 import file %s.\n"), optarg); + break; + case OPTION_TLSDESC_TRAMPOLINE: + tls_desc_trampoline = 1; break; - case OPTION_UPDATE_EX9: - update_ex9_table = 1; - break; - case OPTION_EX9_LIMIT: - if (optarg) - { - ex9_limit = atoi (optarg); - if (ex9_limit > 511 || ex9_limit < 1) - { - einfo (_("ERROR: the range of ex9_limit must between 1 and 511\n")); - exit (1); - } - } + case OPTION_NO_TLSDESC_TRAMPOLINE: + tls_desc_trampoline = 0; break; - case OPTION_EX9_LOOP: - target_optimize = target_optimize | NDS32_RELAX_EX9_ON; - ex9_loop_aware = 1; - break; -#endif -#if defined NDS32_IFC_EXT - case OPTION_JUMP_IFC: - target_optimize = target_optimize | NDS32_RELAX_JUMP_IFC_ON; - break; - case OPTION_NO_JUMP_IFC: - target_optimize = target_optimize & (!NDS32_RELAX_JUMP_IFC_ON); - break; - case OPTION_IFC_LOOP: - target_optimize = target_optimize | NDS32_RELAX_JUMP_IFC_ON; - ifc_loop_aware = 1; + case OPTION_SET_ABI: + if (strcmp (optarg, "AABI") != 0 + && strcmp (optarg, "V2FP+") != 0) + einfo (_("Valid arguments to --mabi=(AABI|V2FP+).\n")); + else + set_output_abi = optarg; break; -#endif ' LDEMUL_AFTER_OPEN=nds32_elf_after_open LDEMUL_AFTER_PARSE=nds32_elf_after_parse diff --git binutils-2.30/ld/scripttempl/nds32elf.sc binutils-2.30-nds32/ld/scripttempl/nds32elf.sc index dd9a0c11f7..6c09275e4d 100644 --- binutils-2.30/ld/scripttempl/nds32elf.sc +++ binutils-2.30-nds32/ld/scripttempl/nds32elf.sc @@ -185,7 +185,7 @@ test "${LARGE_SECTIONS}" = "yes" && LARGE_SECTIONS=" *(.ldata${RELOCATING+ .ldata.* .gnu.linkonce.l.*}) ${RELOCATING+. = ALIGN(. != 0 ? ${ALIGNMENT} : 1);} }" -if test "${ENABLE_INITFINI_ARRAY}" = "yes"; then +if test "${ENABLE_INITFINI_ARRAY}" = "no"; then SORT_INIT_ARRAY="KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))" SORT_FINI_ARRAY="KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))" CTORS_IN_INIT_ARRAY="EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o $OTHER_EXCLUDE_FILES) .ctors" @@ -335,6 +335,9 @@ eval $COMBRELOCCAT <> ldscripts/dyntmp.$$ < #include #include +#include #include "safe-ctype.h" #include "libiberty.h" @@ -43,8 +44,8 @@ #define MAX_KEYWORD_LEN 32 /* This LEX is a plain char or operand. */ #define IS_LEX_CHAR(c) (((c) >> 7) == 0) -#define LEX_SET_FIELD(c) ((c) | SYN_FIELD) -#define LEX_GET_FIELD(c) operand_fields[((c) & 0xff)] +#define LEX_SET_FIELD(k,c) ((c) | (((k) + 1) << 8)) +#define LEX_GET_FIELD(k,c) (nds32_field_table[k])[((c) & 0xff)] /* Get the char in this lexical element. */ #define LEX_CHAR(c) ((c) & 0xff) @@ -60,7 +61,8 @@ static int parse_fe5 (struct nds32_asm_desc *, struct nds32_asm_insn *, char **, int64_t *); static int parse_pi5 (struct nds32_asm_desc *, struct nds32_asm_insn *, char **, int64_t *); -static int parse_aext_reg (char **, int *, int); +static int parse_aext_reg (struct nds32_asm_desc *, char **, + int *, int); static int parse_a30b20 (struct nds32_asm_desc *, struct nds32_asm_insn *, char **, int64_t *); static int parse_rt21 (struct nds32_asm_desc *, struct nds32_asm_insn *, @@ -159,6 +161,7 @@ const field_t operand_fields[] = {"i14s1", 0, 14, 1, HW_INT, NULL}, {"i15s1", 0, 15, 1, HW_INT, NULL}, {"i16s1", 0, 16, 1, HW_INT, NULL}, + {"i16u5", 5, 16, 0, HW_UINT, NULL}, {"i18s1", 0, 18, 1, HW_INT, NULL}, {"i24s1", 0, 24, 1, HW_INT, NULL}, {"i8s2", 0, 8, 2, HW_INT, NULL}, @@ -170,7 +173,6 @@ const field_t operand_fields[] = {"i5u", 0, 5, 0, HW_UINT, NULL}, {"ib5u", 10, 5, 0, HW_UINT, NULL}, /* imm5 field in ALU. */ {"ib5s", 10, 5, 0, HW_INT, NULL}, /* imm5 field in ALU. */ - {"i9u", 0, 9, 0, HW_UINT, NULL}, /* for ex9.it. */ {"ia3u", 3, 3, 0, HW_UINT, NULL}, /* for bmski33, fexti33. */ {"i8u", 0, 8, 0, HW_UINT, NULL}, {"ib8u", 7, 8, 0, HW_UINT, NULL}, /* for ffbi. */ @@ -183,6 +185,8 @@ const field_t operand_fields[] = {"i7u2", 0, 7, 2, HW_UINT, NULL}, {"i5u3", 0, 5, 3, HW_UINT, NULL}, /* for pop25/pop25. */ {"i15s3", 0, 15, 3, HW_INT, NULL}, /* for dprefi.d. */ + {"ib4u", 10, 4, 0, HW_UINT, NULL}, /* imm5 field in ALU. */ + {"ib2u", 10, 2, 0, HW_UINT, NULL}, /* imm5 field in ALU. */ {"a_rt", 15, 5, 0, HW_GPR, NULL}, /* for audio-extension. */ {"a_ru", 10, 5, 0, HW_GPR, NULL}, /* for audio-extension. */ @@ -199,7 +203,9 @@ const field_t operand_fields[] = {"aridx", 0, 5, 0, HW_AEXT_ARIDX, NULL}, /* for audio-extension. */ {"aridx2", 0, 5, 0, HW_AEXT_ARIDX2, NULL}, /* for audio-extension. */ {"aridxi", 16, 4, 0, HW_AEXT_ARIDXI, NULL}, /* for audio-extension. */ - {"imm16", 0, 16, 0, HW_UINT, NULL}, /* for audio-extension. */ + {"aridxi_mx", 16, 4, 0, HW_AEXT_ARIDXI_MX, NULL}, /* for audio-extension. */ + {"imm16s", 0, 16, 0, HW_INT, NULL}, /* for audio-extension. */ + {"imm16u", 0, 16, 0, HW_UINT, NULL}, /* for audio-extension. */ {"im5_i", 0, 5, 0, HW_AEXT_IM_I, parse_im5_ip}, /* for audio-extension. */ {"im5_m", 0, 5, 0, HW_AEXT_IM_M, parse_im5_mr}, /* for audio-extension. */ {"im6_ip", 0, 2, 0, HW_AEXT_IM_I, parse_im6_ip}, /* for audio-extension. */ @@ -209,6 +215,7 @@ const field_t operand_fields[] = {"cp45", 4, 2, 0, HW_CP, NULL}, /* for cop-extension. */ {"i12u", 8, 12, 0, HW_UINT, NULL}, /* for cop-extension. */ {"cpi19", 6, 19, 0, HW_UINT, NULL}, /* for cop-extension. */ + {NULL, 0, 0, 0, 0, NULL} }; @@ -294,7 +301,6 @@ struct nds32_opcode nds32_opcodes[] = {"jrnez", "%rb", JREG (JRNEZ), 4, ATTR (BRANCH) | ATTR_V3, 0, NULL, 0, NULL}, {"jralnez", "%rt,%rb", JREG (JRALNEZ), 4, ATTR (BRANCH) | ATTR_V3, 0, NULL, 0, NULL}, {"ret", "%rb", JREG (JR) | JREG_RET, 4, ATTR (BRANCH) | ATTR_ALL, 0, NULL, 0, NULL}, - {"ifret", "", JREG (JR) | JREG_IFC | JREG_RET, 4, ATTR (BRANCH) | ATTR (IFC_EXT), 0, NULL, 0, NULL}, {"jral", "%rb", JREG (JRAL) | RT (30), 4, ATTR (BRANCH) | ATTR_ALL, 0, NULL, 0, NULL}, {"jralnez", "%rb", JREG (JRALNEZ) | RT (30), 4, ATTR (BRANCH) | ATTR_V3, 0, NULL, 0, NULL}, {"ret", "", JREG (JR) | JREG_RET | RB (30), 4, ATTR (BRANCH) | ATTR_ALL, 0, NULL, 0, NULL}, @@ -306,8 +312,6 @@ struct nds32_opcode nds32_opcodes[] = {"beq", "%rt,%ra,%i14s1", OP6 (BR1), 4, ATTR_PCREL | ATTR_ALL, 0, NULL, 0, NULL}, {"bne", "%rt,%ra,%i14s1", OP6 (BR1) | N32_BIT (14), 4, ATTR_PCREL | ATTR_ALL, 0, NULL, 0, NULL}, /* seg-BR2. */ -#define BR2(sub) (OP6 (BR2) | (N32_BR2_ ## sub << 16)) - {"ifcall", "%i16s1", BR2 (IFCALL), 4, ATTR (IFC_EXT), 0, NULL, 0, NULL}, {"beqz", "%rt,%i16s1", BR2 (BEQZ), 4, ATTR_PCREL | ATTR_ALL, 0, NULL, 0, NULL}, {"bnez", "%rt,%i16s1", BR2 (BNEZ), 4, ATTR_PCREL | ATTR_ALL, 0, NULL, 0, NULL}, {"bgez", "%rt,%i16s1", BR2 (BGEZ), 4, ATTR_PCREL | ATTR_ALL, 0, NULL, 0, NULL}, @@ -377,10 +381,10 @@ struct nds32_opcode nds32_opcodes[] = {"bse", "=rt,%ra,=rb", ALU2 (BSE), 4, ATTR (PERF2_EXT), 0, NULL, 0, NULL}, {"bsp", "=rt,%ra,=rb", ALU2 (BSP), 4, ATTR (PERF2_EXT), 0, NULL, 0, NULL}, {"ffzmism", "=rt,%ra,%rb", ALU2 (FFZMISM), 4, ATTR (STR_EXT), 0, NULL, 0, NULL}, - {"mfusr", "=rt,%usr", ALU2 (MFUSR), 4, ATTR_V3MEX_V1, 0, NULL, 0, NULL}, - {"mtusr", "%rt,%usr", ALU2 (MTUSR), 4, ATTR_V3MEX_V1, 0, NULL, 0, NULL}, - {"mfusr", "=rt,%ridx", ALU2 (MFUSR), 4, ATTR_V3MEX_V1, 0, NULL, 0, NULL}, - {"mtusr", "%rt,%ridx", ALU2 (MTUSR), 4, ATTR_V3MEX_V1, 0, NULL, 0, NULL}, + {"mfusr", "=rt,%usr", ALU2 (MFUSR), 4, ATTR_ALL, 0, NULL, 0, NULL}, + {"mtusr", "%rt,%usr", ALU2 (MTUSR), 4, ATTR_ALL, 0, NULL, 0, NULL}, + {"mfusr", "=rt,%ridx", ALU2 (MFUSR), 4, ATTR_ALL, 0, NULL, 0, NULL}, + {"mtusr", "%rt,%ridx", ALU2 (MTUSR), 4, ATTR_ALL, 0, NULL, 0, NULL}, {"mul", "=rt,%ra,%rb", ALU2 (MUL), 4, ATTR_ALL, 0, NULL, 0, NULL}, {"madds64", "=dt,%ra,%rb", ALU2 (MADDS64), 4, ATTR (MAC) | ATTR_ALL, 0, NULL, 0, NULL}, {"madd64", "=dt,%ra,%rb", ALU2 (MADD64), 4, ATTR (MAC) | ATTR_ALL, 0, NULL, 0, NULL}, @@ -392,22 +396,22 @@ struct nds32_opcode nds32_opcodes[] = /* seg-ALU2_FFBI. */ {"ffb", "=rt,%ra,%rb", ALU2 (FFB), 4, ATTR (STR_EXT), 0, NULL, 0, NULL}, - {"ffbi", "=rt,%ra,%ib8u", ALU2 (FFBI) | N32_BIT (6), 4, ATTR (STR_EXT), 0, NULL, 0, NULL}, + {"ffbi", "=rt,%ra,%ib8u", ALU2_1 (FFBI), 4, ATTR (STR_EXT), 0, NULL, 0, NULL}, /* seg-ALU2_FLMISM. */ {"ffmism", "=rt,%ra,%rb", ALU2 (FFMISM), 4, ATTR (STR_EXT), 0, NULL, 0, NULL}, - {"flmism", "=rt,%ra,%rb", ALU2 (FLMISM) | N32_BIT (6), 4, ATTR (STR_EXT), 0, NULL, 0, NULL}, + {"flmism", "=rt,%ra,%rb", ALU2_1 (FLMISM), 4, ATTR (STR_EXT), 0, NULL, 0, NULL}, /* seg-ALU2_MULSR64. */ {"mults64", "=dt,%ra,%rb", ALU2 (MULTS64), 4, ATTR_ALL, 0, NULL, 0, NULL}, - {"mulsr64", "=rt,%ra,%rb", ALU2 (MULSR64)| N32_BIT (6), 4, ATTR_V3MEX_V2, 0, NULL, 0, NULL}, + {"mulsr64", "=rt,%ra,%rb", ALU2_1 (MULSR64), 4, ATTR_V3MEX_V2, 0, NULL, 0, NULL}, /* seg-ALU2_MULR64. */ {"mult64", "=dt,%ra,%rb", ALU2 (MULT64), 4, ATTR_ALL, 0, NULL, 0, NULL}, - {"mulr64", "=rt,%ra,%rb", ALU2 (MULR64) | N32_BIT (6), 4, ATTR_V3MEX_V2, 0, NULL, 0, NULL}, + {"mulr64", "=rt,%ra,%rb", ALU2_1 (MULR64), 4, ATTR_V3MEX_V2, 0, NULL, 0, NULL}, /* seg-ALU2_MADDR32. */ {"madd32", "=dt,%ra,%rb", ALU2 (MADD32), 4, ATTR (MAC) | ATTR (DXREG) | ATTR_ALL, 0, NULL, 0, NULL}, - {"maddr32", "=rt,%ra,%rb", ALU2 (MADDR32) | N32_BIT (6), 4, ATTR (MAC) | ATTR_V2UP, 0, NULL, 0, NULL}, + {"maddr32", "=rt,%ra,%rb", ALU2_1 (MADDR32), 4, ATTR (MAC) | ATTR_V2UP, 0, NULL, 0, NULL}, /* seg-ALU2_MSUBR32. */ {"msub32", "=dt,%ra,%rb", ALU2 (MSUB32), 4, ATTR (MAC) | ATTR (DXREG) | ATTR_ALL, 0, NULL, 0, NULL}, - {"msubr32", "=rt,%ra,%rb", ALU2 (MSUBR32) | N32_BIT (6), 4, ATTR (MAC) | ATTR_V2UP, 0, NULL, 0, NULL}, + {"msubr32", "=rt,%ra,%rb", ALU2_1 (MSUBR32), 4, ATTR (MAC) | ATTR_V2UP, 0, NULL, 0, NULL}, /* seg-MISC. */ {"standby", "%stdby_st", MISC (STANDBY), 4, ATTR_ALL, 0, NULL, 0, NULL}, @@ -439,8 +443,12 @@ struct nds32_opcode nds32_opcodes[] = {"tlbop", "%ra,%tlbop_st", MISC (TLBOP), 4, ATTR_ALL, 0, NULL, 0, NULL}, {"tlbop", "%ra,%tlbop_stx", MISC (TLBOP), 4, ATTR_ALL, 0, NULL, 0, NULL}, {"tlbop", "%rt,%ra,pb", MISC (TLBOP) | (5 << 5), 4, ATTR_ALL, 0, NULL, 0, NULL}, + {"tlbop", "%rt,%ra,probe", MISC (TLBOP) | (5 << 5), 4, ATTR_ALL, 0, NULL, 0, NULL}, {"tlbop", "flua", MISC (TLBOP) | (7 << 5), 4, ATTR_ALL, 0, NULL, 0, NULL}, {"tlbop", "flushall", MISC (TLBOP) | (7 << 5), 4, ATTR_ALL, 0, NULL, 0, NULL}, + /* seg-MISC_SPECL. */ + {"isps", "%i16u5", MISC (SPECL), 4, ATTR_ALL, 0, NULL, 0, NULL}, + {"isps", "", MISC (SPECL), 4, ATTR_ALL, 0, NULL, 0, NULL}, /* seg-MEM. */ {"lb", "=rt,[%ra+(%rb<<%sv)]", MEM (LB), 4, ATTR_ALL, 0, NULL, 0, NULL}, @@ -542,7 +550,6 @@ struct nds32_opcode nds32_opcodes[] = {"fnmsubs", "=fst,%fsa,%fsb", FS1 (FNMSUBS), 4, ATTR (FPU) | ATTR (FPU_SP_EXT), 0, NULL, 0, NULL}, {"fmuls", "=fst,%fsa,%fsb", FS1 (FMULS), 4, ATTR (FPU) | ATTR (FPU_SP_EXT), 0, NULL, 0, NULL}, {"fdivs", "=fst,%fsa,%fsb", FS1 (FDIVS), 4, ATTR (FPU) | ATTR (FPU_SP_EXT), 0, NULL, 0, NULL}, - /* seg-FPU_FS1_F2OP. */ {"fs2d", "=fdt,%fsa", FS1_F2OP (FS2D), 4, ATTR (FPU) | ATTR (FPU_SP_EXT) | ATTR (FPU_DP_EXT), 0, NULL, 0, NULL}, {"fsqrts", "=fst,%fsa", FS1_F2OP (FSQRTS), 4, ATTR (FPU) | ATTR (FPU_SP_EXT), 0, NULL, 0, NULL}, @@ -601,7 +608,6 @@ struct nds32_opcode nds32_opcodes[] = {"fmfcfg", "=rt", MFCP_XR(FMFCFG), 4, ATTR (FPU), 0, NULL, 0, NULL}, {"fmfcsr", "=rt", MFCP_XR(FMFCSR), 4, ATTR (FPU), 0, NULL, 0, NULL}, /* seg-FPU_MTCP. */ - {"fmtsr", "%rt,=fsa", MTCP (FMTSR), 4, ATTR (FPU), 0, NULL, 0, NULL}, {"fmtdr", "%rt,=fda", MTCP (FMTDR), 4, ATTR (FPU), 0, NULL, 0, NULL}, /* seg-FPU_MTCP_XR. */ @@ -707,14 +713,14 @@ struct nds32_opcode nds32_opcodes[] = {"swi37", "%rt38,[$fp{+%i7u2}]", 0xb880, 2, ATTR_ALL, USE_REG (28), NULL, 0, NULL}, /* SEG10_1 if Rt3=5. */ {"j8", "%i8s1", 0xd500, 2, ATTR_PCREL | ATTR_ALL, 0, NULL, 0, NULL}, + /* SEG11_1 if Rt3=5. */ /* SEG11_2 bit7~bit5. */ - {"jr5", "%ra5", 0xdd00, 2, ATTR_ALL, 0, NULL, 0, NULL}, - {"jral5", "%ra5", 0xdd20, 2, ATTR_ALL, 0, NULL, 0, NULL}, - {"ex9.it", "%i5u", 0xdd40, 2, ATTR (EX9_EXT), 0, NULL, 0, NULL}, - {"ret5", "%ra5", 0xdd80, 2, ATTR_ALL, 0, NULL, 0, NULL}, + {"jr5", "%ra5", 0xdd00, 2, ATTR_ALL | ATTR (BRANCH), 0, NULL, 0, NULL}, + {"jral5", "%ra5", 0xdd20, 2, ATTR_ALL | ATTR (BRANCH), 0, NULL, 0, NULL}, + {"ret5", "%ra5", 0xdd80, 2, ATTR_ALL | ATTR (BRANCH), 0, NULL, 0, NULL}, {"add5.pc", "%ra5", 0xdda0, 2, ATTR_V3, 0, NULL, 0, NULL}, /* SEG11_3 if Ra5=30. */ - {"ret5", "", 0xdd80 | RA5 (30), 2, ATTR_ALL, 0, NULL, 0, NULL}, + {"ret5", "", 0xdd80 | RA5 (30), 2, ATTR_ALL | ATTR (BRANCH), 0, NULL, 0, NULL}, /* SEG12 bit10~bit9. */ {"slts45", "%rt4,%ra5", 0xe000, 2, ATTR_ALL, DEF_REG (15), NULL, 0, NULL}, {"slt45", "%rt4,%ra5", 0xe200, 2, ATTR_ALL, DEF_REG (15), NULL, 0, NULL}, @@ -727,13 +733,10 @@ struct nds32_opcode nds32_opcodes[] = /* SEG13_1 bit8. */ {"beqzs8", "%i8s1", 0xe800, 2, ATTR_PCREL | ATTR_ALL, USE_REG (15), NULL, 0, NULL}, {"bnezs8", "%i8s1", 0xe900, 2, ATTR_PCREL | ATTR_ALL, USE_REG (15), NULL, 0, NULL}, - /* SEG13_2 bit8~bit5. */ - {"ex9.it", "%i9u", 0xea00, 2, ATTR (EX9_EXT), 0, NULL, 0, NULL}, /* SEG14 bit7. */ {"lwi37.sp", "=rt38,[+%i7u2]", 0xf000, 2, ATTR_V2UP, USE_REG (31), NULL, 0, NULL}, {"swi37.sp", "%rt38,[+%i7u2]", 0xf080, 2, ATTR_V2UP, USE_REG (31), NULL, 0, NULL}, /* SEG15 bit10~bit9. */ - {"ifcall9", "%i9u1", 0xf800, 2, ATTR (IFC_EXT), 0, NULL, 0, NULL}, {"movpi45", "=rt4,%pi5", 0xfa00, 2, ATTR_V3MUP, 0, NULL, 0, NULL}, /* SEG15_1 bit8. */ {"movd44", "=rt5e,%ra5e", 0xfd00, 2, ATTR_V3MUP, 0, NULL, 0, NULL}, @@ -749,7 +752,7 @@ struct nds32_opcode nds32_opcodes[] = {"fexti33", "=rt3,%ia3u", 0x9607, 2, ATTR_V3MUP, 0, NULL, 0, NULL}, /* SEG-PUSHPOP25 bit8~bit7. */ {"push25", "%re2,%i5u3", 0xfc00, 2, ATTR_V3MUP, USE_REG (31) | DEF_REG (31), NULL, 0, NULL}, - {"pop25", "%re2,%i5u3", 0xfc80, 2, ATTR_V3MUP, USE_REG (31) | DEF_REG (31), NULL, 0, NULL}, + {"pop25", "%re2,%i5u3", 0xfc80, 2, ATTR_V3MUP | ATTR (BRANCH), USE_REG (31) | DEF_REG (31), NULL, 0, NULL}, /* SEG-MISC33 bit2~bit0. */ {"neg33", "=rt3,%ra3", 0xfe02, 2, ATTR_V3MUP, 0, NULL, 0, NULL}, {"not33", "=rt3,%ra3", 0xfe03, 2, ATTR_V3MUP, 0, NULL, 0, NULL}, @@ -759,29 +762,31 @@ struct nds32_opcode nds32_opcodes[] = {"or33", "=rt3,%ra3", 0xfe07, 2, ATTR_V3MUP, 0, NULL, 0, NULL}, /* SEG-Alias instructions. */ {"nop16", "", 0x9200, 2, ATTR_ALL, 0, NULL, 0, NULL}, - {"ifret16", "", 0x83ff, 2, ATTR (IFC_EXT), 0, NULL, 0, NULL}, /* Saturation ext ISA. */ {"kaddw", "=rt,%ra,%rb", ALU2 (KADD), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, {"ksubw", "=rt,%ra,%rb", ALU2 (KSUB), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, - {"kaddh", "=rt,%ra,%rb", ALU2 (KADD) | N32_BIT (6), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, - {"ksubh", "=rt,%ra,%rb", ALU2 (KSUB) | N32_BIT (6), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, + {"kaddh", "=rt,%ra,%rb", ALU2_1 (KADD), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, + {"ksubh", "=rt,%ra,%rb", ALU2_1 (KSUB), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, {"kdmbb", "=rt,%ra,%rb", ALU2 (KMxy), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, {"kdmbt", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (6), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, {"kdmtb", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (7), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, {"kdmtt", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (6) | N32_BIT (7), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, {"khmbb", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (8), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, - {"khmbt", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (8) | N32_BIT (6), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, - {"khmtb", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (8) | N32_BIT (7), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, - {"khmtt", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (8) | N32_BIT (6) | N32_BIT (7), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, - {"kslraw", "=rt,%ra,%rb", ALU2 (KSLRA), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, - {"rdov", "=rt", ALU2 (MFUSR) | N32_BIT (6) | ( 0x1e << 15), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, - {"clrov", "", ALU2 (MTUSR) | N32_BIT (6) | ( 0x1e << 15), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, + {"khmbt", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (6) | N32_BIT (8), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, + {"khmtb", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (7) | N32_BIT (8), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, + {"khmtt", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (6) | N32_BIT (7) | N32_BIT (8), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, + {"kslraw", "=rt,%ra,%rb", ALU2 (KSLRAW), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, + {"ksll", "=rt,%ra,%rb", ALU2 (KSLRAW), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, + {"kslraw.u", "=rt,%ra,%rb", ALU2 (KSLRAWu), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, + {"rdov", "=rt", ALU2_1 (RDOV) | ( 0x1e << 15), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, + {"clrov", "", ALU2_1 (CLROV) | ( 0x1e << 15), 4, ATTR (SATURATION_EXT), 0, NULL, 0, NULL}, /* Audio ext. instructions. */ - {"amtari", "%aridxi,%imm16", AUDIO (AMTARI), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMADD */ + {"amtari", "%aridxi,%imm16u", AUDIO (AMTARI), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, + {"amtari", "%aridxi_mx,%imm16s", AUDIO (AMTARI), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, + /* N32_AEXT_AMADD. */ {"alr2", "=a_rt,=a_ru,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMADD) | (0x1 << 6), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amaddl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMADD) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amaddl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMADD) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, @@ -791,7 +796,7 @@ struct nds32_opcode nds32_opcodes[] = {"alr", "=a_rt,[%im5_i],%im5_m", AUDIO (AMADD) | (0x01 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amadd", "=a_dx,%ra,%rb", AUDIO (AMADD), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amabbs", "=a_dx,%ra,%rb", AUDIO (AMADD) | 0x01, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMSUB */ + /* N32_AEXT_AMSUB. */ {"amsubl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMSUB) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amsubl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMSUB) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amsubl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMSUB) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, @@ -800,7 +805,7 @@ struct nds32_opcode nds32_opcodes[] = {"asr", "%ra,[%im5_i],%im5_m", AUDIO (AMSUB) | (0x01 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amsub", "=a_dx,%ra,%rb", AUDIO (AMSUB), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amabts", "=a_dx,%ra,%rb", AUDIO (AMSUB) |0x01, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMULT */ + /* N32_AEXT_AMULT. */ {"amultl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMULT) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amultl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMULT) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amultl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMULT) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, @@ -811,14 +816,14 @@ struct nds32_opcode nds32_opcodes[] = {"amatbs", "=a_dx,%ra,%rb", AUDIO (AMULT) |0x01, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"asats48", "=a_dx", AUDIO (AMULT) | (0x02 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"awext", "%ra,%a_dx,%i5u", AUDIO (AMULT) | (0x03 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMFAR */ + /* N32_AEXT_AMFAR. */ {"amatts", "=a_dx,%ra,%rb", AUDIO (AMFAR) | 0x01, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"asa", "=dxh,[%im5_i],%im5_m", AUDIO (AMFAR) | (0x01 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amtar", "%ra,%aridx", AUDIO (AMFAR) | (0x02 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amtar2", "%ra,%aridx2", AUDIO (AMFAR) | (0x12 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amfar", "=ra,%aridx", AUDIO (AMFAR) | (0x03 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amfar2", "=ra,%aridx2", AUDIO (AMFAR) | (0x13 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMADDS */ + /* N32_AEXT_AMADDS. */ {"amaddsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMADDS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amaddsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMADDS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amaddsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMADDS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, @@ -828,7 +833,7 @@ struct nds32_opcode nds32_opcodes[] = {"amadds", "=a_dx,%ra,%rb", AUDIO (AMADDS), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"ambbs", "=a_dx,%ra,%rb", AUDIO (AMADDS) |0x01, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amawbs", "=a_dx,%ra,%rb", AUDIO (AMADDS) |0x02, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMSUBS */ + /* N32_AEXT_AMSUBS. */ {"amsubsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMSUBS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amsubsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMSUBS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amsubsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMSUBS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, @@ -837,7 +842,7 @@ struct nds32_opcode nds32_opcodes[] = {"amsubs", "=a_dx,%ra,%rb", AUDIO (AMSUBS), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"ambts", "=a_dx,%ra,%rb", AUDIO (AMSUBS) |0x01, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amawts", "=a_dx,%ra,%rb", AUDIO (AMSUBS) |0x02, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMULTS */ + /* N32_AEXT_AMULTS. */ {"amultsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMULTS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amultsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMULTS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amultsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMULTS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, @@ -846,7 +851,7 @@ struct nds32_opcode nds32_opcodes[] = {"amults", "=a_dx,%ra,%rb", AUDIO (AMULTS), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amtbs", "=a_dx,%ra,%rb", AUDIO (AMULTS) |0x01, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amwbs", "=a_dx,%ra,%rb", AUDIO (AMULTS) |0x02, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMNEGS */ + /* N32_AEXT_AMNEGS. */ {"amnegsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMNEGS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amnegsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMNEGS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amnegsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMNEGS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, @@ -855,82 +860,258 @@ struct nds32_opcode nds32_opcodes[] = {"amnegs", "=a_dx,%ra,%rb", AUDIO (AMNEGS), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amtts", "=a_dx,%ra,%rb", AUDIO (AMNEGS) |0x01, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amwts", "=a_dx,%ra,%rb", AUDIO (AMNEGS) |0x02, 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AADDL */ + /* N32_AEXT_AADDL. */ {"aaddl", "=a_rte69,%ra,%rb,%a_rte69_1,[%im5_i],%im5_m", AUDIO (AADDL), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"asubl", "=a_rte69,%ra,%rb,%a_rte69_1,[%im5_i],%im5_m", AUDIO (AADDL) | (0x01 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMAWBS */ + /* N32_AEXT_AMAWBS. */ {"amawbsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMAWBS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amawbsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMAWBS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amawbsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMAWBS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amawbsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMAWBS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amawbssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMAWBS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMAWTS */ + /* N32_AEXT_AMAWTS. */ {"amawtsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMAWTS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amawtsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMAWTS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amawtsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMAWTS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amawtsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMAWTS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amawtssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMAWTS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMWBS */ + /* N32_AEXT_AMWBS. */ {"amwbsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMWBS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amwbsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMWBS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amwbsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMWBS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amwbsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMWBS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amwbssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMWBS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amwbssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMWBS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMWTS */ + /* N32_AEXT_AMWTS. */ {"amwtsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMWTS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amwtsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMWTS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amwtsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMWTS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amwtsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMWTS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amwtssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMWTS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMABBS */ + /* N32_AEXT_AMABBS. */ {"amabbsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMABBS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amabbsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMABBS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amabbsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMABBS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amabbsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMABBS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amabbssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMABBS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMABTS */ + /* N32_AEXT_AMABTS. */ {"amabtsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMABTS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amabtsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMABTS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amabtsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMABTS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amabtsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMABTS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amabtssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMABTS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMATBS */ + /* N32_AEXT_AMATBS. */ {"amatbsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMATBS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amatbsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMATBS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amatbsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMATBS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amatbsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMATBS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amatbssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMATBS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMATTS */ + /* N32_AEXT_AMATTS. */ {"amattsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMATTS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amattsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMATTS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amattsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMATTS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amattsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMATTS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amattssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMATTS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMBBS */ + /* N32_AEXT_AMBBS. */ {"ambbsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMBBS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"ambbsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMBBS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"ambbsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMBBS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"ambbsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMBBS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"ambbssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMBBS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMBTS */ + /* N32_AEXT_AMBTS. */ {"ambtsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMBTS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"ambtsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMBTS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"ambtsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMBTS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"ambtsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMBTS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"ambtssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMBTS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMTBS */ + /* N32_AEXT_AMTBS. */ {"amtbsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMTBS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amtbsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMTBS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amtbsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMTBS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amtbsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMTBS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amtbssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMTBS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, - /* N32_AEXT_AMTTS */ + /* N32_AEXT_AMTTS. */ {"amttsl.s", "=a_dx,%ra,%rb,[%im5_i],%im5_m", AUDIO (AMTTS) | (0x04 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amttsl.l", "=a_dx,%a_a30,%a_b20,%a_rt21,[%im5_i],%im5_m", AUDIO (AMTTS) | (0x06 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amttsl2.s", "=a_dx,%ra,%rb,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMTTS) | (0x08 << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amttsl2.l", "=a_dx,%a_a30,%a_b20,%a_rte,%a_rte1,[%im6_ip],[%im6_iq],%im6_mr,%im6_ms", AUDIO (AMTTS) | (0x0A << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, {"amttssa", "=a_dx,%ra,%rb,%dhy,[%im5_i],%im5_m", AUDIO (AMTTS) | (0x0C << 5), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL}, + + /* DSP ISA. */ + /* ALU2 Bit 9-6 = 0000. */ + {"add64", "=rt,%ra,%rb", ALU2 (ADD64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"sub64", "=rt,%ra,%rb", ALU2 (SUB64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smal", "=rt,%ra,%rb", ALU2 (SMAL), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"radd64", "=rt,%ra,%rb", ALU2 (RADD64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"rsub64", "=rt,%ra,%rb", ALU2 (RSUB64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"uradd64", "=rt,%ra,%rb", ALU2 (URADD64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ursub64", "=rt,%ra,%rb", ALU2 (URSUB64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kadd64", "=rt,%ra,%rb", ALU2 (KADD64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ksub64", "=rt,%ra,%rb", ALU2 (KSUB64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ukadd64", "=rt,%ra,%rb", ALU2 (UKADD64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"uksub64", "=rt,%ra,%rb", ALU2 (UKSUB64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + /* ALU2 Bit 9-6 = 0001. */ + {"smar64", "=rt,%ra,%rb", ALU2_1 (SMAR64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"umar64", "=rt,%ra,%rb", ALU2_1 (UMAR64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smsr64", "=rt,%ra,%rb", ALU2_1 (SMSR64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"umsr64", "=rt,%ra,%rb", ALU2_1 (UMSR64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmar64", "=rt,%ra,%rb", ALU2_1 (KMAR64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ukmar64", "=rt,%ra,%rb", ALU2_1 (UKMAR64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmsr64", "=rt,%ra,%rb", ALU2_1 (KMSR64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ukmsr64", "=rt,%ra,%rb", ALU2_1 (UKMSR64), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smalda", "=rt,%ra,%rb", ALU2_1 (SMALDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smslda", "=rt,%ra,%rb", ALU2_1 (SMSLDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smalds", "=rt,%ra,%rb", ALU2_1 (SMALDS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smalbb", "=rt,%ra,%rb", ALU2_1 (SMALBB), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smalxda", "=rt,%ra,%rb", ALU2_1 (SMALXDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smslxda", "=rt,%ra,%rb", ALU2_1 (SMSLXDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smalxds", "=rt,%ra,%rb", ALU2_1 (SMALXDS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smalbt", "=rt,%ra,%rb", ALU2_1 (SMALBT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smalbt", "=rt,%ra,%rb", ALU2_1 (SMALBT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smaldrs", "=rt,%ra,%rb", ALU2_1 (SMALDRS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smaltt", "=rt,%ra,%rb", ALU2_1 (SMALTT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smds", "=rt,%ra,%rb", ALU2_1 (SMDS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smxds", "=rt,%ra,%rb", ALU2_1 (SMXDS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smdrs", "=rt,%ra,%rb", ALU2_1 (SMDRS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmadrs", "=rt,%ra,%rb", ALU2_1 (KMADRS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmads", "=rt,%ra,%rb", ALU2_1 (KMADS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmaxds", "=rt,%ra,%rb", ALU2_1 (KMAXDS), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + /* DSP MISC. */ + {"bpick", "=rt,%ra,%rb,%rd", MISC (BPICK), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + /* ALU_2 KMxy. */ + {"khm16", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (9) | N32_BIT (8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"khmx16", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (9) | N32_BIT (8) | N32_BIT (6), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smul16", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (9), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smulx16", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (9) | N32_BIT (6), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"umul16", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (9) | N32_BIT (7), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"umulx16", "=rt,%ra,%rb", ALU2 (KMxy) | N32_BIT (9) | N32_BIT (7) | N32_BIT (6), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + /* ALU2 Bit 9-6 = 0010. */ + {"kadd16", "=rt,%ra,%rb", ALU2_2 (KADD16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ksub16", "=rt,%ra,%rb", ALU2_2 (KSUB16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kcras16", "=rt,%ra,%rb", ALU2_2 (KCRAS16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kcrsa16", "=rt,%ra,%rb", ALU2_2 (KCRSA16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kadd8", "=rt,%ra,%rb", ALU2_2 (KADD8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ksub8", "=rt,%ra,%rb", ALU2_2 (KSUB8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"wext", "=rt,%ra,%rb", ALU2_2 (WEXT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"wexti", "=rt,%ra,%ib5u", ALU2_2 (WEXTI), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ukadd16", "=rt,%ra,%rb", ALU2_2 (UKADD16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"uksub16", "=rt,%ra,%rb", ALU2_2 (UKSUB16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ukcras16", "=rt,%ra,%rb", ALU2_2 (UKCRAS16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ukcrsa16", "=rt,%ra,%rb", ALU2_2 (UKCRSA16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ukadd8", "=rt,%ra,%rb", ALU2_2 (UKADD8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"uksub8", "=rt,%ra,%rb", ALU2_2 (UKSUB8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + /* ONEOP. */ +#define DSP_ONEOP(n) ((n) << 10) + {"sunpkd810", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x0), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"sunpkd820", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x1), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"sunpkd830", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x2), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"sunpkd831", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x3), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"zunpkd810", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x4), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"zunpkd820", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x5), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"zunpkd830", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x6), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"zunpkd831", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x7), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kabs", "=rt,%ra", ALU2 (ABS), 4, ATTR (PERF_EXT), 0, NULL, 0, NULL}, + {"kabs16", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0x8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kabs8", "=rt,%ra", ALU2_2 (ONEOP) | DSP_ONEOP (0xc), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"insb", "=rt,%ra,%ib2u", ALU2_2 (ONEOP) | DSP_ONEOP (0x10), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smbb", "=rt,%ra,%rb", ALU2_2 (SMBB), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smbt", "=rt,%ra,%rb", ALU2_2 (SMBT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smtt", "=rt,%ra,%rb", ALU2_2 (SMTT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmabb", "=rt,%ra,%rb", ALU2_2 (KMABB), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmabt", "=rt,%ra,%rb", ALU2_2 (KMABT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmatt", "=rt,%ra,%rb", ALU2_2 (KMATT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmda", "=rt,%ra,%rb", ALU2_2 (KMDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmxda", "=rt,%ra,%rb", ALU2_2 (KMXDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmada", "=rt,%ra,%rb", ALU2_2 (KMADA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmaxda", "=rt,%ra,%rb", ALU2_2 (KMAXDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmsda", "=rt,%ra,%rb", ALU2_2 (KMSDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmsxda", "=rt,%ra,%rb", ALU2_2 (KMSXDA), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"radd16", "=rt,%ra,%rb", ALU2_2 (RADD16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"rsub16", "=rt,%ra,%rb", ALU2_2 (RSUB16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"rcras16", "=rt,%ra,%rb", ALU2_2 (RCRAS16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"rcrsa16", "=rt,%ra,%rb", ALU2_2 (RCRSA16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"radd8", "=rt,%ra,%rb", ALU2_2 (RADD8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"rsub8", "=rt,%ra,%rb", ALU2_2 (RSUB8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"raddw", "=rt,%ra,%rb", ALU2_2 (RADDW), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"rsubw", "=rt,%ra,%rb", ALU2_2 (RSUBW), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"uradd16", "=rt,%ra,%rb", ALU2_2 (URADD16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ursub16", "=rt,%ra,%rb", ALU2_2 (URSUB16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"urcras16", "=rt,%ra,%rb", ALU2_2 (URCRAS16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"urcrsa16", "=rt,%ra,%rb", ALU2_2 (URCRSA16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"uradd8", "=rt,%ra,%rb", ALU2_2 (URADD8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ursub8", "=rt,%ra,%rb", ALU2_2 (URSUB8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"uraddw", "=rt,%ra,%rb", ALU2_2 (URADDW), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ursubw", "=rt,%ra,%rb", ALU2_2 (URSUBW), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"add16", "=rt,%ra,%rb", ALU2_2 (ADD16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"sub16", "=rt,%ra,%rb", ALU2_2 (SUB16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"cras16", "=rt,%ra,%rb", ALU2_2 (CRAS16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"crsa16", "=rt,%ra,%rb", ALU2_2 (CRSA16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"add8", "=rt,%ra,%rb", ALU2_2 (ADD8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"sub8", "=rt,%ra,%rb", ALU2_2 (SUB8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"bitrev", "=rt,%ra,%rb", ALU2_2 (BITREV), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"bitrevi", "=rt,%ra,%ib5u", ALU2_2 (BITREVI), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smmul", "=rt,%ra,%rb", ALU2_2 (SMMUL), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smmul.u", "=rt,%ra,%rb", ALU2_2 (SMMULu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmmac", "=rt,%ra,%rb", ALU2_2 (KMMAC), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmmac.u", "=rt,%ra,%rb", ALU2_2 (KMMACu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmmsb", "=rt,%ra,%rb", ALU2_2 (KMMSB), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmmsb.u", "=rt,%ra,%rb", ALU2_2 (KMMSBu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kwmmul", "=rt,%ra,%rb", ALU2_2 (KWMMUL), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kwmmul.u", "=rt,%ra,%rb", ALU2_2 (KWMMULu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + /* ALU2 Bit 9-6 = 0010. */ + {"smmwb", "=rt,%ra,%rb", ALU2_3 (SMMWB), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smmwb.u", "=rt,%ra,%rb", ALU2_3 (SMMWBu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smmwt", "=rt,%ra,%rb", ALU2_3 (SMMWT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smmwt.u", "=rt,%ra,%rb", ALU2_3 (SMMWTu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmmawb", "=rt,%ra,%rb", ALU2_3 (KMMAWB), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmmawb.u", "=rt,%ra,%rb", ALU2_3 (KMMAWBu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmmawt", "=rt,%ra,%rb", ALU2_3 (KMMAWT), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kmmawt.u", "=rt,%ra,%rb", ALU2_3 (KMMAWTu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"pktt16", "=rt,%ra,%rb", ALU2_3 (PKTT16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"pktb16", "=rt,%ra,%rb", ALU2_3 (PKTB16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"pkbt16", "=rt,%ra,%rb", ALU2_3 (PKBT16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"pkbb16", "=rt,%ra,%rb", ALU2_3 (PKBB16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"sclip32", "=rt,%ra,%ib5u", ALU2 (CLIPS), 4, ATTR (PERF_EXT), 0, NULL, 0, NULL}, + {"sclip16", "=rt,%ra,%ib4u", ALU2_3 (SCLIP16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smax16", "=rt,%ra,%rb", ALU2_3 (SMAX16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smax8", "=rt,%ra,%rb", ALU2_3 (SMAX8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"uclip32", "=rt,%ra,%ib5u", ALU2 (CLIP), 4, ATTR (PERF_EXT), 0, NULL, 0, NULL}, + {"uclip16", "=rt,%ra,%ib4u", ALU2_3 (UCLIP16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"umax16", "=rt,%ra,%rb", ALU2_3 (UMAX16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"umax8", "=rt,%ra,%rb", ALU2_3 (UMAX8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"sra16", "=rt,%ra,%rb", ALU2_3 (SRA16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"sra16.u", "=rt,%ra,%rb", ALU2_3 (SRA16u), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"srl16", "=rt,%ra,%rb", ALU2_3 (SRL16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"srl16.u", "=rt,%ra,%rb", ALU2_3 (SRL16u), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"sll16", "=rt,%ra,%rb", ALU2_3 (SLL16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kslra16", "=rt,%ra,%rb", ALU2_3 (KSLRA16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ksll16", "=rt,%ra,%rb", ALU2_3 (KSLRA16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kslra16.u", "=rt,%ra,%rb", ALU2_3 (KSLRA16u), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"sra.u", "=rt,%ra,%rb", ALU2_3 (SRAu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"srai16", "=rt,%ra,%ib4u", ALU2_3 (SRAI16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"srai16.u", "=rt,%ra,%ib4u", ALU2_3 (SRAI16u), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"srli16", "=rt,%ra,%ib4u", ALU2_3 (SRLI16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"srli16.u", "=rt,%ra,%ib4u", ALU2_3 (SRLI16u), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"slli16", "=rt,%ra,%ib4u", ALU2_3 (SLLI16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kslli16", "=rt,%ra,%ib4u", ALU2_3 (KSLLI16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"kslli", "=rt,%ra,%ib5u", ALU2_3 (KSLLI), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"srai.u", "=rt,%ra,%ib5u", ALU2_3 (SRAIu), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"cmpeq16", "=rt,%ra,%rb", ALU2_3 (CMPEQ16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"scmplt16", "=rt,%ra,%rb", ALU2_3 (SCMPLT16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"scmple16", "=rt,%ra,%rb", ALU2_3 (SCMPLE16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smin16", "=rt,%ra,%rb", ALU2_3 (SMIN16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"cmpeq8", "=rt,%ra,%rb", ALU2_3 (CMPEQ8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"scmplt8", "=rt,%ra,%rb", ALU2_3 (SCMPLT8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"scmple8", "=rt,%ra,%rb", ALU2_3 (SCMPLE8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"smin8", "=rt,%ra,%rb", ALU2_3 (SMIN8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ucmplt16", "=rt,%ra,%rb", ALU2_3 (UCMPLT16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ucmple16", "=rt,%ra,%rb", ALU2_3 (UCMPLE16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"umin16", "=rt,%ra,%rb", ALU2_3 (UMIN16), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ucmplt8", "=rt,%ra,%rb", ALU2_3 (UCMPLT8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"ucmple8", "=rt,%ra,%rb", ALU2_3 (UCMPLE8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"umin8", "=rt,%ra,%rb", ALU2_3 (UMIN8), 4, ATTR (DSP_ISAEXT), 0, NULL, 0, NULL}, + {"mtlbi", "%i16s1", BR2 (SOP0) | N32_BIT (20), 4, ATTR (ZOL) | ATTR (DSP_ISAEXT) | ATTR (PCREL), 0, NULL, 0, NULL}, + {"mtlei", "%i16s1", BR2 (SOP0) | N32_BIT (21), 4, ATTR (ZOL) | ATTR (DSP_ISAEXT) | ATTR (PCREL), 0, NULL, 0, NULL}, {NULL, NULL, 0, 0, 0, 0, NULL, 0, NULL}, }; @@ -986,6 +1167,9 @@ const keyword_t keyword_usr[] = {"d0.hi", USRIDX (0, 1), 0}, {"d1.lo", USRIDX (0, 2), 0}, {"d1.hi", USRIDX (0, 3), 0}, + {"lb", USRIDX (0, 25), 0}, + {"le", USRIDX (0, 26), 0}, + {"lc", USRIDX (0, 27), 0}, {"itb", USRIDX (0, 28), 0}, {"ifc_lp", USRIDX (0, 29), 0}, {"pc", USRIDX (0, 31), 0}, @@ -1040,6 +1224,7 @@ const keyword_t keyword_sr[] = {"ipc", SRIDX (1, 5, 1), 0}, {"ir9", SRIDX (1, 5, 1), 0}, {"p_ipc", SRIDX (1, 5, 2), 0}, {"ir10", SRIDX (1, 5, 2), 0}, {"oipc", SRIDX (1, 5, 3), 0}, {"ir11", SRIDX (1, 5, 3), 0}, + {"dipc", SRIDX (1, 5, 3), 0}, {"p_p0", SRIDX (1, 6, 2), 0}, {"ir12", SRIDX (1, 6, 2), 0}, {"p_p1", SRIDX (1, 7, 2), 0}, {"ir13", SRIDX (1, 7, 2), 0}, {"int_mask", SRIDX (1, 8, 0), 0}, {"ir14", SRIDX (1, 8, 0), 0}, @@ -1059,6 +1244,11 @@ const keyword_t keyword_sr[] = {"int_pri2", SRIDX (1, 11, 1), 0}, {"ir28", SRIDX (1, 11, 1), 0}, {"int_trigger", SRIDX (1, 9, 4), 0}, {"ir29", SRIDX (1, 9, 4), 0}, {"int_gpr_push_dis", SRIDX(1, 1, 3), 0}, {"ir30", SRIDX (1, 1, 3), 0}, + {"int_mask3", SRIDX(1, 8, 2), 0}, {"ir31", SRIDX (1, 8, 2), 0}, + {"int_pend3", SRIDX(1, 9, 2), 0}, {"ir32", SRIDX (1, 9, 2), 0}, + {"int_pri3", SRIDX(1, 11, 2), 0}, {"ir33", SRIDX (1, 11, 2), 0}, + {"int_pri4", SRIDX(1, 11, 3), 0}, {"ir34", SRIDX (1, 11, 3), 0}, + {"int_trigger2", SRIDX(1, 9, 5), 0}, {"ir35", SRIDX (1, 9, 5), 0}, {"mmu_ctl", SRIDX (2, 0, 0), 0}, {"mr0", SRIDX (2, 0, 0), 0}, {"l1_pptb", SRIDX (2, 1, 0), 0}, {"mr1", SRIDX (2, 1, 0), 0}, @@ -1077,9 +1267,12 @@ const keyword_t keyword_sr[] = {"pfmc1", SRIDX (4, 0, 1), 0}, {"pfr1", SRIDX (4, 0, 1), 0}, {"pfmc2", SRIDX (4, 0, 2), 0}, {"pfr2", SRIDX (4, 0, 2), 0}, {"pfm_ctl", SRIDX (4, 1, 0), 0}, {"pfr3", SRIDX (4, 1, 0), 0}, + {"pft_ctl", SRIDX (4, 2, 0), 0}, {"pfr4", SRIDX (4, 2, 0), 0}, {"hsp_ctl", SRIDX (4, 6, 0), 0}, {"hspr0", SRIDX (4, 6, 0), 0}, {"sp_bound", SRIDX (4, 6, 1), 0}, {"hspr1", SRIDX (4, 6, 1), 0}, {"sp_bound_priv", SRIDX (4, 6, 2), 0},{"hspr2", SRIDX (4, 6, 2), 0}, + {"sp_base", SRIDX (4, 6, 3), 0}, {"hspr3", SRIDX (4, 6, 3), 0}, + {"sp_base_priv", SRIDX (4, 6, 4), 0}, {"hspr4", SRIDX (4, 6, 4), 0}, {"dma_cfg", SRIDX (5, 0, 0), 0}, {"dmar0", SRIDX (5, 0, 0), 0}, {"dma_gcsw", SRIDX (5, 1, 0), 0}, {"dmar1", SRIDX (5, 1, 0), 0}, @@ -1102,51 +1295,51 @@ const keyword_t keyword_sr[] = {"secur0", SRIDX (6, 0, 0), 0}, {"sfcr", SRIDX (6, 0, 0), 0}, {"secur1", SRIDX (6, 1, 0), 0}, {"sign", SRIDX (6, 1, 0), 0}, - {"secur2", SRIDX (6, 1, 1), 0}, {"isign", SRIDX (6, 1, 1), 0}, - {"secur3", SRIDX (6, 1, 2), 0}, {"p_isign", SRIDX (6, 1, 2), 0}, + {"secur2", SRIDX (6, 1, 1), 0}, {"isign", SRIDX (6, 1, 1), 0}, + {"secur3", SRIDX (6, 1, 2), 0}, {"p_isign", SRIDX (6, 1, 2), 0}, {"prusr_acc_ctl", SRIDX (4, 4, 0), 0}, {"fucpr", SRIDX (4, 5, 0), 0}, {"fucop_ctl", SRIDX (4, 5, 0), 0}, {"bpc0", SRIDX (3, 0, 0), 0}, {"dr0", SRIDX (3, 0, 0), 0}, - {"bpc1", SRIDX (3, 0, 1), 0}, {"dr1", SRIDX (3, 0, 1), 0}, - {"bpc2", SRIDX (3, 0, 2), 0}, {"dr2", SRIDX (3, 0, 2), 0}, - {"bpc3", SRIDX (3, 0, 3), 0}, {"dr3", SRIDX (3, 0, 3), 0}, - {"bpc4", SRIDX (3, 0, 4), 0}, {"dr4", SRIDX (3, 0, 4), 0}, - {"bpc5", SRIDX (3, 0, 5), 0}, {"dr5", SRIDX (3, 0, 5), 0}, - {"bpc6", SRIDX (3, 0, 6), 0}, {"dr6", SRIDX (3, 0, 6), 0}, - {"bpc7", SRIDX (3, 0, 7), 0}, {"dr7", SRIDX (3, 0, 7), 0}, - {"bpa0", SRIDX (3, 1, 0), 0}, {"dr8", SRIDX (3, 1, 0), 0}, - {"bpa1", SRIDX (3, 1, 1), 0}, {"dr9", SRIDX (3, 1, 1), 0}, - {"bpa2", SRIDX (3, 1, 2), 0}, {"dr10", SRIDX (3, 1, 2), 0}, - {"bpa3", SRIDX (3, 1, 3), 0}, {"dr11", SRIDX (3, 1, 3), 0}, - {"bpa4", SRIDX (3, 1, 4), 0}, {"dr12", SRIDX (3, 1, 4), 0}, - {"bpa5", SRIDX (3, 1, 5), 0}, {"dr13", SRIDX (3, 1, 5), 0}, - {"bpa6", SRIDX (3, 1, 6), 0}, {"dr14", SRIDX (3, 1, 6), 0}, - {"bpa7", SRIDX (3, 1, 7), 0}, {"dr15", SRIDX (3, 1, 7), 0}, - {"bpam0", SRIDX (3, 2, 0), 0}, {"dr16", SRIDX (3, 2, 0), 0}, - {"bpam1", SRIDX (3, 2, 1), 0}, {"dr17", SRIDX (3, 2, 1), 0}, - {"bpam2", SRIDX (3, 2, 2), 0}, {"dr18", SRIDX (3, 2, 2), 0}, - {"bpam3", SRIDX (3, 2, 3), 0}, {"dr19", SRIDX (3, 2, 3), 0}, - {"bpam4", SRIDX (3, 2, 4), 0}, {"dr20", SRIDX (3, 2, 4), 0}, - {"bpam5", SRIDX (3, 2, 5), 0}, {"dr21", SRIDX (3, 2, 5), 0}, - {"bpam6", SRIDX (3, 2, 6), 0}, {"dr22", SRIDX (3, 2, 6), 0}, - {"bpam7", SRIDX (3, 2, 7), 0}, {"dr23", SRIDX (3, 2, 7), 0}, - {"bpv0", SRIDX (3, 3, 0), 0}, {"dr24", SRIDX (3, 3, 0), 0}, - {"bpv1", SRIDX (3, 3, 1), 0}, {"dr25", SRIDX (3, 3, 1), 0}, - {"bpv2", SRIDX (3, 3, 2), 0}, {"dr26", SRIDX (3, 3, 2), 0}, - {"bpv3", SRIDX (3, 3, 3), 0}, {"dr27", SRIDX (3, 3, 3), 0}, - {"bpv4", SRIDX (3, 3, 4), 0}, {"dr28", SRIDX (3, 3, 4), 0}, - {"bpv5", SRIDX (3, 3, 5), 0}, {"dr29", SRIDX (3, 3, 5), 0}, - {"bpv6", SRIDX (3, 3, 6), 0}, {"dr30", SRIDX (3, 3, 6), 0}, - {"bpv7", SRIDX (3, 3, 7), 0}, {"dr31", SRIDX (3, 3, 7), 0}, - {"bpcid0", SRIDX (3, 4, 0), 0}, {"dr32", SRIDX (3, 4, 0), 0}, - {"bpcid1", SRIDX (3, 4, 1), 0}, {"dr33", SRIDX (3, 4, 1), 0}, - {"bpcid2", SRIDX (3, 4, 2), 0}, {"dr34", SRIDX (3, 4, 2), 0}, - {"bpcid3", SRIDX (3, 4, 3), 0}, {"dr35", SRIDX (3, 4, 3), 0}, - {"bpcid4", SRIDX (3, 4, 4), 0}, {"dr36", SRIDX (3, 4, 4), 0}, - {"bpcid5", SRIDX (3, 4, 5), 0}, {"dr37", SRIDX (3, 4, 5), 0}, - {"bpcid6", SRIDX (3, 4, 6), 0}, {"dr38", SRIDX (3, 4, 6), 0}, + {"bpc1", SRIDX (3, 0, 1), 0}, {"dr5", SRIDX (3, 0, 1), 0}, + {"bpc2", SRIDX (3, 0, 2), 0}, {"dr10", SRIDX (3, 0, 2), 0}, + {"bpc3", SRIDX (3, 0, 3), 0}, {"dr15", SRIDX (3, 0, 3), 0}, + {"bpc4", SRIDX (3, 0, 4), 0}, {"dr20", SRIDX (3, 0, 4), 0}, + {"bpc5", SRIDX (3, 0, 5), 0}, {"dr25", SRIDX (3, 0, 5), 0}, + {"bpc6", SRIDX (3, 0, 6), 0}, {"dr30", SRIDX (3, 0, 6), 0}, + {"bpc7", SRIDX (3, 0, 7), 0}, {"dr35", SRIDX (3, 0, 7), 0}, + {"bpa0", SRIDX (3, 1, 0), 0}, {"dr1", SRIDX (3, 1, 0), 0}, + {"bpa1", SRIDX (3, 1, 1), 0}, {"dr6", SRIDX (3, 1, 1), 0}, + {"bpa2", SRIDX (3, 1, 2), 0}, {"dr11", SRIDX (3, 1, 2), 0}, + {"bpa3", SRIDX (3, 1, 3), 0}, {"dr16", SRIDX (3, 1, 3), 0}, + {"bpa4", SRIDX (3, 1, 4), 0}, {"dr21", SRIDX (3, 1, 4), 0}, + {"bpa5", SRIDX (3, 1, 5), 0}, {"dr26", SRIDX (3, 1, 5), 0}, + {"bpa6", SRIDX (3, 1, 6), 0}, {"dr31", SRIDX (3, 1, 6), 0}, + {"bpa7", SRIDX (3, 1, 7), 0}, {"dr36", SRIDX (3, 1, 7), 0}, + {"bpam0", SRIDX (3, 2, 0), 0}, {"dr2", SRIDX (3, 2, 0), 0}, + {"bpam1", SRIDX (3, 2, 1), 0}, {"dr7", SRIDX (3, 2, 1), 0}, + {"bpam2", SRIDX (3, 2, 2), 0}, {"dr12", SRIDX (3, 2, 2), 0}, + {"bpam3", SRIDX (3, 2, 3), 0}, {"dr17", SRIDX (3, 2, 3), 0}, + {"bpam4", SRIDX (3, 2, 4), 0}, {"dr22", SRIDX (3, 2, 4), 0}, + {"bpam5", SRIDX (3, 2, 5), 0}, {"dr27", SRIDX (3, 2, 5), 0}, + {"bpam6", SRIDX (3, 2, 6), 0}, {"dr32", SRIDX (3, 2, 6), 0}, + {"bpam7", SRIDX (3, 2, 7), 0}, {"dr37", SRIDX (3, 2, 7), 0}, + {"bpv0", SRIDX (3, 3, 0), 0}, {"dr3", SRIDX (3, 3, 0), 0}, + {"bpv1", SRIDX (3, 3, 1), 0}, {"dr8", SRIDX (3, 3, 1), 0}, + {"bpv2", SRIDX (3, 3, 2), 0}, {"dr13", SRIDX (3, 3, 2), 0}, + {"bpv3", SRIDX (3, 3, 3), 0}, {"dr18", SRIDX (3, 3, 3), 0}, + {"bpv4", SRIDX (3, 3, 4), 0}, {"dr23", SRIDX (3, 3, 4), 0}, + {"bpv5", SRIDX (3, 3, 5), 0}, {"dr28", SRIDX (3, 3, 5), 0}, + {"bpv6", SRIDX (3, 3, 6), 0}, {"dr33", SRIDX (3, 3, 6), 0}, + {"bpv7", SRIDX (3, 3, 7), 0}, {"dr38", SRIDX (3, 3, 7), 0}, + {"bpcid0", SRIDX (3, 4, 0), 0}, {"dr4", SRIDX (3, 4, 0), 0}, + {"bpcid1", SRIDX (3, 4, 1), 0}, {"dr9", SRIDX (3, 4, 1), 0}, + {"bpcid2", SRIDX (3, 4, 2), 0}, {"dr14", SRIDX (3, 4, 2), 0}, + {"bpcid3", SRIDX (3, 4, 3), 0}, {"dr19", SRIDX (3, 4, 3), 0}, + {"bpcid4", SRIDX (3, 4, 4), 0}, {"dr24", SRIDX (3, 4, 4), 0}, + {"bpcid5", SRIDX (3, 4, 5), 0}, {"dr29", SRIDX (3, 4, 5), 0}, + {"bpcid6", SRIDX (3, 4, 6), 0}, {"dr34", SRIDX (3, 4, 6), 0}, {"bpcid7", SRIDX (3, 4, 7), 0}, {"dr39", SRIDX (3, 4, 7), 0}, {"edm_cfg", SRIDX (3, 5, 0), 0}, {"dr40", SRIDX (3, 5, 0), 0}, {"edmsw", SRIDX (3, 6, 0), 0}, {"dr41", SRIDX (3, 6, 0), 0}, @@ -1360,6 +1553,14 @@ const keyword_t keyword_aridxi[] = {NULL, 0, 0} }; +const keyword_t keyword_aridxi_mx[] = +{ + {"m1", 9, 0}, {"m2", 10, 0}, {"m3",11, 0}, + {"m5",13, 0}, {"m6",14, 0}, {"m7",15, 0}, + {NULL, 0, 0} +}; + + const keyword_t *keywords[_HW_LAST] = { keyword_gpr, keyword_usr, keyword_dxr, keyword_sr, keyword_fsr, @@ -1370,15 +1571,21 @@ const keyword_t *keywords[_HW_LAST] = keyword_cctl_lv, keyword_tlbop_st, keyword_standby_st, keyword_msync_st, keyword_im5_i, keyword_im5_m, - keyword_accumulator, keyword_aridx, keyword_aridx2, keyword_aridxi + keyword_accumulator, keyword_aridx, keyword_aridx2, + keyword_aridxi, keyword_aridxi_mx }; + +const keyword_t **nds32_keyword_table[NDS32_CORE_COUNT]; +static unsigned int nds32_keyword_count_table[NDS32_CORE_COUNT]; +const field_t *nds32_field_table[NDS32_CORE_COUNT]; +opcode_t *nds32_opcode_table[NDS32_CORE_COUNT]; /* Hash table for syntax lex. */ static htab_t field_htab; /* Hash table for opcodes. */ static htab_t opcode_htab; /* Hash table for hardware resources. */ -static htab_t hw_ktabs[_HW_LAST]; +static htab_t *hw_ktabs; static hashval_t htab_hash_hash (const void *p) @@ -1396,44 +1603,198 @@ htab_hash_eq (const void *p, const void *q) return strcmp (name, h->name) == 0; } + -/* Build a hash table for array BASE. Each element is in size of SIZE, - and it's first element is a pointer to the key of string. - It stops inserting elements until reach an NULL key. */ +/* These functions parse "share library file name" specified for ACE. */ -static htab_t -build_hash_table (const void *base, size_t size) +static int +nds32_parse_ace (const char *str, unsigned id) { - htab_t htab; - hashval_t hash; - const char *p; + void *obj, *dlc = dlopen (str, RTLD_NOW | RTLD_LOCAL); + char *err; - htab = htab_create_alloc (128, htab_hash_hash, htab_hash_eq, - NULL, xcalloc, free); + if (dlc == NULL) + err = (char*) dlerror (); + else + { + obj = dlsym (dlc, "keyword_count"); + err = (char*) dlerror (); + if (err == NULL) + { + nds32_keyword_count_table[id] = *(unsigned int*) obj; + if (nds32_keyword_count_table[id] != 0) + { + nds32_keyword_table[id] = + (const keyword_t**) dlsym (dlc, "keywords"); + err = (char*) dlerror (); + } + if (err == NULL) + { + nds32_field_table[id] = + (const field_t*) dlsym (dlc, "nds32_ace_field"); + err = (char*) dlerror (); + } + if (err == NULL) + { + nds32_opcode_table[id] = + (opcode_t*) dlsym (dlc, "nds32_ace_opcode"); + err = (char*) dlerror (); + } + + if (err == NULL) + { + if (id != NDS32_ACE) + { + opcode_t *opc = nds32_opcode_table[id]; + unsigned cpid = id - NDS32_COP0; + unsigned matched = 0; + + /* Check whether the coprocessor ID encoded matches. */ + /* If not, coprocessor ID is fixed for flexibitlity. */ + if (N32_OP6 (opc->value) == N32_OP6_COP) + { + if (__GF (opc->value, 4, 2) == cpid) + matched = 1; + } + else + { + if (__GF (opc->value, 13, 2) == cpid) + matched = 1; + } + if (!matched) + { + for (; opc->opcode != NULL; opc++) + { + if (N32_OP6 (opc->value) == N32_OP6_COP) + opc->value = (opc->value >> 6) | __MF(cpid, 4, 2) + | (opc->value & 0xf); + else + opc->value = (opc->value >> 15) | __MF(cpid, 13, 2) + | (opc->value & 0x1fff); + } + } + } + + return 1; + } + } + } + + printf("%s\n", err); + return 0; +} + +int +nds32_parse_udi (const char *str) +{ + return nds32_parse_ace (str, NDS32_ACE); +} - p = base; - while (1) +int +nds32_parse_cop0 (const char *str) +{ + return nds32_parse_ace (str, NDS32_COP0); +} + +int +nds32_parse_cop1 (const char *str) +{ + return nds32_parse_ace (str, NDS32_COP1); +} + +int +nds32_parse_cop2 (const char *str) +{ + return nds32_parse_ace (str, NDS32_COP2); +} + +int +nds32_parse_cop3 (const char *str) +{ + return nds32_parse_ace (str, NDS32_COP3); +} + +static void +build_operand_hash_table (void) +{ + unsigned k; + + field_htab = htab_create_alloc (128, htab_hash_hash, htab_hash_eq, + NULL, xcalloc, free); + + for (k = 0; k < NDS32_CORE_COUNT; k++) { - struct nds32_hash_entry **slot; - struct nds32_hash_entry *h; + const field_t *fld; - h = (struct nds32_hash_entry *) p; + fld = nds32_field_table[k]; + if (fld == NULL) + continue; - if (h->name == NULL) - break; + /* Add op-codes. */ + while (fld->name != NULL) + { + hashval_t hash; + const field_t **slot; - hash = htab_hash_string (h->name); - slot = (struct nds32_hash_entry **) - htab_find_slot_with_hash (htab, h->name, hash, INSERT); + hash = htab_hash_string (fld->name); + slot = (const field_t **) + htab_find_slot_with_hash (field_htab, fld->name, hash, INSERT); - assert (slot != NULL && *slot == NULL); + assert (slot != NULL && *slot == NULL); + *slot = fld++; + } + } +} - *slot = h; +static void +build_keyword_hash_table (void) +{ + unsigned int i, j, k, n; - p = p + size; + /* Count total keyword tables. */ + for (n = 0, i = 0; i < NDS32_CORE_COUNT; i++) + { + n += nds32_keyword_count_table[i]; } - return htab; + /* Allocate space. */ + hw_ktabs = (htab_t *) malloc (n * sizeof (struct htab)); + for (i = 0; i < n; i++) + { + hw_ktabs[i] = htab_create_alloc (128, htab_hash_hash, htab_hash_eq, + NULL, xcalloc, free); + } + + for (n = 0, k = 0; k < NDS32_CORE_COUNT; k++, n += j) + { + const keyword_t **kwd; + + if ((j = nds32_keyword_count_table[k]) == 0) + continue; + + /* Add keywords. */ + kwd = nds32_keyword_table[k]; + for (i = 0; i < j; i++) + { + htab_t htab; + const keyword_t *kw; + + kw = kwd[i]; + htab = hw_ktabs[n + i]; + while (kw->name != NULL) + { + hashval_t hash; + const keyword_t **slot; + + hash = htab_hash_string (kw->name); + slot = (const keyword_t **) + htab_find_slot_with_hash (htab, kw->name, hash, INSERT); + + assert (slot != NULL && *slot == NULL); + *slot = kw++; + } + } + } } /* Build the syntax for a given opcode OPC. It parses the string @@ -1458,36 +1819,31 @@ build_opcode_syntax (struct nds32_opcode *opc) return; opc->syntax = xmalloc (MAX_LEX_NUM * sizeof (lex_t)); + memset (opc->syntax, 0, MAX_LEX_NUM * sizeof (lex_t)); str = opc->instruction; plex = opc->syntax; while (*str) { - int fidx; + int i, k, fidx; switch (*str) { - case '%': - *plex = SYN_INPUT; - break; - case '=': - *plex = SYN_OUTPUT; - break; - case '&': - *plex = SYN_INPUT | SYN_OUTPUT; - break; + case '%': *plex = SYN_INPUT; break; + case '=': *plex = SYN_OUTPUT; break; + case '&': *plex = SYN_INPUT | SYN_OUTPUT; break; case '{': - *plex++ = SYN_LOPT; - opt++; - str++; - continue; + *plex++ = SYN_LOPT; + opt++; + str++; + continue; case '}': - *plex++ = SYN_ROPT; - str++; - continue; + *plex++ = SYN_ROPT; + str++; + continue; default: - *plex++ = *str++; - continue; + *plex++ = *str++; + continue; } str++; @@ -1501,14 +1857,25 @@ build_opcode_syntax (struct nds32_opcode *opc) hash = htab_hash_string (odstr); fd = (field_t *) htab_find_with_hash (field_htab, odstr, hash); - fidx = fd - operand_fields; - if (fd == NULL) { fprintf (stderr, "Internal error: Unknown operand, %s\n", str); } - assert (fd && fidx >= 0 && fidx < (int) ARRAY_SIZE (operand_fields)); - *plex |= LEX_SET_FIELD (fidx); + + /* We are not sure how these tables are organized. */ + /* Thus, the minimal index should be the right one. */ + for (fidx = 256, k = 0, i = 0; i < NDS32_CORE_COUNT; i++) + { + int tmp; + + tmp = fd - nds32_field_table[i]; + if (tmp >= 0 && tmp < fidx) + { + fidx = tmp; + k = i; + } + } + *plex |= LEX_SET_FIELD (k, fidx); str += len; plex++; @@ -1519,44 +1886,37 @@ build_opcode_syntax (struct nds32_opcode *opc) return; } -/* Initialize the assembler. It must be called before assembling. */ - -void -nds32_asm_init (nds32_asm_desc_t *pdesc, int flags) +static void +build_opcode_hash_table (void) { - int i; - hashval_t hash; + unsigned k; - pdesc->flags = flags; - pdesc->mach = flags & NASM_OPEN_ARCH_MASK; - - /* Build keyword tables. */ - field_htab = build_hash_table (operand_fields, - sizeof (operand_fields[0])); - - for (i = 0; i < _HW_LAST; i++) - hw_ktabs[i] = build_hash_table (keywords[i], sizeof (keyword_t)); - - /* Build opcode table. */ - opcode_htab = htab_create_alloc (128, htab_hash_hash, htab_hash_eq, + opcode_htab = htab_create_alloc (512, htab_hash_hash, htab_hash_eq, NULL, xcalloc, free); - for (i = 0; i < (int) ARRAY_SIZE (nds32_opcodes); i++) + for (k = 0; k < NDS32_CORE_COUNT; k++) { - struct nds32_opcode **slot; - struct nds32_opcode *opc; + opcode_t *opc; + + opc = nds32_opcode_table[k]; + if (opc == NULL) + continue; - opc = &nds32_opcodes[i]; - if ((opc->opcode != NULL) && (opc->instruction != NULL)) + /* Add op-codes. */ + while ((opc->opcode != NULL) && (opc->instruction != NULL)) { + hashval_t hash; + opcode_t **slot; + hash = htab_hash_string (opc->opcode); - slot = (struct nds32_opcode **) - htab_find_slot_with_hash (opcode_htab, opc->opcode, hash, INSERT); + slot = (opcode_t **) + htab_find_slot_with_hash (opcode_htab, opc->opcode, hash, + INSERT); #define NDS32_PREINIT_SYNTAX #if defined (NDS32_PREINIT_SYNTAX) - /* Initial SYNTAX when build opcode table, so bug in syntax can be - found when initialized rather than used. */ + /* Initial SYNTAX when build opcode table, so bug in syntax + can be found when initialized rather than used. */ build_opcode_syntax (opc); #endif @@ -1567,16 +1927,44 @@ nds32_asm_init (nds32_asm_desc_t *pdesc, int flags) } else { + opcode_t *ptr; + /* Already exists. Append to the list. */ - opc = *slot; - while (opc->next) - opc = opc->next; - opc->next = &nds32_opcodes[i]; + ptr = *slot; + while (ptr->next) + ptr = ptr->next; + ptr->next = opc; + opc->next = NULL; } + opc++; } } } +/* Initialize the assembler. It must be called before assembling. */ + +void +nds32_asm_init (nds32_asm_desc_t *pdesc, int flags) +{ + pdesc->flags = flags; + pdesc->mach = flags & NASM_OPEN_ARCH_MASK; + + /* Setup main core. */ + nds32_keyword_table[NDS32_MAIN_CORE] = &keywords[0]; + nds32_keyword_count_table[NDS32_MAIN_CORE] = _HW_LAST; + nds32_opcode_table[NDS32_MAIN_CORE] = &nds32_opcodes[0]; + nds32_field_table[NDS32_MAIN_CORE] = &operand_fields[0]; + + /* Build operand hash table. */ + build_operand_hash_table (); + + /* Build keyword hash tables. */ + build_keyword_hash_table (); + + /* Build op-code hash table. */ + build_opcode_hash_table (); +} + /* Parse the input and store operand keyword string in ODSTR. This function is only used for parsing keywords, HW_INT/HW_UINT are parsed parse_operand callback handler. */ @@ -1617,6 +2005,11 @@ parse_re (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, if (__GF (pinsn->insn, 20, 5) > (unsigned int) k->value) return NASM_ERR_OPERAND; + /* Register not allowed in reduced register. */ + if ((pdesc->flags & NASM_OPEN_REDUCED_REG) + && (k->attr & ATTR (RDREG)) == 0) + return NASM_ERR_REG_REDUCED; + *value = k->value; *pstr = end; return NASM_R_CONST; @@ -1644,6 +2037,11 @@ parse_re2 (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, if (k == NULL) return NASM_ERR_OPERAND; + /* Register not allowed in reduced register. */ + if ((pdesc->flags & NASM_OPEN_REDUCED_REG) + && (k->attr & ATTR (RDREG)) == 0) + return NASM_ERR_REG_REDUCED; + if (k->value == 6) *value = 0; else if (k->value == 8) @@ -1699,7 +2097,8 @@ static int aext_im5_ip = 0; static int aext_im6_ip = 0; /* Parse the operand of audio ext. */ static int -parse_aext_reg (char **pstr, int *value, int hw_res) +parse_aext_reg (struct nds32_asm_desc *pdesc, char **pstr, + int *value, int hw_res) { char *end = *pstr; char odstr[MAX_KEYWORD_LEN]; @@ -1716,20 +2115,27 @@ parse_aext_reg (char **pstr, int *value, int hw_res) if (k == NULL) return NASM_ERR_OPERAND; + if (hw_res == HW_GPR + && (pdesc->flags & NASM_OPEN_REDUCED_REG) + && (k->attr & ATTR (RDREG)) == 0) + return NASM_ERR_REG_REDUCED; + *value = k->value; *pstr = end; return NASM_R_CONST; } static int -parse_a30b20 (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, +parse_a30b20 (struct nds32_asm_desc *pdesc, struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, char **pstr, int64_t *value) { int rt_value, ret; - ret = parse_aext_reg (pstr, &rt_value, HW_GPR); + ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_GPR); + if (ret == NASM_ERR_REG_REDUCED) + return NASM_ERR_REG_REDUCED; if ((ret == NASM_ERR_OPERAND) || (rt_value > 15)) return NASM_ERR_OPERAND; @@ -1739,14 +2145,16 @@ parse_a30b20 (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, } static int -parse_rt21 (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, +parse_rt21 (struct nds32_asm_desc *pdesc, struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, char **pstr, int64_t *value) { int rt_value, ret, tmp_value, tmp1, tmp2; - ret = parse_aext_reg (pstr, &rt_value, HW_GPR); + ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_GPR); + if (ret == NASM_ERR_REG_REDUCED) + return NASM_ERR_REG_REDUCED; if ((ret == NASM_ERR_OPERAND) || (rt_value > 15)) return NASM_ERR_OPERAND; tmp1 = (aext_a30b20 & 0x08); @@ -1762,14 +2170,16 @@ parse_rt21 (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, } static int -parse_rte_start (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, +parse_rte_start (struct nds32_asm_desc *pdesc, struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, char **pstr, int64_t *value) { int rt_value, ret, tmp1, tmp2; - ret = parse_aext_reg (pstr, &rt_value, HW_GPR); + ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_GPR); + if (ret == NASM_ERR_REG_REDUCED) + return NASM_ERR_REG_REDUCED; if ((ret == NASM_ERR_OPERAND) || (rt_value > 15) || (rt_value & 0x01)) return NASM_ERR_OPERAND; @@ -1786,13 +2196,16 @@ parse_rte_start (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, } static int -parse_rte_end (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, +parse_rte_end (struct nds32_asm_desc *pdesc, struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, char **pstr, int64_t *value) { int rt_value, ret, tmp1, tmp2; - ret = parse_aext_reg (pstr, &rt_value, HW_GPR); + ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_GPR); + + if (ret == NASM_ERR_REG_REDUCED) + return NASM_ERR_REG_REDUCED; if ((ret == NASM_ERR_OPERAND) || (rt_value > 15) || ((rt_value & 0x01) == 0) || (rt_value != (aext_rte + 1))) @@ -1801,6 +2214,7 @@ parse_rte_end (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, tmp2 = (rt_value & 0x08); if (tmp1 != tmp2) return NASM_ERR_OPERAND; + /* Rt=CONCAT(c, t21, 0), t21:bit11-10. */ rt_value = (rt_value & 0x06) << 4; *value = rt_value; @@ -1808,16 +2222,20 @@ parse_rte_end (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, } static int -parse_rte69_start (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, +parse_rte69_start (struct nds32_asm_desc *pdesc, struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, char **pstr, int64_t *value) { int rt_value, ret; - ret = parse_aext_reg (pstr, &rt_value, HW_GPR); + ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_GPR); + + if (ret == NASM_ERR_REG_REDUCED) + return NASM_ERR_REG_REDUCED; if ((ret == NASM_ERR_OPERAND) || (rt_value & 0x01)) return NASM_ERR_OPERAND; + aext_rte = rt_value; rt_value = (rt_value >> 1); *value = rt_value; @@ -1825,17 +2243,21 @@ parse_rte69_start (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, } static int -parse_rte69_end (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, +parse_rte69_end (struct nds32_asm_desc *pdesc, struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, char **pstr, int64_t *value) { int rt_value, ret; - ret = parse_aext_reg (pstr, &rt_value, HW_GPR); + ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_GPR); + + if (ret == NASM_ERR_REG_REDUCED) + return NASM_ERR_REG_REDUCED; if ((ret == NASM_ERR_OPERAND) || ((rt_value & 0x01) == 0) || (rt_value != (aext_rte + 1))) return NASM_ERR_OPERAND; + aext_rte = rt_value; rt_value = (rt_value >> 1); *value = rt_value; @@ -1843,13 +2265,13 @@ parse_rte69_end (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, } static int -parse_im5_ip (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, +parse_im5_ip (struct nds32_asm_desc *pdesc, struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, char **pstr, int64_t *value) { int rt_value, ret, new_value; - ret = parse_aext_reg (pstr, &rt_value, HW_AEXT_IM_I); + ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_AEXT_IM_I); if (ret == NASM_ERR_OPERAND) return NASM_ERR_OPERAND; /* p = bit[4].bit[1:0], r = bit[4].bit[3:2]. */ @@ -1861,13 +2283,13 @@ parse_im5_ip (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, } static int -parse_im5_mr (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, +parse_im5_mr (struct nds32_asm_desc *pdesc, struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, char **pstr, int64_t *value) { int rt_value, ret, new_value, tmp1, tmp2; - ret = parse_aext_reg (pstr, &rt_value, HW_AEXT_IM_M); + ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_AEXT_IM_M); if (ret == NASM_ERR_OPERAND) return NASM_ERR_OPERAND; /* p = bit[4].bit[1:0], r = bit[4].bit[3:2]. */ @@ -1881,13 +2303,13 @@ parse_im5_mr (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, } static int -parse_im6_ip (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, +parse_im6_ip (struct nds32_asm_desc *pdesc, struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, char **pstr, int64_t *value) { int rt_value, ret; - ret = parse_aext_reg (pstr, &rt_value, HW_AEXT_IM_I); + ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_AEXT_IM_I); if ((ret == NASM_ERR_OPERAND) || (rt_value > 3)) return NASM_ERR_OPERAND; /* p = 0.bit[1:0]. */ @@ -1897,13 +2319,13 @@ parse_im6_ip (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, } static int -parse_im6_iq (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, +parse_im6_iq (struct nds32_asm_desc *pdesc, struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, char **pstr, int64_t *value) { int rt_value, ret; - ret = parse_aext_reg (pstr, &rt_value, HW_AEXT_IM_I); + ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_AEXT_IM_I); if ((ret == NASM_ERR_OPERAND) || (rt_value < 4)) return NASM_ERR_OPERAND; /* q = 1.bit[1:0]. */ @@ -1914,13 +2336,13 @@ parse_im6_iq (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, } static int -parse_im6_mr (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, +parse_im6_mr (struct nds32_asm_desc *pdesc, struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, char **pstr, int64_t *value) { int rt_value, ret; - ret = parse_aext_reg (pstr, &rt_value, HW_AEXT_IM_M); + ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_AEXT_IM_M); if ((ret == NASM_ERR_OPERAND) || (rt_value > 3)) return NASM_ERR_OPERAND; /* r = 0.bit[3:2]. */ @@ -1929,13 +2351,13 @@ parse_im6_mr (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, } static int -parse_im6_ms (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, +parse_im6_ms (struct nds32_asm_desc *pdesc, struct nds32_asm_insn *pinsn ATTRIBUTE_UNUSED, char **pstr, int64_t *value) { int rt_value, ret; - ret = parse_aext_reg (pstr, &rt_value, HW_AEXT_IM_M); + ret = parse_aext_reg (pdesc, pstr, &rt_value, HW_AEXT_IM_M); if ((ret == NASM_ERR_OPERAND) || (rt_value < 4)) return NASM_ERR_OPERAND; /* s = 1.bit[5:4]. */ @@ -1952,9 +2374,9 @@ parse_operand (nds32_asm_desc_t *pdesc, nds32_asm_insn_t *pinsn, char odstr[MAX_KEYWORD_LEN]; char *end; hashval_t hash; - const field_t *fld = &LEX_GET_FIELD (syn); + const field_t *fld = &LEX_GET_FIELD (((syn >> 8) & 0xff) - 1, syn); keyword_t *k; - int64_t value; + int64_t value = 0; /* 0x100000000; Big enough to overflow. */ int r; uint64_t modifier = 0; @@ -1963,23 +2385,31 @@ parse_operand (nds32_asm_desc_t *pdesc, nds32_asm_insn_t *pinsn, if (fld->parse) { r = fld->parse (pdesc, pinsn, &end, &value); - if (r == NASM_ERR_OPERAND) + if (r == NASM_ERR_OPERAND || r == NASM_ERR_REG_REDUCED) { - pdesc->result = NASM_ERR_OPERAND; + pdesc->result = r; return 0; } goto done; } - if (fld->hw_res < _HW_LAST) + /* Check valid keyword group. */ + if (fld->hw_res < HW_INT) { + int n = 0, i; + + /* Calculate index of keyword hash table. */ + for (i = 0; i < (fld->hw_res >> 8); i++) + n += nds32_keyword_count_table[i]; + /* Parse the operand in assembly code. */ if (*end == '$') end++; end = parse_to_delimiter (end, odstr); hash = htab_hash_string (odstr); - k = htab_find_with_hash (hw_ktabs[fld->hw_res], odstr, hash); + k = htab_find_with_hash (hw_ktabs[n + (fld->hw_res & 0xff)], odstr, + hash); if (k == NULL) { @@ -2086,7 +2516,7 @@ done: { /* Sign-ext the value. */ if (((value >> 32) == 0) && (value & 0x80000000)) - value |= (int64_t) -1U << 31; + value |= (int64_t)((uint64_t) -1 << 31); /* Shift the value to positive domain. */ diff --git binutils-2.30/opcodes/nds32-asm.h binutils-2.30-nds32/opcodes/nds32-asm.h index c67e590c64..ea165833c3 100644 --- binutils-2.30/opcodes/nds32-asm.h +++ binutils-2.30-nds32/opcodes/nds32-asm.h @@ -77,6 +77,8 @@ enum NASM_ATTR_SATURATION_EXT = 0x0400000, NASM_ATTR_PCREL = 0x0800000, NASM_ATTR_GPREL = 0x1000000, + NASM_ATTR_DSP_ISAEXT = 0x2000000, + NASM_ATTR_ZOL = (1 << 26), /* Attributes for relocations. */ NASM_ATTR_HI20 = 0x10000000, @@ -84,22 +86,30 @@ enum NASM_ATTR_LO20 = 0x40000000, /* Attributes for registers. */ - NASM_ATTR_RDREG = 0x000100 + NASM_ATTR_RDREG = 0x000100, + }; +#define NDS32_CORE_COUNT 6 +#define NDS32_MAIN_CORE 0 +#define NDS32_ACE 1 +#define NDS32_COP0 2 +#define NDS32_COP1 3 +#define NDS32_COP2 4 +#define NDS32_COP3 5 + enum { - /* This is a field (operand) of just a separator char. */ - SYN_FIELD = 0x100, - /* This operand is used for input or output. (define or use) */ - SYN_INPUT = 0x1000, - SYN_OUTPUT = 0x2000, - SYN_LOPT = 0x4000, - SYN_ROPT = 0x8000, - - /* Hardware resources. */ - HW_GPR = 0, + SYN_INPUT = 0x10000, + SYN_OUTPUT = 0x20000, + SYN_LOPT = 0x40000, + SYN_ROPT = 0x80000, + + /* Hardware resources: + Current set up allows up to 256 resources for each class + defined above. */ + HW_GPR = NDS32_MAIN_CORE << 8, HW_USR, HW_DXR, HW_SR, @@ -128,14 +138,20 @@ enum HW_AEXT_ARIDX, HW_AEXT_ARIDX2, HW_AEXT_ARIDXI, + HW_AEXT_ARIDXI_MX, _HW_LAST, /* TODO: Maybe we should add a new type to distinguish address and - const int. Only the former allows symbols and relocations. */ - HW_INT, + const int. Only the former allows symbols and relocations. */ + HW_ACE_BASE = NDS32_ACE << 8, + HW_COP0_BASE = NDS32_COP0 << 8, + HW_COP1_BASE = NDS32_COP1 << 8, + HW_COP2_BASE = NDS32_COP2 << 8, + HW_COP3_BASE = NDS32_COP3 << 8, + HW_INT = 0x1000, HW_UINT }; -/* for audio-extension. */ +/* For audio-extension. */ enum { N32_AEXT_AMADD = 0, @@ -159,7 +175,7 @@ enum N32_AEXT_AMBBS, N32_AEXT_AMBTS, N32_AEXT_AMTBS, - N32_AEXT_AMTTS + N32_AEXT_AMTTS, }; /* Macro for instruction attribute. */ @@ -212,7 +228,7 @@ typedef struct nds32_opcode struct nds32_opcode *next; /* TODO: Extra constrains and verification. - For example, `mov55 $sp, $sp' is not allowed in v3. */ + For example, `mov55 $sp, $sp' is not allowed in v3. */ } opcode_t; typedef struct nds32_asm_insn @@ -266,6 +282,11 @@ typedef struct nds32_field extern void nds32_assemble (nds32_asm_desc_t *, nds32_asm_insn_t *, char *); extern void nds32_asm_init (nds32_asm_desc_t *, int); +extern int nds32_parse_udi (const char *); +extern int nds32_parse_cop0 (const char *); +extern int nds32_parse_cop1 (const char *); +extern int nds32_parse_cop2 (const char *); +extern int nds32_parse_cop3 (const char *); #define OP6(op6) (N32_OP6_ ## op6 << 25) @@ -277,6 +298,9 @@ extern void nds32_asm_init (nds32_asm_desc_t *, int); #define SIMD(sub) (OP6 (SIMD) | N32_SIMD_ ## sub) #define ALU1(sub) (OP6 (ALU1) | N32_ALU1_ ## sub) #define ALU2(sub) (OP6 (ALU2) | N32_ALU2_ ## sub) +#define ALU2_1(sub) (OP6 (ALU2) | N32_BIT (6) | N32_ALU2_ ## sub) +#define ALU2_2(sub) (OP6 (ALU2) | N32_BIT (7) | N32_ALU2_ ## sub) +#define ALU2_3(sub) (OP6 (ALU2) | N32_BIT (6) | N32_BIT (7) | N32_ALU2_ ## sub) #define MISC(sub) (OP6 (MISC) | N32_MISC_ ## sub) #define MEM(sub) (OP6 (MEM) | N32_MEM_ ## sub) #define FPU_RA_IMMBI(sub) (OP6 (sub) | N32_BIT (12)) diff --git binutils-2.30/opcodes/nds32-dis.c binutils-2.30-nds32/opcodes/nds32-dis.c index 418019ae87..bb5106f954 100644 --- binutils-2.30/opcodes/nds32-dis.c +++ binutils-2.30-nds32/opcodes/nds32-dis.c @@ -35,92 +35,71 @@ /* Get fields macro define. */ #define MASK_OP(insn, mask) ((insn) & (0x3f << 25 | (mask))) +/* For mapping symbol. */ +enum map_type +{ + MAP_DATA0, + MAP_DATA1, + MAP_DATA2, + MAP_DATA3, + MAP_DATA4, + MAP_CODE, +}; + +struct nds32_private_data +{ + /* Whether any mapping symbols are present in the provided symbol + table. -1 if we do not know yet, otherwise 0 or 1. */ + int has_mapping_symbols; + + /* Track the last type (although this doesn't seem to be useful). */ + enum map_type last_mapping_type; + + /* Tracking symbol table information. */ + int last_symbol_index; + bfd_vma last_addr; +}; /* Default text to print if an instruction isn't recognized. */ #define UNKNOWN_INSN_MSG _("*unknown*") + #define NDS32_PARSE_INSN16 0x01 #define NDS32_PARSE_INSN32 0x02 -#define NDS32_PARSE_EX9IT 0x04 -#define NDS32_PARSE_EX9TAB 0x08 +static void print_insn16 (bfd_vma, disassemble_info *, + uint32_t, uint32_t); +static void print_insn32 (bfd_vma, disassemble_info *, uint32_t, + uint32_t); +static uint32_t nds32_mask_opcode (uint32_t); +static void nds32_special_opcode (uint32_t, struct nds32_opcode **); +static int get_mapping_symbol_type (struct disassemble_info *, int, + enum map_type *); +static int is_mapping_symbol (struct disassemble_info *, int, + enum map_type *); + +extern const field_t *nds32_field_table[NDS32_CORE_COUNT]; +extern opcode_t *nds32_opcode_table[NDS32_CORE_COUNT]; +extern keyword_t **nds32_keyword_table[NDS32_CORE_COUNT]; extern struct nds32_opcode nds32_opcodes[]; extern const field_t operand_fields[]; -extern const keyword_t *keywords[]; +extern keyword_t *keywords[]; extern const keyword_t keyword_gpr[]; -static void print_insn16 (bfd_vma pc, disassemble_info *info, - uint32_t insn, uint32_t parse_mode); -static void print_insn32 (bfd_vma pc, disassemble_info *info, uint32_t insn, - uint32_t parse_mode); -static uint32_t nds32_mask_opcode (uint32_t); -static void nds32_special_opcode (uint32_t, struct nds32_opcode **); -/* define in objdump.c. */ +/* Defined in objdump.c. */ struct objdump_disasm_info { - bfd * abfd; - asection * sec; - bfd_boolean require_sec; - arelent ** dynrelbuf; - long dynrelcount; + bfd *abfd; + asection *sec; + bfd_boolean require_sec; + arelent **dynrelbuf; + long dynrelcount; disassembler_ftype disassemble_fn; - arelent * reloc; + arelent *reloc; }; -/* file_ptr ex9_filepos=NULL;. */ -bfd_byte *ex9_data = NULL; -int ex9_ready = 0, ex9_base_offset = 0; - /* Hash function for disassemble. */ static htab_t opcode_htab; -static void -nds32_ex9_info (bfd_vma pc ATTRIBUTE_UNUSED, - disassemble_info *info, uint32_t ex9_index) -{ - uint32_t insn; - static asymbol *itb = NULL; - bfd_byte buffer[4]; - long unsigned int isec_vma; - - /* Lookup itb symbol. */ - if (!itb) - { - int i; - - for (i = 0; i < info->symtab_size; i++) - if (bfd_asymbol_name (info->symtab[i]) - && (strcmp (bfd_asymbol_name (info->symtab[i]), "$_ITB_BASE_") == 0 - || strcmp (bfd_asymbol_name (info->symtab[i]), - "_ITB_BASE_") == 0)) - { - itb = info->symtab[i]; - break; - } - - /* Lookup it only once, in case _ITB_BASE_ doesn't exist at all. */ - if (itb == NULL) - itb = (void *) -1; - } - - if (itb == (void *) -1) - return; - - isec_vma = itb->section->vma; - isec_vma = itb->section->vma - bfd_asymbol_value (itb); - if (!itb->section || !itb->section->owner) - return; - bfd_get_section_contents (itb->section->owner, itb->section, buffer, - ex9_index * 4 - isec_vma, 4); - insn = bfd_getb32 (buffer); - /* 16-bit instructions in ex9 table. */ - if (insn & 0x80000000) - print_insn16 (pc, info, (insn & 0x0000FFFF), - NDS32_PARSE_INSN16 | NDS32_PARSE_EX9IT); - /* 32-bit instructions in ex9 table. */ - else - print_insn32 (pc, info, insn, NDS32_PARSE_INSN32 | NDS32_PARSE_EX9IT); -} - /* Find the value map register name. */ static keyword_t * @@ -155,7 +134,7 @@ nds32_parse_audio_ext (const field_t *pfd, else int_value = __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; - if (int_value < 10) + if (int_value < 0) func (stream, "#%d", int_value); else func (stream, "#0x%x", int_value); @@ -186,7 +165,7 @@ nds32_parse_audio_ext (const field_t *pfd, { new_value |= 0x04; } - /* Rt CONCAT(c, t21, t0). */ + /* Rt CONCAT(c, t21, t0). */ else if (strcmp (pfd->name, "a_rt21") == 0) { new_value = (insn & 0x00000020) >> 5; @@ -221,12 +200,33 @@ nds32_parse_audio_ext (const field_t *pfd, func (stream, "$%s", psys_reg->name); } -/* Dump instruction. If the opcode is unknown, return FALSE. */ +/* Match instruction opcode with keyword table. */ + +static field_t * +match_field (char *name) +{ + field_t *pfd; + int k; + + for (k = 0; k < NDS32_CORE_COUNT; k++) + { + pfd = (field_t *) nds32_field_table[k]; + while (1) + { + if (pfd->name == NULL) + break; + if (strcmp (name, pfd->name) == 0) + return pfd; + pfd++; + } + } + + return NULL; +} static void nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, - disassemble_info *info, uint32_t insn, - uint32_t parse_mode) + disassemble_info *info, uint32_t insn, uint32_t parse_mode) { int op = 0; fprintf_ftype func = info->fprintf_func; @@ -245,9 +245,6 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, return; } - if (parse_mode & NDS32_PARSE_EX9IT) - func (stream, " !"); - pstr_src = opc->instruction; if (*pstr_src == 0) { @@ -259,7 +256,6 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, { func (stream, "%s ", opc->opcode); } - /* NDS32_PARSE_INSN32. */ else { @@ -269,7 +265,7 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, else if (strstr (opc->instruction, "tito")) func (stream, "%s", opc->opcode); else - func (stream, "%s\t", opc->opcode); + func (stream, "%s ", opc->opcode); } while (*pstr_src) @@ -280,7 +276,7 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, case '=': case '&': pstr_src++; - /* Compare with operand_fields[].name. */ + /* Compare name with operand table entries. */ pstr_tmp = &tmp_string[0]; while (*pstr_src) { @@ -293,18 +289,9 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, *pstr_tmp++ = *pstr_src++; } *pstr_tmp = 0; + if ((pfd = match_field (&tmp_string[0])) == NULL) + return; - pfd = (const field_t *) &operand_fields[0]; - while (1) - { - if (pfd->name == NULL) - return; - else if (strcmp (&tmp_string[0], pfd->name) == 0) - break; - pfd++; - } - - /* For insn-16. */ if (parse_mode & NDS32_PARSE_INSN16) { if (pfd->hw_res == HW_GPR) @@ -331,7 +318,7 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, if (pfd->hw_res == HW_INT) int_value = N32_IMMS ((insn >> pfd->bitpos), - pfd->bitsize) << pfd->shift; + pfd->bitsize) << pfd->shift; else int_value = __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; @@ -348,12 +335,11 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, int_value = 0 - (128 - int_value); func (stream, "#%d", int_value); } - /* beqz38/bnez38/beqs38/bnes38/j8/beqzs8/bnezs8/ifcall9. */ + /* beqz38/bnez38/beqs38/bnes38/j8/beqzs8/bnezs8. */ else if ((opc->value == 0xc000) || (opc->value == 0xc800) || (opc->value == 0xd000) || (opc->value == 0xd800) || (opc->value == 0xd500) || (opc->value == 0xe800) - || (opc->value == 0xe900) - || (opc->value == 0xf800)) + || (opc->value == 0xe900)) { info->print_address_func (int_value + pc, info); } @@ -365,28 +351,17 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, func (stream, "~$%s", keyword_gpr[push25gpr].name); func (stream, ", $fp, $gp, $lp}"); } - /* ex9.it. */ - else if ((opc->value == 0xdd40) || (opc->value == 0xea00)) - { - func (stream, "#%d", int_value); - nds32_ex9_info (pc, info, int_value); - } else if (pfd->hw_res == HW_INT) { - if (int_value < 10) + if (int_value < 0) func (stream, "#%d", int_value); else func (stream, "#0x%x", int_value); } - else /* if (pfd->hw_res == HW_UINT). */ - { - if (int_value < 10) - func (stream, "#%u", int_value); - else - func (stream, "#0x%x", int_value); - } + /* if(pfd->hw_res == HW_UINT). */ + else + func (stream, "#0x%x", int_value); } - } /* for audio-ext. */ else if (op == N32_OP6_AEXT) @@ -394,12 +369,13 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, nds32_parse_audio_ext (pfd, info, insn); } /* for insn-32. */ - else if (pfd->hw_res < _HW_LAST) + else if (pfd->hw_res < HW_INT) { int_value = __GF (insn, pfd->bitpos, pfd->bitsize) << pfd->shift; - psys_reg = (keyword_t*) keywords[pfd->hw_res]; + psys_reg = *(nds32_keyword_table[pfd->hw_res >> 8] + + (pfd->hw_res & 0xff)); psys_reg = nds32_find_reg_keyword (psys_reg, int_value); /* For HW_SR, dump the index when it can't @@ -444,15 +420,7 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, /* FIXME: Handle relocation. */ if (info->flags & INSN_HAS_RELOC) pc = 0; - /* Check if insn32 in ex9 table. */ - if (parse_mode & NDS32_PARSE_EX9IT) - info->print_address_func ((pc & 0xFE000000) | int_value, - info); - /* Check if decode ex9 table, PC(31,25)|Inst(23,0)<<1. */ - else if (parse_mode & NDS32_PARSE_EX9TAB) - func (stream, "PC(31,25)|#0x%x", int_value); - else - info->print_address_func (int_value + pc, info); + info->print_address_func (int_value + pc, info); } else if (op == N32_OP6_LSMW) { @@ -496,17 +464,14 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, } else if (pfd->hw_res == HW_INT) { - if (int_value < 10) + if (int_value < 0) func (stream, "#%d", int_value); else func (stream, "#0x%x", int_value); } - else /* if (pfd->hw_res == HW_UINT). */ + else /* if(pfd->hw_res == HW_UINT). */ { - if (int_value < 10) - func (stream, "#%u", int_value); - else - func (stream, "#0x%x", int_value); + func (stream, "#0x%x", int_value); } } break; @@ -516,34 +481,13 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED, pstr_src++; break; - case ',': - func (stream, ", "); - pstr_src++; - break; - - case '+': - func (stream, " + "); - pstr_src++; - break; - - case '<': - if (pstr_src[1] == '<') - { - func (stream, " << "); - pstr_src += 2; - } - else - { - func (stream, " <"); - pstr_src++; - } - break; - default: func (stream, "%c", *pstr_src++); break; - } - } + } /* switch (*pstr_src). */ + + } /* while (*pstr_src). */ + return; } /* Filter instructions with some bits must be fixed. */ @@ -571,7 +515,7 @@ nds32_filter_unknown_insn (uint32_t insn, struct nds32_opcode **opc) if (__GF (insn, 5, 5) != 0) *opc = NULL; break; - case BR2 (IFCALL): + case BR2 (SOP0): if (__GF (insn, 20, 5) != 0) *opc = NULL; break; @@ -692,6 +636,7 @@ print_insn16 (bfd_vma pc, disassemble_info *info, } break; } + opcode = insn & mask; opc = (struct nds32_opcode *) htab_find (opcode_htab, &opcode); @@ -715,6 +660,21 @@ htab_hash_eq (const void *p, const void *q) return (pinsn == qinsn); } +static uint32_t +mask_CEXT (uint32_t insn) +{ + opcode_t *opc = nds32_opcode_table[NDS32_ACE], *max_opc = NULL; + + for (; opc != NULL && opc->opcode != NULL; opc++) + { + if ((insn & opc->value) == opc->value + && (max_opc == NULL || opc->value > max_opc->value)) + max_opc = opc; + } + + return max_opc ? max_opc->value : insn; +} + /* Get the format of instruction. */ static uint32_t @@ -754,18 +714,26 @@ nds32_mask_opcode (uint32_t insn) case N32_OP6_ORI: case N32_OP6_SLTI: case N32_OP6_SLTSI: - case N32_OP6_CEXT: case N32_OP6_BITCI: return MASK_OP (insn, 0); + case N32_OP6_CEXT: + return mask_CEXT (insn); case N32_OP6_ALU2: /* FFBI */ if (__GF (insn, 0, 7) == (N32_ALU2_FFBI | N32_BIT (6))) return MASK_OP (insn, 0x7f); - else if (__GF (insn, 0, 7) == (N32_ALU2_MFUSR | N32_BIT (6)) - || __GF (insn, 0, 7) == (N32_ALU2_MTUSR | N32_BIT (6))) + else if (__GF (insn, 0, 10) == (N32_ALU2_MFUSR | N32_BIT (6)) + || __GF (insn, 0, 10) == (N32_ALU2_MTUSR | N32_BIT (6))) /* RDOV CLROV */ return MASK_OP (insn, 0xf81ff); - return MASK_OP (insn, 0x1ff); + else if (__GF (insn, 0, 10) == (N32_ALU2_ONEOP | N32_BIT (7))) + { + /* INSB */ + if (__GF (insn, 12, 3) == 4) + return MASK_OP (insn, 0x73ff); + return MASK_OP (insn, 0x7fff); + } + return MASK_OP (insn, 0x3ff); case N32_OP6_ALU1: case N32_OP6_SIMD: return MASK_OP (insn, 0x1f); @@ -794,113 +762,116 @@ nds32_mask_opcode (uint32_t insn) case N32_OP6_BR1: return MASK_OP (insn, 0x1 << 14); case N32_OP6_BR2: - return MASK_OP (insn, 0xf << 16); + if (__GF (insn, 16, 4) == 0) + return MASK_OP (insn, 0x1ff << 16); + else + return MASK_OP (insn, 0xf << 16); case N32_OP6_BR3: return MASK_OP (insn, 0x1 << 19); case N32_OP6_MISC: - switch (__GF (insn, 0, 5)) - { - case N32_MISC_MTSR: - /* SETGIE and SETEND */ - if (__GF (insn, 5, 5) == 0x1 || __GF (insn, 5, 5) == 0x2) - return MASK_OP (insn, 0x1fffff); - return MASK_OP (insn, 0x1f); - case N32_MISC_TLBOP: - if (__GF (insn, 5, 5) == 5 || __GF (insn, 5, 5) == 7) - /* PB FLUA */ - return MASK_OP (insn, 0x3ff); - return MASK_OP (insn, 0x1f); - default: - return MASK_OP (insn, 0x1f); - } + switch (__GF (insn, 0, 5)) + { + case N32_MISC_MTSR: + /* SETGIE and SETEND */ + if (__GF (insn, 5, 5) == 0x1 || __GF (insn, 5, 5) == 0x2) + return MASK_OP (insn, 0x1fffff); + return MASK_OP (insn, 0x1f); + case N32_MISC_TLBOP: + if (__GF (insn, 5, 5) == 5 || __GF (insn, 5, 5) == 7) + /* PB FLUA */ + return MASK_OP (insn, 0x3ff); + return MASK_OP (insn, 0x1f); + default: + return MASK_OP (insn, 0x1f); + } case N32_OP6_COP: - if (__GF (insn, 4, 2) == 0) - { - /* FPU */ - switch (__GF (insn, 0, 4)) - { - case 0x0: - case 0x8: - /* FS1/F2OP FD1/F2OP */ - if (__GF (insn, 6, 4) == 0xf) - return MASK_OP (insn, 0x7fff); - /* FS1 FD1 */ - return MASK_OP (insn, 0x3ff); - case 0x4: - case 0xc: - /* FS2 */ - return MASK_OP (insn, 0x3ff); - case 0x1: - case 0x9: - /* XR */ - if (__GF (insn, 6, 4) == 0xc) - return MASK_OP (insn, 0x7fff); - /* MFCP MTCP */ - return MASK_OP (insn, 0x3ff); - default: - return MASK_OP (insn, 0xff); - } - } - else if (__GF (insn, 0, 2) == 0) - return MASK_OP (insn, 0xf); - return MASK_OP (insn, 0xcf); + if (__GF (insn, 4, 2) == 0) + { + /* FPU */ + switch (__GF (insn, 0, 4)) + { + case 0x0: + case 0x8: + /* FS1/F2OP FD1/F2OP */ + if (__GF (insn, 6, 4) == 0xf) + return MASK_OP (insn, 0x7fff); + /* FS1 FD1 */ + return MASK_OP (insn, 0x3ff); + case 0x4: + case 0xc: + /* FS2 */ + return MASK_OP (insn, 0x3ff); + case 0x1: + case 0x9: + /* XR */ + if (__GF (insn, 6, 4) == 0xc) + return MASK_OP (insn, 0x7fff); + /* MFCP MTCP */ + return MASK_OP (insn, 0x3ff); + default: + return MASK_OP (insn, 0xff); + } + } + else if (__GF (insn, 0, 2) == 0) + return MASK_OP (insn, 0xf); + return MASK_OP (insn, 0xcf); case N32_OP6_AEXT: - /* AUDIO */ - switch (__GF (insn, 23, 2)) - { - case 0x0: - if (__GF (insn, 5, 4) == 0) - /* AMxxx AMAyyS AMyyS AMAWzS AMWzS */ - return MASK_OP (insn, (0x1f << 20) | 0x1ff); - else if (__GF (insn, 5, 4) == 1) - /* ALR ASR ALA ASA AUPI */ - return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); - else if (__GF (insn, 20, 3) == 0 && __GF (insn, 6, 3) == 1) - /* ALR2 */ - return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); - else if (__GF (insn, 20 ,3) == 2 && __GF (insn, 6, 3) == 1) - /* AWEXT ASATS48 */ - return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); - else if (__GF (insn, 20 ,3) == 3 && __GF (insn, 6, 3) == 1) - /* AMTAR AMTAR2 AMFAR AMFAR2 */ - return MASK_OP (insn, (0x1f << 20) | (0x1f << 5)); - else if (__GF (insn, 7, 2) == 3) - /* AMxxxSA */ - return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); - else if (__GF (insn, 6, 3) == 2) - /* AMxxxL.S */ - return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); - else - /* AmxxxL.l AmxxxL2.S AMxxxL2.L */ - return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); - case 0x1: - if (__GF (insn, 20, 3) == 0) - /* AADDL ASUBL */ - return MASK_OP (insn, (0x1f << 20) | (0x1 << 5)); - else if (__GF (insn, 20, 3) == 1) - /* AMTARI Ix AMTARI Mx */ - return MASK_OP (insn, (0x1f << 20)); - else if (__GF (insn, 6, 3) == 2) - /* AMAWzSl.S AMWzSl.S */ - return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); - else if (__GF (insn, 7, 2) == 3) - /* AMAWzSSA AMWzSSA */ - return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); - else - /* AMAWzSL.L AMAWzSL2.S AMAWzSL2.L AMWzSL.L AMWzSL.L AMWzSL2.S */ - return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); - case 0x2: - if (__GF (insn, 6, 3) == 2) - /* AMAyySl.S AMWyySl.S */ - return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); - else if (__GF (insn, 7, 2) == 3) - /* AMAWyySSA AMWyySSA */ - return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); - else - /* AMAWyySL.L AMAWyySL2.S AMAWyySL2.L AMWyySL.L AMWyySL.L AMWyySL2.S */ - return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); - } - return MASK_OP (insn, 0x1f << 20); + /* AUDIO */ + switch (__GF (insn, 23, 2)) + { + case 0x0: + if (__GF (insn, 5, 4) == 0) + /* AMxxx AMAyyS AMyyS AMAWzS AMWzS */ + return MASK_OP (insn, (0x1f << 20) | 0x1ff); + else if (__GF (insn, 5, 4) == 1) + /* ALR ASR ALA ASA AUPI */ + return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); + else if (__GF (insn, 20, 3) == 0 && __GF (insn, 6, 3) == 1) + /* ALR2 */ + return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); + else if (__GF (insn, 20 ,3) == 2 && __GF (insn, 6, 3) == 1) + /* AWEXT ASATS48 */ + return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); + else if (__GF (insn, 20 ,3) == 3 && __GF (insn, 6, 3) == 1) + /* AMTAR AMTAR2 AMFAR AMFAR2 */ + return MASK_OP (insn, (0x1f << 20) | (0x1f << 5)); + else if (__GF (insn, 7, 2) == 3) + /* AMxxxSA */ + return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); + else if (__GF (insn, 6, 3) == 2) + /* AMxxxL.S */ + return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); + else + /* AmxxxL.l AmxxxL2.S AMxxxL2.L */ + return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); + case 0x1: + if (__GF (insn, 20, 3) == 0) + /* AADDL ASUBL */ + return MASK_OP (insn, (0x1f << 20) | (0x1 << 5)); + else if (__GF (insn, 20, 3) == 1) + /* AMTARI Ix AMTARI Mx */ + return MASK_OP (insn, (0x1f << 20)); + else if (__GF (insn, 6, 3) == 2) + /* AMAWzSl.S AMWzSl.S */ + return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); + else if (__GF (insn, 7, 2) == 3) + /* AMAWzSSA AMWzSSA */ + return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); + else + /* AMAWzSL.L AMAWzSL2.S AMAWzSL2.L AMWzSL.L AMWzSL.L AMWzSL2.S */ + return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); + case 0x2: + if (__GF (insn, 6, 3) == 2) + /* AMAyySl.S AMWyySl.S */ + return MASK_OP (insn, (0x1f << 20) | (0xf << 5)); + else if (__GF (insn, 7, 2) == 3) + /* AMAWyySSA AMWyySSA */ + return MASK_OP (insn, (0x1f << 20) | (0x3 << 7)); + else + /* AMAWyySL.L AMAWyySL2.S AMAWyySL2.L AMWyySL.L AMWyySL.L AMWyySL2.S */ + return MASK_OP (insn, (0x1f << 20) | (0x7 << 6)); + } + return MASK_OP (insn, 0x1f << 20); default: return (1 << 31); } @@ -971,11 +942,6 @@ nds32_special_opcode (uint32_t insn, struct nds32_opcode **opc) break; case N32_OP6_COP: break; - case 0xea00: - /* break16 ex9 */ - if (__GF (insn, 5, 4) != 0) - string = "ex9"; - break; case 0x9200: /* nop16 */ if (__GF (insn, 0, 9) == 0) @@ -1005,46 +971,195 @@ print_insn_nds32 (bfd_vma pc, disassemble_info *info) { int status; bfd_byte buf[4]; + bfd_byte buf_data[16]; + long long given; + long long given1; uint32_t insn; - static int init = 1; - int i = 0; - struct nds32_opcode *opc; - struct nds32_opcode **slot; + int n; + int last_symbol_index = -1; + bfd_vma addr; + int is_data = FALSE; + bfd_boolean found = FALSE; + struct nds32_private_data *private_data; + unsigned int size = 16; + enum map_type mapping_type = MAP_CODE; + + if (info->private_data == NULL) + { + /* Note: remain lifecycle throughout whole execution. */ + static struct nds32_private_data private; + private.has_mapping_symbols = -1; /* unknown yet. */ + private.last_symbol_index = -1; + private.last_addr = 0; + info->private_data = &private; + } + private_data = info->private_data; - if (init) + if (info->symtab_size != 0) { - /* Build opcode table. */ - opcode_htab = htab_create_alloc (1024, htab_hash_hash, htab_hash_eq, - NULL, xcalloc, free); + int start; + if (pc == 0) + start = 0; + else + { + start = info->symtab_pos; + if (start < private_data->last_symbol_index) + start = private_data->last_symbol_index; + } - while (nds32_opcodes[i].opcode != NULL) + if (0 > start) + start = 0; + + if (private_data->has_mapping_symbols != 0 + && ((strncmp (".text", info->section->name, 5) == 0))) { - opc = &nds32_opcodes[i]; - slot = - (struct nds32_opcode **) htab_find_slot (opcode_htab, &opc->value, - INSERT); - if (*slot == NULL) + for (n = start; n < info->symtab_size; n++) { - /* This is the new one. */ - *slot = opc; + addr = bfd_asymbol_value (info->symtab[n]); + if (addr > pc) + break; + if (get_mapping_symbol_type (info, n, &mapping_type)) + { + last_symbol_index = n; + found = TRUE; + } } - else + + if (found) + private_data->has_mapping_symbols = 1; + else if (!found && private_data->has_mapping_symbols == -1) + { + /* Make sure there are no any mapping symbol. */ + for (n = 0; n < info->symtab_size; n++) + { + if (is_mapping_symbol (info, n, &mapping_type)) + { + private_data->has_mapping_symbols = -1; + break; + } + } + if (private_data->has_mapping_symbols == -1) + private_data->has_mapping_symbols = 0; + + } + + private_data->last_symbol_index = last_symbol_index; + private_data->last_mapping_type = mapping_type; + is_data = (private_data->last_mapping_type == MAP_DATA0 + || private_data->last_mapping_type == MAP_DATA1 + || private_data->last_mapping_type == MAP_DATA2 + || private_data->last_mapping_type == MAP_DATA3 + || private_data->last_mapping_type == MAP_DATA4); + } + } + + /* Wonder data or instruction. */ + if (is_data) + { + unsigned int i1; + + /* fix corner case: there is no next mapping symbol, + * let mapping type decides size */ + if (last_symbol_index + 1 >= info->symtab_size) + { + if (mapping_type == MAP_DATA0) + size = 1; + if (mapping_type == MAP_DATA1) + size = 2; + if (mapping_type == MAP_DATA2) + size = 4; + if (mapping_type == MAP_DATA3) + size = 8; + if (mapping_type == MAP_DATA4) + size = 16; + } + for (n = last_symbol_index + 1; n < info->symtab_size; n++) + { + addr = bfd_asymbol_value (info->symtab[n]); + + enum map_type fake_mapping_type; + if (get_mapping_symbol_type (info, n, &fake_mapping_type)) + { + if (addr > pc + && ((info->section == NULL) + || (info->section == info->symtab[n]->section))) + { + if (addr - pc < size) + { + size = addr - pc; + break; + } + } + } + } + + + if (size == 3) + size = (pc & 1) ? 1 : 2; + + + /* Read bytes from BFD. */ + info->read_memory_func (pc, (bfd_byte *) buf_data, size, info); + given = 0; + given1 = 0; + /* Start assembling data. */ + /* Little endian of data. */ + if (info->endian == BFD_ENDIAN_LITTLE) + { + for (i1 = size - 1;; i1--) { - /* Already exists. Append to the list. */ - opc = *slot; - while (opc->next) - opc = opc->next; - opc->next = &nds32_opcodes[i]; + if (i1 >= 8) + given1 = buf_data[i1] | (given1 << 8); + else + given = buf_data[i1] | (given << 8); + if (i1 == 0) + break; } - i++; } - init = 0; + else + { + /* Big endian of data. */ + for (i1 = 0; i1 < size; i1++) { + if (i1 <= 7) + given = buf_data[i1] | (given << 8); + else + given1 = buf_data[i1] | (given1 << 8); + } + } + + info->bytes_per_line = 4; + + if (size == 16) + { + info->fprintf_func (info->stream, ".qword\t0x%016llx%016llx", + given, given1); + } + else if (size == 8) + { + info->fprintf_func (info->stream, ".dword\t0x%016llx", given); + } + else if (size == 4) + { + info->fprintf_func (info->stream, ".word\t0x%08llx", given); + } + else if (size == 2) /* short */ + { + if (mapping_type == MAP_DATA0) + info->fprintf_func (info->stream, ".byte\t0x%02llx", given & 0xFF); + else + info->fprintf_func (info->stream, ".short\t0x%04llx", given); + } + else + { /* byte */ + info->fprintf_func (info->stream, ".byte\t0x%02llx", given); + } + return size; } status = info->read_memory_func (pc, (bfd_byte *) buf, 4, info); if (status) { - /* for the last 16-bit instruction. */ + /* For the last 16-bit instruction. */ status = info->read_memory_func (pc, (bfd_byte *) buf, 2, info); if (status) { @@ -1052,17 +1167,10 @@ print_insn_nds32 (bfd_vma pc, disassemble_info *info) return -1; } } - insn = bfd_getb32 (buf); /* 16-bit instruction. */ if (insn & 0x80000000) { - if (info->section && strstr (info->section->name, ".ex9.itable") != NULL) - { - print_insn16 (pc, info, (insn & 0x0000FFFF), - NDS32_PARSE_INSN16 | NDS32_PARSE_EX9TAB); - return 4; - } print_insn16 (pc, info, (insn >> 16), NDS32_PARSE_INSN16); return 2; } @@ -1070,11 +1178,206 @@ print_insn_nds32 (bfd_vma pc, disassemble_info *info) /* 32-bit instructions. */ else { - if (info->section - && strstr (info->section->name, ".ex9.itable") != NULL) - print_insn32 (pc, info, insn, NDS32_PARSE_INSN32 | NDS32_PARSE_EX9TAB); - else - print_insn32 (pc, info, insn, NDS32_PARSE_INSN32); + print_insn32 (pc, info, insn, NDS32_PARSE_INSN32); return 4; } } + +/* Ignore disassembling unnecessary name. */ + +static bfd_boolean +nds32_symbol_is_valid (asymbol *sym, + struct disassemble_info *info ATTRIBUTE_UNUSED) +{ + const char *name; + + if (sym == NULL) + return FALSE; + + name = bfd_asymbol_name (sym); + + /* Mapping symbol is invalid. */ + if (name[0] == '$') + return FALSE; + return TRUE; +} + +static void +nds32_add_opcode_hash_table (unsigned indx) +{ + opcode_t *opc; + + opc = nds32_opcode_table[indx]; + if (opc == NULL) + return; + + while (opc->opcode != NULL) + { + opcode_t **slot; + + slot = (opcode_t **) htab_find_slot (opcode_htab, &opc->value, INSERT); + if (*slot == NULL) + { + /* This is the new one. */ + *slot = opc; + } + else + { + opcode_t *tmp; + + /* Already exists. Append to the list. */ + tmp = *slot; + while (tmp->next) + tmp = tmp->next; + tmp->next = opc; + opc->next = NULL; + } + opc++; + } +} + +void +disassemble_init_nds32 (struct disassemble_info *info) +{ + static unsigned init_done = 0; + const char *ptr; + unsigned k; + + /* Set up symbol checking function. */ + info->symbol_is_valid = nds32_symbol_is_valid; + + /* Only need to initialize once: */ + /* High level will call this function for every object file. */ + /* For example, when disassemble all members of a library. */ + if (init_done) + return; + + /* Setup main core. */ + nds32_keyword_table[NDS32_MAIN_CORE] = &keywords[0]; + nds32_opcode_table[NDS32_MAIN_CORE] = &nds32_opcodes[0]; + nds32_field_table[NDS32_MAIN_CORE] = &operand_fields[0]; + + /* Process command line options. */ + ptr = info->disassembler_options; + if (ptr != NULL) + { + const char *start, *end; + do + { + char name[256]; + + /* Get one option. */ + start = strchr(ptr, '='); + end = strchr(ptr, ','); + if (start == NULL) + fprintf (stderr, "Unknown nds32 disassembler option: %s\n", ptr); + else + { + start++; + if (end == NULL) + strcpy (name, start); + else + strncpy (name, start, end - start); + + /* Parse and process the option. */ + if (strncmp (ptr, "ace=", 4) == 0) + nds32_parse_udi (name); + else if (strncmp (ptr, "cop0=", 5) == 0) + nds32_parse_cop0 (name); + else if (strncmp (ptr, "cop1=", 5) == 0) + nds32_parse_cop1 (name); + else if (strncmp (ptr, "cop2=", 5) == 0) + nds32_parse_cop2 (name); + else if (strncmp (ptr, "cop3=", 5) == 0) + nds32_parse_cop3 (name); + else + fprintf (stderr, "Unknown nds32 disassembler option: %s\n", + ptr); + + if (end == NULL) + break; + ptr = end + 1; + } + } while (1); + } + + /* Build opcode table. */ + opcode_htab = htab_create_alloc (1024, htab_hash_hash, htab_hash_eq, NULL, + xcalloc, free); + + for (k = 0; k < NDS32_CORE_COUNT; k++) + { + /* Add op-codes. */ + nds32_add_opcode_hash_table (k); + } + + init_done = 1; +} + +static int +is_mapping_symbol (struct disassemble_info *info, int n, + enum map_type *map_type) +{ + const char *name = NULL; + + /* Get symbol name. */ + name = bfd_asymbol_name (info->symtab[n]); + + if (name[1] == 'c') + { + *map_type = MAP_CODE; + return TRUE; + } + else if (name[1] == 'd' && name[2] == '0') + { + *map_type = MAP_DATA0; + return TRUE; + } + else if (name[1] == 'd' && name[2] == '1') + { + *map_type = MAP_DATA1; + return TRUE; + } + else if (name[1] == 'd' && name[2] == '2') + { + *map_type = MAP_DATA2; + return TRUE; + } + else if (name[1] == 'd' && name[2] == '3') + { + *map_type = MAP_DATA3; + return TRUE; + } + else if (name[1] == 'd' && name[2] == '4') + { + *map_type = MAP_DATA4; + return TRUE; + } + + return FALSE; +} + +static int +get_mapping_symbol_type (struct disassemble_info *info, int n, + enum map_type *map_type) +{ + /* If the symbol is in a different section, ignore it. */ + if (info->section != NULL && info->section != info->symtab[n]->section) + return FALSE; + + return is_mapping_symbol (info, n, map_type); +} + +void +print_nds32_disassembler_options (FILE *stream) +{ + fprintf (stream, _("\n\ +The following Andes specific disassembler options are supported for use with\n\ +the -M switch:\n")); + + fprintf (stream, " ace= Support user defined instruction extension\n"); + fprintf (stream, " cop0= Support coprocessor 0 extension\n"); + fprintf (stream, " cop1= Support coprocessor 1 extension\n"); + fprintf (stream, " cop2= Support coprocessor 2 extension\n"); + fprintf (stream, " cop3= Support coprocessor 3 extension\n\n"); +}