Andes Technology has good news for you, we plan to update the nds32 port of binutils...
authorNick Clifton <nickc@redhat.com>
Thu, 20 Sep 2018 12:27:31 +0000 (13:27 +0100)
committerNick Clifton <nickc@redhat.com>
Thu, 20 Sep 2018 12:32:58 +0000 (13:32 +0100)
We have not only removed all unsupported and obsolete code, but also supported lost of new features,
including better link-time relaxations and TLS implementations. Besides, the files generated by the
newly assembler and linker usually get higher performance and more optimized code size.

ld * emultempl/nds32elf.em (hyper_relax): New variable.
(nds32_elf_create_output_section_statements):
the parameters of bfd_elf32_nds32_set_target_option
(PARSE_AND_LIST_PROLOGUE, PARSE_AND_LIST_OPTIONS,
PARSE_AND_LIST_ARGS_CASES): Add new option --mhyper-relax.
* emultempl/nds32elf.em (nds32_elf_after_open): Updated.
* emultempl/nds32elf.em (tls_desc_trampoline): New variable.
* (nds32_elf_create_output_section_statements): Updated.
* (nds32_elf_after_parse): Disable relaxations when PIC is enable.
* (PARSE_AND_LIST_PROLOGUE, PARSE_AND_LIST_OPTIONS,
PARSE_AND_LIST_ARGS_CASES): Add new option --m[no-]tlsdesc-trampoline.

include * elf/nds32.h: Remove the unused target features.
* dis-asm.h (disassemble_init_nds32): Declared.
* elf/nds32.h (E_NDS32_NULL): Removed.
(E_NDS32_HAS_DSP_INST, E_NDS32_HAS_ZOL): New.
* opcode/nds32.h: Ident.
(N32_SUB6, INSN_LW): New macros.
(enum n32_opcodes): Updated.
* elf/nds32.h: Doc fixes.
* elf/nds32.h: Add R_NDS32_LSI.
* elf/nds32.h: Add new relocations for TLS.

gas  * config/tc-nds32.c: Remove the unused target features.
(nds32_relax_relocs, md_pseudo_table, nds32_elf_record_fixup_exp,
nds32_set_elf_flags_by_insn, nds32_insert_relax_entry,
nds32_apply_fix): Likewise.
(nds32_no_ex9_begin): Removed.
* config/tc-nds32.c (add_mapping_symbol_for_align,
make_mapping_symbol, add_mapping_symbol): New functions.
* config/tc-nds32.h (enum mstate): New.
(nds32_segment_info_type): Likewise.
* configure.ac (--enable-dsp-ext, --enable-zol-ext): New options.
* config.in: Regenerated.
* configure: Regenerated.
* config/tc-nds32.c (nds32_dx_regs):
Set the value according to the configuration.
(nds32_perf_ext, nds32_perf_ext2, nds32_string_ext, nds32_audio_ext):
Likewise.
(nds32_dsp_ext): New variable. Set the value according to the
configuration.
(nds32_zol_ext): Likewise.
(asm_desc, nds32_pseudo_opcode_table): Make them static.
(nds32_set_elf_flags_by_insn): Updated.
(nds32_check_insn_available): Updated.
(nds32_str_tolower): New function.
* config/tc-nds32.c (relax_table): Updated.
(md_begin): Updated.
(md_assemble): Use XNEW macro to allocate space for `insn.info',
and then remember to free it.
(md_section_align): Cast (-1) to ValueT.
(nds32_get_align): Cast (~0U) to addressT.
(nds32_relax_branch_instructions): Updated.
(md_convert_frag): Add new local variable `final_r_type'.
(invalid_prev_frag): Add new bfd_boolean parameter `relax'.
All callers changed.
* config/tc-nds32.c (struct nds32_relocs_pattern): Add `insn' field.
(struct nds32_hint_map): Add `option_list' field.
(struct suffix_name, suffix_table): Remove the unused `pic' field.
(do_pseudo_b, do_pseudo_bal): Remove the suffix checking.
(do_pseudo_la_internal, do_pseudo_pushpopm): Indent.
(relax_hint_bias, relax_hint_id_current): New static variables.
(reset_bias, relax_hint_begin): New variables.
(nds_itoa): New function.
(CLEAN_REG, GET_OPCODE): New macros.
(struct relax_hint_id): New.
(nds32_relax_hint): For .relax_hint directive, we can use `begin'
and `end' to mark the relax pattern without giving exactly id number.
(nds32_elf_append_relax_relocs): Handle the case that the .relax_hint
directives are attached to pseudo instruction.
(nds32_elf_save_pseudo_pattern): Change the second parameter from
instruction's opcode to byte code.
(nds32_elf_build_relax_relation): Add new bfd_boolean parameter
`pseudo_hint'.
(nds32_lookup_pseudo_opcode): Fix the overflow issue.
(enum nds32_insn_type): Add N32_RELAX_ALU1 and N32_RELAX_16BIT.
(nds32_elf_record_fixup_exp, relax_ls_table, hint_map,
nds32_find_reloc_table, nds32_match_hint_insn, nds32_parse_name):
Updated.
* config/tc-nds32.h (MAX_RELAX_NUM): Extend it to 6.
(enum nds32_relax_hint_type): Merge NDS32_RELAX_HINT_LA and
NDS32_RELAX_HINT_LS into NDS32_RELAX_HINT_LALS. Add
NDS32_RELAX_HINT_LA_PLT, NDS32_RELAX_HINT_LA_GOT and
NDS32_RELAX_HINT_LA_GOTOFF.
* config/tc-nds32.h (relax_ls_table): Add floating load/store
to gp relax pattern.
(hint_map, nds32_find_reloc_table): Likewise.
* configure.ac: Define NDS32_LINUX_TOOLCHAIN.
* configure: Regenerated.
* config.in: Regenerated.
* config/tc-nds32.h (enum nds32_ramp): Updated.
(enum nds32_relax_hint_type): Likewise.
* config/tc-nds32.c: Include "errno.h" and "limits.h".
(relax_ls_table): Add TLS relax patterns.
(nds32_elf_append_relax_relocs): Attach BFD_RELOC_NDS32_GROUP on
each instructions of TLS patterns.
(nds32_elf_record_fixup_exp): Updated.
(nds32_apply_fix): Likewise.
(suffix_table): Add TLSDESC suffix.

binutils* testsuite/binutils-all/objcopy.exp: Set the unsupported reloc number
from 215 to 255 for NDS32.

bfd * elf32-nds32.c (nds32_elf_relax_loadstore):
Remove the unused target features.
(bfd_elf32_nds32_set_target_option): Remove the unused parameters.
(nds32_elf_relax_piclo12, nds32_elf_relax_letlslo12,
nds32_elf_relax_letlsadd, nds32_elf_relax_letlsls,
nds32_elf_relax_pltgot_suff, nds32_elf_relax_got_suff
nds32_elf_relax_gotoff_suff, calculate_plt_memory_address,
calculate_plt_offset, calculate_got_memory_address,
nds32_elf_check_dup_relocs): Removed.
All callers changed.
* elf32-nds32.h: Remove the unused macros and defines.
(elf_nds32_link_hash_table): Remove the unused variable.
(bfd_elf32_nds32_set_target_option): Update prototype.
(nds32_elf_ex9_init): Removed.
* elf32-nds32.c (nds32_convert_32_to_16): Updated.
* elf32-nds32.c (HOWTO2, HOWTO3): Define new HOWTO macros
to initialize array nds32_elf_howto_table in any order
without lots of EMPTY_HOWTO.
(nds32_reloc_map): Updated.
* reloc.c: Add BFD_RELOC_NDS32_LSI.
* bfd-in2.h: Regenerated.
* bfd/libbfd.h: Regenerated.
* elf32-nds32.c (nds32_elf_relax_howto_table): Add R_NDS32_LSI.
(nds32_reloc_map): Likewise.
(nds32_elf_relax_flsi): New function.
(nds32_elf_relax_section): Support floating load/store relaxation.
* elf32-nds32.c (NDS32_GUARD_SEC_P, elf32_nds32_local_gp_offset):
New macro.
(struct elf_nds32_link_hash_entry): New `offset_to_gp' field.
(struct elf_nds32_obj_tdata): New `offset_to_gp' and `hdr_size' fields.
(elf32_nds32_allocate_local_sym_info, nds32_elf_relax_guard,
nds32_elf_is_target_special_symbol, nds32_elf_maybe_function_sym):
New functions.
(nds32_info_to_howto_rel): Add BFD_ASSERT.
(bfd_elf32_bfd_reloc_type_table_lookup, nds32_elf_link_hash_newfunc,
nds32_elf_link_hash_table_create, nds32_elf_relocate_section,
nds32_elf_relax_loadstore, nds32_elf_relax_lo12, nds32_relax_adjust_label,
bfd_elf32_nds32_set_target_option, nds32_fag_mark_relax): Updated.
(nds32_elf_final_sda_base): Improve it to find the better gp value.
(insert_nds32_elf_blank): Must consider `len' when inserting blanks.
* elf32-nds32.h (bfd_elf32_nds32_set_target_option): Update prototype.
(struct elf_nds32_link_hash_table): Add new variable `hyper_relax'.
* elf32-nds32.c (elf32_nds32_allocate_dynrelocs): New function.
(create_got_section): Likewise.
(allocate_dynrelocs, nds32_elf_size_dynamic_sections,
nds32_elf_relocate_section, nds32_elf_finish_dynamic_symbol): Updated.
(nds32_elf_check_relocs): Fix the issue that the shared library may
has TEXTREL entry in the dynamic section.
(nds32_elf_create_dynamic_sections): Enable to call readonly_dynrelocs
since the TEXTREL issue is fixed in the nds32_elf_check_relocs.
(nds32_elf_finish_dynamic_sections): Update and add DT_RELASZ
dynamic entry.
(calculate_offset): Remove the unused parameter `pic_ext_target' and
related codes.
All callers changed.
(elf_backend_dtrel_excludes_plt): Disable it temporarily since it
will cause some errors for our test cases.
* elf32-nds32.c (nds32_elf_merge_private_bfd_data): Allow to link the
generic object.
* reloc.c: Add TLS relocations.
* libbfd.h: Regenerated.
* bfd-in2.h: Regenerated.
* elf32-nds32.h (struct section_id_list_t): New.
(elf32_nds32_lookup_section_id, elf32_nds32_check_relax_group,
elf32_nds32_unify_relax_group, nds32_elf_unify_tls_model):
New prototypes.
(elf32_nds32_compute_jump_table_size, elf32_nds32_local_tlsdesc_gotent):
New macro.
(nds32_insertion_sort, bfd_elf32_nds32_set_target_option,
elf_nds32_link_hash_table): Updated.
* elf32-nds32.c (enum elf_nds32_tls_type): New.
(struct elf32_nds32_relax_group_t, struct relax_group_list_t): New.
(elf32_nds32_add_dynreloc, patch_tls_desc_to_ie, get_tls_type,
fls, ones32, list_insert, list_insert_sibling, dump_chain,
elf32_nds32_check_relax_group, elf32_nds32_lookup_section_id,
elf32_nds32_unify_relax_group, nds32_elf_unify_tls_model): New functions.
(elf_nds32_obj_tdata): Add new fields.
(elf32_nds32_relax_group_ptr, nds32_elf_local_tlsdesc_gotent): New macros.
(nds32_elf_howto_table): Add TLS relocations.
(nds32_reloc_map): Likewise.
(nds32_elf_copy_indirect_symbol, nds32_elf_size_dynamic_sections,
nds32_elf_finish_dynamic_symbol, elf32_nds32_allocate_local_sym_info,
nds32_elf_relocate_section, bfd_elf32_nds32_set_target_option,
nds32_elf_check_relocs, allocate_dynrelocs): Updated.
(nds32_elf_relax_section): Call nds32_elf_unify_tls_model.
(dtpoff_base): Rename it to `gottpof' and then update it.

opcodes * nds32-asm.c (operand_fields): Remove the unused fields.
(nds32_opcodes): Remove the unused instructions.
* nds32-dis.c (nds32_ex9_info): Removed.
(nds32_parse_opcode): Updated.
(print_insn_nds32): Likewise.
* nds32-asm.c (config.h, stdlib.h, string.h): New includes.
(LEX_SET_FIELD, LEX_GET_FIELD): Update defines.
(nds32_asm_init, build_operand_hash_table, build_keyword_hash_table,
build_opcode_hash_table): New functions.
(nds32_keyword_table, nds32_keyword_count_table, nds32_field_table,
nds32_opcode_table): New.
(hw_ktabs): Declare it to a pointer rather than an array.
(build_hash_table): Removed.
* nds32-asm.h (enum): Add SYN_INPUT, SYN_OUTPUT, SYN_LOPT,
SYN_ROPT and upadte HW_GPR and HW_INT.
* nds32-dis.c (keywords): Remove const.
(match_field): New function.
(nds32_parse_opcode): Updated.
* disassemble.c (disassemble_init_for_target):
Add disassemble_init_nds32.
* nds32-dis.c (eum map_type): New.
(nds32_private_data): Likewise.
(get_mapping_symbol_type, is_mapping_symbol, nds32_symbol_is_valid,
nds32_add_opcode_hash_table, disassemble_init_nds32): New functions.
(print_insn_nds32): Updated.
* nds32-asm.c (parse_aext_reg): Add new parameter.
(parse_re, parse_re2, parse_aext_reg): Only reduced registers
are allowed to use.
All callers changed.
* nds32-asm.c (keyword_usr, keyword_sr): Updated.
(operand_fields): Add new fields.
(nds32_opcodes): Add new instructions.
(keyword_aridxi_mx): New keyword.
* nds32-asm.h (enum): Add NASM_ATTR_DSP_ISAEXT, HW_AEXT_ARIDXI_MX
and NASM_ATTR_ZOL.
(ALU2_1, ALU2_2, ALU2_3): New macros.
* nds32-dis.c (nds32_filter_unknown_insn): Updated.

58 files changed:
bfd/ChangeLog
bfd/bfd-in2.h
bfd/elf32-nds32.c
bfd/elf32-nds32.h
bfd/libbfd.h
bfd/reloc.c
binutils/ChangeLog
binutils/testsuite/binutils-all/group-5.d
binutils/testsuite/binutils-all/objcopy.exp
binutils/testsuite/binutils-all/strip-2.d
binutils/testsuite/binutils-all/strip-5.d
binutils/testsuite/binutils-all/strip-7.d
binutils/testsuite/binutils-all/strip-9.d
gas/ChangeLog
gas/config.in
gas/config/tc-nds32.c
gas/config/tc-nds32.h
gas/configure
gas/configure.ac
gas/testsuite/gas/all/gas.exp
gas/testsuite/gas/elf/group0b.d
gas/testsuite/gas/elf/group1b.d
gas/testsuite/gas/elf/group3.d
gas/testsuite/gas/elf/groupautob.d
gas/testsuite/gas/elf/section12a.d
gas/testsuite/gas/nds32/br-1.d
gas/testsuite/gas/nds32/br-2.d
gas/testsuite/gas/nds32/ji-jr.d
include/ChangeLog
include/dis-asm.h
include/elf/nds32.h
include/opcode/nds32.h
ld/ChangeLog
ld/emultempl/nds32elf.em
ld/testsuite/ld-elf/group10.d
ld/testsuite/ld-elf/group2.d
ld/testsuite/ld-elf/group4.d
ld/testsuite/ld-elf/group5.d
ld/testsuite/ld-elf/group6.d
ld/testsuite/ld-elf/group7.d
ld/testsuite/ld-elf/group8a.d
ld/testsuite/ld-elf/group8b.d
ld/testsuite/ld-elf/group9a.d
ld/testsuite/ld-elf/group9b.d
ld/testsuite/ld-elf/linkonce2.d
ld/testsuite/ld-elf/merge.d
ld/testsuite/ld-elf/relocatable.d
ld/testsuite/ld-elfcomm/elfcomm.exp
ld/testsuite/ld-nds32/branch.d
ld/testsuite/ld-nds32/gp.d
ld/testsuite/ld-nds32/imm.d
ld/testsuite/ld-nds32/relax_jmp.d
ld/testsuite/ld-nds32/relax_load_store.d
opcodes/ChangeLog
opcodes/disassemble.c
opcodes/nds32-asm.c
opcodes/nds32-asm.h
opcodes/nds32-dis.c

index 81b9e56072b7cbc828a2c0af3f01a8d28ff8a24d..2b688ca524705ca4da78e89e6847444bed88d30b 100644 (file)
@@ -1,3 +1,92 @@
+2018-09-20  Nelson Chu <nelson.chu1990@gmail.com>
+
+       * elf32-nds32.c (nds32_elf_relax_loadstore):
+       Remove the unused target features.
+       (bfd_elf32_nds32_set_target_option): Remove the unused parameters.
+       (nds32_elf_relax_piclo12, nds32_elf_relax_letlslo12,
+       nds32_elf_relax_letlsadd, nds32_elf_relax_letlsls,
+       nds32_elf_relax_pltgot_suff, nds32_elf_relax_got_suff
+       nds32_elf_relax_gotoff_suff, calculate_plt_memory_address,
+       calculate_plt_offset, calculate_got_memory_address,
+       nds32_elf_check_dup_relocs): Removed.
+       All callers changed.
+       * elf32-nds32.h: Remove the unused macros and defines.
+       (elf_nds32_link_hash_table): Remove the unused variable.
+       (bfd_elf32_nds32_set_target_option): Update prototype.
+       (nds32_elf_ex9_init): Removed.
+       * elf32-nds32.c (nds32_convert_32_to_16): Updated.
+       * elf32-nds32.c (HOWTO2, HOWTO3): Define new HOWTO macros
+       to initialize array nds32_elf_howto_table in any order
+       without lots of EMPTY_HOWTO.
+       (nds32_reloc_map): Updated.
+       * reloc.c: Add BFD_RELOC_NDS32_LSI.
+       * bfd-in2.h: Regenerated.
+       * bfd/libbfd.h: Regenerated.
+       * elf32-nds32.c (nds32_elf_relax_howto_table): Add R_NDS32_LSI.
+       (nds32_reloc_map): Likewise.
+       (nds32_elf_relax_flsi): New function.
+       (nds32_elf_relax_section): Support floating load/store relaxation.
+       * elf32-nds32.c (NDS32_GUARD_SEC_P, elf32_nds32_local_gp_offset):
+       New macro.
+       (struct elf_nds32_link_hash_entry): New `offset_to_gp' field.
+       (struct elf_nds32_obj_tdata): New `offset_to_gp' and `hdr_size' fields.
+       (elf32_nds32_allocate_local_sym_info, nds32_elf_relax_guard,
+       nds32_elf_is_target_special_symbol, nds32_elf_maybe_function_sym):
+       New functions.
+       (nds32_info_to_howto_rel): Add BFD_ASSERT.
+       (bfd_elf32_bfd_reloc_type_table_lookup, nds32_elf_link_hash_newfunc,
+       nds32_elf_link_hash_table_create, nds32_elf_relocate_section,
+       nds32_elf_relax_loadstore, nds32_elf_relax_lo12, nds32_relax_adjust_label,
+       bfd_elf32_nds32_set_target_option, nds32_fag_mark_relax): Updated.
+       (nds32_elf_final_sda_base): Improve it to find the better gp value.
+       (insert_nds32_elf_blank): Must consider `len' when inserting blanks.
+       * elf32-nds32.h (bfd_elf32_nds32_set_target_option): Update prototype.
+       (struct elf_nds32_link_hash_table): Add new variable `hyper_relax'.
+       * elf32-nds32.c (elf32_nds32_allocate_dynrelocs): New function.
+       (create_got_section): Likewise.
+       (allocate_dynrelocs, nds32_elf_size_dynamic_sections,
+       nds32_elf_relocate_section, nds32_elf_finish_dynamic_symbol): Updated.
+       (nds32_elf_check_relocs): Fix the issue that the shared library may
+       has TEXTREL entry in the dynamic section.
+       (nds32_elf_create_dynamic_sections): Enable to call readonly_dynrelocs
+       since the TEXTREL issue is fixed in the nds32_elf_check_relocs.
+       (nds32_elf_finish_dynamic_sections): Update and add DT_RELASZ
+       dynamic entry.
+       (calculate_offset): Remove the unused parameter `pic_ext_target' and
+       related codes.
+       All callers changed.
+       (elf_backend_dtrel_excludes_plt): Disable it temporarily since it
+       will cause some errors for our test cases.
+       * elf32-nds32.c (nds32_elf_merge_private_bfd_data): Allow to link the
+       generic object.
+       * reloc.c: Add TLS relocations.
+       * libbfd.h: Regenerated.
+       * bfd-in2.h: Regenerated.
+       * elf32-nds32.h (struct section_id_list_t): New.
+       (elf32_nds32_lookup_section_id, elf32_nds32_check_relax_group,
+       elf32_nds32_unify_relax_group, nds32_elf_unify_tls_model):
+       New prototypes.
+       (elf32_nds32_compute_jump_table_size, elf32_nds32_local_tlsdesc_gotent):
+       New macro.
+       (nds32_insertion_sort, bfd_elf32_nds32_set_target_option,
+       elf_nds32_link_hash_table): Updated.
+       * elf32-nds32.c (enum elf_nds32_tls_type): New.
+       (struct elf32_nds32_relax_group_t, struct relax_group_list_t): New.
+       (elf32_nds32_add_dynreloc, patch_tls_desc_to_ie, get_tls_type,
+       fls, ones32, list_insert, list_insert_sibling, dump_chain,
+       elf32_nds32_check_relax_group, elf32_nds32_lookup_section_id,
+       elf32_nds32_unify_relax_group, nds32_elf_unify_tls_model): New functions.
+       (elf_nds32_obj_tdata): Add new fields.
+       (elf32_nds32_relax_group_ptr, nds32_elf_local_tlsdesc_gotent): New macros.
+       (nds32_elf_howto_table): Add TLS relocations.
+       (nds32_reloc_map): Likewise.
+       (nds32_elf_copy_indirect_symbol, nds32_elf_size_dynamic_sections,
+       nds32_elf_finish_dynamic_symbol, elf32_nds32_allocate_local_sym_info,
+       nds32_elf_relocate_section, bfd_elf32_nds32_set_target_option,
+       nds32_elf_check_relocs, allocate_dynrelocs): Updated.
+       (nds32_elf_relax_section): Call nds32_elf_unify_tls_model.
+       (dtpoff_base): Rename it to `gottpof' and then update it.
+
 2018-09-20  Alan Modra  <amodra@gmail.com>
 
        PR 23685
index e5f7101e52aa47e61475fff0ef0a0dbaaa96839e..59819224a6253034b3f261847bbb8242a40abe95 100644 (file)
@@ -4275,18 +4275,36 @@ 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,
+
+/* For floating load store relaxation.  */
+  BFD_RELOC_NDS32_LSI,
 
 /* This is a 9-bit reloc  */
   BFD_RELOC_V850_9_PCREL,
index ae43cdfd8af898e60612fe9256a100192295ff26..6215f2880093858b58c9c5e5a141f97e1b6705ad 100644 (file)
@@ -59,7 +59,7 @@ static bfd_reloc_status_type nds32_elf_do_9_pcrel_reloc
 
 /* Nds32 helper functions.  */
 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 int nds32_get_local_syms (bfd *, asection *ATTRIBUTE_UNUSED,
@@ -87,6 +87,10 @@ enum
    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
@@ -176,6 +180,18 @@ struct elf_nds32_pcrel_relocs_copied
   bfd_size_type count;
 };
 
+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),
+};
+
 /* Nds32 ELF linker hash entry.  */
 
 struct elf_nds32_link_hash_entry
@@ -186,10 +202,9 @@ struct elf_nds32_link_hash_entry
   struct elf_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;
 };
 
 /* Get the nds32 ELF linker hash table from a link_info structure.  */
@@ -200,12 +215,30 @@ static int check_start_export_sym = 0;
 /* 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;
+
+  /* GOTPLT entries for TLS descriptors.  */
+  bfd_vma *local_tlsdesc_gotent;
+
+  /* for R_NDS32_RELAX_GROUP handling.  */
+  elf32_nds32_relax_group_t relax_group;
+
+  unsigned int hdr_size;
+  int* offset_to_gp;
 };
 
 #define elf_nds32_tdata(bfd) \
@@ -214,8 +247,14 @@ 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_hash_entry(ent) ((struct elf_nds32_link_hash_entry *)(ent))
 
+#define elf32_nds32_relax_group_ptr(bfd) \
+  &(elf_nds32_tdata (bfd)->relax_group)
+
 static bfd_boolean
 nds32_elf_mkobject (bfd *abfd)
 {
@@ -224,1980 +263,2262 @@ nds32_elf_mkobject (bfd *abfd)
 }
 
 /* Relocations used for relocation.  */
+/* Define HOWTO2 (for relocation) and HOWTO3 (for relaxation) to
+   initialize array nds32_elf_howto_table in any order. The benefit
+   is that we can add any new relocations with any numbers and don't
+   need to fill the gap by lots of EMPTY_HOWTO. */
+#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.
      i.e. branches in the right insn slot use the address of the left insn
      slot for pc.  */
-  /* ??? It's not clear whether this should have partial_inplace set or not.
+  /* 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_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.
+  /* 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 */
+  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  */
+
+  /* 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  */
+
+  /* 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_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  */
+
+  /* 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  */
+
   /* 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_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  */
 
   /* 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  */
