From: Marcus Comstedt Date: Tue, 5 Jan 2021 21:50:32 +0000 (+0100) Subject: RISC-V: Implement support for big endian targets. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=fbc09e7af715f19f6e5c700a9df6d13cdd05e1e5;p=binutils-gdb.git RISC-V: Implement support for big endian targets. RISC-V instruction/code is always little endian, but data might be big-endian. Therefore, we can not use the original bfd_get/bfd_put to get/put the code for big endian targets. Add new riscv_get_insn and riscv_put_insn to always get/put code as little endian can resolve the problem. Just remember to update them once we have supported the 48-bit/128-bit instructions in the future patches. bfd/ * config.bfd: Added targets riscv64be*-*-*, riscv32be*-*-* and riscvbe*-*-*. Also added riscv_elf[32|64]_be_vec. * configure.ac: Handle riscv_elf[32|64]_be_vec. * configure: Regenerate. * elfnn-riscv.c: Include and define CHAR_BIT for riscv_is_insn_reloc. (riscv_get_insn): RISC-V instructions are always little endian, but bfd_get may be used for big-endian, so add new riscv_get_insn to handle the insturctions. (riscv_put_insn): Likewsie. (riscv_is_insn_reloc): Check if we are relocaing an instruction. (perform_relocation): Call riscv_is_insn_reloc to decide if we should use riscv_[get|put]_insn or bfd_[get|put]. (riscv_zero_pcrel_hi_reloc): Use riscv_[get|put]_insn, bfd_[get|put]l32 or bfd_[get|put]l16 for code. (riscv_elf_relocate_section): Likewise. (riscv_elf_finish_dynamic_symbol): Likewise. (riscv_elf_finish_dynamic_sections): Likewise. (_bfd_riscv_relax_call): Likewise. (_bfd_riscv_relax_lui): Likewise. (_bfd_riscv_relax_align): Likewise. (_bfd_riscv_relax_pc): Likewise. (riscv_elf_object_p): Handled for big endian. (TARGET_BIG_SYM, TARGET_BIG_NAME): Defined. * targets.c: Add riscv_elf[32|64]_be_vec. (_bfd_target_vector): Likewise. gas/ * config/tc-riscv.c (riscv_target_format): Add elf64-bigriscv and elf32-bigriscv. (install_insn): Always write instructions as little endian. (riscv_make_nops): Likewise. (md_convert_frag_branch): Likewise. (md_number_to_chars): Write data in target endianness. (options, md_longopts): Add -mbig-endian and -mlittle-endian options. (md_parse_option): Handle the endian options. * config/tc-riscv.h: Only define TARGET_BYTES_BIG_ENDIAN if not already defined. * configure.tgt: Added riscv64be*, riscv32be*, riscvbe*. ld/ * configure.tgt: Added riscvbe-*-*, riscv32be*-*-*, riscv64be*-*-*, riscv32be*-*-linux*, and riscv64be*-*-linux*. * Makefile.am: Added eelf32briscv.c, eelf32briscv_ilp32f.c and eelf32briscv_ilp32.c. * Makefile.in: Regenerate. * emulparams/elf32briscv.sh: Added. * emulparams/elf32briscv_ilp32.sh: Likewise. * emulparams/elf32briscv_ilp32f.sh: Likewise. * emulparams/elf64briscv.sh: Likewise. * emulparams/elf64briscv_lp64.sh: Likewise. * emulparams/elf64briscv_lp64f.sh: Likewise. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 6c050b1c199..a629e8ad6fa 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,32 @@ +2021-01-06 Marcus Comstedt + + * config.bfd: Added targets riscv64be*-*-*, riscv32be*-*-* and + riscvbe*-*-*. Also added riscv_elf[32|64]_be_vec. + * configure.ac: Handle riscv_elf[32|64]_be_vec. + * configure: Regenerate. + * elfnn-riscv.c: Include and define CHAR_BIT for + riscv_is_insn_reloc. + (riscv_get_insn): RISC-V instructions are always little endian, but + bfd_get may be used for big-endian, so add new riscv_get_insn to handle + the insturctions. + (riscv_put_insn): Likewsie. + (riscv_is_insn_reloc): Check if we are relocaing an instruction. + (perform_relocation): Call riscv_is_insn_reloc to decide if we should + use riscv_[get|put]_insn or bfd_[get|put]. + (riscv_zero_pcrel_hi_reloc): Use riscv_[get|put]_insn, bfd_[get|put]l32 + or bfd_[get|put]l16 for code. + (riscv_elf_relocate_section): Likewise. + (riscv_elf_finish_dynamic_symbol): Likewise. + (riscv_elf_finish_dynamic_sections): Likewise. + (_bfd_riscv_relax_call): Likewise. + (_bfd_riscv_relax_lui): Likewise. + (_bfd_riscv_relax_align): Likewise. + (_bfd_riscv_relax_pc): Likewise. + (riscv_elf_object_p): Handled for big endian. + (TARGET_BIG_SYM, TARGET_BIG_NAME): Defined. + * targets.c: Add riscv_elf[32|64]_be_vec. + (_bfd_target_vector): Likewise. + 2021-01-05 Alan Modra * elflink.c (bfd_elf_link_record_dynamic_symbol): Handle no_export diff --git a/bfd/config.bfd b/bfd/config.bfd index f276386d852..bbd0aaa9ef1 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -1158,14 +1158,24 @@ case "${targ}" in ;; #ifdef BFD64 + riscvbe-*-* | riscv32be*-*-*) + targ_defvec=riscv_elf32_be_vec + targ_selvecs="riscv_elf32_vec riscv_elf64_vec riscv_elf32_be_vec riscv_elf64_be_vec" + want64=true + ;; riscv-*-* | riscv32*-*-*) targ_defvec=riscv_elf32_vec - targ_selvecs="riscv_elf32_vec riscv_elf64_vec" + targ_selvecs="riscv_elf32_vec riscv_elf64_vec riscv_elf32_be_vec riscv_elf64_be_vec" + want64=true + ;; + riscv64be*-*-*) + targ_defvec=riscv_elf64_be_vec + targ_selvecs="riscv_elf32_vec riscv_elf64_vec riscv_elf32_be_vec riscv_elf64_be_vec" want64=true ;; riscv64*-*-*) targ_defvec=riscv_elf64_vec - targ_selvecs="riscv_elf32_vec riscv_elf64_vec" + targ_selvecs="riscv_elf32_vec riscv_elf64_vec riscv_elf32_be_vec riscv_elf64_be_vec" want64=true ;; #endif diff --git a/bfd/configure b/bfd/configure index 5d84aed069d..1460bbdfba3 100755 --- a/bfd/configure +++ b/bfd/configure @@ -14919,6 +14919,8 @@ do pru_elf32_vec) tb="$tb elf32-pru.lo elf32.lo $elf" ;; riscv_elf32_vec) tb="$tb elf32-riscv.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf" ;; riscv_elf64_vec) tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf"; target_size=64 ;; + riscv_elf32_be_vec) tb="$tb elf32-riscv.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf" ;; + riscv_elf64_be_vec) tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf"; target_size=64 ;; rl78_elf32_vec) tb="$tb elf32-rl78.lo elf32.lo $elf" ;; rs6000_xcoff64_vec) tb="$tb coff64-rs6000.lo aix5ppc-core.lo $xcoff"; target_size=64 ;; rs6000_xcoff64_aix_vec) tb="$tb coff64-rs6000.lo aix5ppc-core.lo $xcoff"; target_size=64 ;; diff --git a/bfd/configure.ac b/bfd/configure.ac index 819c9852210..0797a08ff37 100644 --- a/bfd/configure.ac +++ b/bfd/configure.ac @@ -625,6 +625,8 @@ do pru_elf32_vec) tb="$tb elf32-pru.lo elf32.lo $elf" ;; riscv_elf32_vec) tb="$tb elf32-riscv.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf" ;; riscv_elf64_vec) tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf"; target_size=64 ;; + riscv_elf32_be_vec) tb="$tb elf32-riscv.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf" ;; + riscv_elf64_be_vec) tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf"; target_size=64 ;; rl78_elf32_vec) tb="$tb elf32-rl78.lo elf32.lo $elf" ;; rs6000_xcoff64_vec) tb="$tb coff64-rs6000.lo aix5ppc-core.lo $xcoff"; target_size=64 ;; rs6000_xcoff64_aix_vec) tb="$tb coff64-rs6000.lo aix5ppc-core.lo $xcoff"; target_size=64 ;; diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index 9da415e604e..098fe9efa6b 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -33,6 +33,13 @@ #include "opcode/riscv.h" #include "objalloc.h" +#ifdef HAVE_LIMITS_H +#include +#endif +#ifndef CHAR_BIT +#define CHAR_BIT 8 +#endif + /* Internal relocations used exclusively by the relaxation pass. */ #define R_RISCV_DELETE (R_RISCV_max + 1) @@ -125,6 +132,18 @@ struct riscv_elf_link_hash_table bfd_vma last_iplt_index; }; +/* Instruction access functions. */ + +#define riscv_get_insn(bits, ptr) \ + ((bits) == 16 ? bfd_getl16 (ptr) \ + : (bits) == 32 ? bfd_getl32 (ptr) \ + : (bits) == 64 ? bfd_getl64 (ptr) \ + : (abort (), (bfd_vma) - 1)) +#define riscv_put_insn(bits, val, ptr) \ + ((bits) == 16 ? bfd_putl16 (val, ptr) \ + : (bits) == 32 ? bfd_putl32 (val, ptr) \ + : (bits) == 64 ? bfd_putl64 (val, ptr) \ + : (abort (), (void) 0)) /* Get the RISC-V ELF linker hash table from a link_info structure. */ #define riscv_elf_hash_table(p) \ @@ -152,6 +171,19 @@ riscv_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel) bed->s->swap_reloca_out (abfd, rel, loc); } +/* Return true if a relocation is modifying an instruction. */ + +static bfd_boolean +riscv_is_insn_reloc (const reloc_howto_type *howto) +{ + /* Heuristic: A multibyte destination with a nontrivial mask + is an instruction */ + return (howto->bitsize > 8 + && howto->dst_mask != 0 + && ~(howto->dst_mask | (howto->bitsize < sizeof(bfd_vma) * CHAR_BIT + ? (MINUS_ONE << howto->bitsize) : (bfd_vma)0)) != 0); +} + /* PLT/GOT stuff. */ #define PLT_HEADER_INSNS 8 @@ -1645,10 +1677,10 @@ perform_relocation (const reloc_howto_type *howto, /* Linker relaxation can convert an address equal to or greater than 0x800 to slightly below 0x800. C.LUI does not accept zero as a valid immediate. We can fix this by converting it to a C.LI. */ - bfd_vma insn = bfd_get (howto->bitsize, input_bfd, - contents + rel->r_offset); + bfd_vma insn = riscv_get_insn (howto->bitsize, + contents + rel->r_offset); insn = (insn & ~MATCH_C_LUI) | MATCH_C_LI; - bfd_put (howto->bitsize, input_bfd, insn, contents + rel->r_offset); + riscv_put_insn (howto->bitsize, insn, contents + rel->r_offset); value = ENCODE_RVC_IMM (0); } else if (!VALID_RVC_LUI_IMM (RISCV_CONST_HIGH_PART (value))) @@ -1684,9 +1716,16 @@ perform_relocation (const reloc_howto_type *howto, return bfd_reloc_notsupported; } - bfd_vma word = bfd_get (howto->bitsize, input_bfd, contents + rel->r_offset); + bfd_vma word; + if (riscv_is_insn_reloc (howto)) + word = riscv_get_insn (howto->bitsize, contents + rel->r_offset); + else + word = bfd_get (howto->bitsize, input_bfd, contents + rel->r_offset); word = (word & ~howto->dst_mask) | (value & howto->dst_mask); - bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset); + if (riscv_is_insn_reloc (howto)) + riscv_put_insn (howto->bitsize, word, contents + rel->r_offset); + else + bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset); return bfd_reloc_ok; } @@ -1764,7 +1803,7 @@ riscv_zero_pcrel_hi_reloc (Elf_Internal_Rela *rel, bfd_vma addr, bfd_byte *contents, const reloc_howto_type *howto, - bfd *input_bfd) + bfd *input_bfd ATTRIBUTE_UNUSED) { /* We may need to reference low addreses in PC-relative modes even when the * PC is far away from these addresses. For example, undefweak references @@ -1790,9 +1829,9 @@ riscv_zero_pcrel_hi_reloc (Elf_Internal_Rela *rel, rel->r_info = ELFNN_R_INFO(addr, R_RISCV_HI20); - bfd_vma insn = bfd_get(howto->bitsize, input_bfd, contents + rel->r_offset); + bfd_vma insn = riscv_get_insn(howto->bitsize, contents + rel->r_offset); insn = (insn & ~MASK_AUIPC) | MATCH_LUI; - bfd_put(howto->bitsize, input_bfd, insn, contents + rel->r_offset); + riscv_put_insn(howto->bitsize, insn, contents + rel->r_offset); return TRUE; } @@ -2380,10 +2419,9 @@ riscv_elf_relocate_section (bfd *output_bfd, && (!bfd_link_pic (info) || h->plt.offset == MINUS_ONE)) { /* We can use x0 as the base register. */ - bfd_vma insn = bfd_get_32 (input_bfd, - contents + rel->r_offset + 4); + bfd_vma insn = bfd_getl32 (contents + rel->r_offset + 4); insn &= ~(OP_MASK_RS1 << OP_SH_RS1); - bfd_put_32 (input_bfd, insn, contents + rel->r_offset + 4); + bfd_putl32 (insn, contents + rel->r_offset + 4); /* Set the relocation value so that we get 0 after the pc relative adjustment. */ relocation = sec_addr (input_section) + rel->r_offset; @@ -2416,10 +2454,10 @@ riscv_elf_relocate_section (bfd *output_bfd, if (VALID_ITYPE_IMM (relocation + rel->r_addend)) { /* We can use tp as the base register. */ - bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset); + bfd_vma insn = bfd_getl32 (contents + rel->r_offset); insn &= ~(OP_MASK_RS1 << OP_SH_RS1); insn |= X_TP << OP_SH_RS1; - bfd_put_32 (input_bfd, insn, contents + rel->r_offset); + bfd_putl32 (insn, contents + rel->r_offset); } else r = bfd_reloc_overflow; @@ -2433,14 +2471,14 @@ riscv_elf_relocate_section (bfd *output_bfd, if (x0_base || VALID_ITYPE_IMM (relocation + rel->r_addend - gp)) { /* We can use x0 or gp as the base register. */ - bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset); + bfd_vma insn = bfd_getl32 (contents + rel->r_offset); insn &= ~(OP_MASK_RS1 << OP_SH_RS1); if (!x0_base) { rel->r_addend -= gp; insn |= X_GP << OP_SH_RS1; } - bfd_put_32 (input_bfd, insn, contents + rel->r_offset); + bfd_putl32 (insn, contents + rel->r_offset); } else r = bfd_reloc_overflow; @@ -2864,7 +2902,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd, return FALSE; for (i = 0; i < PLT_ENTRY_INSNS; i++) - bfd_put_32 (output_bfd, plt_entry[i], loc + 4*i); + bfd_putl32 (plt_entry[i], loc + 4*i); /* Fill in the initial value of the .got.plt entry. */ loc = gotplt->contents + (got_address - sec_addr (gotplt)); @@ -3161,7 +3199,7 @@ riscv_elf_finish_dynamic_sections (bfd *output_bfd, return ret; for (i = 0; i < PLT_HEADER_INSNS; i++) - bfd_put_32 (output_bfd, plt_header[i], splt->contents + 4*i); + bfd_putl32 (plt_header[i], splt->contents + 4*i); elf_section_data (splt->output_section)->this_hdr.sh_entsize = PLT_ENTRY_SIZE; @@ -4118,8 +4156,8 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec, /* Shorten the function call. */ BFD_ASSERT (rel->r_offset + 8 <= sec->size); - auipc = bfd_get_32 (abfd, contents + rel->r_offset); - jalr = bfd_get_32 (abfd, contents + rel->r_offset + 4); + auipc = bfd_getl32 (contents + rel->r_offset); + jalr = bfd_getl32 (contents + rel->r_offset + 4); rd = (jalr >> OP_SH_RD) & OP_MASK_RD; rvc = rvc && VALID_RVC_J_IMM (foff); @@ -4149,7 +4187,7 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec, /* Replace the R_RISCV_CALL reloc. */ rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), r_type); /* Replace the AUIPC. */ - bfd_put (8 * len, abfd, auipc, contents + rel->r_offset); + riscv_put_insn (8 * len, auipc, contents + rel->r_offset); /* Delete unnecessary JALR. */ *again = TRUE; @@ -4223,9 +4261,9 @@ _bfd_riscv_relax_lui (bfd *abfd, if (undefined_weak) { /* Change the RS1 to zero. */ - bfd_vma insn = bfd_get_32 (abfd, contents + rel->r_offset); + bfd_vma insn = bfd_getl32 (contents + rel->r_offset); insn &= ~(OP_MASK_RS1 << OP_SH_RS1); - bfd_put_32 (abfd, insn, contents + rel->r_offset); + bfd_putl32 (insn, contents + rel->r_offset); } else rel->r_info = ELFNN_R_INFO (sym, R_RISCV_GPREL_I); @@ -4235,9 +4273,9 @@ _bfd_riscv_relax_lui (bfd *abfd, if (undefined_weak) { /* Change the RS1 to zero. */ - bfd_vma insn = bfd_get_32 (abfd, contents + rel->r_offset); + bfd_vma insn = bfd_getl32 (contents + rel->r_offset); insn &= ~(OP_MASK_RS1 << OP_SH_RS1); - bfd_put_32 (abfd, insn, contents + rel->r_offset); + bfd_putl32 (insn, contents + rel->r_offset); } else rel->r_info = ELFNN_R_INFO (sym, R_RISCV_GPREL_S); @@ -4268,13 +4306,13 @@ _bfd_riscv_relax_lui (bfd *abfd, : ELF_MAXPAGESIZE))) { /* Replace LUI with C.LUI if legal (i.e., rd != x0 and rd != x2/sp). */ - bfd_vma lui = bfd_get_32 (abfd, contents + rel->r_offset); + bfd_vma lui = bfd_getl32 (contents + rel->r_offset); unsigned rd = ((unsigned)lui >> OP_SH_RD) & OP_MASK_RD; if (rd == 0 || rd == X_SP) return TRUE; lui = (lui & (OP_MASK_RD << OP_SH_RD)) | MATCH_C_LUI; - bfd_put_32 (abfd, lui, contents + rel->r_offset); + bfd_putl32 (lui, contents + rel->r_offset); /* Replace the R_RISCV_HI20 reloc. */ rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), R_RISCV_RVC_LUI); @@ -4376,11 +4414,11 @@ _bfd_riscv_relax_align (bfd *abfd, asection *sec, /* Write as many RISC-V NOPs as we need. */ for (pos = 0; pos < (nop_bytes & -4); pos += 4) - bfd_put_32 (abfd, RISCV_NOP, contents + rel->r_offset + pos); + bfd_putl32 (RISCV_NOP, contents + rel->r_offset + pos); /* Write a final RVC NOP if need be. */ if (nop_bytes % 4 != 0) - bfd_put_16 (abfd, RVC_NOP, contents + rel->r_offset + pos); + bfd_putl16 (RVC_NOP, contents + rel->r_offset + pos); /* Delete the excess bytes. */ return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + nop_bytes, @@ -4487,9 +4525,9 @@ _bfd_riscv_relax_pc (bfd *abfd ATTRIBUTE_UNUSED, { /* Change the RS1 to zero, and then modify the relocation type to R_RISCV_LO12_I. */ - bfd_vma insn = bfd_get_32 (abfd, contents + rel->r_offset); + bfd_vma insn = bfd_getl32 (contents + rel->r_offset); insn &= ~(OP_MASK_RS1 << OP_SH_RS1); - bfd_put_32 (abfd, insn, contents + rel->r_offset); + bfd_putl32 (insn, contents + rel->r_offset); rel->r_info = ELFNN_R_INFO (sym, R_RISCV_LO12_I); rel->r_addend = hi_reloc.hi_addend; } @@ -4505,9 +4543,9 @@ _bfd_riscv_relax_pc (bfd *abfd ATTRIBUTE_UNUSED, { /* Change the RS1 to zero, and then modify the relocation type to R_RISCV_LO12_S. */ - bfd_vma insn = bfd_get_32 (abfd, contents + rel->r_offset); + bfd_vma insn = bfd_getl32 (contents + rel->r_offset); insn &= ~(OP_MASK_RS1 << OP_SH_RS1); - bfd_put_32 (abfd, insn, contents + rel->r_offset); + bfd_putl32 (insn, contents + rel->r_offset); rel->r_info = ELFNN_R_INFO (sym, R_RISCV_LO12_S); rel->r_addend = hi_reloc.hi_addend; } @@ -4919,7 +4957,8 @@ static bfd_boolean riscv_elf_object_p (bfd *abfd) { /* There are only two mach types in RISCV currently. */ - if (strcmp (abfd->xvec->name, "elf32-littleriscv") == 0) + if (strcmp (abfd->xvec->name, "elf32-littleriscv") == 0 + || strcmp (abfd->xvec->name, "elf32-bigriscv") == 0) bfd_default_set_arch_mach (abfd, bfd_arch_riscv, bfd_mach_riscv32); else bfd_default_set_arch_mach (abfd, bfd_arch_riscv, bfd_mach_riscv64); @@ -4938,6 +4977,8 @@ riscv_elf_obj_attrs_arg_type (int tag) #define TARGET_LITTLE_SYM riscv_elfNN_vec #define TARGET_LITTLE_NAME "elfNN-littleriscv" +#define TARGET_BIG_SYM riscv_elfNN_be_vec +#define TARGET_BIG_NAME "elfNN-bigriscv" #define elf_backend_reloc_type_class riscv_reloc_type_class diff --git a/bfd/targets.c b/bfd/targets.c index e9d76ef8c7a..8086f03e464 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -843,6 +843,8 @@ extern const bfd_target powerpc_xcoff_vec; extern const bfd_target pru_elf32_vec; extern const bfd_target riscv_elf32_vec; extern const bfd_target riscv_elf64_vec; +extern const bfd_target riscv_elf32_be_vec; +extern const bfd_target riscv_elf64_be_vec; extern const bfd_target rl78_elf32_vec; extern const bfd_target rs6000_xcoff64_vec; extern const bfd_target rs6000_xcoff64_aix_vec; @@ -1237,6 +1239,8 @@ static const bfd_target * const _bfd_target_vector[] = #ifdef BFD64 &riscv_elf32_vec, &riscv_elf64_vec, + &riscv_elf32_be_vec, + &riscv_elf64_be_vec, #endif &rl78_elf32_vec, diff --git a/gas/ChangeLog b/gas/ChangeLog index 03ea1a1c9c3..57bc038a563 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,17 @@ +2021-01-06 Marcus Comstedt + + * config/tc-riscv.c (riscv_target_format): Add elf64-bigriscv and + elf32-bigriscv. + (install_insn): Always write instructions as little endian. + (riscv_make_nops): Likewise. + (md_convert_frag_branch): Likewise. + (md_number_to_chars): Write data in target endianness. + (options, md_longopts): Add -mbig-endian and -mlittle-endian options. + (md_parse_option): Handle the endian options. + * config/tc-riscv.h: Only define TARGET_BYTES_BIG_ENDIAN if not + already defined. + * configure.tgt: Added riscv64be*, riscv32be*, riscvbe*. + 2021-01-04 H.J. Lu PR ld/26256 diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index e938a8812d9..55d5f1b50d9 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -445,7 +445,10 @@ static char *expr_end; const char * riscv_target_format (void) { - return xlen == 64 ? "elf64-littleriscv" : "elf32-littleriscv"; + if (target_big_endian) + return xlen == 64 ? "elf64-bigriscv" : "elf32-bigriscv"; + else + return xlen == 64 ? "elf64-littleriscv" : "elf32-littleriscv"; } /* Return the length of instruction INSN. */ @@ -474,7 +477,7 @@ static void install_insn (const struct riscv_cl_insn *insn) { char *f = insn->frag->fr_literal + insn->where; - md_number_to_chars (f, insn->insn_opcode, insn_length (insn)); + number_to_chars_littleendian (f, insn->insn_opcode, insn_length (insn)); } /* Move INSN to offset WHERE in FRAG. Adjust the fixups accordingly @@ -2662,7 +2665,10 @@ md_atof (int type, char *litP, int *sizeP) void md_number_to_chars (char *buf, valueT val, int n) { - number_to_chars_littleendian (buf, val, n); + if (target_big_endian) + number_to_chars_bigendian (buf, val, n); + else + number_to_chars_littleendian (buf, val, n); } const char *md_shortopts = "O::g::G:"; @@ -2681,6 +2687,8 @@ enum options OPTION_NO_CSR_CHECK, OPTION_MISA_SPEC, OPTION_MPRIV_SPEC, + OPTION_BIG_ENDIAN, + OPTION_LITTLE_ENDIAN, OPTION_END_OF_ENUM }; @@ -2699,6 +2707,8 @@ struct option md_longopts[] = {"mno-csr-check", no_argument, NULL, OPTION_NO_CSR_CHECK}, {"misa-spec", required_argument, NULL, OPTION_MISA_SPEC}, {"mpriv-spec", required_argument, NULL, OPTION_MPRIV_SPEC}, + {"mbig-endian", no_argument, NULL, OPTION_BIG_ENDIAN}, + {"mlittle-endian", no_argument, NULL, OPTION_LITTLE_ENDIAN}, {NULL, no_argument, NULL, 0} }; @@ -2777,6 +2787,14 @@ md_parse_option (int c, const char *arg) case OPTION_MPRIV_SPEC: return riscv_set_default_priv_spec (arg); + case OPTION_BIG_ENDIAN: + target_big_endian = 1; + break; + + case OPTION_LITTLE_ENDIAN: + target_big_endian = 0; + break; + default: return 0; } @@ -3258,13 +3276,13 @@ riscv_make_nops (char *buf, bfd_vma bytes) /* Use at most one 2-byte NOP. */ if ((bytes - i) % 4 == 2) { - md_number_to_chars (buf + i, RVC_NOP, 2); + number_to_chars_littleendian (buf + i, RVC_NOP, 2); i += 2; } /* Fill the remainder with 4-byte NOPs. */ for ( ; i < bytes; i += 4) - md_number_to_chars (buf + i, RISCV_NOP, 4); + number_to_chars_littleendian (buf + i, RISCV_NOP, 4); } /* Called from md_do_align. Used to create an alignment frag in a @@ -3468,14 +3486,14 @@ md_convert_frag_branch (fragS *fragp) insn = bfd_getl32 (buf); insn ^= MATCH_BEQ ^ MATCH_BNE; insn |= ENCODE_SBTYPE_IMM (8); - md_number_to_chars ((char *) buf, insn, 4); + bfd_putl32 (insn, buf); buf += 4; jump: /* Jump to the target. */ fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal, 4, &exp, FALSE, BFD_RELOC_RISCV_JMP); - md_number_to_chars ((char *) buf, MATCH_JAL, 4); + bfd_putl32 (MATCH_JAL, buf); buf += 4; break; diff --git a/gas/config/tc-riscv.h b/gas/config/tc-riscv.h index a503fc52437..6f202887b29 100644 --- a/gas/config/tc-riscv.h +++ b/gas/config/tc-riscv.h @@ -28,7 +28,9 @@ struct frag; struct expressionS; +#ifndef TARGET_BYTES_BIG_ENDIAN #define TARGET_BYTES_BIG_ENDIAN 0 +#endif #define TARGET_ARCH bfd_arch_riscv diff --git a/gas/configure.tgt b/gas/configure.tgt index b17336bfa4f..6f46e0a6329 100644 --- a/gas/configure.tgt +++ b/gas/configure.tgt @@ -89,7 +89,9 @@ case ${cpu} in pj*) cpu_type=pj endian=big ;; powerpc*le*) cpu_type=ppc endian=little ;; powerpc*) cpu_type=ppc endian=big ;; + riscv64be*) cpu_type=riscv endian=big arch=riscv64 ;; riscv64*) cpu_type=riscv endian=little arch=riscv64 ;; + riscv32be*|riscvbe*) cpu_type=riscv endian=big arch=riscv32 ;; riscv32* | riscv*) cpu_type=riscv endian=little arch=riscv32 ;; rs6000*) cpu_type=ppc ;; rl78*) cpu_type=rl78 ;; @@ -357,7 +359,7 @@ case ${generic_target} in pru-*-*) fmt=elf ;; - riscv*-*-*) fmt=elf endian=little ;; + riscv*-*-*) fmt=elf ;; rx-*-linux*) fmt=elf em=linux ;; diff --git a/ld/ChangeLog b/ld/ChangeLog index b939f616f3a..2e51333bb1b 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,17 @@ +2021-01-06 Marcus Comstedt + + * configure.tgt: Added riscvbe-*-*, riscv32be*-*-*, riscv64be*-*-*, + riscv32be*-*-linux*, and riscv64be*-*-linux*. + * Makefile.am: Added eelf32briscv.c, eelf32briscv_ilp32f.c and + eelf32briscv_ilp32.c. + * Makefile.in: Regenerate. + * emulparams/elf32briscv.sh: Added. + * emulparams/elf32briscv_ilp32.sh: Likewise. + * emulparams/elf32briscv_ilp32f.sh: Likewise. + * emulparams/elf64briscv.sh: Likewise. + * emulparams/elf64briscv_lp64.sh: Likewise. + * emulparams/elf64briscv_lp64f.sh: Likewise. + 2021-01-05 Nick Alcock * testsuite/ld-ctf/enum-forward.c: New test. diff --git a/ld/Makefile.am b/ld/Makefile.am index 241df9f703e..2c9a487335c 100644 --- a/ld/Makefile.am +++ b/ld/Makefile.am @@ -266,6 +266,9 @@ ALL_EMULATION_SOURCES = \ eelf32lriscv.c \ eelf32lriscv_ilp32f.c \ eelf32lriscv_ilp32.c \ + eelf32briscv.c \ + eelf32briscv_ilp32f.c \ + eelf32briscv_ilp32.c \ eelf32rl78.c \ eelf32rx.c \ eelf32rx_linux.c \ @@ -435,6 +438,9 @@ ALL_64_EMULATION_SOURCES = \ eelf64lriscv.c \ eelf64lriscv_lp64f.c \ eelf64lriscv_lp64.c \ + eelf64briscv.c \ + eelf64briscv_lp64f.c \ + eelf64briscv_lp64.c \ eelf64ltsmip.c \ eelf64ltsmip_fbsd.c \ eelf64mmix.c \ @@ -751,6 +757,9 @@ $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS) @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lriscv.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lriscv_ilp32f.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lriscv_ilp32.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv_ilp32f.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv_ilp32.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rl78.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rx.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rx_linux.Pc@am__quote@ @@ -916,6 +925,9 @@ $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS) @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_lp64f.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_lp64.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv_lp64f.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv_lp64.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip_fbsd.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64mmix.Pc@am__quote@ diff --git a/ld/Makefile.in b/ld/Makefile.in index 8d6738a94a4..c1c42aa9ec1 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -521,6 +521,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -755,6 +756,9 @@ ALL_EMULATION_SOURCES = \ eelf32lriscv.c \ eelf32lriscv_ilp32f.c \ eelf32lriscv_ilp32.c \ + eelf32briscv.c \ + eelf32briscv_ilp32f.c \ + eelf32briscv_ilp32.c \ eelf32rl78.c \ eelf32rx.c \ eelf32rx_linux.c \ @@ -923,6 +927,9 @@ ALL_64_EMULATION_SOURCES = \ eelf64lriscv.c \ eelf64lriscv_lp64f.c \ eelf64lriscv_lp64.c \ + eelf64briscv.c \ + eelf64briscv_lp64f.c \ + eelf64briscv_lp64.c \ eelf64ltsmip.c \ eelf64ltsmip_fbsd.c \ eelf64mmix.c \ @@ -1318,6 +1325,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32bfinfd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32bmip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32bmipn32.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv_ilp32.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv_ilp32f.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32bsmip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32btsmip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32btsmip_fbsd.Po@am__quote@ @@ -1403,6 +1413,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64alpha_nbsd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64bmip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64bpf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv_lp64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv_lp64f.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip_fbsd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64hppa.Po@am__quote@ @@ -2403,6 +2416,9 @@ $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS) @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lriscv.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lriscv_ilp32f.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lriscv_ilp32.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv_ilp32f.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32briscv_ilp32.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rl78.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rx.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32rx_linux.Pc@am__quote@ @@ -2568,6 +2584,9 @@ $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS) @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_lp64f.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv_lp64.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv_lp64f.Pc@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64briscv_lp64.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip_fbsd.Pc@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64mmix.Pc@am__quote@ diff --git a/ld/configure.tgt b/ld/configure.tgt index 893d2daef94..0c780b24d57 100644 --- a/ld/configure.tgt +++ b/ld/configure.tgt @@ -738,21 +738,38 @@ powerpc-*-windiss*) targ_emul=elf32ppcwindiss ;; pru*-*-*) targ_emul=pruelf ;; +riscv32be*-*-linux*) targ_emul=elf32briscv + targ_extra_emuls="elf32briscv_ilp32f elf32briscv_ilp32 elf64briscv elf64briscv_lp64f elf64briscv_lp64 elf32lriscv elf32lriscv_ilp32f elf32lriscv_ilp32 elf64lriscv elf64lriscv_lp64f elf64lriscv_lp64" + targ_extra_libpath=$targ_extra_emuls + ;; riscv32*-*-linux*) targ_emul=elf32lriscv - targ_extra_emuls="elf32lriscv_ilp32f elf32lriscv_ilp32 elf64lriscv elf64lriscv_lp64f elf64lriscv_lp64" + targ_extra_emuls="elf32lriscv_ilp32f elf32lriscv_ilp32 elf64lriscv elf64lriscv_lp64f elf64lriscv_lp64 elf32briscv elf32briscv_ilp32f elf32briscv_ilp32 elf64briscv elf64briscv_lp64f elf64briscv_lp64" + targ_extra_libpath=$targ_extra_emuls + ;; +riscvbe-*-* | riscv32be*-*-*) + targ_emul=elf32briscv + targ_extra_emuls="elf64briscv elf32lriscv elf64lriscv" targ_extra_libpath=$targ_extra_emuls ;; riscv-*-* | riscv32*-*-*) targ_emul=elf32lriscv - targ_extra_emuls="elf64lriscv" + targ_extra_emuls="elf64lriscv elf32briscv elf64briscv" + targ_extra_libpath=$targ_extra_emuls + ;; +riscv64be*-*-linux*) targ_emul=elf64briscv + targ_extra_emuls="elf64briscv_lp64f elf64briscv_lp64 elf32briscv elf32briscv_ilp32f elf32briscv_ilp32 elf64lriscv elf64lriscv_lp64f elf64lriscv_lp64 elf32lriscv elf32lriscv_ilp32f elf32lriscv_ilp32" targ_extra_libpath=$targ_extra_emuls ;; riscv64*-*-linux*) targ_emul=elf64lriscv - targ_extra_emuls="elf64lriscv_lp64f elf64lriscv_lp64 elf32lriscv elf32lriscv_ilp32f elf32lriscv_ilp32" + targ_extra_emuls="elf64lriscv_lp64f elf64lriscv_lp64 elf32lriscv elf32lriscv_ilp32f elf32lriscv_ilp32 elf64briscv elf64briscv_lp64f elf64briscv_lp64 elf32briscv elf32briscv_ilp32f elf32briscv_ilp32" + targ_extra_libpath=$targ_extra_emuls + ;; +riscv64be*-*-*) targ_emul=elf64briscv + targ_extra_emuls="elf32briscv elf64lriscv elf32lriscv" targ_extra_libpath=$targ_extra_emuls ;; riscv64*-*-*) targ_emul=elf64lriscv - targ_extra_emuls="elf32lriscv" + targ_extra_emuls="elf32lriscv elf64briscv elf32briscv" targ_extra_libpath=$targ_extra_emuls ;; rs6000-*-aix[5-9]*) targ_emul=aix5rs6 diff --git a/ld/emulparams/elf32briscv.sh b/ld/emulparams/elf32briscv.sh new file mode 100644 index 00000000000..bad02bd5cf2 --- /dev/null +++ b/ld/emulparams/elf32briscv.sh @@ -0,0 +1,2 @@ +source_sh ${srcdir}/emulparams/elf32lriscv.sh +OUTPUT_FORMAT="elf32-bigriscv" diff --git a/ld/emulparams/elf32briscv_ilp32.sh b/ld/emulparams/elf32briscv_ilp32.sh new file mode 100644 index 00000000000..c150108d3a8 --- /dev/null +++ b/ld/emulparams/elf32briscv_ilp32.sh @@ -0,0 +1,2 @@ +source_sh ${srcdir}/emulparams/elf32lriscv_ilp32.sh +OUTPUT_FORMAT="elf32-bigriscv" diff --git a/ld/emulparams/elf32briscv_ilp32f.sh b/ld/emulparams/elf32briscv_ilp32f.sh new file mode 100644 index 00000000000..52117e6b0cc --- /dev/null +++ b/ld/emulparams/elf32briscv_ilp32f.sh @@ -0,0 +1,2 @@ +source_sh ${srcdir}/emulparams/elf32lriscv_ilp32f.sh +OUTPUT_FORMAT="elf32-bigriscv" diff --git a/ld/emulparams/elf64briscv.sh b/ld/emulparams/elf64briscv.sh new file mode 100644 index 00000000000..86a429f10fd --- /dev/null +++ b/ld/emulparams/elf64briscv.sh @@ -0,0 +1,2 @@ +source_sh ${srcdir}/emulparams/elf64lriscv.sh +OUTPUT_FORMAT="elf64-bigriscv" diff --git a/ld/emulparams/elf64briscv_lp64.sh b/ld/emulparams/elf64briscv_lp64.sh new file mode 100644 index 00000000000..b00717c31af --- /dev/null +++ b/ld/emulparams/elf64briscv_lp64.sh @@ -0,0 +1,2 @@ +source_sh ${srcdir}/emulparams/elf64lriscv_lp64.sh +OUTPUT_FORMAT="elf64-bigriscv" diff --git a/ld/emulparams/elf64briscv_lp64f.sh b/ld/emulparams/elf64briscv_lp64f.sh new file mode 100644 index 00000000000..a54a3f41c65 --- /dev/null +++ b/ld/emulparams/elf64briscv_lp64f.sh @@ -0,0 +1,2 @@ +source_sh ${srcdir}/emulparams/elf64lriscv_lp64f.sh +OUTPUT_FORMAT="elf64-bigriscv"