From 206209851203c7ec20143060cf23080dc37c864e Mon Sep 17 00:00:00 2001 From: Nelson Chu Date: Thu, 23 Aug 2018 10:56:04 +0800 Subject: [PATCH 09/13] NDS32: Support floating load/store to gp relaxation. The relaxation is only supported for the v3f/v3s toolchain, the pattern generated by compiler is shown as below: .relax_hint ID la $r0, symbol .relax_hint ID flsi $fs0, [$r0 + (4)] .relax_hint ID flsi $fs1, [$r0 + 0] ... First, assembler will the extend pseudo `la' to two instructions (sethi + ori), and then linker will relax them to the following code: flsi $fs0, [$gp + off1] flsi $fs1, [$gp + off2] ... bfd/ * 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. gas/ * config/tc-nds32.h (relax_ls_table): Add floating load/store to gp relax pattern. (hint_map, nds32_find_reloc_table): Likewise. include/ * elf/nds32.h: Add R_NDS32_LSI. --- bfd/bfd-in2.h | 3 ++ bfd/elf32-nds32.c | 101 +++++++++++++++++++++++++++++++++++++++++- bfd/libbfd.h | 1 + bfd/reloc.c | 4 ++ gas/config/tc-nds32.c | 36 ++++++++++++++- gas/config/tc-nds32.h | 1 + include/elf/nds32.h | 5 ++- 7 files changed, 147 insertions(+), 4 deletions(-) diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index e5f7101e52..b5ca04c149 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -4288,6 +4288,9 @@ This is a 5 bit absolute address. */ BFD_RELOC_NDS32_TLS_LE_15S1, BFD_RELOC_NDS32_TLS_LE_15S2, +/* For floating load store relaxation. */ + BFD_RELOC_NDS32_LSI, + /* This is a 9-bit reloc */ BFD_RELOC_V850_9_PCREL, diff --git a/bfd/elf32-nds32.c b/bfd/elf32-nds32.c index 3b2690a18d..49b35ef9eb 100644 --- a/bfd/elf32-nds32.c +++ b/bfd/elf32-nds32.c @@ -2208,6 +2208,21 @@ static reloc_howto_type nds32_elf_relax_howto_table[] = { 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), }; @@ -2822,6 +2837,7 @@ static const struct nds32_reloc_map_entry nds32_reloc_map[] = {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_LSI, R_NDS32_LSI}, }; /* Patch tag. */ @@ -10635,6 +10651,84 @@ nds32_elf_relax_ptr (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, return TRUE; } +/* Relax LWC relocation for nds32_elf_relax_section. */ + +static void +nds32_elf_relax_flsi (struct bfd_link_info *link_info, bfd *abfd, + asection *sec, Elf_Internal_Rela *irel, + Elf_Internal_Rela *internal_relocs, + bfd_byte *contents, Elf_Internal_Sym *isymbuf, + Elf_Internal_Shdr *symtab_hdr, bfd_boolean *again) +{ + /* Pattern: + sethi ra, hi20(symbol) ; HI20/LOADSTORE + ori ra, ra, lo12(symbol) ; LO12S0/PTR/PTR/.../INSN16 + flsi fsa, [ra + offset1] ; LSI/PTR_RESOLVED/INSN16 + flsi fsb, [ra + offset2] ; LSI/PTR_RESOLVED/INSN16 + ... */ + + uint32_t insn; + bfd_vma local_sda, laddr; + unsigned long reloc; + bfd_vma access_addr, flsi_offset; + bfd_vma range_l = 0, range_h = 0; /* Upper/lower bound. */ + Elf_Internal_Rela *irelend, *re_irel; + unsigned int opcode; + + irelend = internal_relocs + sec->reloc_count; + laddr = irel->r_offset; + insn = bfd_getb32 (contents + laddr); + + if ((insn & 0x80000000) || !is_sda_access_insn (insn)) + return; + + /* Can not do relaxation for bi format. */ + if ((insn & 0x1000)) + return; + + /* Only deal with flsi, fssi, fldi, fsdi, so far. */ + opcode = N32_OP6 (insn); + if ((opcode == N32_OP6_LWC) || (opcode == N32_OP6_SWC)) + reloc = R_NDS32_SDA12S2_SP_RELA; + else if ((opcode == N32_OP6_LDC) || (opcode == N32_OP6_SDC)) + reloc = R_NDS32_SDA12S2_DP_RELA; + else + return; + + re_irel = find_relocs_at_address (irel, internal_relocs, irelend, + R_NDS32_PTR_RESOLVED); + if (re_irel == irelend) + { + _bfd_error_handler (unrecognized_reloc_msg, abfd, "R_NDS32_LSI", + (uint64_t) irel->r_offset); + return; + } + + /* For SDA base relative relaxation. */ + nds32_elf_final_sda_base (sec->output_section->owner, link_info, + &local_sda, FALSE); + access_addr = calculate_memory_address (abfd, irel, isymbuf, symtab_hdr); + flsi_offset = (insn & 0xfff) << 2; + access_addr += flsi_offset; + range_l = sdata_range[0][0]; + range_h = sdata_range[0][1]; + + if ((local_sda <= access_addr && (access_addr - local_sda) < range_h) + || (local_sda > access_addr && (local_sda - access_addr) <= range_l)) + { + /* Turn flsi instruction into sda access format. */ + insn = (insn & 0x7ff07000) | (REG_GP << 15); + + /* Add relocation type to flsi. */ + irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), reloc); + irel->r_addend += flsi_offset; + bfd_putb32 (insn, contents + re_irel->r_offset); + + re_irel->r_addend |= 1; + *again = TRUE; + } +} + static bfd_boolean nds32_relax_adjust_label (bfd *abfd, asection *sec, Elf_Internal_Rela *internal_relocs, @@ -11059,7 +11153,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; @@ -11155,6 +11250,10 @@ nds32_elf_relax_section (bfd *abfd, asection *sec, 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: diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 34f05dd2e7..1e0cf17153 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -2014,6 +2014,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_NDS32_TLS_LE_15S0", "BFD_RELOC_NDS32_TLS_LE_15S1", "BFD_RELOC_NDS32_TLS_LE_15S2", + "BFD_RELOC_NDS32_LSI", "BFD_RELOC_V850_9_PCREL", "BFD_RELOC_V850_22_PCREL", "BFD_RELOC_V850_SDA_16_16_OFFSET", diff --git a/bfd/reloc.c b/bfd/reloc.c index 67457418e6..86ae1257d6 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -4279,6 +4279,10 @@ ENUMX BFD_RELOC_NDS32_TLS_LE_15S2 ENUMDOC For TLS. +ENUM + BFD_RELOC_NDS32_LSI +ENUMDOC + For floating load store relaxation. ENUM diff --git a/gas/config/tc-nds32.c b/gas/config/tc-nds32.c index 1f468ab928..015d5d4017 100644 --- a/gas/config/tc-nds32.c +++ b/gas/config/tc-nds32.c @@ -5018,6 +5018,27 @@ nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out, static struct nds32_relax_hint_table relax_ls_table[] = { + { + /* 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} + } + }, { /* Load Address / Load-Store (LALS). */ .main_type = NDS32_RELAX_HINT_LALS, @@ -5460,6 +5481,16 @@ static struct nds32_hint_map hint_map [] = 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). */ @@ -5564,6 +5595,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: @@ -5717,7 +5750,8 @@ 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)) + || insn == OP6 (LWC) || insn == OP6 (SWC) + || insn == OP6 (LDC) || insn == OP6 (SDC)) return TRUE; break; case OP6 (BR2): diff --git a/gas/config/tc-nds32.h b/gas/config/tc-nds32.h index 9fecdbdf76..e48d4c1f9b 100644 --- a/gas/config/tc-nds32.h +++ b/gas/config/tc-nds32.h @@ -290,6 +290,7 @@ typedef struct nds32_relax_info enum nds32_relax_hint_type { NDS32_RELAX_HINT_NONE = 0, + NDS32_RELAX_HINT_LA_FLSI, NDS32_RELAX_HINT_LALS, NDS32_RELAX_HINT_LA_PLT, NDS32_RELAX_HINT_LA_GOT, diff --git a/include/elf/nds32.h b/include/elf/nds32.h index 802dd91318..ff8efbca66 100644 --- a/include/elf/nds32.h +++ b/include/elf/nds32.h @@ -146,7 +146,6 @@ 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-191. */ /* These used only for relaxations */ @@ -172,8 +171,10 @@ START_RELOC_NUMBERS (elf_nds32_reloc_type) RELOC_NUMBER (R_NDS32_TLS_LE_ADD, 211) RELOC_NUMBER (R_NDS32_TLS_LE_LS, 212) RELOC_NUMBER (R_NDS32_EMPTY, 213) + /* Reserved numbers: 214-220. */ + RELOC_NUMBER (R_NDS32_LSI, 221) + /* Reserved numbers: 222-255. */ - /* Reserved numbers: 214-255. */ END_RELOC_NUMBERS (R_NDS32_max) /* Processor specific section indices. These sections do not actually -- 2.19.0