+
+  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  */
+
+  /* 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  */
 };
 
 /* 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_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_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  */
+  /* 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  */
+  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  */
+  /* 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),
 };
 
-\f
+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              */
+};
+
+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 ().  */
 
@@ -2260,21 +2581,24 @@ 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.  */
 
 static bfd_reloc_status_type
-nds32_elf_9_pcrel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                        void *data, asection *input_section, bfd *output_bfd,
-                        char **error_message ATTRIBUTE_UNUSED)
+nds32_elf_9_pcrel_reloc (bfd *       abfd,
+                        arelent *   reloc_entry,
+                        asymbol *   symbol,
+                        void *      data,
+                        asection *  input_section,
+                        bfd *       output_bfd,
+                        char **     error_message ATTRIBUTE_UNUSED)
 {
   /* This part is from bfd_elf_generic_reloc.  */
   if (output_bfd != (bfd *) NULL
@@ -2305,11 +2629,14 @@ nds32_elf_9_pcrel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 #define N_ONES(n) (((((bfd_vma) 1 << ((n) - 1)) - 1) << 1) | 1)
 
 static bfd_reloc_status_type
-nds32_elf_do_9_pcrel_reloc (bfd *abfd, reloc_howto_type *howto,
-                           asection *input_section, bfd_byte *data,
-                           bfd_vma offset,
-                           asection *symbol_section ATTRIBUTE_UNUSED,
-                           bfd_vma symbol_value, bfd_vma addend)
+nds32_elf_do_9_pcrel_reloc (bfd *               abfd,
+                           reloc_howto_type *  howto,
+                           asection *          input_section,
+                           bfd_byte *          data,
+                           bfd_vma             offset,
+                           asection *          symbol_section ATTRIBUTE_UNUSED,
+                           bfd_vma             symbol_value,
+                           bfd_vma             addend)
 {
   bfd_signed_vma relocation;
   unsigned short x;
@@ -2370,9 +2697,13 @@ struct nds32_hi20
 static struct nds32_hi20 *nds32_hi20_list;
 
 static bfd_reloc_status_type
-nds32_elf_hi20_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
-                     asymbol *symbol, void *data, asection *input_section,
-                     bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED)
+nds32_elf_hi20_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+                     arelent *reloc_entry,
+                     asymbol *symbol,
+                     void *data,
+                     asection *input_section,
+                     bfd *output_bfd,
+                     char **error_message ATTRIBUTE_UNUSED)
 {
   bfd_reloc_status_type ret;
   bfd_vma relocation;
@@ -2425,8 +2756,10 @@ nds32_elf_hi20_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
 
 static void
 nds32_elf_relocate_hi20 (bfd *input_bfd ATTRIBUTE_UNUSED,
-                        int type ATTRIBUTE_UNUSED, Elf_Internal_Rela *relhi,
-                        Elf_Internal_Rela *rello, bfd_byte *contents,
+                        int type ATTRIBUTE_UNUSED,
+                        Elf_Internal_Rela *relhi,
+                        Elf_Internal_Rela *rello,
+                        bfd_byte *contents,
                         bfd_vma addend)
 {
   unsigned long insn;
@@ -2693,14 +3026,15 @@ 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},
+  {BFD_RELOC_VTABLE_INHERIT, R_NDS32_RELA_GNU_VTINHERIT},
+  {BFD_RELOC_VTABLE_ENTRY, R_NDS32_RELA_GNU_VTENTRY},
+
   {BFD_RELOC_NDS32_20, R_NDS32_20_RELA},
-  {BFD_RELOC_NDS32_5, R_NDS32_5_RELA},
   {BFD_RELOC_NDS32_9_PCREL, R_NDS32_9_PCREL_RELA},
   {BFD_RELOC_NDS32_WORD_9_PCREL, R_NDS32_WORD_9_PCREL_RELA},
   {BFD_RELOC_NDS32_15_PCREL, R_NDS32_15_PCREL_RELA},
   {BFD_RELOC_NDS32_17_PCREL, R_NDS32_17_PCREL_RELA},
   {BFD_RELOC_NDS32_25_PCREL, R_NDS32_25_PCREL_RELA},
-  {BFD_RELOC_NDS32_10_UPCREL, R_NDS32_10_UPCREL_RELA},
   {BFD_RELOC_NDS32_HI20, R_NDS32_HI20_RELA},
   {BFD_RELOC_NDS32_LO12S3, R_NDS32_LO12S3_RELA},
   {BFD_RELOC_NDS32_LO12S2, R_NDS32_LO12S2_RELA},
@@ -2711,9 +3045,10 @@ static const struct nds32_reloc_map_entry nds32_reloc_map[] =
   {BFD_RELOC_NDS32_SDA15S2, R_NDS32_SDA15S2_RELA},
   {BFD_RELOC_NDS32_SDA15S1, R_NDS32_SDA15S1_RELA},
   {BFD_RELOC_NDS32_SDA15S0, R_NDS32_SDA15S0_RELA},
-  {BFD_RELOC_VTABLE_INHERIT, R_NDS32_RELA_GNU_VTINHERIT},
-  {BFD_RELOC_VTABLE_ENTRY, R_NDS32_RELA_GNU_VTENTRY},
-
+  {BFD_RELOC_NDS32_SDA16S3, R_NDS32_SDA16S3_RELA},
+  {BFD_RELOC_NDS32_SDA17S2, R_NDS32_SDA17S2_RELA},
+  {BFD_RELOC_NDS32_SDA18S1, R_NDS32_SDA18S1_RELA},
+  {BFD_RELOC_NDS32_SDA19S0, R_NDS32_SDA19S0_RELA},
   {BFD_RELOC_NDS32_GOT20, R_NDS32_GOT20},
   {BFD_RELOC_NDS32_9_PLTREL, R_NDS32_9_PLTREL},
   {BFD_RELOC_NDS32_25_PLTREL, R_NDS32_25_PLTREL},
@@ -2722,98 +3057,127 @@ static const struct nds32_reloc_map_entry nds32_reloc_map[] =
   {BFD_RELOC_NDS32_JMP_SLOT, R_NDS32_JMP_SLOT},
   {BFD_RELOC_NDS32_RELATIVE, R_NDS32_RELATIVE},
   {BFD_RELOC_NDS32_GOTOFF, R_NDS32_GOTOFF},
+  {BFD_RELOC_NDS32_GOTOFF_HI20, R_NDS32_GOTOFF_HI20},
+  {BFD_RELOC_NDS32_GOTOFF_LO12, R_NDS32_GOTOFF_LO12},
   {BFD_RELOC_NDS32_GOTPC20, R_NDS32_GOTPC20},
   {BFD_RELOC_NDS32_GOT_HI20, R_NDS32_GOT_HI20},
   {BFD_RELOC_NDS32_GOT_LO12, R_NDS32_GOT_LO12},
-  {BFD_RELOC_NDS32_GOT_LO15, R_NDS32_GOT_LO15},
-  {BFD_RELOC_NDS32_GOT_LO19, R_NDS32_GOT_LO19},
   {BFD_RELOC_NDS32_GOTPC_HI20, R_NDS32_GOTPC_HI20},
   {BFD_RELOC_NDS32_GOTPC_LO12, R_NDS32_GOTPC_LO12},
-  {BFD_RELOC_NDS32_GOTOFF_HI20, R_NDS32_GOTOFF_HI20},
-  {BFD_RELOC_NDS32_GOTOFF_LO12, R_NDS32_GOTOFF_LO12},
-  {BFD_RELOC_NDS32_GOTOFF_LO15, R_NDS32_GOTOFF_LO15},
-  {BFD_RELOC_NDS32_GOTOFF_LO19, R_NDS32_GOTOFF_LO19},
   {BFD_RELOC_NDS32_INSN16, R_NDS32_INSN16},
   {BFD_RELOC_NDS32_LABEL, R_NDS32_LABEL},
   {BFD_RELOC_NDS32_LONGCALL1, R_NDS32_LONGCALL1},
   {BFD_RELOC_NDS32_LONGCALL2, R_NDS32_LONGCALL2},
   {BFD_RELOC_NDS32_LONGCALL3, R_NDS32_LONGCALL3},
-  {BFD_RELOC_NDS32_LONGCALL4, R_NDS32_LONGCALL4},
-  {BFD_RELOC_NDS32_LONGCALL5, R_NDS32_LONGCALL5},
-  {BFD_RELOC_NDS32_LONGCALL6, R_NDS32_LONGCALL6},
   {BFD_RELOC_NDS32_LONGJUMP1, R_NDS32_LONGJUMP1},
   {BFD_RELOC_NDS32_LONGJUMP2, R_NDS32_LONGJUMP2},
   {BFD_RELOC_NDS32_LONGJUMP3, R_NDS32_LONGJUMP3},
-  {BFD_RELOC_NDS32_LONGJUMP4, R_NDS32_LONGJUMP4},
-  {BFD_RELOC_NDS32_LONGJUMP5, R_NDS32_LONGJUMP5},
-  {BFD_RELOC_NDS32_LONGJUMP6, R_NDS32_LONGJUMP6},
-  {BFD_RELOC_NDS32_LONGJUMP7, R_NDS32_LONGJUMP7},
   {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},
   {BFD_RELOC_NDS32_17_FIXED, R_NDS32_17_FIXED_RELA},
   {BFD_RELOC_NDS32_25_FIXED, R_NDS32_25_FIXED_RELA},
+  {BFD_RELOC_NDS32_LONGCALL4, R_NDS32_LONGCALL4},
+  {BFD_RELOC_NDS32_LONGCALL5, R_NDS32_LONGCALL5},
+  {BFD_RELOC_NDS32_LONGCALL6, R_NDS32_LONGCALL6},
+  {BFD_RELOC_NDS32_LONGJUMP4, R_NDS32_LONGJUMP4},
+  {BFD_RELOC_NDS32_LONGJUMP5, R_NDS32_LONGJUMP5},
+  {BFD_RELOC_NDS32_LONGJUMP6, R_NDS32_LONGJUMP6},
+  {BFD_RELOC_NDS32_LONGJUMP7, R_NDS32_LONGJUMP7},
   {BFD_RELOC_NDS32_PLTREL_HI20, R_NDS32_PLTREL_HI20},
   {BFD_RELOC_NDS32_PLTREL_LO12, R_NDS32_PLTREL_LO12},
   {BFD_RELOC_NDS32_PLT_GOTREL_HI20, R_NDS32_PLT_GOTREL_HI20},
   {BFD_RELOC_NDS32_PLT_GOTREL_LO12, R_NDS32_PLT_GOTREL_LO12},
-  {BFD_RELOC_NDS32_PLT_GOTREL_LO15, R_NDS32_PLT_GOTREL_LO15},
-  {BFD_RELOC_NDS32_PLT_GOTREL_LO19, R_NDS32_PLT_GOTREL_LO19},
-  {BFD_RELOC_NDS32_PLT_GOTREL_LO20, R_NDS32_PLT_GOTREL_LO20},
   {BFD_RELOC_NDS32_SDA12S2_DP, R_NDS32_SDA12S2_DP_RELA},
   {BFD_RELOC_NDS32_SDA12S2_SP, R_NDS32_SDA12S2_SP_RELA},
   {BFD_RELOC_NDS32_LO12S2_DP, R_NDS32_LO12S2_DP_RELA},
   {BFD_RELOC_NDS32_LO12S2_SP, R_NDS32_LO12S2_SP_RELA},
-  {BFD_RELOC_NDS32_SDA16S3, R_NDS32_SDA16S3_RELA},
-  {BFD_RELOC_NDS32_SDA17S2, R_NDS32_SDA17S2_RELA},
-  {BFD_RELOC_NDS32_SDA18S1, R_NDS32_SDA18S1_RELA},
-  {BFD_RELOC_NDS32_SDA19S0, R_NDS32_SDA19S0_RELA},
-  {BFD_RELOC_NDS32_SDA_FP7U2_RELA, R_NDS32_SDA_FP7U2_RELA},
   {BFD_RELOC_NDS32_DWARF2_OP1, R_NDS32_DWARF2_OP1_RELA},
   {BFD_RELOC_NDS32_DWARF2_OP2, R_NDS32_DWARF2_OP2_RELA},
   {BFD_RELOC_NDS32_DWARF2_LEB, R_NDS32_DWARF2_LEB_RELA},
   {BFD_RELOC_NDS32_UPDATE_TA, R_NDS32_UPDATE_TA_RELA},
-  {BFD_RELOC_NDS32_GOT_SUFF, R_NDS32_GOT_SUFF},
-  {BFD_RELOC_NDS32_GOTOFF_SUFF, R_NDS32_GOTOFF_SUFF},
+  {BFD_RELOC_NDS32_PLT_GOTREL_LO20, R_NDS32_PLT_GOTREL_LO20},
+  {BFD_RELOC_NDS32_PLT_GOTREL_LO15, R_NDS32_PLT_GOTREL_LO15},
+  {BFD_RELOC_NDS32_PLT_GOTREL_LO19, R_NDS32_PLT_GOTREL_LO19},
+  {BFD_RELOC_NDS32_GOT_LO15, R_NDS32_GOT_LO15},
+  {BFD_RELOC_NDS32_GOT_LO19, R_NDS32_GOT_LO19},
+  {BFD_RELOC_NDS32_GOTOFF_LO15, R_NDS32_GOTOFF_LO15},
+  {BFD_RELOC_NDS32_GOTOFF_LO19, R_NDS32_GOTOFF_LO19},
   {BFD_RELOC_NDS32_GOT15S2, R_NDS32_GOT15S2_RELA},
   {BFD_RELOC_NDS32_GOT17S2, R_NDS32_GOT17S2_RELA},
+  {BFD_RELOC_NDS32_5, R_NDS32_5_RELA},
+  {BFD_RELOC_NDS32_10_UPCREL, R_NDS32_10_UPCREL_RELA},
+  {BFD_RELOC_NDS32_SDA_FP7U2_RELA, R_NDS32_SDA_FP7U2_RELA},
+  {BFD_RELOC_NDS32_RELAX_ENTRY, R_NDS32_RELAX_ENTRY},
+  {BFD_RELOC_NDS32_GOT_SUFF, R_NDS32_GOT_SUFF},
+  {BFD_RELOC_NDS32_GOTOFF_SUFF, R_NDS32_GOTOFF_SUFF},
+  {BFD_RELOC_NDS32_PLT_GOT_SUFF, R_NDS32_PLT_GOT_SUFF},
+  {BFD_RELOC_NDS32_MULCALL_SUFF, R_NDS32_MULCALL_SUFF},
   {BFD_RELOC_NDS32_PTR, R_NDS32_PTR},
   {BFD_RELOC_NDS32_PTR_COUNT, R_NDS32_PTR_COUNT},
-  {BFD_RELOC_NDS32_PLT_GOT_SUFF, R_NDS32_PLT_GOT_SUFF},
   {BFD_RELOC_NDS32_PTR_RESOLVED, R_NDS32_PTR_RESOLVED},
-  {BFD_RELOC_NDS32_RELAX_ENTRY, R_NDS32_RELAX_ENTRY},
-  {BFD_RELOC_NDS32_MULCALL_SUFF, R_NDS32_MULCALL_SUFF},
   {BFD_RELOC_NDS32_PLTBLOCK, R_NDS32_PLTBLOCK},
   {BFD_RELOC_NDS32_RELAX_REGION_BEGIN, R_NDS32_RELAX_REGION_BEGIN},
   {BFD_RELOC_NDS32_RELAX_REGION_END, R_NDS32_RELAX_REGION_END},
   {BFD_RELOC_NDS32_MINUEND, R_NDS32_MINUEND},
   {BFD_RELOC_NDS32_SUBTRAHEND, R_NDS32_SUBTRAHEND},
-  {BFD_RELOC_NDS32_EMPTY, R_NDS32_EMPTY},
-
   {BFD_RELOC_NDS32_DIFF8, R_NDS32_DIFF8},
   {BFD_RELOC_NDS32_DIFF16, R_NDS32_DIFF16},
   {BFD_RELOC_NDS32_DIFF32, R_NDS32_DIFF32},
   {BFD_RELOC_NDS32_DIFF_ULEB128, R_NDS32_DIFF_ULEB128},
+  {BFD_RELOC_NDS32_EMPTY, R_NDS32_EMPTY},
   {BFD_RELOC_NDS32_25_ABS, R_NDS32_25_ABS_RELA},
   {BFD_RELOC_NDS32_DATA, R_NDS32_DATA},
   {BFD_RELOC_NDS32_TRAN, R_NDS32_TRAN},
   {BFD_RELOC_NDS32_17IFC_PCREL, R_NDS32_17IFC_PCREL_RELA},
   {BFD_RELOC_NDS32_10IFCU_PCREL, R_NDS32_10IFCU_PCREL_RELA},
+  /* Not sure.  */
+  {BFD_RELOC_NDS32_TPOFF, R_NDS32_TLS_TPOFF},
+  /* Missing: BFD_RELOC_NDS32_GOTTPOFF.  */
   {BFD_RELOC_NDS32_TLS_LE_HI20, R_NDS32_TLS_LE_HI20},
   {BFD_RELOC_NDS32_TLS_LE_LO12, R_NDS32_TLS_LE_LO12},
-  {BFD_RELOC_NDS32_TLS_LE_ADD, R_NDS32_TLS_LE_ADD},
-  {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_LE_ADD, R_NDS32_TLS_LE_ADD},
+  {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_LO12, R_NDS32_TLS_IE_LO12},
+  {BFD_RELOC_NDS32_TLS_IE_LO12S2, R_NDS32_TLS_IE_LO12S2},
+  {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_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_20, R_NDS32_TLS_DESC_20},
+  {BFD_RELOC_NDS32_TLS_DESC_SDA17S2, R_NDS32_TLS_DESC_SDA17S2},
+  {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_REMOVE, R_NDS32_RELAX_REMOVE},
+  {BFD_RELOC_NDS32_GROUP, R_NDS32_RELAX_GROUP},
+  {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)
@@ -2843,6 +3207,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];
@@ -2859,7 +3230,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;
@@ -2882,6 +3253,8 @@ nds32_info_to_howto_rel (bfd *abfd, arelent *cache_ptr,
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
     }
+
+  BFD_ASSERT (ELF32_R_TYPE (dst->r_info) <= R_NDS32_GNU_VTENTRY);
   cache_ptr->howto = bfd_elf32_bfd_reloc_type_table_lookup (r_type);
   return TRUE;
 }
@@ -2903,7 +3276,7 @@ nds32_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
   /* xgettext:c-format */
   _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, r_type);
   bfd_set_error (bfd_error_bad_value);
-  return FALSE;  
+  return FALSE;
 }
 
 /* Support for core dump NOTE sections.
@@ -2918,7 +3291,7 @@ 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 */
       elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12);
@@ -2932,7 +3305,7 @@ nds32_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
       break;
 
     case 0xfc:
-      /* Linux/NDS32 32-bit */
+      /* Linux/NDS32 32-bit */
 
       /* pr_cursig */
       elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12);
@@ -2960,7 +3333,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 =
@@ -3037,7 +3410,6 @@ nds32_elf_add_symbol_hook (bfd *abfd,
   return TRUE;
 }
 
-
 /* This function can figure out the best location for a base register to access
    data relative to this base register
    INPUT:
@@ -3086,19 +3458,22 @@ static asection *sda_rela_sec = NULL;
 #define SDA_SECTION_NUM 10
 
 static bfd_reloc_status_type
-nds32_elf_final_sda_base (bfd *output_bfd, struct bfd_link_info *info,
-                         bfd_vma *psb, bfd_boolean add_symbol)
+nds32_elf_final_sda_base (bfd *                   output_bfd,
+                         struct bfd_link_info *  info,
+                         bfd_vma *               psb,
+                         bfd_boolean             add_symbol)
 {
   int relax_fp_as_gp;
   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))
+  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.  */
@@ -3116,7 +3491,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))
@@ -3158,7 +3533,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)
@@ -3173,45 +3548,81 @@ 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;
       sda_base = sda_base & (~7);
 
       if (!_bfd_generic_link_add_one_symbol
-            (info, output_bfd, "_SDA_BASE_", BSF_GLOBAL | BSF_WEAK, first,
-             (bfd_vma) sda_base, (const char *) NULL, FALSE,
-             get_elf_backend_data (output_bfd)->collect, &h))
+         (info, output_bfd, "_SDA_BASE_", BSF_GLOBAL | BSF_WEAK, first,
+          (bfd_vma) sda_base, (const char *) NULL, FALSE,
+          get_elf_backend_data (output_bfd)->collect, &h))
        return FALSE;
 
       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;
-       }
+  /* 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)
@@ -3230,8 +3641,9 @@ nds32_elf_final_sda_base (bfd *output_bfd, struct bfd_link_info *info,
        }
     }
 
-  *psb = h->u.def.value + h->u.def.section->output_section->vma
-        + h->u.def.section->output_offset;
+  *psb = h->u.def.value
+    + h->u.def.section->output_section->vma
+    + h->u.def.section->output_offset;
   return bfd_reloc_ok;
 }
 \f
@@ -3239,7 +3651,6 @@ nds32_elf_final_sda_base (bfd *output_bfd, struct bfd_link_info *info,
 /* Return size of a PLT entry.  */
 #define elf_nds32_sizeof_plt(info) PLT_ENTRY_SIZE
 
-
 /* Create an entry in an nds32 ELF linker hash table.  */
 
 static struct bfd_hash_entry *
@@ -3271,6 +3682,7 @@ 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;
     }
 
   return (struct bfd_hash_entry *) ret;
@@ -3289,7 +3701,7 @@ nds32_elf_link_hash_table_create (bfd *abfd)
   if (ret == NULL)
     return NULL;
 
-  /* patch tag.  */
+  /* Patch tag.  */
   if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
                                      nds32_elf_link_hash_newfunc,
                                      sizeof (struct elf_nds32_link_hash_entry),
@@ -3299,22 +3711,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
@@ -3331,7 +3782,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))
@@ -3360,40 +3811,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)
     {
@@ -3479,9 +3923,19 @@ nds32_elf_copy_indirect_symbol (struct bfd_link_info *info,
       eind->dyn_relocs = NULL;
     }
 
+  if (ind->root.type == bfd_link_hash_indirect)
+    {
+      if (dir->got.refcount <= 0)
+       {
+         edir->tls_type = eind->tls_type;
+         eind->tls_type = GOT_UNKNOWN;
+       }
+    }
+
   _bfd_elf_link_hash_copy_indirect (info, dir, ind);
 }
 \f
+
 /* Find dynamic relocs for H that apply to read-only sections.  */
 
 static asection *
@@ -3584,7 +4038,7 @@ nds32_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   /* 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))
+  if (!readonly_dynrelocs (h))
     {
       h->non_got_ref = 0;
       return TRUE;
@@ -3649,6 +4103,7 @@ 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;
@@ -3656,18 +4111,25 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   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.  */
@@ -3679,7 +4141,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.  */
@@ -3704,10 +4166,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
        {
@@ -3723,7 +4187,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;
 
@@ -3735,22 +4199,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;
@@ -3806,7 +4292,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
       eh->dyn_relocs = NULL;
 
-    keep:;
+keep:;
     }
 
   /* Finally, allocate space.  */
@@ -3819,6 +4305,25 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   return TRUE;
 }
 
+/* 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);
+}
+
 /* Set DF_TEXTREL if we find any dynamic relocs that apply to
    read-only sections.  */
 
@@ -3856,13 +4361,17 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   bfd *dynobj;
   asection *s;
   bfd_boolean relocs;
+  bfd_boolean plt;
   bfd *ibfd;
 
   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)
@@ -3882,7 +4391,10 @@ 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;
@@ -3905,8 +4417,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;
                }
@@ -3920,19 +4432,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;
+           }
        }
     }
 
@@ -3940,8 +4490,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)
     {
@@ -3952,18 +4530,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
@@ -4012,13 +4591,13 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 #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)
@@ -4027,6 +4606,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)
@@ -4331,52 +4918,219 @@ 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;
+
+  tp_base = elf_hash_table (info)->tls_sec->vma;
+  tp_offset = address - tp_base;
+
+  return tp_offset;
 }
 
 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;
+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)]
+     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;
 
   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 = htab->root.sgot;
-  splt = htab->root.splt;
+  sgot = ehtab->sgot;
+  splt = ehtab->splt;
   sreloc = NULL;
 
   rel = relocs;
