summaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorMarcus Comstedt <marcus@mc.pp.se>2021-01-05 22:50:32 +0100
committerNelson Chu <nelson.chu@sifive.com>2021-01-06 17:57:52 +0800
commitfbc09e7af715f19f6e5c700a9df6d13cdd05e1e5 (patch)
treeb7cfb144e27508c018d5ea332e56d36548216e9b /gas
parent865288236d881acecdcf0aaa636fd28fd811d862 (diff)
downloadbinutils-gdb-fbc09e7af715f19f6e5c700a9df6d13cdd05e1e5.tar.gz
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 <limits.h> 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.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog14
-rw-r--r--gas/config/tc-riscv.c32
-rw-r--r--gas/config/tc-riscv.h2
-rw-r--r--gas/configure.tgt4
4 files changed, 44 insertions, 8 deletions
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 <marcus@mc.pp.se>
+
+ * 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 <hongjiu.lu@intel.com>
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 ;;