@@ -4384,7 +5138,9 @@ nds32_elf_relocate_section (bfd *            output_bfd ATTRIBUTE_UNUSED,
 
   table = nds32_elf_hash_table (info);
   eliminate_gc_relocs = table->eliminate_gc_relocs;
+
   /* By this time, we can adjust the value of _SDA_BASE_.  */
+  /* Explain _SDA_BASE_  */
   if ((!bfd_link_relocatable (info)))
     {
       is_SDA_BASE_set = 1;
@@ -4393,11 +5149,15 @@ nds32_elf_relocate_section (bfd *                  output_bfd ATTRIBUTE_UNUSED,
        return FALSE;
     }
 
+  /* Do TLS model conversion once at first.  */
+  nds32_elf_unify_tls_model (input_bfd, input_section, contents, 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);
 
+  /* Deal with (dynamic) relocations.  */
   for (rel = relocs; rel < relend; rel++)
     {
       enum elf_nds32_reloc_type r_type;
@@ -4407,6 +5167,9 @@ nds32_elf_relocate_section (bfd *            output_bfd ATTRIBUTE_UNUSED,
       Elf_Internal_Sym *sym = NULL;
       asection *sec;
       bfd_vma relocation;
+      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
@@ -4434,8 +5197,7 @@ 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
@@ -4456,9 +5218,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.  */
+      /* 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);
@@ -4477,10 +5243,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;
 
@@ -4489,10 +5271,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:
@@ -4503,19 +5302,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.  */
@@ -4525,9 +5311,7 @@ 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)
@@ -4576,11 +5360,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))
            {
+             /* Maybe we should 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.  */
+             if (h)
+               h->plt.offset = (bfd_vma) -1;   /* Cancel PLT trampoline.  */
              relocation -= elf_gp (output_bfd);
              break;
            }
@@ -4632,21 +5423,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.  */
@@ -4660,8 +5448,8 @@ nds32_elf_relocate_section (bfd *            output_bfd ATTRIBUTE_UNUSED,
 
          if (h != NULL)
            {
+             /* External symbol  */
              bfd_boolean dyn;
-             bfd_vma off;
 
              off = h->got.offset;
              BFD_ASSERT (off != (bfd_vma) - 1);
@@ -4686,7 +5474,7 @@ nds32_elf_relocate_section (bfd *            output_bfd ATTRIBUTE_UNUSED,
                     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)
+                 if ((off & 1) != 0)   /* clear LSB  */
                    off &= ~1;
                  else
                    {
@@ -4699,7 +5487,7 @@ nds32_elf_relocate_section (bfd *            output_bfd ATTRIBUTE_UNUSED,
            }
          else
            {
-             bfd_vma off;
+             /* Local symbol  */
              bfd_byte *loc;
 
              BFD_ASSERT (local_got_offsets != NULL
@@ -4710,7 +5498,7 @@ nds32_elf_relocate_section (bfd *            output_bfd ATTRIBUTE_UNUSED,
              /* 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
                {
@@ -4723,7 +5511,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)
@@ -4834,15 +5622,40 @@ 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;
                    }
@@ -4879,123 +5692,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.  */
@@ -5031,51 +5836,49 @@ 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
-                   (_("%pB: 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
+               (_("%pB: 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 */
-                   (_("%pB(%pA): 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
+               /* xgettext:c-format */
+               (_("%pB(%pA): 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 */
+         /* Do nothing.  */
          break;
 
        case R_NDS32_TLS_LE_HI20:
@@ -5084,28 +5887,39 @@ handle_sda:
        case R_NDS32_TLS_LE_15S0:
        case R_NDS32_TLS_LE_15S1:
        case R_NDS32_TLS_LE_15S2:
+         /* We do not have garbage collection for got entries.
+            Therefore, 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)
@@ -5115,76 +5929,158 @@ 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);
+                     }
                  }
-             }
-         }
-       break;
-
-         /* DON'T   fall through.  */
-
-       default:
-         /* OLD_NDS32_RELOC.  */
-
-         r = _bfd_final_link_relocate (howto, input_bfd, input_section,
-                                       contents, offset, relocation, addend);
-         goto check_reloc;
-       }
-
-      switch ((int) r_type)
-       {
+               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;
+         /* DON'T fall through.  */
+
+       default:
+         /* OLD_NDS32_RELOC.  */
+
+         r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+                                       contents, offset, relocation, addend);
+         goto check_reloc;
+       }
+
+      switch ((int) r_type)
+       {
        case R_NDS32_20_RELA:
        case R_NDS32_5_RELA:
        case R_NDS32_9_PCREL_RELA:
@@ -5247,6 +6143,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,
@@ -5312,7 +6214,7 @@ check_reloc:
              errmsg = _("internal error: unknown error");
              /* Fall through.  */
 
-           common_error:
+common_error:
              (*info->callbacks->warning) (info, errmsg, name, input_bfd,
                                           input_section, offset);
              break;
@@ -5320,6 +6222,10 @@ check_reloc:
        }
     }
 
+  /* 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;
 }
 
@@ -5330,10 +6236,12 @@ 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_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)
     {
@@ -5351,9 +6259,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
@@ -5399,8 +6307,6 @@ nds32_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info,
          unsigned long insn;
          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);
          insn = PLT_PIC_ENTRY_WORD0 + ((offset >> 12) & 0xfffff);
@@ -5451,18 +6357,19 @@ 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));
@@ -5472,14 +6379,21 @@ 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);
+
+         if ((h->got.offset & 1) == 0)
+           {
+             bfd_put_32 (output_bfd, rela.r_addend,
+                         sgot->contents + h->got.offset);
+           }
        }
       else
        {
@@ -5490,10 +6404,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)
@@ -5535,23 +6450,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);
@@ -5569,25 +6493,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))
@@ -5595,14 +6554,11 @@ nds32_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
              unsigned long insn;
              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);
@@ -5625,7 +6581,7 @@ nds32_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
              unsigned long addr;
 
              /* addr = .got + 4 */
-             addr = sgot->output_section->vma + sgot->output_offset + 4;
+             addr = sgotplt->output_section->vma + sgotplt->output_offset + 4;
              insn = PLT0_ENTRY_WORD0 | ((addr >> 12) & 0xfffff);
              bfd_putb32 (insn, splt->contents);
 
@@ -5645,21 +6601,46 @@ 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;
+
+         /* 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;
@@ -5863,134 +6844,148 @@ 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
-       (_("%pB: 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))
+  /* -B option in objcopy cannot work as expected. e_flags = 0 shall be
+     treat as generic one without checking and 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;
-       }
-      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));
+         _bfd_error_handler
+           (_("%pB: warning: older version of object file encountered, "
+              "please recompile with current tool chain"), ibfd);
        }
-      else
-       {
-         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;
 
-      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)
+      /* 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))
        {
-         return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
-                                   bfd_get_mach (ibfd));
+         /* 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));
+           }
        }
 
-      return TRUE;
-    }
+      /* 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;
+
+         elf_flags_init (obfd) = TRUE;
+         elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
 
-  /* Check flag compatibility.  */
-  if ((in_flags & EF_NDS_ABI) != (out_flags & EF_NDS_ABI))
-    {
-      _bfd_error_handler
-       (_("%pB: error: ABI mismatch with previous modules"), ibfd);
+         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));
+           }
 
-      bfd_set_error (bfd_error_bad_value);
-      return FALSE;
-    }
+         return TRUE;
+       }
 
-  if ((in_flags & EF_NDS_ARCH) != (out_flags & EF_NDS_ARCH))
-    {
-      if (((in_flags & EF_NDS_ARCH) != E_N1_ARCH))
+      /* Check flag compatibility.  */
+      if ((in_flags & EF_NDS_ABI) != (out_flags & EF_NDS_ABI))
        {
          _bfd_error_handler
-           (_("%pB: error: instruction set mismatch with previous modules"),
-            ibfd);
-
+           (_("%pB: error: ABI mismatch with previous modules"), ibfd);
          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 */
-         (_("%pB: warning: incompatible elf-versions %s and %s"),
-          ibfd, nds32_elfver_strtab[out_version],
-          nds32_elfver_strtab[in_version]);
+      if ((in_flags & EF_NDS_ARCH) != (out_flags & EF_NDS_ARCH))
+       {
+         if (((in_flags & EF_NDS_ARCH) != E_N1_ARCH))
+           {
+             _bfd_error_handler
+               (_("%pB: error: instruction set mismatch with previous modules"),
+                ibfd);
+
+             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 */
+             (_("%pB: 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;
@@ -6054,6 +7049,81 @@ 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.  */
@@ -6066,12 +7136,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;
+    {
+      elf32_nds32_check_relax_group (abfd, sec);
+      return TRUE;
+    }
 
   /* Don't do anything special with non-loaded, non-alloced sections.
      In particular, any relocs in such sections should not affect GOT
@@ -6089,6 +7164,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;
 
@@ -6098,7 +7174,7 @@ 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;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
       r_type = ELF32_R_TYPE (rel->r_info);
@@ -6112,10 +7188,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)
            {
@@ -6135,10 +7212,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;
 
@@ -6147,6 +7230,7 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
            }
        }
 
+      /* Check relocation type.  */
       switch ((int) r_type)
        {
        case R_NDS32_GOT_HI20:
@@ -6154,52 +7238,47 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_NDS32_GOT_LO15:
        case R_NDS32_GOT_LO19:
        case R_NDS32_GOT20:
+       case R_NDS32_TLS_LE_HI20:
+       case R_NDS32_TLS_LE_LO12:
        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 have issued an error message if there
             is a TLS/non-TLS mismatch, based on the symbol
             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)
@@ -6229,7 +7308,8 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          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;
@@ -6384,9 +7464,48 @@ nds32_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                }
 
              p->count += 1;
+
+             /* 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;
@@ -6437,8 +7556,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;
@@ -6467,7 +7585,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;
@@ -6480,9 +7597,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)
        {
@@ -6505,84 +7619,8 @@ calculate_offset (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
          - (irel->r_offset + sec->output_section->vma + sec->output_offset));
   return foff;
 }
-
-static bfd_vma
-calculate_plt_memory_address (bfd *abfd, struct bfd_link_info *link_info,
-                             Elf_Internal_Sym *isymbuf,
-                             Elf_Internal_Rela *irel,
-                             Elf_Internal_Shdr *symtab_hdr)
-{
-  bfd_vma symval;
-
-  if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
-    {
-      Elf_Internal_Sym *isym;
-      asection *sym_sec;
-      /* A local symbol.  */
-      isym = isymbuf + ELF32_R_SYM (irel->r_info);
-
-      if (isym->st_shndx == SHN_UNDEF)
-       sym_sec = bfd_und_section_ptr;
-      else if (isym->st_shndx == SHN_ABS)
-       sym_sec = bfd_abs_section_ptr;
-      else if (isym->st_shndx == SHN_COMMON)
-       sym_sec = bfd_com_section_ptr;
-      else
-       sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
-      symval = isym->st_value + sym_sec->output_section->vma
-              + sym_sec->output_offset;
-    }
-  else
-    {
-      unsigned long indx;
-      struct elf_link_hash_entry *h;
-      struct elf_nds32_link_hash_table *htab;
-      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;
-
-      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;
-
-      if (h->plt.offset == (bfd_vma) - 1)
-       {
-         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.  */
-           return 0;
-         symval = (h->root.u.def.value
-                   + h->root.u.def.section->output_section->vma
-                   + h->root.u.def.section->output_offset);
-       }
-      else
-       symval = splt->output_section->vma + h->plt.offset;
-    }
-
-  return symval;
-}
-
-static bfd_signed_vma
-calculate_plt_offset (bfd *abfd, asection *sec, struct bfd_link_info *link_info,
-                     Elf_Internal_Sym *isymbuf, Elf_Internal_Rela *irel,
-                     Elf_Internal_Shdr *symtab_hdr)
-{
-  bfd_vma foff;
-  if ((foff = calculate_plt_memory_address (abfd, link_info, isymbuf, irel,
-                                           symtab_hdr)) == 0)
-    return 0;
-  else
-    return foff - (irel->r_offset
-                  + sec->output_section->vma + sec->output_offset);
-}
 \f
+
 /* Convert a 32-bit instruction to 16-bit one.
    INSN is the input 32-bit instruction, INSN16 is the output 16-bit
    instruction.  If INSN_TYPE is not NULL, it the CGEN instruction
@@ -7178,8 +8216,8 @@ nds32_convert_32_to_16 (bfd *abfd, uint32_t insn, uint16_t *pinsn16,
            }
          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;
@@ -7437,7 +8475,7 @@ nds32_convert_16_to_32 (bfd *abfd, uint16_t insn16, uint32_t *pinsn)
       goto done;
 
     case 0x3c:                 /* ifcall9 */
-      insn = N32_BR2 (IFCALL, 0, N16_IMM9U (insn16));
+      insn = N32_BR2 (SOP0, 0, N16_IMM9U (insn16));
       goto done;
     case 0x3d:                 /* movpi45 */
       insn = N32_TYPE1 (MOVI, N16_RT4 (insn16), N16_IMM5U (insn16) + 16);
@@ -7542,7 +8580,7 @@ nds32_convert_16_to_32 (bfd *abfd, uint16_t insn16, uint32_t *pinsn)
       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))
@@ -7584,6 +8622,7 @@ done:
   return 1;
 }
 \f
+
 static bfd_boolean
 is_sda_access_insn (unsigned long insn)
 {
@@ -7799,44 +8838,6 @@ calculate_memory_address (bfd *abfd, Elf_Internal_Rela *irel,
   return foff;
 }
 
-static bfd_vma
-calculate_got_memory_address (bfd *abfd, struct bfd_link_info *link_info,
-                             Elf_Internal_Rela *irel,
-                             Elf_Internal_Shdr *symtab_hdr)
-{
-  int symndx;
-  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);
-
-  /* An external symbol.  */
-  symndx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
-  h = elf_sym_hashes (abfd)[symndx];
-  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;
-
-  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)]);
-    }
-
-  /* The _GLOBAL_OFFSET_TABLE_ may be undefweak(or should be?).  */
-  /* The check of h->root.type is passed.  */
-}
-
 static int
 is_16bit_NOP (bfd *abfd ATTRIBUTE_UNUSED,
              asection *sec, Elf_Internal_Rela *rel)
@@ -7872,7 +8873,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;
@@ -7911,8 +8911,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;
@@ -7959,8 +8958,7 @@ is_convert_32_to_16 (bfd *abfd, asection *sec,
        }
       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;
@@ -8090,50 +9088,18 @@ find_relocs_at_address_addr (Elf_Internal_Rela *reloc,
   return find_relocs_at_address (rel_t, relocs, irelend, reloc_type);
 }
 
-static bfd_boolean
-nds32_elf_check_dup_relocs (Elf_Internal_Rela *reloc,
-                           Elf_Internal_Rela *internal_relocs,
-                           Elf_Internal_Rela *irelend,
-                           unsigned char reloc_type)
+typedef struct nds32_elf_blank nds32_elf_blank_t;
+struct nds32_elf_blank
 {
-  Elf_Internal_Rela *rel_t;
-
-  for (rel_t = reloc;
-       rel_t >= internal_relocs && rel_t->r_offset == reloc->r_offset;
-       rel_t--)
-    if (ELF32_R_TYPE (rel_t->r_info) == reloc_type)
-      {
-       if (ELF32_R_SYM (rel_t->r_info) == ELF32_R_SYM (reloc->r_info)
-           && rel_t->r_addend == reloc->r_addend)
-         continue;
-       return TRUE;
-      }
-
-  for (rel_t = reloc; rel_t < irelend && rel_t->r_offset == reloc->r_offset;
-       rel_t++)
-    if (ELF32_R_TYPE (rel_t->r_info) == reloc_type)
-      {
-       if (ELF32_R_SYM (rel_t->r_info) == ELF32_R_SYM (reloc->r_info)
-           && rel_t->r_addend == reloc->r_addend)
-         continue;
-       return TRUE;
-      }
-
-  return FALSE;
-}
-
-typedef struct nds32_elf_blank nds32_elf_blank_t;
-struct nds32_elf_blank
-{
-  /* Where the blank begins.  */
-  bfd_vma offset;
-  /* The size of the blank.  */
-  bfd_vma size;
-  /* The accumulative size before this blank.  */
-  bfd_vma total_size;
-  nds32_elf_blank_t *next;
-  nds32_elf_blank_t *prev;
-};
+  /* Where the blank begins.  */
+  bfd_vma offset;
+  /* The size of the blank.  */
+  bfd_vma size;
+  /* The accumulative size before this blank.  */
+  bfd_vma total_size;
+  nds32_elf_blank_t *next;
+  nds32_elf_blank_t *prev;
+};
 
 static nds32_elf_blank_t *blank_free_list = NULL;
 
@@ -8254,8 +9220,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
     {
@@ -8717,7 +9684,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;
@@ -8800,7 +9767,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;
 
@@ -8823,15 +9789,15 @@ nds32_elf_relax_longcall1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
     }
 
   /* 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
@@ -8887,7 +9853,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;
@@ -8906,10 +9871,10 @@ nds32_elf_relax_longcall2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
   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
+  if (foff == 0
+      || foff < -CONSERVATIVE_16BIT_S1
       || foff >= CONSERVATIVE_16BIT_S1)
     return FALSE;
 
@@ -8986,7 +9951,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;
 
@@ -9010,10 +9974,10 @@ nds32_elf_relax_longcall3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
     }
 
   /* 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;
 
@@ -9119,7 +10083,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;
@@ -9144,15 +10107,17 @@ nds32_elf_relax_longjump1 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
     }
 
   /* 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))
+  if (insn16_on
+      && foff >= -ACCURATE_8BIT_S1
+      && foff < ACCURATE_8BIT_S1
+      && (seq_len & 0x2))
     {
       /* j8    label */
       /* 16-bit on, but not optimized for speed.  */
@@ -9312,7 +10277,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;
@@ -9333,7 +10298,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,
@@ -9350,10 +10315,9 @@ nds32_elf_relax_longjump2 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
     }
 
   /* 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
+  foff = calculate_offset (abfd, sec, i2_irelfn, isymbuf, symtab_hdr);
+  if (foff == 0
+      || foff < -CONSERVATIVE_16BIT_S1
       || foff >= CONSERVATIVE_16BIT_S1)
     return FALSE;
 
@@ -9497,7 +10461,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;
@@ -9525,7 +10489,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,
@@ -9534,7 +10498,9 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
        break;
     }
 
-  if (hi_irelfn == irelend || lo_irelfn == irelend || cond_irelfn == irelend)
+  if (hi_irelfn == irelend
+      || lo_irelfn == irelend
+      || cond_irelfn == irelend)
     {
       _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LONGJUMP3",
                          (uint64_t) irel->r_offset);
@@ -9542,10 +10508,10 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
     }
 
   /* 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;
 
@@ -9569,7 +10535,8 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
      that would be more work, but would require less memory when
      the linker is run.  */
 
-  if (re_insn16 && foff >= -ACCURATE_8BIT_S1 - first_size
+  if (re_insn16
+      && foff >= -ACCURATE_8BIT_S1 - first_size
       && foff < ACCURATE_8BIT_S1 - first_size)
     {
       if (!(seq_len & 0x2))
@@ -9664,6 +10631,7 @@ nds32_elf_relax_longjump3 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
     else
       {
        irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), reloc);
+       irel->r_addend = irel->r_addend;
        hi_irelfn->r_info = ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info),
                                          cond_reloc);
       }
@@ -9701,7 +10669,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;
@@ -9721,15 +10688,15 @@ nds32_elf_relax_longcall4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
     }
 
   /* 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
@@ -9801,7 +10768,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;
@@ -9822,15 +10788,15 @@ nds32_elf_relax_longcall5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
     }
 
   /* 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
+  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);
@@ -9880,7 +10846,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;
@@ -9900,10 +10865,10 @@ nds32_elf_relax_longcall6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
     }
 
   /* 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;
 
@@ -9916,7 +10881,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;
@@ -10014,7 +10979,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;
@@ -10037,10 +11001,10 @@ nds32_elf_relax_longjump4 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
     }
 
   /* 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;
 
@@ -10104,7 +11068,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;
@@ -10133,10 +11096,10 @@ nds32_elf_relax_longjump5 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
     }
 
   /* 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;
 
@@ -10181,7 +11144,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);
@@ -10238,7 +11201,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;
@@ -10262,10 +11224,10 @@ nds32_elf_relax_longjump6 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
     }
 
   /* 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;
 
@@ -10291,7 +11253,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;
@@ -10299,7 +11261,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;
@@ -10356,7 +11318,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,
@@ -10408,7 +11370,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;
@@ -10432,10 +11393,10 @@ nds32_elf_relax_longjump7 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
     }
 
   /* 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;
 
@@ -10489,6 +11450,134 @@ nds32_elf_relax_longjump7 (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
   return TRUE;
 }
 
+/* We figure out and reassign the best gp value in nds32_elf_final_sda_base
+   for each relax round. But the gp may changed dramatically and then cause
+   the truncated to fit errors for the the converted gp instructions.
+   Therefore, we must reserve the minimum but safe enough size to prevent it.  */
+
+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)
+
+{
+  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;
+
+  /* Do not relax the load/store patterns for the first
+     relax 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;
+    }
+
+  /* Generally, _SDA_BASE_ is fixed or smaller. But the large
+     DATA_SEGMENT_ALIGN size in the linker script may make it
+     get even bigger.  */
+  if (record_sda == 0)
+    record_sda = local_sda;
+  else if (local_sda > record_sda)
+    sda_offset = local_sda - record_sda;
+
+  /* Assume the instruction will be removed in the best case.  */
+  count++;
+
+  /* We record the offset to gp for each symbol, and then check
+     if it is changed dramatically after relaxing.
+     (global symbol): elf32_nds32_hash_entry (h)->offset_to_gp
+     (local symbol) : elf32_nds32_local_gp_offset (abfd)[r_symndx].  */
+  r_symndx = ELF32_R_SYM (irel->r_info);
+  if (r_symndx >= symtab_hdr->sh_info)
+    {
+      /* Global symbols.  */
+      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)
+           {
+             /* This may cause the error, so we reserve the
+                safe enough size for relaxing.  */
+             if (*access_addr >= local_sda)
+               *access_addr += (record_count * 4);
+             else
+               *access_addr -= (record_count * 4);
+           }
+         return sec_pass;
+       }
+    }
+  else
+    {
+      /* Local symbols.  */
+      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)
+           {
+             /* This may cause the error, so we reserve the
+                safe enough size for relaxing.  */
+             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.  */
@@ -10498,7 +11587,8 @@ 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;
@@ -10508,6 +11598,8 @@ nds32_elf_relax_loadstore (struct bfd_link_info *link_info, bfd *abfd,
   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,
@@ -10531,9 +11623,11 @@ 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",
-                         (uint64_t) irel->r_offset);
-       return FALSE;
+      /* Not R_NDS32_HI20_RELA.  */
+      if (i != 0)
+       _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LOADSTORE",
+                           (uint64_t) irel->r_offset);
+      return FALSE;
     }
 
   range_type = GET_LOADSTORE_RANGE (irel->r_addend);
@@ -10547,36 +11641,36 @@ 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];
+       }
 
-         if ((access_addr < CONSERVATIVE_20BIT)
-             && (!h || (h && strcmp (h->root.root.string, FP_BASE_NAME) != 0)))
-           {
-             eliminate_sethi = 1;
-             break;
-           }
+      /* Try movi.  */
+      if (range_type == NDS32_LOADSTORE_IMM
+         && 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_symbol (&h->root))
-           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)
@@ -10591,57 +11685,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;
     }
@@ -10656,8 +11699,10 @@ 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.  */
@@ -10666,7 +11711,8 @@ 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;
@@ -10696,6 +11742,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)))
     {
@@ -10704,13 +11751,16 @@ 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_symbol (&h->root))
-    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))
@@ -10741,7 +11791,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)
            {
@@ -10769,225 +11820,6 @@ nds32_elf_relax_lo12 (struct bfd_link_info *link_info, bfd *abfd,
   return;
 }
 
-/* Relax low part of PIC instruction pattern.  */
-
-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,
-                        Elf_Internal_Shdr *symtab_hdr)
-{
-  uint32_t insn;
-  bfd_vma local_sda, laddr;
-  bfd_signed_vma foff;
-  unsigned long reloc;
-
-  nds32_elf_final_sda_base (sec->output_section->owner, link_info,
-                           &local_sda, FALSE);
-  laddr = irel->r_offset;
-  insn = bfd_getb32 (contents + laddr);
-
-  if (N32_OP6 (insn) != N32_OP6_ORI)
-    return;
-
-  if (ELF32_R_TYPE (irel->r_info) == R_NDS32_GOT_LO12)
-    {
-      foff = calculate_got_memory_address (abfd, link_info, irel,
-                                          symtab_hdr) - local_sda;
-      reloc = R_NDS32_GOT20;
-    }
-  else if (ELF32_R_TYPE (irel->r_info) == R_NDS32_PLT_GOTREL_LO12)
-    {
-      foff = calculate_plt_memory_address (abfd, link_info, isymbuf, irel,
-                                          symtab_hdr) - local_sda;
-      reloc = R_NDS32_PLT_GOTREL_LO20;
-    }
-  else if (ELF32_R_TYPE (irel->r_info) == R_NDS32_GOTOFF_LO12)
-    {
-      foff = calculate_memory_address (abfd, irel, isymbuf,
-                                      symtab_hdr) - local_sda;
-      reloc = R_NDS32_GOTOFF;
-    }
-  else if (ELF32_R_TYPE (irel->r_info) == R_NDS32_GOTPC_LO12)
-    {
-      foff = local_sda - sec->output_section->vma + sec->output_offset
-       + irel->r_offset + irel->r_addend;
-      reloc = R_NDS32_GOTPC20;
-    }
-  else
-    return;
-
-  if ((foff < CONSERVATIVE_20BIT) && (foff >= -CONSERVATIVE_20BIT))
-    {
-      /* Turn into MOVI.  */
-      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), reloc);
-      insn = N32_TYPE1 (MOVI, N32_RT5 (insn), 0);
-      bfd_putb32 (insn, contents + laddr);
-    }
-}
-
-/* Relax low part of LE TLS instruction pattern.  */
-
-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,
-                          Elf_Internal_Shdr *symtab_hdr)
-{
-  uint32_t insn;
-  bfd_vma laddr;
-  bfd_signed_vma foff;
-  unsigned long reloc;
-
-  laddr = irel->r_offset;
-  foff = calculate_memory_address (abfd, irel, isymbuf, symtab_hdr);
-  BFD_ASSERT (elf_hash_table (link_info)->tls_sec != NULL);
-  foff -= (elf_hash_table (link_info)->tls_sec->vma + TP_OFFSET);
-  insn = bfd_getb32 (contents + laddr);
-
-  if ( (bfd_signed_vma) (foff) < CONSERVATIVE_20BIT
-      && (bfd_signed_vma) (foff) >= -CONSERVATIVE_20BIT)
-    {
-      /* Pattern sethi-ori transform to movi.  */
-      reloc = R_NDS32_TLS_LE_20;
-      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), reloc);
-      insn = N32_TYPE1 (MOVI, N32_RT5 (insn), 0);
-      bfd_putb32 (insn, contents + laddr);
-    }
-}
-
-/* Relax LE TLS calculate address instruction pattern.  */
-
-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,
-                         bfd_byte *contents, Elf_Internal_Sym *isymbuf,
-                         Elf_Internal_Shdr *symtab_hdr, bfd_boolean *again)
-{
-  /* Local TLS non-pic
-     sethi    ta, hi20(symbol@tpoff)     ; TLS_LE_HI20
-     ori      ta, ta, lo12(symbol@tpoff)  ; TLS_LE_LO12
-     add      ra, ta, tp                 ; TLS_LE_ADD */
-
-  uint32_t insn;
-  bfd_vma laddr;
-  bfd_signed_vma foff;
-  Elf_Internal_Rela *i1_irelfn, *irelend;
-
-  irelend = internal_relocs + sec->reloc_count;
-  laddr = irel->r_offset;
-  insn = bfd_getb32 (contents + laddr);
-  i1_irelfn = find_relocs_at_address (irel, internal_relocs, irelend,
-                                     R_NDS32_PTR_RESOLVED);
-  foff = calculate_memory_address (abfd, irel, isymbuf, symtab_hdr);
-  BFD_ASSERT (elf_hash_table (link_info)->tls_sec != NULL);
-  foff -= (elf_hash_table (link_info)->tls_sec->vma + TP_OFFSET);
-
-  /* The range is +/-16k.  */
-  if ((bfd_signed_vma) (foff) < CONSERVATIVE_15BIT
-      && (bfd_signed_vma) (foff) >= -CONSERVATIVE_15BIT)
-    {
-      /* Transform add to addi.  */
-      insn = N32_TYPE2 (ADDI, N32_RT5 (insn), N32_RB5 (insn), 0);
-      irel->r_info =
-       ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_TLS_LE_15S0);
-
-      bfd_putb32 (insn, contents + laddr);
-      if (i1_irelfn != irelend)
-       {
-         i1_irelfn->r_addend |= 1;
-         *again = TRUE;
-       }
-    }
-}
-
-/* Relax LE TLS load store instruction pattern.  */
-
-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;
-  Elf_Internal_Rela *i1_irelfn, *irelend;
-  int success = 0;
-
-  irelend = internal_relocs + sec->reloc_count;
-  laddr = irel->r_offset;
-  insn = bfd_getb32 (contents + laddr);
-  i1_irelfn = find_relocs_at_address (irel, internal_relocs, irelend,
-                                     R_NDS32_PTR_RESOLVED);
-  foff = calculate_memory_address (abfd, irel, isymbuf, symtab_hdr);
-  BFD_ASSERT (elf_hash_table (link_info)->tls_sec != NULL);
-  foff -= (elf_hash_table (link_info)->tls_sec->vma + TP_OFFSET);
-
-  switch ((N32_OP6 (insn) << 8) | (insn & 0xff))
-    {
-    case (N32_OP6_MEM << 8) | N32_MEM_LB:
-    case (N32_OP6_MEM << 8) | N32_MEM_SB:
-    case (N32_OP6_MEM << 8) | N32_MEM_LBS:
-      /* The range is +/-16k.  */
-      if ((bfd_signed_vma) (foff) < CONSERVATIVE_15BIT
-         && (bfd_signed_vma) (foff) >= -CONSERVATIVE_15BIT)
-       {
-         insn =
-           ((insn & 0xff) << 25) | (insn & 0x1f00000) | ((insn & 0x7c00) << 5);
-         irel->r_info =
-           ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_TLS_LE_15S0);
-         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:
-      /* The range is +/-32k.  */
-      if ((bfd_signed_vma) (foff) < CONSERVATIVE_15BIT_S1
-         && (bfd_signed_vma) (foff) >= -CONSERVATIVE_15BIT_S1)
-       {
-         insn =
-           ((insn & 0xff) << 25) | (insn & 0x1f00000) | ((insn & 0x7c00) << 5);
-         irel->r_info =
-           ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_TLS_LE_15S1);
-         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.  */
-      if ((bfd_signed_vma) (foff) < CONSERVATIVE_15BIT_S2
-         && (bfd_signed_vma) (foff) >= -CONSERVATIVE_15BIT_S2)
-       {
-         insn =
-           ((insn & 0xff) << 25) | (insn & 0x1f00000) | ((insn & 0x7c00) << 5);
-         irel->r_info =
-           ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_TLS_LE_15S2);
-         success = 1;
-         break;
-       }
-      /* Fall through.  */
-    default:
-      break;
-    }
-
-  if (success)
-    {
-      bfd_putb32 (insn, contents + laddr);
-      if (i1_irelfn != irelend)
-       {
-         i1_irelfn->r_addend |= 1;
-         *again = TRUE;
-       }
-    }
-}
-
 /* Relax PTR relocation for nds32_elf_relax_section.  */
 
 static bfd_boolean
@@ -11039,241 +11871,82 @@ nds32_elf_relax_ptr (bfd *abfd, asection *sec, Elf_Internal_Rela *irel,
   return TRUE;
 }
 
-/* Relax PLT_GOT_SUFF relocation for nds32_elf_relax_section.  */
+/* Relax LWC relocation for nds32_elf_relax_section.  */
 
 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,
-                            bfd_byte *contents, Elf_Internal_Sym *isymbuf,
-                            Elf_Internal_Shdr *symtab_hdr, bfd_boolean *again)
+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:
+     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_signed_vma foff;
-  Elf_Internal_Rela *i1_irelfn, *irelend;
   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);
 
-  /* FIXME: It's a little trouble to turn JRAL5 to JAL since
-     we need additional space.  It might be help if we could
-     borrow some space from instructions to be eliminated
-     such as sethi, ori, add.  */
-  if (insn & 0x80000000)
+  if ((insn & 0x80000000) || !is_sda_access_insn (insn))
     return;
 
-  if (nds32_elf_check_dup_relocs
-      (irel, internal_relocs, irelend, R_NDS32_PLT_GOT_SUFF))
+  /* Can not do relaxation for bi format.  */
+  if ((insn & 0x1000))
     return;
 
-  i1_irelfn =
-    find_relocs_at_address (irel, internal_relocs, irelend,
-                           R_NDS32_PTR_RESOLVED);
-
-  /* FIXIT 090606
-     The boundary should be reduced since the .plt section hasn't
-     been created and the address of specific entry is still unknown
-     Maybe the range between the function call and the begin of the
-     .text section can be used to decide if the .plt is in the range
-     of function call.  */
-
-  if (N32_OP6 (insn) == N32_OP6_ALU1
-      && N32_SUB5 (insn) == N32_ALU1_ADD)
-    {
-      /* Get the value of the symbol referred to by the reloc.  */
-      nds32_elf_final_sda_base (sec->output_section->owner, link_info,
-                               &local_sda, FALSE);
-      foff = (bfd_signed_vma) (calculate_plt_memory_address
-                              (abfd, link_info, isymbuf, irel,
-                               symtab_hdr) - local_sda);
-      /* This condition only happened when symbol is undefined.  */
-      if (foff == 0)
-       return;
-
-      if (foff < -CONSERVATIVE_19BIT || foff >= CONSERVATIVE_19BIT)
-       return;
-      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
-                                  R_NDS32_PLT_GOTREL_LO19);
-      /* addi.gp */
-      insn = N32_TYPE1 (SBGP, N32_RT5 (insn), N32_BIT (19));
-    }
-  else if (N32_OP6 (insn) == N32_OP6_JREG
-          && N32_SUB5 (insn) == N32_JREG_JRAL)
-    {
-      /* Get the value of the symbol referred to by the reloc.  */
-      foff =
-       calculate_plt_offset (abfd, sec, link_info, isymbuf, irel, symtab_hdr);
-      /* This condition only happened when symbol is undefined.  */
-      if (foff == 0)
-       return;
-      if (foff < -CONSERVATIVE_24BIT_S1 || foff >= CONSERVATIVE_24BIT_S1)
-       return;
-      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_25_PLTREL);
-      insn = INSN_JAL;
-    }
+  /* 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;
 
-  bfd_putb32 (insn, contents + laddr);
-  if (i1_irelfn != irelend)
+  re_irel = find_relocs_at_address (irel, internal_relocs, irelend,
+                                   R_NDS32_PTR_RESOLVED);
+  if (re_irel == irelend)
     {
-      i1_irelfn->r_addend |= 1;
-      *again = TRUE;
+      _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LSI",
+                         (uint64_t) irel->r_offset);
+      return;
     }
-}
-
-/* Relax GOT_SUFF relocation for nds32_elf_relax_section.  */
-
-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,
-                         bfd_byte *contents, Elf_Internal_Shdr *symtab_hdr,
-                         bfd_boolean *again)
-{
-  uint32_t insn;
-  bfd_signed_vma foff;
-  Elf_Internal_Rela *i1_irelfn, *irelend;
-  bfd_vma local_sda, laddr;
-
-  irelend = internal_relocs + sec->reloc_count;
-  laddr = irel->r_offset;
-  insn = bfd_getb32 (contents + laddr);
-  if (insn & 0x80000000)
-    return;
-
-  if (nds32_elf_check_dup_relocs
-      (irel, internal_relocs, irelend, R_NDS32_GOT_SUFF))
-    return;
-
-  i1_irelfn = find_relocs_at_address (irel, internal_relocs, irelend,
-                                     R_NDS32_PTR_RESOLVED);
 
+  /* For SDA base relative relaxation.  */
   nds32_elf_final_sda_base (sec->output_section->owner, link_info,
                            &local_sda, FALSE);
-  foff = calculate_got_memory_address (abfd, link_info, irel,
-                                      symtab_hdr) - local_sda;
+  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 (foff < CONSERVATIVE_19BIT && foff >= -CONSERVATIVE_19BIT)
+  if ((local_sda <= access_addr && (access_addr - local_sda) < range_h)
+      || (local_sda > access_addr && (local_sda - access_addr) <= range_l))
     {
-      /* Turn LW to LWI.GP.  Change relocation type to R_NDS32_GOT_REL.  */
-      insn = N32_TYPE1 (HWGP, N32_RT5 (insn), __MF (6, 17, 3));
-      irel->r_info =
-       ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_GOT17S2_RELA);
-      bfd_putb32 (insn, contents + laddr);
-      if (i1_irelfn != irelend)
-       {
-         i1_irelfn->r_addend |= 1;
-         *again = TRUE;
-       }
-    }
-}
-
-/* Relax PLT_GOT_SUFF relocation for nds32_elf_relax_section.  */
-
-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,
-                            bfd_byte *contents, Elf_Internal_Sym *isymbuf,
-                            Elf_Internal_Shdr *symtab_hdr, bfd_boolean *again)
-{
-  int opc_insn_gotoff;
-  uint32_t insn;
-  bfd_signed_vma foff;
-  Elf_Internal_Rela *i1_irelfn, *i2_irelfn, *irelend;
-  bfd_vma local_sda, laddr;
-
-  irelend = internal_relocs + sec->reloc_count;
-  laddr = irel->r_offset;
-  insn = bfd_getb32 (contents + laddr);
+      /* Turn flsi instruction into sda access format.  */
+      insn = (insn & 0x7ff07000) | (REG_GP << 15);
 
-  if (insn & 0x80000000)
-    return;
-
-  if (nds32_elf_check_dup_relocs
-      (irel, internal_relocs, irelend, R_NDS32_GOTOFF_SUFF))
-    return;
-
-  i1_irelfn = find_relocs_at_address (irel, internal_relocs, irelend,
-                                     R_NDS32_PTR_RESOLVED);
-  nds32_elf_final_sda_base (sec->output_section->owner, link_info,
-                           &local_sda, FALSE);
-  foff = calculate_memory_address (abfd, irel, isymbuf, symtab_hdr);
-  foff = foff - local_sda;
-
-  if (foff >= CONSERVATIVE_19BIT || foff < -CONSERVATIVE_19BIT)
-    return;
-
-  /* Concatenate opcode and sub-opcode for switch case.
-     It may be MEM or ALU1.  */
-  opc_insn_gotoff = (N32_OP6 (insn) << 8) | (insn & 0xff);
-  switch (opc_insn_gotoff)
-    {
-    case (N32_OP6_MEM << 8) | N32_MEM_LW:
-      /* 4-byte aligned.  */
-      insn = N32_TYPE1 (HWGP, N32_RT5 (insn), __MF (6, 17, 3));
-      irel->r_info =
-       ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_SDA17S2_RELA);
-      break;
-    case (N32_OP6_MEM << 8) | N32_MEM_SW:
-      insn = N32_TYPE1 (HWGP, N32_RT5 (insn), __MF (7, 17, 3));
-      irel->r_info =
-       ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_SDA17S2_RELA);
-      break;
-    case (N32_OP6_MEM << 8) | N32_MEM_LH:
-      /* 2-byte aligned.  */
-      insn = N32_TYPE1 (HWGP, N32_RT5 (insn), 0);
-      irel->r_info =
-       ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_SDA18S1_RELA);
-      break;
-    case (N32_OP6_MEM << 8) | N32_MEM_LHS:
-      insn = N32_TYPE1 (HWGP, N32_RT5 (insn), N32_BIT (18));
-      irel->r_info =
-       ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_SDA18S1_RELA);
-      break;
-    case (N32_OP6_MEM << 8) | N32_MEM_SH:
-      insn = N32_TYPE1 (HWGP, N32_RT5 (insn), N32_BIT (19));
-      irel->r_info =
-       ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_SDA18S1_RELA);
-      break;
-    case (N32_OP6_MEM << 8) | N32_MEM_LB:
-      /* 1-byte aligned.  */
-      insn = N32_TYPE1 (LBGP, N32_RT5 (insn), 0);
-      irel->r_info =
-       ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_SDA19S0_RELA);
-      break;
-    case (N32_OP6_MEM << 8) | N32_MEM_LBS:
-      insn = N32_TYPE1 (LBGP, N32_RT5 (insn), N32_BIT (19));
-      irel->r_info =
-       ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_SDA19S0_RELA);
-      break;
-    case (N32_OP6_MEM << 8) | N32_MEM_SB:
-      insn = N32_TYPE1 (SBGP, N32_RT5 (insn), 0);
-      irel->r_info =
-       ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_SDA19S0_RELA);
-      break;
-    case (N32_OP6_ALU1 << 8) | N32_ALU1_ADD:
-      insn = N32_TYPE1 (SBGP, N32_RT5 (insn), N32_BIT (19));
-      irel->r_info =
-       ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_SDA19S0_RELA);
-      break;
-    default:
-      return;
-    }
+      /* 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);
 
-  bfd_putb32 (insn, contents + laddr);
-  if (i1_irelfn != irelend)
-    {
-      i1_irelfn->r_addend |= 1;
+      re_irel->r_addend |= 1;
       *again = TRUE;
     }
-  if ((i2_irelfn = find_relocs_at_address (irel, internal_relocs, irelend,
-                                          R_NDS32_INSN16)) != irelend)
-    i2_irelfn->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_NDS32_NONE);
-
 }
 
 static bfd_boolean
@@ -11360,9 +12033,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 =
@@ -11389,7 +12064,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)
@@ -11576,7 +12252,8 @@ nds32_elf_relax_section (bfd *abfd, asection *sec,
       || (sec->flags & SEC_RELOC) == 0
       || (sec->flags & SEC_EXCLUDE) != 0
       || (sec->flags & SEC_CODE) == 0
-      || sec->size == 0)
+      || sec->size == 0
+      || sec->reloc_count == 0)
     return TRUE;
 
   /* 09.12.11 Workaround.  */
@@ -11585,10 +12262,19 @@ nds32_elf_relax_section (bfd *abfd, asection *sec,
   if (sec->alignment_power > 2)
     return TRUE;
 
+  /* Do TLS model conversion once at first.  */
+  nds32_elf_unify_tls_model (abfd, sec, contents, link_info);
+
   /* The optimization type to do.  */
 
   table = nds32_elf_hash_table (link_info);
 
+  /* Save the first section for abs symbol relaxation.
+     This is used for checking gp relaxation in the
+     nds32_elf_relax_loadstore and nds32_elf_relax_lo12.  */
+  nds32_elf_relax_guard (NULL, 0, sec, NULL, again, TRUE,
+                        table, NULL, NULL);
+
   /* The begining of general relaxation.  */
 
   if (is_SDA_BASE_set == 0)
@@ -11700,7 +12386,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;
@@ -11779,72 +12466,43 @@ 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)
        {
          if (!insert_nds32_elf_blank
@@ -11990,13 +12648,10 @@ void
 bfd_elf32_nds32_set_target_option (struct bfd_link_info *link_info,
                                   int relax_fp_as_gp,
                                   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)
+                                  FILE * sym_ld_script,
+                                  int hyper_relax,
+                                  int tls_desc_trampoline,
+                                  int load_store_relax)
 {
   struct elf_nds32_link_hash_table *table;
 
@@ -12007,18 +12662,12 @@ bfd_elf32_nds32_set_target_option (struct bfd_link_info *link_info,
   table->relax_fp_as_gp = relax_fp_as_gp;
   table->eliminate_gc_relocs = eliminate_gc_relocs;
   table->sym_ld_script = sym_ld_script;
+  table->hyper_relax = hyper_relax;
+  table->tls_desc_trampoline = tls_desc_trampoline;
   table ->load_store_relax = load_store_relax;
-  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;
 }
 \f
+
 /* These functions and data-structures are used for fp-as-gp
    optimization.  */
 
@@ -12204,7 +12853,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)
 {
@@ -12212,7 +12861,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;
 
@@ -12368,7 +13017,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.  */
@@ -12445,12 +13094,9 @@ nds32_fag_remove_unused_fpbase (bfd *abfd, asection *sec,
   bfd_boolean unused_region = FALSE;
 
   /*
-     NOTE: Disable fp-as-gp if we encounter ifcall relocations.
-     * R_NDS32_17IFC_PCREL_RELA
-     * R_NDS32_10IFCU_PCREL_RELA
-
-     CASE??????????????
-  */
+     NOTE: Disable fp-as-gp if we encounter ifcall relocations:
+       R_NDS32_17IFC_PCREL_RELA
+       R_NDS32_10IFCU_PCREL_RELA.  */
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   nds32_get_section_contents (abfd, sec, &contents, TRUE);
@@ -12658,8 +13304,765 @@ error_return:
   free (reloc_vector);
   return NULL;
 }
+
+/* Check target symbol.  */
+
+static bfd_boolean
+nds32_elf_is_target_special_symbol (bfd *abfd ATTRIBUTE_UNUSED, asymbol *sym)
+{
+  if (!sym || !sym->name || sym->name[0] != '$')
+    return FALSE;
+  return TRUE;
+}
+
+/* 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)
+{
+  if (nds32_elf_is_target_special_symbol (NULL, (asymbol *) sym))
+    return 0;
+
+  return _bfd_elf_maybe_function_sym (sym, sec, code_off);
+}
 \f
 
+/* Do TLS model conversion.  */
+
+typedef struct relax_group_list_t
+{
+  Elf_Internal_Rela *relo;
+  struct relax_group_list_t *next;
+  struct relax_group_list_t *next_sibling;
+  int id;
+} relax_group_list_t;
+
+int
+list_insert (relax_group_list_t *pHead, Elf_Internal_Rela *pElem);
+
+int
+list_insert_sibling (relax_group_list_t *pNode, Elf_Internal_Rela *pElem);
+
+void
+dump_chain (relax_group_list_t *pHead);
+
+int
+list_insert (relax_group_list_t *pHead, Elf_Internal_Rela *pElem)
+{
+  relax_group_list_t *pNext = pHead;
+
+  /* Find place.  */
+  while (pNext->next)
+    {
+      if (pNext->next->id > (int) pElem->r_addend)
+       break;
+
+      pNext = pNext->next;
+    }
+
+  /* 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;
+
+  pNew->id = pElem->r_addend;
+  pNew->relo = pElem;
+  pNew->next = tmp;
+  pNew->next_sibling = NULL;
+
+  return TRUE;
+}
+
+int
+list_insert_sibling (relax_group_list_t *pNode, Elf_Internal_Rela *pElem)
+{
+  relax_group_list_t *pNext = pNode;
+
+  /* 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;
+
+  relax_group_list_t *tmp = pNext->next_sibling;
+  pNext->next_sibling = pNew;
+
+  pNew->id = -1;
+  pNew->relo = pElem;
+  pNew->next = NULL;
+  pNew->next_sibling = tmp;
+
+  return TRUE;
+}
+
+void
+dump_chain (relax_group_list_t *pHead)
+{
+  relax_group_list_t *pNext = pHead->next;
+  while (pNext)
+    {
+      printf("group %d @ 0x%08x", pNext->id, (unsigned)pNext->relo->r_offset);
+      relax_group_list_t *pNextSib = pNext->next_sibling;
+      while (pNextSib)
+       {
+         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;
+
+      /* Check R_NDS32_RELAX_GROUP.  */
+      relend = relocs + asec->reloc_count;
+      for (rel = relocs; rel < relend; rel++)
+       {
+         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;
+       }
+    }
+  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;
+}
+
+/* Reorder RELAX_GROUP ID when command line option '-r' is applied.  */
+struct section_id_list_t *relax_group_section_id_list = NULL;
+
+struct section_id_list_t *
+elf32_nds32_lookup_section_id (int id, struct section_id_list_t **lst_ptr)
+{
+  struct section_id_list_t *result = NULL;
+  struct section_id_list_t *lst = *lst_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
+    {
+      struct section_id_list_t *cur = lst;
+      struct section_id_list_t *prv = NULL;
+      struct section_id_list_t *sec = NULL;
+
+      while (cur)
+       {
+         if (cur->id < id)
+           {
+             prv = cur;
+             cur = cur->next;
+             continue;
+           }
+
+         if (cur->id > id)
+           {
+             cur = NULL; /* To insert after prv.  */
+             sec = cur;  /* In case prv == NULL.  */
+           }
+
+         break;
+       }
+
+      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;
+           }
+         else
+           {
+             *lst_ptr = result;
+             result->next = sec;
+           }
+       }
+    }
+
+  return result;
+}
+
+int
+elf32_nds32_unify_relax_group (bfd *abfd, asection *asec)
+{
+  static int next_relax_group_bias = 0;
+
+  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 (0 == relax_group_ptr->count)
+       break;
+
+      /* Check if this section has been 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)
+       {
+         BFD_ASSERT (0); /* feed me */
+         break;
+       }
+
+      /* 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;
+       }
+
+      /* 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;
+
+         /* Change it.  */
+         rel->r_addend += relax_group_ptr->bias;
+         /* Debugging count.  */
+         count++;
+       }
+    }
+  while (FALSE);
+
+  if (relocs != NULL && elf_section_data (asec)->relocs != relocs)
+    free (relocs);
+
+  return result;
+}
+
+int
+nds32_elf_unify_tls_model (bfd *inbfd, asection *insec, bfd_byte *incontents,
+                          struct bfd_link_info *lnkinfo)
+{
+  bfd_boolean result = TRUE;
+  Elf_Internal_Rela *irel;
+  Elf_Internal_Rela *irelend;
+  Elf_Internal_Rela *internal_relocs;
+  unsigned long r_symndx;
+  enum elf_nds32_reloc_type r_type;
+
+  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);
+      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;
+    }
+
+  /* Collect group relocations.  */
+  /* Presume relocations are sorted.  */
+  relax_group_list_t *pNext = chain.next;
+  while (pNext)
+    {
+      for (irel = internal_relocs; irel < irelend; irel++)
+       {
+         if (irel->r_offset == pNext->relo->r_offset)
+           {
+             /* 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;
+
+             if (!list_insert_sibling (pNext, irel))
+               goto error_return;
+           }
+         else if (irel->r_offset > pNext->relo->r_offset)
+           {
+             pNext = pNext->next;
+             if (!pNext)
+               break;
+
+             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
+           {
+             /* This shouldn't be reached.  */
+           }
+       }
+      if (pNext)
+       pNext = pNext->next;
+    }
+
+#ifdef DUBUG_VERBOSE
+  dump_chain(&chain);
+#endif
+
+  /* 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;
+
+  char *local_got_tls_type = elf32_nds32_local_got_tls_type (inbfd);
+
+  /* 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)
+    {
+      relax_group_list_t *pNextSig = pNext->next_sibling;
+      while (pNextSig)
+       {
+         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)
+           {
+             cur_grp_id = pNext->id;
+             org_tls_type = get_tls_type (r_type, NULL);
+             if (r_symndx >= symtab_hdr->sh_info)
+               {
+                 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
+               {
+                 tls_type = local_got_tls_type
+                   ? local_got_tls_type[r_symndx]
+                   : GOT_NORMAL;
+               }
+
+             eff_tls_type = 1 << (fls (tls_type) - 1);
+             sethi_rt = N32_RT5(bfd_getb32 (contents + irel->r_offset));
+           }
+
+         if (eff_tls_type != org_tls_type)
+           {
+             switch (org_tls_type)
+               {
+                 /* DESC to IEGP/IE/LE.  */
+               case GOT_TLS_DESC:
+                 switch (eff_tls_type)
+                   {
+                   case GOT_TLS_IE:
+                     switch (r_type)
+                       {
+                       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);
+                         }
+                         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;
+                       }
+                     break;
+                   case GOT_TLS_IEGP:
+                     switch (r_type)
+                       {
+                       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);
+                         }
+                         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;
+                       }
+                     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:
+                     break;
+                   }
+                 break;
+                 /* IEGP to IE/LE.  */
+               case GOT_TLS_IEGP:
+                 switch (eff_tls_type)
+                   {
+                   case GOT_TLS_IE:
+                     switch (r_type)
+                       {
+                       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;
+                       }
+                     break;
+                   case GOT_TLS_LE:
+                     switch (r_type)
+                       {
+                       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:
+                         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;
+                       }
+                     break;
+                   default:
+                     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_LOADSTORE:
+                       case R_NDS32_PTR:
+                       case R_NDS32_NONE:
+                       case R_NDS32_LABEL:
+                         break;
+                       default:
+                         BFD_ASSERT(0);
+                         break;
+                       }
+                     break;
+                   default:
+                     break;
+                   }
+                 break;
+               default:
+                 break;
+               }
+           }
+         pNextSig = pNextSig->next_sibling;
+       }
+
+#if 1
+      pNext = pNext->next;
+#else
+      while (pNext)
+       {
+         if (pNext->id != cur_grp_id)
+           break;
+         pNext = pNext->next;
+       }
+#endif
+    }
+
+finish:
+  if (incontents)
+    contents = NULL;
+
+  if (internal_relocs != NULL
+      && elf_section_data (insec)->relocs != internal_relocs)
+    free (internal_relocs);
+
+  if (contents != NULL
+      && elf_section_data (insec)->this_hdr.contents != contents)
+    free (contents);
+
+  if (local_syms != NULL && symtab_hdr->contents != (bfd_byte *) local_syms)
+    free (local_syms);
+
+  if (chain.next)
+    {
+      pNext = chain.next;
+      relax_group_list_t *pDel;
+      while (pNext)
+       {
+         pDel = pNext;
+         pNext = pNext->next;
+         free (pDel);
+       }
+    }
+
+  return result;
+
+error_return:
+  result = FALSE;
+  goto finish;
+}
+
+/* End TLS model conversion.  */
+
 #define ELF_ARCH                               bfd_arch_nds32
 #define ELF_MACHINE_CODE                       EM_NDS32
 #define ELF_MAXPAGESIZE                                0x1000
@@ -12701,6 +14104,8 @@ error_return:
 #define elf_backend_special_sections           nds32_elf_special_sections
 #define bfd_elf32_bfd_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
@@ -12711,22 +14116,22 @@ error_return:
 #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
+#define elf_backend_dtrel_excludes_plt         0
 
 #include "elf32-target.h"
 
 #undef ELF_MAXPAGESIZE
 #define ELF_MAXPAGESIZE                                0x2000
 
-#undef TARGET_BIG_SYM
+#undef  TARGET_BIG_SYM
 #define TARGET_BIG_SYM                         nds32_elf32_linux_be_vec
-#undef TARGET_BIG_NAME
+#undef  TARGET_BIG_NAME
 #define TARGET_BIG_NAME                                "elf32-nds32be-linux"
-#undef TARGET_LITTLE_SYM
+#undef  TARGET_LITTLE_SYM
 #define TARGET_LITTLE_SYM                      nds32_elf32_linux_le_vec
-#undef TARGET_LITTLE_NAME
+#undef  TARGET_LITTLE_NAME
 #define TARGET_LITTLE_NAME                     "elf32-nds32le-linux"
-#undef elf32_bed
+#undef  elf32_bed
 #define elf32_bed                              elf32_nds32_lin_bed
 
 #include "elf32-target.h"
index bf2e93f581c535d801fc52076a733d9aa4bb551a..5817e3bf5a253f6677f4fe769fafd63a8484af7b 100644 (file)
@@ -40,12 +40,6 @@ extern "C" {
 /* To distinguish the assembly code generated by compiler
    or written manually.  */
 #define R_NDS32_RELAX_ENTRY_VERBATIM_FLAG                      (1 << 28)
-/* EX9 and link-time IFC must be explicitly enabled, so we
-   won't mess up handcraft assembly code.  */
-/* Enable EX9 optimization for this section.  */
-#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)
@@ -73,8 +67,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,43 +83,38 @@ enum
   NDS32_LOADSTORE_IMM = 0x20
 };
 
-/* Relax tag for nds32_elf_relax_section, we have to specify which
-   optimization do in this round.  */
-enum
+struct section_id_list_t
 {
-  NDS32_RELAX_NONE_ROUND = 0,
-  NDS32_RELAX_NORMAL_ROUND,
-  NDS32_RELAX_JUMP_IFC_ROUND,
-  NDS32_RELAX_EX9_BUILD_ROUND,
-  NDS32_RELAX_EX9_REPLACE_ROUND,
-  NDS32_RELAX_EMPTY_ROUND
+  int id;
+  struct section_id_list_t *next;
 };
 
-/* Optimization status mask.  */
-#define NDS32_RELAX_JUMP_IFC_DONE      (1 << 0)
-#define NDS32_RELAX_EX9_DONE           (1 << 1)
-
-/* Optimization turn on mask.  */
-#define NDS32_RELAX_JUMP_IFC_ON                (1 << 0)
-#define NDS32_RELAX_EX9_ON             (1 << 1)
-\f
+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 nds32_insertion_sort
-  (void *, size_t, size_t, int (*) (const void *, const void *));
+(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);
+                                                     int, int, FILE *,
+                                                     int, int, int);
 
 #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)
 
+#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.  */
 
@@ -143,24 +130,43 @@ struct elf_nds32_link_hash_table
   struct sym_cache sym_cache;
 
   /* Target dependent options.  */
-  int relax_fp_as_gp;          /* --mrelax-omit-fp  */
-  int eliminate_gc_relocs;     /* --meliminate-gc-relocs  */
-  FILE *sym_ld_script;         /* --mgen-symbol-ld-script=<file>  */
+  int relax_fp_as_gp;          /* --mrelax-omit-fp.  */
+  int eliminate_gc_relocs;     /* --meliminate-gc-relocs.  */
+  FILE *sym_ld_script;         /* --mgen-symbol-ld-script=<file>.  */
+  bfd_boolean hyper_relax;     /* Relax for symbol not in RW sections.  */
+  int tls_desc_trampoline;     /* --m[no-]tlsdesc-trampoline.  */
   /* Disable if linking a dynamically linked executable.  */
   int load_store_relax;
-  int target_optimize;         /* Switch optimization.  */
-  int relax_status;            /* Finished optimization.  */
-  int relax_round;             /* Going optimization.  */
-  FILE *ex9_export_file;       /* --mexport-ex9=<file>  */
-  FILE *ex9_import_file;       /* --mimport-ex9=<file>  */
-  int update_ex9_table;                /* --mupdate-ex9.  */
-  int ex9_limit;
-  bfd_boolean ex9_loop_aware;  /* Ignore ex9 if inside a loop.  */
-  bfd_boolean ifc_loop_aware;  /* Ignore ifc if inside a loop.  */
+
+  /* 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
 }
 #endif
 
-#endif
+#endif /* ELF32_NDS32_H */
index 34f05dd2e70d61dae16ed896f69358b8ed3feca3..d37716c3633fdc29b43c8fef64d7071fff577067 100644 (file)
@@ -2002,18 +2002,34 @@ 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_LSI",
   "BFD_RELOC_V850_9_PCREL",
   "BFD_RELOC_V850_22_PCREL",
   "BFD_RELOC_V850_SDA_16_16_OFFSET",
index 67457418e6ed6358dfd09259fc0fe48a94ef26d8..07be1a4c7bfbf323f6804d07bc9b87cd43289fac 100644 (file)
@@ -4253,32 +4253,66 @@ ENUMDOC
   For ex9 and ifc using.
 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_NDS32_LSI
+ENUMDOC
+  For floating load store relaxation.
 
 
 ENUM
index 8c7a9e6fac983afe60e7c2f65d5269f33c5d79a8..d8e7f498c1e177391f23ad0c8b638b4025938228 100644 (file)
@@ -1,3 +1,8 @@
+2018-09-20  Nelson Chu <nelson.chu1990@gmail.com>
+
+       * testsuite/binutils-all/objcopy.exp: Set the unsupported reloc number
+       from 215 to 255 for NDS32.
+
 2018-09-17  H.J. Lu  <hongjiu.lu@intel.com>
 
        * objcopy.c (strip_specific_buffer): New.
index 3c88ba906904466b46dbd1dc1d46820c6b160e29..2d8ffa1a906450f30a2a8782d997a9feaf2dcb48 100644 (file)
@@ -12,8 +12,9 @@
 #...
   \[[ 0-9]+\] \.data.*[ \t]+PROGBITS[ \t0-9a-f]+WAG.*
 #...
-COMDAT group section \[[ 0-9]+\] `\.group' \[foo_group\] contains 2 sections:
+COMDAT group section \[[ 0-9]+\] `\.group' \[foo_group\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   .text.*
+#...
    \[[ 0-9]+\]   .data.*
 #pass
index df9935e6c9c04fdd32bdd23159ceab4deb535fec..a1610297adc68b4980b2a44d5488b4a3b0c5fbdb 100644 (file)
@@ -1098,7 +1098,11 @@ if [is_elf_format] {
        set reloc_format mips64
     }
     # A relocation type not supported by any target
-    set reloc 215
+    if { [istarget "nds32*-*"] } {
+       set reloc 255
+    } else {
+       set reloc 215
+    }
     run_dump_test "strip-13" [list \
                                  [list source strip-13${reloc_format}.s] \
                                  [list as "${elf64} --defsym RELOC=${reloc}"]]
index 9922f475dc9755c2c16e884924f42379d52cb4a3..6b97de295471d5153bc99dbcd729440bf66cf4dc 100644 (file)
@@ -11,8 +11,9 @@
 #...
   \[[ 0-9]+\] \.data.*[ \t]+PROGBITS[ \t0-9a-f]+WAG[ \t]+.*
 #...
-COMDAT group section \[[ 0-9]+\] `\.group' \[foo_group\] contains 2 sections:
+COMDAT group section \[[ 0-9]+\] `\.group' \[foo_group\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   .text.*
+#...
    \[[ 0-9]+\]   .data.*
 #pass
index 8dd233183f8f330d1709f3f66834bb599afc8893..cbe517c33551141e51a00ebc5a553f2d4991f709 100644 (file)
@@ -11,8 +11,9 @@
 #...
   \[[ 0-9]+\] \.data.*[ \t]+PROGBITS[ \t0-9a-f]+WAG[ \t]+.*
 #...
-COMDAT group section \[[ 0-9]+\] `.group' \[.text.foo\] contains 2 sections:
+COMDAT group section \[[ 0-9]+\] `.group' \[.text.foo\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   .text.*
+#...
    \[[ 0-9]+\]   .data.*
 #pass
index 791463b81b7500e967ab81532f4577af8d23b81a..d8a2ba8e87e60c2c9065e0f279c886a33cf0d4b7 100644 (file)
@@ -11,8 +11,9 @@
 #...
   \[[ 0-9]+\] \.data.*[ \t]+PROGBITS[ \t0-9a-f]+WAG[ \t]+.*
 #...
-COMDAT group section \[[ 0-9]+\] `.group' \[foo3\] contains 2 sections:
+COMDAT group section \[[ 0-9]+\] `.group' \[foo3\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   .text.*
+#...
    \[[ 0-9]+\]   .data.*
 #pass
index 7f07a0da377b94fabb55efa905f387f2707d762c..36ee7a0fbaacebb15e46c6575f595890cd0a82c6 100644 (file)
@@ -11,8 +11,9 @@
 #...
   \[[ 0-9]+\] \.data.*[ \t]+PROGBITS[ \t0-9a-f]+WAG[ \t]+.*
 #...
-COMDAT group section \[[ 0-9]+\] `.group' \[foo4\] contains 2 sections:
+COMDAT group section \[[ 0-9]+\] `.group' \[foo4\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   .text.*
+#...
    \[[ 0-9]+\]   .data.*
 #pass
index 6f2a1ef319dfbb85124bb2325f840050b6690231..d495233e717d403bae4ebb82873b2fd2b1f64ca8 100644 (file)
@@ -1,3 +1,82 @@
+2018-09-20  Nelson Chu <nelson.chu1990@gmail.com>
+
+       * config/tc-nds32.c: Remove the unused target features.
+       (nds32_relax_relocs, md_pseudo_table, nds32_elf_record_fixup_exp,
+       nds32_set_elf_flags_by_insn, nds32_insert_relax_entry,
+       nds32_apply_fix): Likewise.
+       (nds32_no_ex9_begin): Removed.
+       * config/tc-nds32.c (add_mapping_symbol_for_align,
+       make_mapping_symbol, add_mapping_symbol): New functions.
+       * config/tc-nds32.h (enum mstate): New.
+       (nds32_segment_info_type): Likewise.
+       * configure.ac (--enable-dsp-ext, --enable-zol-ext): New options.
+       * config.in: Regenerated.
+       * configure: Regenerated.
+       * config/tc-nds32.c (nds32_dx_regs):
+       Set the value according to the configuration.
+       (nds32_perf_ext, nds32_perf_ext2, nds32_string_ext, nds32_audio_ext):
+       Likewise.
+       (nds32_dsp_ext): New variable. Set the value according to the
+       configuration.
+       (nds32_zol_ext): Likewise.
+       (asm_desc, nds32_pseudo_opcode_table): Make them static.
+       (nds32_set_elf_flags_by_insn): Updated.
+       (nds32_check_insn_available): Updated.
+       (nds32_str_tolower): New function.
+       * config/tc-nds32.c (relax_table): Updated.
+       (md_begin): Updated.
+       (md_assemble): Use XNEW macro to allocate space for `insn.info',
+       and then remember to free it.
+       (md_section_align): Cast (-1) to ValueT.
+       (nds32_get_align): Cast (~0U) to addressT.
+       (nds32_relax_branch_instructions): Updated.
+       (md_convert_frag): Add new local variable `final_r_type'.
+       (invalid_prev_frag): Add new bfd_boolean parameter `relax'.
+       All callers changed.
+       * config/tc-nds32.c (struct nds32_relocs_pattern): Add `insn' field.
+       (struct nds32_hint_map): Add `option_list' field.
+       (struct suffix_name, suffix_table): Remove the unused `pic' field.
+       (do_pseudo_b, do_pseudo_bal): Remove the suffix checking.
+       (do_pseudo_la_internal, do_pseudo_pushpopm): Indent.
+       (relax_hint_bias, relax_hint_id_current): New static variables.
+       (reset_bias, relax_hint_begin): New variables.
+       (nds_itoa): New function.
+       (CLEAN_REG, GET_OPCODE): New macros.
+       (struct relax_hint_id): New.
+       (nds32_relax_hint): For .relax_hint directive, we can use `begin'
+       and `end' to mark the relax pattern without giving exactly id number.
+       (nds32_elf_append_relax_relocs): Handle the case that the .relax_hint
+       directives are attached to pseudo instruction.
+       (nds32_elf_save_pseudo_pattern): Change the second parameter from
+       instruction's opcode to byte code.
+       (nds32_elf_build_relax_relation): Add new bfd_boolean parameter
+       `pseudo_hint'.
+       (nds32_lookup_pseudo_opcode): Fix the overflow issue.
+       (enum nds32_insn_type): Add N32_RELAX_ALU1 and N32_RELAX_16BIT.
+       (nds32_elf_record_fixup_exp, relax_ls_table, hint_map,
+       nds32_find_reloc_table, nds32_match_hint_insn, nds32_parse_name):
+       Updated.
+       * config/tc-nds32.h (MAX_RELAX_NUM): Extend it to 6.
+       (enum nds32_relax_hint_type): Merge NDS32_RELAX_HINT_LA and
+       NDS32_RELAX_HINT_LS into NDS32_RELAX_HINT_LALS. Add
+       NDS32_RELAX_HINT_LA_PLT, NDS32_RELAX_HINT_LA_GOT and
+       NDS32_RELAX_HINT_LA_GOTOFF.
+       * config/tc-nds32.h (relax_ls_table): Add floating load/store
+       to gp relax pattern.
+       (hint_map, nds32_find_reloc_table): Likewise.
+       * configure.ac: Define NDS32_LINUX_TOOLCHAIN.
+       * configure: Regenerated.
+       * config.in: Regenerated.
+       * config/tc-nds32.h (enum nds32_ramp): Updated.
+       (enum nds32_relax_hint_type): Likewise.
+       * config/tc-nds32.c: Include "errno.h" and "limits.h".
+       (relax_ls_table): Add TLS relax patterns.
+       (nds32_elf_append_relax_relocs): Attach BFD_RELOC_NDS32_GROUP on
+       each instructions of TLS patterns.
+       (nds32_elf_record_fixup_exp): Updated.
+       (nds32_apply_fix): Likewise.
+       (suffix_table): Add TLSDESC suffix.
+
 2018-09-18 Tamar Christina  <tamar.christina@arm.com>
 
        * config/tc-aarch64.c (output_operand_error_report): Apply filtering to
index 1170689ef18049a56b0988ad6b343cb4c8a22d0b..9c15a070a33770e8ec261d222f17f88d640471bd 100644 (file)
 /* 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
 
 /* Define default value for nds32_string_ext */
 #undef NDS32_DEFAULT_STRING_EXT
 
+/* Define default value for nds32_zol_ext */
+#undef NDS32_DEFAULT_ZOL_EXT
+
+/* Define default value for nds32_linux_toolchain */
+#undef NDS32_LINUX_TOOLCHAIN
+
 /* Define if environ is not declared in system header files. */
 #undef NEED_DECLARATION_ENVIRON
 
index 01bc17b6c22e8f09feccaa3b88a9ec44e07db966..24dc3906313ef700f41f0c85747ec0d5bf515ad9 100644 (file)
@@ -35,6 +35,8 @@
 #include "opcode/nds32.h"
 
 #include <stdio.h>
+#include <errno.h>
+#include <limits.h>
 
 /* GAS definitions.  */
 
@@ -66,6 +68,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 +77,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,10 +90,6 @@ 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.  */
 static int optimize = 0;
 /* Save option -Os for code size.  */
@@ -110,60 +109,78 @@ enum ict_option {
 };
 static enum ict_option ict_flag = ICT_NONE;
 \f
+
 static struct hash_control *nds32_relax_info_hash;
+
+/* Branch patterns.  */
 static relax_info_t relax_table[] =
 {
   {
-    "jal",                                     /* opcode */
-    BR_RANGE_S16M,                             /* br_range */
-    {{0, 0, 0, FALSE}},                        /* cond_field */
-    {
+    .opcode = "jal",
+    .br_range = BR_RANGE_S16M,
+    .cond_field =
       {
-        INSN_JAL /* jal label */
-      }, /* BR_RANGE_S256 */
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
       {
-        INSN_JAL /* jal label */
-      }, /* BR_RANGE_S16K */
+       INSN_JAL        /* jal label */
+      },
+    .relax_code_size[BR_RANGE_S256] = 4,
+    .relax_branch_isize[BR_RANGE_S256] = 4,
+    .relax_fixup[BR_RANGE_S256] =
       {
-        INSN_JAL /* jal label */
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_JAL /* jal label */
-      }, /* BR_RANGE_S16M */
+       INSN_JAL        /* jal label */
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        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}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       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}
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       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}
-      }, /* BR_RANGE_S16M */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
       {
-        {0, 4, 0, BFD_RELOC_NDS32_HI20},
+       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},
@@ -171,169 +188,213 @@ static relax_info_t relax_table[] =
        {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 */
+    .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] =
       {
-        INSN_BLTZAL /* bltzal $rt, label */
-      }, /* BR_RANGE_S16K */
-      {
-        INSN_BLTZAL /* bltzal $rt, label */
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-       INSN_BGEZ, /* bgez $rt, $1 */
-        INSN_JAL /* jal label */
-      }, /* BR_RANGE_S16M */
+       INSN_BGEZAL     /* bgezal $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-       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},
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       INSN_BGEZAL     /* bgezal $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* 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, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[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 */
-    {
+       INSN_BLTZ,      /* bltz $rt, $1 */
+       INSN_JAL        /* jal label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {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_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {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] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       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, 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, 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_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, 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 */
+       {0, 0, 0, 0}
+      },
   },
   {
-    "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 */
+    .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] =
       {
-        INSN_BGEZAL /* bgezal $rt, label */
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_BGEZAL /* bgezal $rt, label */
-      }, /* BR_RANGE_S64K */
+       INSN_BLTZAL     /* bltzal $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        INSN_BLTZ, /* bltz $rt, $1 */
-        INSN_JAL /* jal label */
-      }, /* BR_RANGE_S16M */
+       {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] =
       {
-        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, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       INSN_BLTZAL     /* bltzal $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* 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, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[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 */
-    {
+       INSN_BGEZ,      /* bgez $rt, $1 */
+       INSN_JAL        /* jal label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {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_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {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] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       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, 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, 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_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, 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},
@@ -341,60 +402,74 @@ static relax_info_t relax_table[] =
        {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 */
-    {
+    .opcode = "j",
+    .br_range = BR_RANGE_S16M,
+    .cond_field =
       {
-        (INSN_J8 << 16) /* j8 label */
-      }, /* BR_RANGE_S256 */
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
       {
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16K */
+       (INSN_J8 << 16) /* j8 label */
+      },
+    .relax_code_size[BR_RANGE_S256] = 2,
+    .relax_branch_isize[BR_RANGE_S256] = 2,
+    .relax_fixup[BR_RANGE_S256] =
       {
-        INSN_J /* j label */
-      }, /* BR_RANGE_S64K */
+       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       INSN_J          /* j label */
+      },
+    . relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        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, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       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}
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       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}
-      }, /* 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, 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},
@@ -402,60 +477,74 @@ static relax_info_t relax_table[] =
        {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 */
-    {
+    .opcode = "j8",
+    .br_range = BR_RANGE_S256,
+    .cond_field =
       {
-        (INSN_J8 << 16) /* j8 label */
-      }, /* BR_RANGE_S256 */
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
       {
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16K */
+       (INSN_J8 << 16) /* j8 label */
+      },
+    .relax_code_size[BR_RANGE_S256] = 2,
+    .relax_branch_isize[BR_RANGE_S256] = 2,
+    .relax_fixup[BR_RANGE_S256] =
       {
-        INSN_J /* j label */
-      }, /* BR_RANGE_S64K */
+       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       INSN_J          /* j label */
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        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, 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, 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}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       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}
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       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, 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},
@@ -463,85 +552,113 @@ static relax_info_t relax_table[] =
        {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 */
-    {
+    .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] =
       {
-        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, 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] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       INSN_BEQZ       /* beqz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {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, 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, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       INSN_BEQZ       /* beqz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* 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}
-      }, /* BR_RANGE_S16M */
+      },
+
+    .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, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {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},
@@ -551,83 +668,104 @@ static relax_info_t relax_table[] =
        {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 */
+       {0, 0, 0, 0}
+      },
   },
   {
-    "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 */
+    .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] =
       {
-        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, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       INSN_BGEZ       /* bgez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* 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, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       INSN_BGEZ       /* bgez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {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, 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}
-      }, /* BR_RANGE_S256 */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       INSN_BLTZ,      /* bltz $rt, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {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}
-      }, /* BR_RANGE_S16M */
+       {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_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},
@@ -637,85 +775,107 @@ static relax_info_t relax_table[] =
        {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 */
+    .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] =
       {
-        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, 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] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       INSN_BNEZ       /* bnez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* 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, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       INSN_BNEZ       /* bnez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {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, 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, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       INSN_BEQZ,      /* beqz $rt, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {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}
-      }, /* BR_RANGE_S16M */
+       {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, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {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},
@@ -726,82 +886,104 @@ static relax_info_t relax_table[] =
        {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 */
-    {
+    .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] =
       {
-        INSN_BGTZ /* bgtz $rt, label */
-      }, /* BR_RANGE_S256 */
-      {
-        INSN_BGTZ /* bgtz $rt, label */
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_BGTZ /* bgtz $rt, label */
-      }, /* BR_RANGE_S64K */
+       INSN_BGTZ       /* bgtz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        INSN_BLEZ, /* blez $rt, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       {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] =
       {
-        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, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       INSN_BGTZ       /* bgtz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       {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, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* 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}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {4, 4, 4, 8, 16},                          /* relax_code_size */
-    {4, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       {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_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {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] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       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, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {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_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},
@@ -811,82 +993,104 @@ static relax_info_t relax_table[] =
        {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 */
+    .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] =
       {
-        INSN_BLEZ /* blez $rt, label */
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_BLEZ /* blez $rt, label */
-      }, /* BR_RANGE_S64K */
+       INSN_BLEZ       /* blez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        INSN_BGTZ, /* bgtz $rt, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       {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] =
       {
-        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, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       INSN_BLEZ       /* blez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       {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, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* 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}
-      } /* BR_RANGE_U4G */
-    },                                         /* relax_code_condition */
-    {4, 4, 4, 8, 16},                          /* relax_code_size */
-    {4, 4, 4, 4, 4},                           /* relax_branch_isize */
-    {
+       {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_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {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] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       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, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {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_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},
@@ -896,82 +1100,104 @@ static relax_info_t relax_table[] =
        {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 */
-    {
+    .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] =
       {
-        INSN_BLTZ /* bltz $rt, label */
-      }, /* 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 */
-      }, /* BR_RANGE_S16K */
+       INSN_BLTZ       /* bltz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        INSN_BLTZ /* bltz $rt, label */
-      }, /* BR_RANGE_S64K */
+       {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] =
       {
-        INSN_BGEZ, /* bgez $rt, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        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 */
-    {
+       INSN_BLTZ       /* bltz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       {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, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       INSN_BGEZ,      /* bgez $rt, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* 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, 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_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] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       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, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {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_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},
@@ -981,97 +1207,118 @@ static relax_info_t relax_table[] =
        {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 */
+    .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] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 15, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       INSN_BEQ        /* beq $rt, $ra, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {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}
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {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, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
-        {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       INSN_BNE,       /* bne $rt, $ra, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {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}
-      }, /* BR_RANGE_S64K */
+       {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_ABS, BFD_RELOC_NDS32_EMPTY},
        {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16M */
+       {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, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {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},
@@ -1082,96 +1329,118 @@ static relax_info_t relax_table[] =
        {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 */
+    .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] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 15, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       INSN_BNE        /* bne $rt, $ra, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {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}
+      },
+    .relax_code_size[BR_RANGE_S16K] = 4,
+    .relax_branch_isize[BR_RANGE_S16K] = 4,
+    .relax_fixup[BR_RANGE_S16K] =
       {
-        {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, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
-        {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       INSN_BEQ,       /* beq $rt, $ra, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {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}
-      }, /* BR_RANGE_S64K */
+       {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}
-      }, /* BR_RANGE_S16M */
+       {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, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {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},
@@ -1182,84 +1451,106 @@ static relax_info_t relax_table[] =
        {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 */
+    .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] =
       {
-        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, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        {0, 8, 0x7, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       INSN_BEQZ       /* beqz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* 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, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       INSN_BEQZ       /* beqz $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {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, 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, 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}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       INSN_BNEZ,      /* bnez $rt, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {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}
-      }, /* BR_RANGE_S16M */
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       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},
@@ -1270,84 +1561,106 @@ static relax_info_t relax_table[] =
        {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 */
+    .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] =
       {
-        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, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        {0, 8, 0x7, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
+       INSN_BNEZ       /* bnez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* 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, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       INSN_BNEZ       /* bnez $rt, label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {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, 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, 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}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       INSN_BEQZ,      /* beqz $rt, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       {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}
-      }, /* BR_RANGE_S16M */
+       {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, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {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},
@@ -1358,66 +1671,80 @@ static relax_info_t relax_table[] =
        {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 = "beqzs8",
+    .br_range = BR_RANGE_S256,
+    .cond_field =
       {
-        INSN_BEQZS8 << 16 /* beqz $r15, label */
-      }, /* BR_RANGE_S256 */
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
       {
-        INSN_BEQZ_TA /* bnez $rt, label */
-      }, /* BR_RANGE_S16K */
+       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] =
       {
-        INSN_BEQZ_TA /* bnez $rt, label */
-      }, /* BR_RANGE_S64K */
+       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_BNEZ_TA, /* bnez $r15, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       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] =
       {
-        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 */
-    {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       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}
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       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}
-      }, /* BR_RANGE_S16M */
+       {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 $ta */
+      },
+    .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_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},
@@ -1427,67 +1754,81 @@ static relax_info_t relax_table[] =
        {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 */
+       {0, 0, 0, 0}
+      },
   },
   {
-    "bnezs8",                                  /* opcode */
-    BR_RANGE_S256,                             /* br_range */
-    {{0, 0, 0, FALSE}},                        /* cond_field */
-    {
+    .opcode = "bnezs8",
+    .br_range = BR_RANGE_S256,
+    .cond_field =
       {
-        INSN_BNEZS8 << 16 /* bnez $r15, label */
-      }, /* BR_RANGE_S256 */
+       {0, 0, 0, FALSE}
+      },
+    .relax_code_seq[BR_RANGE_S256] =
       {
-        INSN_BNEZ_TA /* bnez $r15, label */
-      }, /* BR_RANGE_S16K */
+       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] =
       {
-        INSN_BNEZ_TA /* bnez $r15, label */
-      }, /* BR_RANGE_S64K */
+       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        INSN_BEQZ_TA, /* beqz $r15, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       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] =
       {
-        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 */
-    {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       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}
-      }, /* BR_RANGE_S16K */
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S64K */
+       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}
-      }, /* BR_RANGE_S16M */
+       {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 $ta */
+      },
+    .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_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},
@@ -1498,89 +1839,111 @@ static relax_info_t relax_table[] =
        {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 */
-    {
-      {0, 8, 0x7, FALSE},
-      {0, 0, 0, FALSE}
-    },                                                 /* cond_field */
-    {
-      {
-        INSN_BNES38 << 16 /* bne $rt, $R5, label */
-      }, /* BR_RANGE_S256 */
+    .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] =
       {
-        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 */
-    {
-      {
-        {0, 8, 0x7, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
-      {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       INSN_BNE_R5     /* bne $rt, $r5, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       {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, 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 */
-    {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       INSN_BEQ_R5,    /* beq $rt, $r5, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {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}
-      }, /* BR_RANGE_S64K */
+       {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}
-      }, /* BR_RANGE_S16M */
+       {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 $ta */
+      },
+    .relax_code_condition[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {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},
@@ -1591,89 +1954,111 @@ static relax_info_t relax_table[] =
        {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 */
-    {
-      {0, 8, 0x7, 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] =
       {
-        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 */
-    {
-      {
-        {0, 8, 0x7, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S256 */
-      {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S64K */
+       INSN_BEQ_R5     /* beq $rt, $r5, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16M */
+       {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, 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 */
-    {
+       {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-       {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       INSN_BNE_R5,    /* bne $rt, $r5, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S64K] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S16K */
+       {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}
-      }, /* BR_RANGE_S64K */
+       {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}
-      }, /* BR_RANGE_S16M */
+       {0, 0, 0, 0}
+      },
+
+    .relax_code_seq[BR_RANGE_U4G] =
       {
-        {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
+       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 */
+      },
+    .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},
@@ -1684,191 +2069,238 @@ static relax_info_t relax_table[] =
        {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 */
-    {
-      {0, 8, 0x7FF, TRUE},
-      {0, 20, 0x1F, FALSE},
-      {0, 0, 0, FALSE}
-    },                                                 /* cond_field */
-    {
-      {
-        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 */
+    .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_BNEC, /* bnec $rt, imm11s, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       INSN_MOVI_TA,   /* movi $ta, imm11s */
+       INSN_BEQ_TA     /* beq $rt, $ta, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        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 */
-    {
+       {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, 8, 0x7FF, TRUE},
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* 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}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 0, 0xFFFFF, FALSE},
-        {4, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       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}
-      }, /* 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, 8, 0x7FF, FALSE},
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* 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_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 */
-    {
+       INSN_BNEC,      /* bnec $rt, imm11s, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {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_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},
+       {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 $ta */
+      },
+    .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}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
+       {0, 0, 0, 0}
+      },
   },
   {
-    "bnec",                                    /* opcode */
-    BR_RANGE_S256,                             /* br_range */
-    {
-      {0, 8, 0x7FF, TRUE},
-      {0, 20, 0x1F, FALSE},
-      {0, 0, 0, FALSE}
-    },                                                 /* cond_field */
-    {
-      {
-        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 */
+    .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_BEQC, /* beqc $rt, imm11s, $1 */
-        INSN_J /* j label */
-      }, /* BR_RANGE_S16M */
+       INSN_MOVI_TA,   /* movi $ta, imm11s */
+       INSN_BNE_TA     /* bne $rt, $ta, label */
+      },
+    .relax_code_condition[BR_RANGE_S16K] =
       {
-        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 */
-    {
+       {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, 8, 0x7FF, TRUE},
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* 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}
+      },
+
+    .relax_code_seq[BR_RANGE_S64K] =
       {
-        {0, 0, 0xFFFFF, FALSE},
-        {4, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* BR_RANGE_S16K */
+       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}
-      }, /* 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, 8, 0x7FF, FALSE},
-        {0, 20, 0x1F, FALSE},
-        {0, 0, 0, FALSE}
-      }, /* 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_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 */
-    {
+       INSN_BEQC,      /* beqc $rt, imm11s, $1 */
+       INSN_J          /* j label */
+      },
+    .relax_code_condition[BR_RANGE_S16M] =
       {
-        {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
-        {0, 0, 0, 0}
-      }, /* BR_RANGE_S256 */
+       {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_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},
+       {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 $ta */
+      },
+    .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}
-      } /* BR_RANGE_U4G */
-    }                                          /* relax_fixup */
-  }
+       {0, 0, 0, 0}
+      },
+  },
+  {
+    .opcode = NULL,
+  },
 };
 \f
+
 /* GAS definitions for command-line options.  */
 enum options
 {
@@ -1935,6 +2367,9 @@ static int nds32_parse_arch (const char *str);
 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 [] =
 {
@@ -1959,11 +2394,13 @@ static struct nds32_parse_option_table parse_opts [] =
 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;
@@ -1994,6 +2431,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}
 };
 
@@ -2007,7 +2446,7 @@ nds32_asm_parse_operand (struct nds32_asm_desc *pdesc,
                         char **pstr, int64_t *value);
 
 \f
-struct nds32_asm_desc asm_desc;
+static struct nds32_asm_desc asm_desc;
 
 /* md_after_parse_args ()
 
@@ -2196,7 +2635,7 @@ do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[],
   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);
@@ -2217,12 +2656,11 @@ do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[],
   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
@@ -2336,7 +2774,7 @@ 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);
@@ -2690,11 +3128,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
@@ -2898,7 +3336,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},
@@ -2974,8 +3412,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 },
@@ -3015,22 +3453,23 @@ nds32_init_nds32_pseudo_opcodes (void)
 static struct nds32_pseudo_opcode *
 nds32_lookup_pseudo_opcode (const char *str)
 {
+  struct nds32_pseudo_opcode *result;
   int i = 0;
-  /* Assume pseudo-opcode are less than 16-char in length.  */
-  char op[16] = {0};
 
-  for (i = 0; i < (int)ARRAY_SIZE (op); i++)
+  /* (*op) is the first word of current source line (*str)  */
+  int maxlen = strlen (str);
+  char *op = xmalloc (maxlen + 1);
+
+  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);
+  result = hash_find (nds32_pseudo_opcode_hash, op);
+  free (op);
+  return result;
 }
 
 static void
@@ -3205,6 +3644,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;
 }
@@ -3418,6 +3861,21 @@ 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 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,
      LBYTE: .byte      0x12
@@ -3451,7 +3909,10 @@ nds32_adjust_label (int n)
   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);
 
@@ -3516,16 +3977,70 @@ nds32_cons_align (int size ATTRIBUTE_UNUSED)
      I think we should just adjust label in `nds32_aligned_X_cons' instead of here.  */
 }
 
+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;
@@ -3585,7 +4100,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))
@@ -3602,14 +4117,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;
@@ -3659,31 +4166,6 @@ 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)
-{
-  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;
-      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;
-      fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
-                  BFD_RELOC_NDS32_RELAX_REGION_END);
-    }
-}
-
 static void
 nds32_loop_begin (int mode)
 {
@@ -3713,16 +4195,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))
@@ -3731,12 +4246,57 @@ 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);
+      memset (relocs, 0, sizeof (struct nds32_relocs_pattern));
       hash_insert (nds32_hint_hash, name, relocs);
     }
   else
@@ -3745,6 +4305,7 @@ nds32_relax_hint (int mode ATTRIBUTE_UNUSED)
        relocs=relocs->next;
       relocs->next = XNEW (struct nds32_relocs_pattern);
       relocs = relocs->next;
+      memset (relocs, 0, sizeof (struct nds32_relocs_pattern));
     }
 
   relocs->next = NULL;
@@ -3757,6 +4318,7 @@ nds32_relax_hint (int mode ATTRIBUTE_UNUSED)
      instructions relative to the same instruction.  It to connect to
      next instruction after md_assemble.  */
   new = XNEW (struct nds32_relocs_group);
+  memset (new, 0, sizeof (struct nds32_relocs_group));
   new->pattern = relocs;
   new->next = NULL;
   group = nds32_relax_hint_current;
@@ -3840,6 +4402,7 @@ nds32_flag (int ignore ATTRIBUTE_UNUSED)
   *input_line_pointer = saved_char;
   ignore_rest_of_line ();
 }
+
 static void
 ict_model (int ignore ATTRIBUTE_UNUSED)
 {
@@ -3940,8 +4503,6 @@ 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},
@@ -3964,6 +4525,7 @@ 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.  */
@@ -4050,13 +4612,16 @@ 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.  */
   nds32_gprs_hash = hash_new ();
@@ -4065,9 +4630,8 @@ md_begin (void)
 
   /* 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 ();
@@ -4185,11 +4749,12 @@ 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->seg = now_seg;
@@ -4199,6 +4764,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;
 }
@@ -4240,10 +4806,18 @@ 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;
-       default:        /* No suffix.  */
-         reloc = BFD_RELOC_NDS32_HI20;
+       case BFD_RELOC_NDS32_TLS_DESC:  /* @TLSDESC */
+         reloc = BFD_RELOC_NDS32_TLS_DESC_HI20;
+         break;
+       default:        /* No suffix */
+         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,
@@ -4275,8 +4849,19 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str,
            case BFD_RELOC_NDS32_TPOFF:         /* @TPOFF */
              reloc = BFD_RELOC_NDS32_TLS_LE_LO12;
              break;
-           default:    /* No suffix.  */
-             reloc = BFD_RELOC_NDS32_LO12S0;
+           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;
+           default:    /* No suffix */
+             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;
            }
        }
@@ -4288,9 +4873,9 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str,
          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;
-           default:    /* No suffix */
+           default:    /* No suffix */
              reloc = BFD_RELOC_NDS32_LO12S2;
              break;
            }
@@ -4298,7 +4883,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);
@@ -4354,20 +4939,6 @@ nds32_elf_record_fixup_exp (fragS *fragP, const char *str,
       else
        abort ();
 
-      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);
     }
@@ -4382,8 +4953,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;
@@ -4393,10 +4965,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;
@@ -4414,7 +5008,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);
@@ -4430,40 +5024,199 @@ 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 */
+    /* 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}
+      }
+  },
+  {
+    .main_type = 0,
+    .relax_code_seq = {0},
+    .relax_fixup = {{0, 0 , 0, 0}}
   }
 };
 
@@ -4524,122 +5277,190 @@ nds32_elf_sethi_range (struct nds32_relocs_pattern *pattern)
 
 /* The args means: instruction size, the 1st instruction is converted to 16 or
    not, optimize option, 16 bit instruction is enable.  */
+
 #define SET_ADDEND(size, convertible, optimize, insn16_on) \
   (((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_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_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.  */
@@ -4654,97 +5475,199 @@ 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,
+  },
+  /* last one */
+  {0, NULL, 0, 0 ,0, 0}
 };
 
 /* Find the relaxation pattern according to instructions.  */
@@ -4786,6 +5709,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;
@@ -4807,6 +5733,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:
@@ -4829,18 +5757,20 @@ nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
        }
       else
        {
-         /* 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++)
+         /* 2 byte instruction.  Compare by opcode name because
+            the opcode of 2byte instruction is not regular.  */
+         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;
     }
@@ -4848,23 +5778,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->frag->fr_line);
       return FALSE;
     }
 
@@ -4923,12 +5865,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;
 
@@ -4944,22 +5888,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;
        }
@@ -4967,8 +5912,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;
 }
@@ -4976,7 +5941,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;
@@ -4989,7 +5954,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;
@@ -5010,6 +5975,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;
@@ -5026,15 +5992,37 @@ 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)
     {
+      if (count >= relax_code_size / 4)
+       count = 0;
+
       /* Choose the match fixup 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));
 
@@ -5043,8 +6031,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));
@@ -5140,7 +6131,109 @@ 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
            {
@@ -5157,6 +6250,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;
@@ -5167,6 +6273,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
@@ -5174,6 +6293,29 @@ 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 = xmalloc (strlen (str) + 1);
+  nds32_str_tolower (str, s);
+  if (verbatim
+      && (((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;
+    }
+  free (s);
+
+  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;
@@ -5209,16 +6351,16 @@ void
 md_assemble (char *str)
 {
   struct nds32_asm_insn insn;
-  expressionS insn_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
@@ -5227,11 +6369,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)
@@ -5245,7 +6399,7 @@ md_assemble (char *str)
     }
 
   label_exist = 0;
-  insn.info = &insn_expr;
+  insn.info = XNEW (expressionS);
   asm_desc.result = NASM_OK;
   nds32_assemble (&asm_desc, &insn, str);
 
@@ -5282,11 +6436,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))
@@ -5304,8 +6460,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,
@@ -5321,6 +6477,8 @@ md_assemble (char *str)
       else if (insn.opcode->isize == 2)
        bfd_putb16 (insn.insn, out);
       fragP->tc_frag_data.flag |= NDS32_FRAG_BRANCH;
+
+      free (insn.info);
       return;
       /* md_convert_frag will insert relocations.  */
     }
@@ -5331,7 +6489,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)
        {
@@ -5361,6 +6519,8 @@ md_assemble (char *str)
        bfd_putb16 (insn_16, out);
       else if (insn.opcode->isize == 2)
        bfd_putb16 (insn.insn, out);
+
+      free (insn.info);
       return;
     }
   else if ((verbatim || !relaxing) && optimize && label)
@@ -5390,18 +6550,21 @@ 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);
+
+  free (insn.info);
 }
 
 /* md_macro_start  */
@@ -5449,7 +6612,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
@@ -5552,7 +6715,6 @@ nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn,
     }
 }
 
-
 static int
 nds32_relax_branch_instructions (segT segment, fragS *fragP,
                                 long stretch ATTRIBUTE_UNUSED,
@@ -5581,15 +6743,36 @@ nds32_relax_branch_instructions (segT segment, fragS *fragP,
   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);
@@ -5598,15 +6781,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];
@@ -5639,7 +6828,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;
        }
     }
@@ -5678,19 +6867,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)
@@ -5758,7 +6947,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);
@@ -5795,7 +6984,7 @@ md_estimate_size_before_relax (fragS *fragP, segT segment)
   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);
@@ -5845,6 +7034,7 @@ 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;
+  enum bfd_reloc_code_real final_r_type;
 
   /* Replace with gas_assert (branch_symbol != NULL); */
   if (branch_symbol == NULL && !(fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED))
@@ -6025,9 +7215,10 @@ 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;
              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;
            }
        }
@@ -6251,12 +7442,12 @@ nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
   seginfo = seg_info (sec);
   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 && ict_flag == ICT_NONE)
+
+  if (!fixp && !verbatim && ict_flag == ICT_NONE)
     return;
 
   subseg_change (sec, 0);
@@ -6264,7 +7455,7 @@ 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;
@@ -6273,10 +7464,6 @@ nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
       /* These flags are only enabled when global relax is enabled.
         Maybe we can check DISABLE_RELAX_FLAG at link-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_flag == ICT_SMALL)
@@ -6515,12 +7702,12 @@ nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
       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.  */
+        Tag tls data for linker.  */
       switch (fixP->fx_r_type)
        {
        case BFD_RELOC_NDS32_DATA:
-         if (!enable_relax_ex9)
-           fixP->fx_done = 1;
+         /* This reloc is obselete, we do not need it so far.  */
+         fixP->fx_done = 1;
          break;
        case BFD_RELOC_NDS32_TPOFF:
        case BFD_RELOC_NDS32_TLS_LE_HI20:
@@ -6530,6 +7717,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:
@@ -6712,13 +7905,14 @@ 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},
 };
 
 /* Implement md_parse_name.  */
@@ -6739,7 +7933,7 @@ nds32_parse_name (char const *name, expressionS *exprP,
 
   /* Check the special 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 != '@')
@@ -6753,13 +7947,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;
@@ -6769,6 +7961,7 @@ nds32_parse_name (char const *name, expressionS *exprP,
            }
        }
     }
+
   return 1;
 }
 
index 178ca4ec33b63d1505c04e48c097992b0441e12a..150fbda8691e4396f0eee8644e942ecda7439229 100644 (file)
 
 #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")
 
@@ -231,7 +246,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
@@ -254,8 +273,8 @@ typedef struct nds32_cond_field
 /* The max relaxation pattern is 20-bytes including the nop.  */
 #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
+   is 6, but its number of relocation may be 12.  */
+#define MAX_RELAX_NUM 6
 #define MAX_RELAX_FIX 12
 
 typedef struct nds32_relax_info
@@ -275,8 +294,17 @@ 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,
 };
 
 struct nds32_relax_hint_table
index 35effb4006dd84dd3060f2577e4c6deb28996986..27b6e8e8c6aa8faf0e763db4170b5ef3629db082 100755 (executable)
@@ -12841,6 +12841,17 @@ _ACEOF
        ;;
 
       nds32)
+       # setup NDS32_LINUX_TOOLCHAIN definition
+       if test "linux" = $em; then
+
+$as_echo "#define NDS32_LINUX_TOOLCHAIN 1" >>confdefs.h
+
+       else
+
+$as_echo "#define NDS32_LINUX_TOOLCHAIN 0" >>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
@@ -12932,6 +12943,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)
index d8fddfb19e41b47cdbdf878f758e7bdff2146535..93faa4113d08c17b0683e34ca0ca7ad27b850f54 100644 (file)
@@ -446,6 +446,15 @@ changequote([,])dnl
        ;;
 
       nds32)
+       # setup NDS32_LINUX_TOOLCHAIN definition
+       if test "linux" = $em; then
+         AC_DEFINE(NDS32_LINUX_TOOLCHAIN, 1,
+           [Define value for nds32_linux_toolchain])
+       else
+         AC_DEFINE(NDS32_LINUX_TOOLCHAIN, 0,
+           [Define default value for nds32_linux_toolchain])
+       fi
+
        # Decide BASELINE, REDUCED_REGS, FPU_DP_EXT, FPU_SP_EXT features
        # based on arch_name.
        AC_MSG_CHECKING(for default configuration of --with-arch)
@@ -512,6 +521,26 @@ changequote([,])dnl
                    [Define default value for nds32_audio_ext])
        fi
        AC_MSG_RESULT($enable_audio_ext)
+
+       AC_MSG_CHECKING(for default configuration of --enable-dsp-ext)
+       if test "x${enable_dsp_ext}" = xno; then
+         AC_DEFINE(NDS32_DEFAULT_DSP_EXT, 0,
+                   [Define value for nds32_dsp_ext])
+       else
+         AC_DEFINE(NDS32_DEFAULT_DSP_EXT, 1,
+                   [Define default value for nds32_dsp_ext])
+       fi
+       AC_MSG_RESULT($enable_dsp_ext)
+
+       AC_MSG_CHECKING(for default configuration of --enable-zol-ext)
+       if test "x${enable_zol_ext}" = xno; then
+         AC_DEFINE(NDS32_DEFAULT_ZOL_EXT, 0,
+                   [Define value for nds32_zol_ext])
+       else
+         AC_DEFINE(NDS32_DEFAULT_ZOL_EXT, 1,
+                   [Define default value for nds32_zol_ext])
+       fi
+       AC_MSG_RESULT($enable_zol_ext)
        ;;
 
       aarch64 | i386 | riscv | s390 | sparc)
index b658da33e97786aeb7647845ae6cb3b741aaba7c..5335c896fec09d487d9e2814ae022868e6df15f1 100644 (file)
@@ -109,7 +109,7 @@ case $target_triplet in {
        # Some targets don't manage to resolve BFD_RELOC_8 for constants.
        setup_xfail "alpha*-*-*" "*c30*-*-*" "*c4x*-*-*" \
            "d\[13\]0v*-*-*" \
-           "nds32*-*-*" "pdp11-*-*" "xtensa*-*-*"
+           "pdp11-*-*" "xtensa*-*-*"
        run_dump_test forward
     }
 }
@@ -389,7 +389,6 @@ if { ![istarget "bfin-*-*"] && ![istarget "nds32*-*-*"] } then {
 run_dump_test sleb128
 run_dump_test sleb128-2
 run_dump_test sleb128-3
-setup_xfail "nds32*-*-*"
 run_dump_test sleb128-4
 run_dump_test sleb128-5
 # .byte is not 8 bits on either tic4x or tic54x
index c2b5f58890775713b50ca9c13ac5b8613489e268..c979f9203a3b6213b31231ac8ecde08ae2dec299 100644 (file)
@@ -3,8 +3,10 @@
 #source: group0.s
 
 #...
-COMDAT group section \[    1\] `\.group' \[.foo_group\] contains 2 sections:
+COMDAT group section \[    1\] `\.group' \[.foo_group\] contains . sections:
 [      ]+\[Index\][    ]+Name
+#...
 [      ]+\[.*\][       ]+.foo
+#...
 [      ]+\[.*\][       ]+.bar
 #pass
index 9c592edaaad51be84e8d19133161ae595ff72c5f..8043f2038dee672a5c13ba2f9471c837c8be1326 100644 (file)
@@ -3,7 +3,8 @@
 #source: group1.s
 
 #...
-COMDAT group section \[    1\] `\.group' \[.foo_group\] contains 1 sections:
+COMDAT group section \[    1\] `\.group' \[.foo_group\] contains . sections:
 [      ]+\[Index\][    ]+Name
+#...
 [      ]+\[.*\][       ]+.text
 #pass
index 80390e51c17b8bb5e6c24122e787baac23e04e9f..cd92f545e508aaa28104e226cb9ca973f25443ba 100644 (file)
@@ -1,7 +1,8 @@
 #readelf: -g --wide
 
-COMDAT group section \[[ 0-9]+\] `.group' \[foo\] contains 3 sections:
+COMDAT group section \[[ 0-9]+\] `.group' \[foo\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   \.foo
+#...
    \[[ 0-9]+\]   \.bar
    \[[ 0-9]+\]   \.rela?\.bar
index 5f6081fb2ac19b0e6f7f3e0a70ddbc940527f72c..b8d8e8302448b25e62b20ab515c9b0788d9d6147 100644 (file)
@@ -3,8 +3,9 @@
 #source: groupauto.s
 
 #...
-COMDAT group section \[    1\] `\.group' \[some_group\] contains [23] sections:
+COMDAT group section \[    1\] `\.group' \[some_group\] contains . sections:
 [      ]+\[Index\][    ]+Name
 [      ]+\[.*\][       ]+.text
+#...
 [      ]+\[.*\][       ]+.note.bar
 #pass
index 784081fd22f40c9bc374f9dfd462983906a2337f..9eec5e83c476f2dfd173f7f0b4dcf6606e3b8419 100644 (file)
@@ -26,7 +26,7 @@
 #...
   \[[ 0-9]+\] \.mbind\.text[   ]+PROGBITS[     ]+0+0 0+[0-9a-f]+ 0+1 00 AXGD  0   3  1
 #...
-COMDAT group section \[    1\] `\.group' \[\.foo_group\] contains 4 sections:
+COMDAT group section \[    1\] `\.group' \[\.foo_group\] contains . sections:
 [      ]+\[Index\][    ]+Name
 [      ]+\[[ 0-9]+][   ]+\.mbind\.rodata
 [      ]+\[[ 0-9]+][   ]+\.mbind\.data
index b4842d8e1bd2147219296736c9a9d3e7cd36092e..d2a7d56d43952066d0881d92fd3705d4947bfdd9 100644 (file)
@@ -9,6 +9,8 @@
 Disassembly of section .text:
 0+0000 <[^>]*> beq     \$r0, \$r1, 00000000 <foo>
                        0: R_NDS32_15_PCREL_RELA        .text
-                       0: R_NDS32_RELAX_ENTRY  .text
+                       0: R_NDS32_INSN16       \*ABS\*
+                       0: R_NDS32_RELAX_ENTRY  \*ABS\*
 0+0004 <[^>]*> bne     \$r0, \$r1, 00000004 <foo\+0x4>
                        4: R_NDS32_15_PCREL_RELA        .text
+                       4: R_NDS32_INSN16       \*ABS\*
index 24ce15790ddb4532bc0df9b31e722c5533752934..07381b4d0afe57abe59dae7da5f9f864fa4ab46f 100644 (file)
@@ -9,7 +9,8 @@
 Disassembly of section .text:
 0+0000 <[^>]*> beqz    \$r0, 00000000 <foo>
                        0: R_NDS32_17_PCREL_RELA        .text
-                       0: R_NDS32_RELAX_ENTRY  .text
+                       0: R_NDS32_INSN16       \*ABS\*
+                       0: R_NDS32_RELAX_ENTRY  \*ABS\*
 0+0004 <[^>]*> bgez    \$r0, 00000004 <foo\+0x4>
                        4: R_NDS32_17_PCREL_RELA        .text
 0+0008 <[^>]*> bgezal  \$r0, 00000008 <foo\+0x8>
index 120c8c1b137583e9896940cc31d3dd95083941a7..c4f89de16f55c7e395f5691f9ca35980a58bc8fc 100644 (file)
@@ -7,11 +7,11 @@
 .*:     file format .*
 
 Disassembly of section .text:
-0+0000 <[^>]*> j8      00000000 <foo>
-                       0: R_NDS32_9_PCREL_RELA .text
-                       0: R_NDS32_RELAX_ENTRY  .text
-0+0002 <[^>]*> jal     00000002 <foo\+0x2>
-                       2: R_NDS32_25_PCREL_RELA        .text
-0+0006 <[^>]*> jr      \$r0
-0+000a <[^>]*> jral    \$lp, \$r0
-0+000e <[^>]*> ret     \$lp
+0+0000 <[^>]*> j       00000000 <foo>
+                       0: R_NDS32_25_PCREL_RELA        .text
+                       0: R_NDS32_RELAX_ENTRY  \*ABS\*
+0+0004 <[^>]*> jal     00000004 <foo\+0x4>
+                       4: R_NDS32_25_PCREL_RELA        .text
+0+0008 <[^>]*> jr[     ]+\$r0
+0+000c <[^>]*> jral[   ]+\$lp, \$r0
+0+0010 <[^>]*> ret[    ]+\$lp
index e277c7c7755ac41debd6bb52704032ef35f5c1d9..34dcb8c536cdbb5a7af6264e2b15af7e1e92fc75 100644 (file)
@@ -1,3 +1,16 @@
+2018-09-20  Nelson Chu <nelson.chu1990@gmail.com>
+
+       * elf/nds32.h: Remove the unused target features.
+       * dis-asm.h (disassemble_init_nds32): Declared.
+       * elf/nds32.h (E_NDS32_NULL): Removed.
+       (E_NDS32_HAS_DSP_INST, E_NDS32_HAS_ZOL): New.
+       * opcode/nds32.h: Ident.
+       (N32_SUB6, INSN_LW): New macros.
+       (enum n32_opcodes): Updated.
+       * elf/nds32.h: Doc fixes.
+       * elf/nds32.h: Add R_NDS32_LSI.
+       * elf/nds32.h: Add new relocations for TLS.
+
 2018-09-20  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * elf/common.h (AT_SUN_HWCAP): Rename to ...
index 949ccde77b90bfa29e3edfdd0a7298aae8ee635b..c46380b42c395a68c9671f1dbce08072b34444ad 100644 (file)
@@ -304,6 +304,7 @@ extern bfd_boolean csky_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_and_args_t *disassembler_options_arm (void);
 extern const disasm_options_and_args_t *disassembler_options_mips (void);
 extern const disasm_options_and_args_t *disassembler_options_powerpc (void);
index 1b3a3219d095deffd4d5700def33e1d59ee7de4e..72c5dfb798c6c1924cad0076612d582339059337 100644 (file)
@@ -24,8 +24,8 @@
 
 #include "elf/reloc-macros.h"
 
-/* Relocations.  */
 START_RELOC_NUMBERS (elf_nds32_reloc_type)
+  /* These used for relocations.  */
   RELOC_NUMBER (R_NDS32_NONE, 0)
   /* REL relocations.  */
   RELOC_NUMBER (R_NDS32_16, 1)
@@ -46,7 +46,6 @@ START_RELOC_NUMBERS (elf_nds32_reloc_type)
   RELOC_NUMBER (R_NDS32_SDA15S0, 16)
   RELOC_NUMBER (R_NDS32_GNU_VTINHERIT, 17)
   RELOC_NUMBER (R_NDS32_GNU_VTENTRY, 18)
-
   /* RELA relocations.  */
   RELOC_NUMBER (R_NDS32_16_RELA, 19)
   RELOC_NUMBER (R_NDS32_32_RELA, 20)
@@ -66,7 +65,7 @@ START_RELOC_NUMBERS (elf_nds32_reloc_type)
   RELOC_NUMBER (R_NDS32_SDA15S0_RELA, 34)
   RELOC_NUMBER (R_NDS32_RELA_GNU_VTINHERIT, 35)
   RELOC_NUMBER (R_NDS32_RELA_GNU_VTENTRY, 36)
-
+  /* GOT and PLT.  */
   RELOC_NUMBER (R_NDS32_GOT20, 37)
   RELOC_NUMBER (R_NDS32_25_PLTREL, 38)
   RELOC_NUMBER (R_NDS32_COPY, 39)
@@ -81,15 +80,17 @@ START_RELOC_NUMBERS (elf_nds32_reloc_type)
   RELOC_NUMBER (R_NDS32_GOTPC_LO12, 48)
   RELOC_NUMBER (R_NDS32_GOTOFF_HI20, 49)
   RELOC_NUMBER (R_NDS32_GOTOFF_LO12, 50)
+  /* 32_to_16 relaxations.  */
   RELOC_NUMBER (R_NDS32_INSN16, 51)
+  /* Alignment tag.  */
   RELOC_NUMBER (R_NDS32_LABEL, 52)
-  RELOC_NUMBER (R_NDS32_LONGCALL1, 53)
-  RELOC_NUMBER (R_NDS32_LONGCALL2, 54)
-  RELOC_NUMBER (R_NDS32_LONGCALL3, 55)
-  RELOC_NUMBER (R_NDS32_LONGJUMP1, 56)
-  RELOC_NUMBER (R_NDS32_LONGJUMP2, 57)
-  RELOC_NUMBER (R_NDS32_LONGJUMP3, 58)
-  RELOC_NUMBER (R_NDS32_LOADSTORE, 59)
+  RELOC_NUMBER (R_NDS32_LONGCALL1, 53)         /* This is obsoleted.  */
+  RELOC_NUMBER (R_NDS32_LONGCALL2, 54)         /* This is obsoleted.  */
+  RELOC_NUMBER (R_NDS32_LONGCALL3, 55)         /* This is obsoleted.  */
+  RELOC_NUMBER (R_NDS32_LONGJUMP1, 56)         /* This is obsoleted.  */
+  RELOC_NUMBER (R_NDS32_LONGJUMP2, 57)         /* This is obsoleted.  */
+  RELOC_NUMBER (R_NDS32_LONGJUMP3, 58)         /* This is obsoleted.  */
+  RELOC_NUMBER (R_NDS32_LOADSTORE, 59)         /* This is obsoleted.  */
   RELOC_NUMBER (R_NDS32_9_FIXED_RELA, 60)
   RELOC_NUMBER (R_NDS32_15_FIXED_RELA, 61)
   RELOC_NUMBER (R_NDS32_17_FIXED_RELA, 62)
@@ -107,9 +108,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)
@@ -126,8 +127,9 @@ START_RELOC_NUMBERS (elf_nds32_reloc_type)
   RELOC_NUMBER (R_NDS32_SDA_FP7U2_RELA, 93)
   RELOC_NUMBER (R_NDS32_WORD_9_PCREL_RELA, 94)
   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_17IFC_PCREL_RELA, 96)  /* This is obsoleted.  */
+  RELOC_NUMBER (R_NDS32_10IFCU_PCREL_RELA, 97) /* This is obsoleted.  */
+  /* TLS support.  */
   RELOC_NUMBER (R_NDS32_TLS_LE_HI20, 98)
   RELOC_NUMBER (R_NDS32_TLS_LE_LO12, 99)
   RELOC_NUMBER (R_NDS32_TLS_IE_HI20, 100)
@@ -144,7 +146,20 @@ 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)
+  /* Reserved numbers: 114.  */
+  /* TLS support */
+  RELOC_NUMBER (R_NDS32_TLS_IE_LO12, 115)
+  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)
+  /* Reserved numbers: 124-191.  */
 
+  /* These used only for relaxations  */
   RELOC_NUMBER (R_NDS32_RELAX_ENTRY, 192)
   RELOC_NUMBER (R_NDS32_GOT_SUFF, 193)
   RELOC_NUMBER (R_NDS32_GOTOFF_SUFF, 194)
@@ -164,9 +179,19 @@ 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)
+  /* 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_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)
+  RELOC_NUMBER (R_NDS32_TLS_IEGP_LW, 220)
+  RELOC_NUMBER (R_NDS32_LSI, 221)
+  /* Reserved numbers: 222-255.  */
 
 END_RELOC_NUMBERS (R_NDS32_max)
 
@@ -217,7 +242,6 @@ END_RELOC_NUMBERS (R_NDS32_max)
 /* MFUSR rt, PC and correct ISYNC, MSYNC instructions.
    Old N1213HC has no such instructions.  */
 #define E_NDS32_HAS_MFUSR_PC_INST              0x00000100 /* Reclaimed.  */
-#define E_NDS32_HAS_EX9_INST                   0x00000100 /* v3, ELF 1.4.  */
 /* C/C++ performance extension instructions.  */
 #define E_NDS32_HAS_EXT_INST                   0x00000200
 /* Performance extension set II instructions.  */
@@ -232,7 +256,6 @@ END_RELOC_NUMBERS (R_NDS32_max)
 #define E_NDS32_HAS_DIV_DX_INST                        0x00002000 /* v2.  */
 /* 16-bit instructions.  */
 #define E_NDS32_HAS_16BIT_INST                 0x00004000 /* Reclaimed.  */
-#define E_NDS32_HAS_IFC_INST                   0x00004000 /* v3, ELF 1.4.  */
 /* String operation instructions.  */
 #define E_NDS32_HAS_STRING_INST                        0x00008000
 /* Reduced register file.  */
@@ -259,12 +282,14 @@ END_RELOC_NUMBERS (R_NDS32_max)
 #define E_NDS32_FPU_REG_32SP_32DP              0x3
 /* FPU MAC instruction used.  */
 #define E_NDS32_HAS_FPU_MAC_INST               0x01000000
-/* <<<Empty Check>>>.  */
-#define E_NDS32_NULL                           0x02000000
+/* DSP extension.  */
+#define E_NDS32_HAS_DSP_INST                   0x02000000
 /* PIC enabled.  */
 #define E_NDS32_HAS_PIC                                0x04000000
 /* Use custom section.  */
 #define E_NDS32_HAS_CUSTOM_SEC                 0x08000000
+/* Hardware zero-overhead loop enabled.  */
+#define E_NDS32_HAS_ZOL                                (1 << 26)
 
 /* 4-bit for ABI signature, allow up to 16 ABIs
    0: for OLD ABI V0, phase out
@@ -293,7 +318,7 @@ END_RELOC_NUMBERS (R_NDS32_max)
 /* Andes ELF Version 1.31.  */
 #define E_NDS32_ELF_VER_1_3                    0x1
 /* Andes ELF Version 1.4. Change the way we fix .debug_* and .gcc_except_table.
-   Change three bit for EX9, IFC and SAT.  */
+   Change three bit for SAT.  */
 #define E_NDS32_ELF_VER_1_4                    0x2
 
 #endif
index 4d113be8b8601b03a3d63daf5e5502b3cc850beb..82782dee1b48546d55d8f0bbc861ad31742267c5 100644 (file)
 #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)
 \f
 /* Macros for extracting fields or making an instruction.  */
 static const int nds32_r45map[] ATTRIBUTE_UNUSED =
@@ -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,
@@ -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
index 14b507069b38e9b0c00effbc116f98e0d88ab8e6..9d407418d0388e424735dabb4febedf17bb83990 100644 (file)
@@ -1,3 +1,17 @@
+2018-09-20  Nelson Chu <nelson.chu1990@gmail.com>
+
+       * emultempl/nds32elf.em (hyper_relax): New variable.
+       (nds32_elf_create_output_section_statements):
+       the parameters of bfd_elf32_nds32_set_target_option
+       (PARSE_AND_LIST_PROLOGUE, PARSE_AND_LIST_OPTIONS,
+       PARSE_AND_LIST_ARGS_CASES): Add new option --mhyper-relax.
+       * emultempl/nds32elf.em (nds32_elf_after_open): Updated.
+       * emultempl/nds32elf.em (tls_desc_trampoline): New variable.
+       * (nds32_elf_create_output_section_statements): Updated.
+       * (nds32_elf_after_parse): Disable relaxations when PIC is enable.
+       * (PARSE_AND_LIST_PROLOGUE, PARSE_AND_LIST_OPTIONS,
+       PARSE_AND_LIST_ARGS_CASES): Add new option --m[no-]tlsdesc-trampoline.
+
 2018-09-19  Alan Modra  <amodra@gmail.com>
 
        PR ld/23648
index eb29d0472f42355f3f5c2e80aa54022c90a5c641..6fb5a485cac691890af7599d664df6b5f0baabb9 100644 (file)
@@ -30,17 +30,10 @@ fragment <<EOF
 static int relax_fp_as_gp = 1;         /* --mrelax-omit-fp  */
 static int eliminate_gc_relocs = 0;    /* --meliminate-gc-relocs  */
 static FILE *sym_ld_script = NULL;     /* --mgen-symbol-ld-script=<file>  */
+static int hyper_relax = 1;            /* --mhyper-relax  */
+static int tls_desc_trampoline = 0;    /* --m[no]tlsdesc-trampoline.  */
 /* Disable if linking a dynamically linked executable.  */
 static int load_store_relax = 1;
-static int target_optimize = 0;        /* Switch optimization.  */
-static int relax_status = 0;   /* Finished optimization.  */
-static int relax_round = 0;            /* Going optimization.  */
-static FILE *ex9_export_file = NULL;   /* --mexport-ex9=<file>  */
-static FILE *ex9_import_file = NULL;   /* --mimport-ex9=<file>  */
-static int update_ex9_table = 0;       /* --mupdate-ex9.  */
-static int ex9_limit = 511;
-static bfd_boolean ex9_loop_aware = FALSE;     /* Ignore ex9 if inside a loop.  */
-static bfd_boolean ifc_loop_aware = FALSE;     /* Ignore ifc if inside a loop.  */
 
 /* Save the target options into output bfd to avoid using to many global
    variables. Do this after the output has been created, but before
@@ -56,42 +49,24 @@ nds32_elf_create_output_section_statements (void)
       return;
     }
 
-  bfd_elf32_nds32_set_target_option (&link_info, relax_fp_as_gp,
+  bfd_elf32_nds32_set_target_option (&link_info,
+                                    relax_fp_as_gp,
                                     eliminate_gc_relocs,
                                     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,
+                                    load_store_relax);
 }
 
 static void
 nds32_elf_after_parse (void)
 {
-  if (bfd_link_relocatable (&link_info))
+  if (bfd_link_relocatable (&link_info)
+      || bfd_link_pic (&link_info))
     DISABLE_RELAXATION;
 
   if (!RELAXATION_ENABLED)
-    {
-      target_optimize = target_optimize & (!NDS32_RELAX_JUMP_IFC_ON);
-      target_optimize = target_optimize & (!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);
-    }
+    relax_fp_as_gp = 0;
 
   gld${EMULATION_NAME}_after_parse ();
 }
@@ -124,64 +99,19 @@ nds32_elf_after_open (void)
          einfo (_("%F%P: %pB: 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
     }
 
   /* 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 (_("%P: %pB: 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.  */
+      /* This may support in the future.  */
+      load_store_relax = 0 ;
+      relax_fp_as_gp = 0;
     }
 
   /* Call the standard elf routine.  */
@@ -210,31 +140,17 @@ 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)
 '
 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},
   /* 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},
@@ -243,50 +159,16 @@ 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"));
   fprintf (file, _("\
   --mexport-symbols=FILE      Exporting symbols in linker script\n"));
-
-#if defined NDS32_EX9_EXT
-  fprintf (file, _("\
-  --m[no-]ex9                 Disable/enable link-time EX9 relaxation\n"));
   fprintf (file, _("\
-  --mexport-ex9=FILE          Export EX9 table after linking\n"));
+  --mhyper-relax=level        Adjust relax level (low|medium|high). default: medium\n"));
   fprintf (file, _("\
-  --mimport-ex9=FILE          Import Ex9 table for EX9 relaxation\n"));
-  fprintf (file, _("\
-  --mupdate-ex9               Update existing EX9 table\n"));
-  fprintf (file, _("\
-  --mex9-limit=NUM            Maximum number of entries in ex9 table\n"));
-  fprintf (file, _("\
-  --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"));
-  fprintf (file, _("\
-  --mifc-loop-aware           Avoid generate IFC instruction inside loop\n"));
-#endif
+  --m[no-]tlsdesc-trampoline  Disable/enable TLS DESC trampoline\n"));
 '
 PARSE_AND_LIST_ARGS_CASES='
   case OPTION_BASELINE:
@@ -316,62 +198,26 @@ PARSE_AND_LIST_ARGS_CASES='
          einfo (_("%F%P: 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 (_("%P: missing file for --mexport-ex9=<file>\n"));
-
-    if(strcmp (optarg, "-") == 0)
-      ex9_export_file = stdout;
+      einfo (_("%P: valid arguments to --mhyper-relax=(low|medium|high)\n"));
+
+    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 (_("%F%P: cannot open ex9 export file %s\n"), optarg);
-      }
-    break;
-  case OPTION_IMPORT_EX9:
-    if (!optarg)
-      einfo (_("%P: missing file for --mimport-ex9=<file>\n"));
+      einfo (_("%P: valid arguments to --mhyper-relax=(low|medium|high)\n"));
 
-    ex9_import_file = fopen (optarg, "rb+");
-    if(ex9_import_file == NULL)
-      einfo (_("%F%P: cannot open ex9 import file %s\n"), optarg);
-    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 (_("%F%P: the range of ex9_limit must between 1 and 511\n"));
-      }
-    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_TLSDESC_TRAMPOLINE:
+    tls_desc_trampoline = 1;
     break;
-#endif
+  case OPTION_NO_TLSDESC_TRAMPOLINE:
+    tls_desc_trampoline = 0;
+     break;
 '
 LDEMUL_AFTER_OPEN=nds32_elf_after_open
 LDEMUL_AFTER_PARSE=nds32_elf_after_parse
index 6fcf83fa8d5d90c5afc5e05e9fb95527c2557d89..6dbe49e090c1ff13669e6985a2b9b3d50188587d 100644 (file)
@@ -3,9 +3,10 @@
 #readelf: -Sg --wide
 
 #...
-group section \[[ 0-9]+\] `\.group' \[foo_group\] contains 4 sections:
+group section \[[ 0-9]+\] `\.group' \[foo_group\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   \.text.*
+#...
    \[[ 0-9]+\]   \.rodata\.str.*
    \[[ 0-9]+\]   \.data.*
    \[[ 0-9]+\]   \.keepme.*
index 664c49af7b3a91a147b815679c30856b2591b9a4..d127d4d93fc6f1ff0eae3746cfcbc15e04d692e0 100644 (file)
@@ -13,8 +13,9 @@
 #...
   \[[ 0-9]+\] \.data.*[ \t]+PROGBITS[ \t0-9a-f]+WAG.*
 #...
-COMDAT group section \[[ 0-9]+\] `\.group' \[foo_group\] contains 2 sections:
+COMDAT group section \[[ 0-9]+\] `\.group' \[foo_group\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   .text.*
+#...
    \[[ 0-9]+\]   .data.*
 #pass
index af4ca4d0fdab6daf6a3720ff18e1ea692e19755c..2e400cdcf6bb7d9627e428de50812968151612b2 100644 (file)
@@ -13,8 +13,9 @@
 #...
   \[[ 0-9]+\] \.data.*[ \t]+PROGBITS[ \t0-9a-f]+WAG[ \t]+.*
 #...
-COMDAT group section \[[ 0-9]+\] `.group' \[.text.foo\] contains 2 sections:
+COMDAT group section \[[ 0-9]+\] `.group' \[.text.foo\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   .text.*
+#...
    \[[ 0-9]+\]   .data.*
 #pass
index 5102f817fb2e68cc7ef17eb6b98cd5036b1dbedf..b41dce6dd54b67ae8cfe90215b087fa9795ab7bf 100644 (file)
@@ -13,8 +13,9 @@
 #...
   \[[ 0-9]+\] \.data.*[ \t]+PROGBITS[ \t0-9a-f]+WAG[ \t]+.*
 #...
-COMDAT group section \[[ 0-9]+\] `.group' \[foo3\] contains 2 sections:
+COMDAT group section \[[ 0-9]+\] `.group' \[foo3\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   .text.*
+#...
    \[[ 0-9]+\]   .data.*
 #pass
index 0e8441f571d759e6ae720ba6a41df60a200bbe27..eef058537960fcd8a04fb2666b485d9368a53252 100644 (file)
@@ -13,8 +13,9 @@
 #...
   \[[ 0-9]+\] \.data.*[ \t]+PROGBITS[ \t0-9a-f]+WAG[ \t]+.*
 #...
-COMDAT group section \[[ 0-9]+\] `.group' \[foo4\] contains 2 sections:
+COMDAT group section \[[ 0-9]+\] `.group' \[foo4\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   .text.*
+#...
    \[[ 0-9]+\]   .data.*
 #pass
index 602a4c8acc3f4890210c4c4f991e249c3aca39dd..47c2b7b8083a81ee16489885bda59b8a81fe3c13 100644 (file)
@@ -9,23 +9,27 @@
 # well with unique group sections under ld -r.
 
 #...
-COMDAT group section \[[ 0-9]+\] `\.group' \[foo_group\] contains 2 sections:
+COMDAT group section \[[ 0-9]+\] `\.group' \[foo_group\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   .text.foo
+#...
    \[[ 0-9]+\]   .data.foo
 #...
-COMDAT group section \[[ 0-9]+\] `.group' \[.text.foo\] contains 2 sections:
+COMDAT group section \[[ 0-9]+\] `.group' \[.text.foo\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   .text.foo
+#...
    \[[ 0-9]+\]   .data.bar
 #...
-COMDAT group section \[[ 0-9]+\] `.group' \[foo3\] contains 2 sections:
+COMDAT group section \[[ 0-9]+\] `.group' \[foo3\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   .text.foo3
+#...
    \[[ 0-9]+\]   .data.bar3
 #...
-COMDAT group section \[[ 0-9]+\] `.group' \[foo4\] contains 2 sections:
+COMDAT group section \[[ 0-9]+\] `.group' \[foo4\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   .text.foo4
+#...
    \[[ 0-9]+\]   .data.foo4
 #pass
index c3b1546e6bc2b8cf654007c9c9813154b2c90312..303346274d1bcc0ad068e1593911ae4810230c42 100644 (file)
@@ -7,6 +7,7 @@
 # cr16 and crx use non-standard scripts with memory regions, which don't play
 # well with unique group sections under ld -r.
 
-COMDAT group section \[[ 0-9]+\] `.group' \[foo\] contains 1 sections:
+COMDAT group section \[[ 0-9]+\] `.group' \[foo\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   .text.foo
+#pass
index 1178b4f3deea2a81a7d2d1689e05a0fb5fe767c7..bfe4b77594b9494f956db91fcef756d2a5463576 100644 (file)
@@ -7,6 +7,7 @@
 # cr16 and crx use non-standard scripts with memory regions, which don't play
 # well with unique group sections under ld -r.
 
-COMDAT group section \[[ 0-9]+\] `.group' \[bar\] contains 1 sections:
+COMDAT group section \[[ 0-9]+\] `.group' \[bar\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   .text.bar
+#pass
index 403283cfa771466c0d5c0abb3f60222357bced5b..08a1c267c02f977bdde3920fd1b72dbaba4271ab 100644 (file)
@@ -7,7 +7,9 @@
 # cr16 and crx use non-standard scripts with memory regions, which don't play
 # well with unique group sections under ld -r.
 
-COMDAT group section \[[ 0-9]+\] `.group' \[foo\] contains 2 sections:
+COMDAT group section \[[ 0-9]+\] `.group' \[foo\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   .text.foo
+#...
    \[[ 0-9]+\]   .data.foo
+#pass
index c4475f793ba0858a310673f7298cf4828f3fb32d..11676991ae97adea3f60eb0fcef5ecc60e6f8fe6 100644 (file)
@@ -7,12 +7,15 @@
 # cr16 and crx use non-standard scripts with memory regions, which don't play
 # well with unique group sections under ld -r.
 
-COMDAT group section \[[ 0-9]+\] `.group' \[foo\] contains 2 sections:
+COMDAT group section \[[ 0-9]+\] `.group' \[foo\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   \.text\.foo
+#...
    \[[ 0-9]+\]   \.data\.foo
-
-COMDAT group section \[[ 0-9]+\] `.group' \[bar\] contains 2 sections:
+#...
+COMDAT group section \[[ 0-9]+\] `.group' \[bar\] contains . sections:
    \[Index\]    Name
    \[[ 0-9]+\]   \.text\.bar
+#...
    \[[ 0-9]+\]   \.rela?\.text\.bar
+#pass
index 5a00e056b0563cbfb51c9fe93365cb953d1ede61..66d553497aae2ae201d31a8c6753e24dbf070421 100644 (file)
@@ -6,7 +6,7 @@
 # generic elf targets don't emit relocs
 
 .*:     file format .*
-
+#...
 RELOCATION RECORDS FOR \[.debug_frame\]:
 OFFSET[        ]+TYPE[         ]+VALUE[        ]*
 .*(NONE|unused|UNUSED).*\*ABS\*
index c0a8511fcd6ef0872f1128254373f99b641c9401..28c713cd2f6b2f9e0418bcec9f9bb80472373dfb 100644 (file)
@@ -4,7 +4,7 @@
 #xfail: bfin-*-* cr16-*-* cris*-*-* crx-*-* csky-*-* d10v-*-* d30v-*-* dlx-*-*
 #xfail: fr30-*-* frv-*-* ft32-*-* h8300-*-* hppa*64*-*-* ip2k-*-* iq2000-*-*
 #xfail: lm32-*-* m68hc11-*-* mcore-*-* mep-*-* metag-*-* mn102*-*-* ms1-*-*
-#xfail: nios2-*-* or32-*-* pj-*-* pru-*-* s12z-*-* score-*-* tic6x-*-*
+#xfail: nds32*-*-* nios2-*-* or32-*-* pj-*-* pru-*-* s12z-*-* score-*-* tic6x-*-*
 #xfail: vax-*-* xgate-*-* xstormy16-*-* xtensa*-*-*
 
 .*:     file format .*elf.*
index 458244a0390b3bcc91cb267716fb0513120691ef..d0fba97a104b14c31e38cf686950cb4828a547a1 100644 (file)
@@ -6,5 +6,6 @@
 
 #...
   \[[ 0-9]+\] \.text.*[ \t]+PROGBITS[ \t]+0+800000[ \t0-9a-f]+AX.*
+#...
   \[[ 0-9]+\] \.data.*[ \t]+PROGBITS[ \t]+0+900000[ \t0-9a-f]+WA.*
 #pass
index 52b5cd2333eae9c6bd31bb4c2890109cd478ab5d..d1f3b7550355091a6b9decb1b77df4923e42e30e 100644 (file)
@@ -59,7 +59,7 @@ proc test_sort_common {} {
     }
 
     if { ![ld_link $ld tmpdir/sort-common.dx "--sort-common=descending tmpdir/sort-common.o"] } {
-       fail "$test"
+       fail "$test (could not link)"
        return 0
     }
 
@@ -73,7 +73,7 @@ proc test_sort_common {} {
     #  section and large commons in a .bss section.
     if {   ![regexp ".*var_16.*var_8.*var_4.*var_2.*var_1.*" $exec_output]
         && ![regexp ".*sbss.*var_8.*var_4.*var_2.*var_1.*bss.*var_16.*" $exec_output] } {      
-       fail $test
+       fail "$test (variables in wrong order)"
     } else {
        pass $test
     }
@@ -83,7 +83,7 @@ proc test_sort_common {} {
     verbose "Check to see that --sort-common=ascending sorts in ascending alignment"
 
     if { ![ld_link $ld tmpdir/sort-common.ax "--sort-common=ascending tmpdir/sort-common.o"] } {
-       fail "$test"
+       fail "$test (could not link)"
        return 0
     }
 
@@ -91,7 +91,7 @@ proc test_sort_common {} {
     set exec_output [run_host_cmd "$objdump" "--syms tmpdir/sort-common.ax | grep var | sort"]
 
     if {![regexp ".*var_1.*var_2.*var_4.*var_8.*var_16.*" $exec_output]} {      
-       fail $test
+       fail "$test (variables in wrong order)"
        return 0
     }
 
index 85798e93effe647ad62c8c51df40b2ea38232775..7ce4ca05f3af1cfd082ddc7e3d81888e82e19a11 100644 (file)
@@ -6,19 +6,15 @@
 
 
 Disassembly of section .text:
-0+0000 <[^>]*> beq     \$r0, \$r1, 0000002c <main>
-0+0004 <[^>]*> bne     \$r0, \$r1, 0000002c <main>
-0+0008 <[^>]*> bnez38  \$r0, 0000002c <main>
-0+000a <[^>]*> beqz38  \$r0, 0000002c <main>
-0+000c <[^>]*> bgez    \$r0, 0000002c <main>
+0+0000 <[^>]*> beq[    ]+\$r0, \$r1, 00000024 <main>
+0+0004 <[^>]*> bne[    ]+\$r0, \$r1, 00000024 <main>
+0+0008 <[^>]*> beqz38[         ]+\$r0, 00000024 <main>
+0+000a <[^>]*> bnez38[         ]+\$r0, 00000024 <main>
+0+000c <[^>]*> bgez[   ]+\$r0, 00000024 <main>
 .*
-0+0012 <[^>]*> bgezal  \$r0, 0000002c <main>
-0+0016 <[^>]*> bgtz    \$r0, 0000002c <main>
+0+0014 <[^>]*> bgtz[   ]+\$r0, 00000024 <main>
 .*
-0+001c <[^>]*> blez    \$r0, 0000002c <main>
+0+001c <[^>]*> bltz[   ]+\$r0, 00000024 <main>
 .*
-0+0022 <[^>]*> bltz    \$r0, 0000002c <main>
-0+0026 <[^>]*> srli45  \$r0, 0
-0+0028 <[^>]*> bltzal  \$r0, 0000002c <main>
-0+002c <main>.*
-
+0+0024 <[^>]*> nop16
+#pass
index dac6eaa426710e40cd6c66288c18e6343bfbbc70..552062ade96c15d9bc1a67150e6eedcecfceac8b 100644 (file)
@@ -6,13 +6,13 @@
 
 
 Disassembly of section .text:
-0+0000 <[^>]*> addi.gp \$r0, 8192
-0+0004 <[^>]*> lbi.gp  \$r0, \[\+ 8192\]
-0+0008 <[^>]*> lbsi.gp \$r0, \[\+ 8192\]
-0+000c <[^>]*> lhi.gp  \$r0, \[\+ 8192\]
-0+0010 <[^>]*> lhsi.gp \$r0, \[\+ 8192\]
-0+0014 <[^>]*> lwi.gp  \$r0, \[\+ 8192\]
-0+0018 <[^>]*> sbi.gp  \$r0, \[\+ 8192\]
-0+001c <[^>]*> shi.gp  \$r0, \[\+ 8192\]
-0+0020 <[^>]*> swi.gp  \$r0, \[\+ 8192\]
+0+0000 <[^>]*> addi.gp \$r0, .*
+0+0004 <[^>]*> lbi.gp  \$r0, \[.*\]
+0+0008 <[^>]*> lbsi.gp \$r0, \[.*\]
+0+000c <[^>]*> lhi.gp  \$r0, \[.*\]
+0+0010 <[^>]*> lhsi.gp \$r0, \[.*\]
+0+0014 <[^>]*> lwi.gp  \$r0, \[.*\]
+0+0018 <[^>]*> sbi.gp  \$r0, \[.*\]
+0+001c <[^>]*> shi.gp  \$r0, \[.*\]
+0+0020 <[^>]*> swi.gp  \$r0, \[.*\]
 
index fdaacf3df5aa9211f044a651be6c4fa75654fcf2..730c5ad1c8c353a8c40954aeb61cd2e1bcf2a2ad 100644 (file)
@@ -8,8 +8,8 @@
 
 
 Disassembly of section .text:
-0+1000 <[^>]*> sethi   \$r0, 0x11223
-0+1004 <[^>]*> ori     \$r0, \$r0, 836
-0+1008 <[^>]*> movi    \$r0, 70179
-0+100c <[^>]*> movi55  \$r0, 15
+0+1000 <[^>]*> sethi   \$r0, #0x11223
+0+1004 <[^>]*> ori     \$r0, \$r0, #0x344
+0+1008 <[^>]*> movi    \$r0, #0x11223
+0+100c <[^>]*> movi55[         ]+\$r0, #0xf
 
index b1d20514a3a0673e14d9d3583de69eb7700c3eed..4b1268dd7cf31ebbc334621f6c7f9dec9a8bbfc2 100644 (file)
@@ -6,7 +6,7 @@
 
 
 Disassembly of section .text:
-0+0000 <[^>]*> j8      00000006 <main>
-0+0002 <[^>]*> jal     00000006 <main>
-0+0006 <[^>]*> srli45  \$r0, 0
+0+0000 <[^>]*> j       00000008 <main>
+0+0004 <[^>]*> jal     00000008 <main>
+0+0008 <[^>]*> nop16
 
index 07c4fe72eb222a78f38da0d0912dc898a36a0d9b..d7829f79370147a4cfdb91394321184e7d416301 100644 (file)
@@ -6,7 +6,7 @@
 
 
 Disassembly of section .text:
-0+0000 <[^>]*> lwi.gp  \$r0, \[\+ 0\]
-0+0004 <[^>]*> lhi.gp  \$r0, \[\+ 4\]
-0+0008 <[^>]*> lbi.gp  \$r0, \[\+ 6\]
+0+0000 <[^>]*> lwi.gp  \$r0, \[ \+ #0\]
+0+0004 <[^>]*> lhi.gp  \$r0, \[ \+ #4\]
+0+0008 <[^>]*> lbi.gp  \$r0, \[ \+ #6\]
 
index 19475dae8ad92cbcba0f977e8dc531a0b6305361..746565a9ea7226e1abe42c0afa5198bc0fe18781 100644 (file)
@@ -1,3 +1,43 @@
+2018-09-20  Nelson Chu <nelson.chu1990@gmail.com>
+
+       * nds32-asm.c (operand_fields): Remove the unused fields.
+       (nds32_opcodes): Remove the unused instructions.
+       * nds32-dis.c (nds32_ex9_info): Removed.
+       (nds32_parse_opcode): Updated.
+       (print_insn_nds32): Likewise.
+       * nds32-asm.c (config.h, stdlib.h, string.h): New includes.
+       (LEX_SET_FIELD, LEX_GET_FIELD): Update defines.
+       (nds32_asm_init, build_operand_hash_table, build_keyword_hash_table,
+       build_opcode_hash_table): New functions.
+       (nds32_keyword_table, nds32_keyword_count_table, nds32_field_table,
+       nds32_opcode_table): New.
+       (hw_ktabs): Declare it to a pointer rather than an array.
+       (build_hash_table): Removed.
+       * nds32-asm.h (enum): Add SYN_INPUT, SYN_OUTPUT, SYN_LOPT,
+       SYN_ROPT and upadte HW_GPR and HW_INT.
+       * nds32-dis.c (keywords): Remove const.
+       (match_field): New function.
+       (nds32_parse_opcode): Updated.
+       * disassemble.c (disassemble_init_for_target):
+       Add disassemble_init_nds32.
+       * nds32-dis.c (eum map_type): New.
+       (nds32_private_data): Likewise.
+       (get_mapping_symbol_type, is_mapping_symbol, nds32_symbol_is_valid,
+       nds32_add_opcode_hash_table, disassemble_init_nds32): New functions.
+       (print_insn_nds32): Updated.
+       * nds32-asm.c (parse_aext_reg): Add new parameter.
+       (parse_re, parse_re2, parse_aext_reg): Only reduced registers
+       are allowed to use.
+       All callers changed.
+       * nds32-asm.c (keyword_usr, keyword_sr): Updated.
+       (operand_fields): Add new fields.
+       (nds32_opcodes): Add new instructions.
+       (keyword_aridxi_mx): New keyword.
+       * nds32-asm.h (enum): Add NASM_ATTR_DSP_ISAEXT, HW_AEXT_ARIDXI_MX
+       and NASM_ATTR_ZOL.
+       (ALU2_1, ALU2_2, ALU2_3): New macros.
+       * nds32-dis.c (nds32_filter_unknown_insn): Updated.
+
 2018-09-17  Kito Cheng  <kito@andestech.com>
 
        * riscv-opc.c (riscv_opcodes): Adjust the order of ble and bleu.
index ce83423b6dd76b1980a7861bcd89f0438d07d76c..750d76ad8654e599e11927592db226fa7c39c462 100644 (file)
@@ -666,6 +666,11 @@ disassemble_init_for_target (struct disassemble_info * info)
       disassemble_init_s390 (info);
       break;
 #endif
+#ifdef ARCH_nds32
+    case bfd_arch_nds32:
+      disassemble_init_nds32 (info);
+      break;
+ #endif
     default:
       break;
     }
index b5309fbd54ffdb42ac4e531a44841d995644ffce..f0dd3266f95f04a9c72a815c7667a2c3a4355699 100644 (file)
 #include "bfd.h"
 #include "opintl.h"
 
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+
 #include "opcode/nds32.h"
 #include "nds32-asm.h"
 
@@ -42,8 +46,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)
 
@@ -59,7 +63,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 *,
@@ -158,6 +163,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},
@@ -169,7 +175,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.  */
@@ -182,6 +187,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.  */
@@ -198,7 +205,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.  */
@@ -293,7 +302,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},
@@ -305,8 +313,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},
@@ -376,10 +382,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},
@@ -438,6 +444,7 @@ 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},
 
@@ -709,7 +716,6 @@ struct nds32_opcode nds32_opcodes[] =
   /* 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},
   {"add5.pc", "%ra5",  0xdda0, 2, ATTR_V3, 0, NULL, 0, NULL},
   /* SEG11_3  if Ra5=30.  */
@@ -726,13 +732,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},
@@ -758,7 +761,6 @@ 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},
@@ -773,13 +775,16 @@ struct nds32_opcode nds32_opcodes[] =
   {"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},
+  {"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 (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},
 
   /* Audio ext. instructions.  */
 
-  {"amtari", "%aridxi,%imm16", AUDIO (AMTARI), 4, ATTR (AUDIO_ISAEXT), 0, NULL, 0, NULL},
+  {"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},
@@ -930,6 +935,182 @@ struct nds32_opcode nds32_opcodes[] =
   {"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},
 };
 
@@ -985,6 +1166,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},
@@ -1039,6 +1223,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},
@@ -1058,6 +1243,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},
@@ -1076,9 +1266,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},
@@ -1101,51 +1294,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},
@@ -1359,6 +1552,13 @@ 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,
@@ -1369,15 +1569,22 @@ 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];
 \f
+
 /* 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,43 +1603,88 @@ htab_hash_eq (const void *p, const void *q)
   return strcmp (name, h->name) == 0;
 }
 \f
-/* 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.  */
 
-static htab_t
-build_hash_table (const void *base, size_t size)
+static void
+build_operand_hash_table (void)
 {
-  htab_t htab;
-  hashval_t hash;
-  const char *p;
+  unsigned k;
 
-  htab = htab_create_alloc (128, htab_hash_hash, htab_hash_eq,
-                           NULL, xcalloc, free);
+  field_htab = htab_create_alloc (128, htab_hash_hash, htab_hash_eq,
+                                 NULL, xcalloc, free);
 
-  p = base;
-  while (1)
+  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
@@ -1457,12 +1709,13 @@ 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 fidx, i, k;
 
       switch (*str)
        {
@@ -1500,7 +1753,6 @@ 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)
        {
@@ -1508,8 +1760,22 @@ build_opcode_syntax (struct nds32_opcode *opc)
          opcodes_error_handler (_("internal error: unknown operand, %s"), str);
          abort ();
        }
+
+      /* 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;
+           }
+       }
       assert (fidx >= 0 && fidx < (int) ARRAY_SIZE (operand_fields));
-      *plex |= LEX_SET_FIELD (fidx);
+      *plex |= LEX_SET_FIELD (k, fidx);
 
       str += len;
       plex++;
@@ -1520,44 +1786,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
 
@@ -1568,16 +1827,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.  */
@@ -1618,6 +1905,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;
@@ -1645,6 +1937,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)
@@ -1700,7 +1997,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];
@@ -1717,20 +2015,26 @@ 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;
 
@@ -1740,16 +2044,18 @@ 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);
   tmp2 = (rt_value & 0x08);
   if (tmp1 != tmp2)
@@ -1763,17 +2069,19 @@ 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;
+
   tmp1 = (aext_a30b20 & 0x08);
   tmp2 = (rt_value & 0x08);
   if (tmp1 != tmp2)
@@ -1787,21 +2095,25 @@ 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)))
     return NASM_ERR_OPERAND;
+
   tmp1 = (aext_a30b20 & 0x08);
   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;
@@ -1809,16 +2121,19 @@ 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;
@@ -1826,17 +2141,20 @@ 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;
@@ -1844,15 +2162,16 @@ 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].  */
   new_value = (rt_value & 0x04) << 2;
   new_value |= (rt_value & 0x03);
@@ -1862,35 +2181,38 @@ 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].  */
   new_value = (rt_value & 0x07) << 2;
   tmp1 = (aext_im5_ip & 0x10);
   tmp2 = (new_value & 0x10);
   if (tmp1 != tmp2)
     return NASM_ERR_OPERAND;
+
   *value = new_value;
   return NASM_R_CONST;
 }
 
 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].  */
   aext_im6_ip = rt_value;
   *value = aext_im6_ip;
@@ -1898,47 +2220,51 @@ 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].  */
   if ((rt_value & 0x03) != aext_im6_ip)
     return NASM_ERR_OPERAND;
+
   *value = aext_im6_ip;
   return NASM_R_CONST;
 }
 
 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].  */
   *value = (rt_value & 0x03);
   return NASM_R_CONST;
 }
 
 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].  */
   *value = (rt_value & 0x03);
   return NASM_R_CONST;
@@ -1953,9 +2279,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;
 
@@ -1964,23 +2290,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)
        {
index c67e590c641c91d8a3b473820bace00f2c2d6e8d..c8431baf3fc74ed67bbe37cf957c73e3a3d49a2b 100644 (file)
@@ -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,
@@ -87,19 +89,22 @@ enum
   NASM_ATTR_RDREG              = 0x000100
 };
 
+/* We only support one core for now.  */
+#define NDS32_CORE_COUNT       1
+#define NDS32_MAIN_CORE                0
+
 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,10 +133,9 @@ 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,
+  HW_INT = 0x1000,
   HW_UINT
 };
 
@@ -277,6 +281,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))
index 418019ae873031942b690e068564ccbf4062b0b4..81ae124c1d64ecc773238a2ed901815c5233ac51 100644 (file)
 /* 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
 
+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);
@@ -52,6 +78,10 @@ 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 **);
+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 *);
 
 /* define in objdump.c.  */
 struct objdump_disasm_info
@@ -65,62 +95,10 @@ struct objdump_disasm_info
   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 *
@@ -221,6 +199,30 @@ nds32_parse_audio_ext (const field_t *pfd,
     func (stream, "$%s", psys_reg->name);
 }
 
+/* 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;
+}
+
 /* Dump instruction.  If the opcode is unknown, return FALSE.  */
 
 static void
@@ -245,9 +247,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)
     {
@@ -294,15 +293,8 @@ nds32_parse_opcode (struct nds32_opcode *opc, bfd_vma pc ATTRIBUTE_UNUSED,
            }
          *pstr_tmp = 0;
 
-         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++;
-           }
+         if ((pfd = match_field (&tmp_string[0])) == NULL)
+           return;
 
          /* For insn-16.  */
          if (parse_mode & NDS32_PARSE_INSN16)
@@ -348,12 +340,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,12 +356,6 @@ 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)
@@ -394,12 +379,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 +430,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)
                {
@@ -571,7 +549,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;
@@ -765,7 +743,14 @@ nds32_mask_opcode (uint32_t insn)
               || __GF (insn, 0, 7) == (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,7 +779,10 @@ 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:
@@ -887,7 +875,8 @@ nds32_mask_opcode (uint32_t insn)
            /* AMAWzSSA AMWzSSA */
            return MASK_OP (insn, (0x1f << 20) | (0x3 << 7));
          else
-           /* AMAWzSL.L AMAWzSL2.S AMAWzSL2.L AMWzSL.L AMWzSL.L AMWzSL2.S */
+           /* 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)
@@ -897,7 +886,8 @@ nds32_mask_opcode (uint32_t insn)
            /* AMAWyySSA AMWyySSA */
            return MASK_OP (insn, (0x1f << 20) | (0x3 << 7));
          else
-           /* AMAWyySL.L AMAWyySL2.S AMAWyySL2.L AMWyySL.L AMWyySL.L AMWyySL2.S */
+           /* 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);
@@ -968,13 +958,8 @@ nds32_special_opcode (uint32_t insn, struct nds32_opcode **opc)
     case JREG (JR) | JREG_RET:
       if (__GF (insn, 8, 2) != 0)
        string = "tit";
-    break;
+      break;
     case N32_OP6_COP:
-    break;
-    case 0xea00:
-      /* break16 ex9 */
-      if (__GF (insn, 5, 4) != 0)
-       string = "ex9";
       break;
     case 0x9200:
       /* nop16 */
@@ -1005,46 +990,187 @@ 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;
+       }
+
+      if (0 > start)
+       start = 0;
 
-      while (nds32_opcodes[i].opcode != NULL)
+      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)
+             && (addr > pc
+                 && ((info->section == NULL)
+                     || (info->section == info->symtab[n]->section)))
+             && (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)
        {
@@ -1057,12 +1183,6 @@ print_insn_nds32 (bfd_vma pc, disassemble_info *info)
   /* 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 +1190,149 @@ 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;
+  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];
+
+  /* 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);
+}