From 2922d21da14b4711872371abacb16e8ab7c70894 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sun, 18 Dec 2016 22:53:50 -0800 Subject: [PATCH] Re-work RISC-V gas flags: now we just support -mabi and -march We've decided to standardize on two flags for RISC-V: "-march" sets the target architecture (which determines which instructions can be generated), and "-mabi" sets the target ABI. We needed to rework this because the old flag set didn't support soft-float or single-float ABIs, and didn't support an x32-style ABI on RISC-V. Additionally, we've changed the behavior of the -march flag: it's now a lot stricter and only parses things we can actually understand. Additionally, it's now lowercase-only: the rationale is that while the RISC-V ISA manual specifies that ISA strings are case-insensitive, in Linux-land things are usually case-sensitive. Since this flag can be used to determine library paths, we didn't want to bake some case-insensitivity in there that would case trouble later. This patch implements these two new flags and removes the old flags that could conflict with these. There wasn't a RISC-V release before, so we want to just support a clean flag set. include/ * elf/riscv.h (EF_RISCV_SOFT_FLOAT): Don't define. (EF_RISCV_FLOAT_ABI, EF_RISCV_FLOAT_ABI_SOFT): Define. (EF_RISCV_FLOAT_ABI_SINGLE, EF_RISCV_FLOAT_ABI_DOUBLE): Define. (EF_RISCV_FLOAT_ABI_QUAD): Define. bfd/ * elfnn-riscv.c (_bfd_riscv_elf_merge_private_bfd_data): Use EF_RISCV_FLOAT_ABI_SOFT instead of EF_RISCV_SOFT_FLOAT. binutils/ * readelf.c (get_machine_flags): Use EF_RISCV_FLOAT_ABI_{SOFT,SINGLE,DOBULE,QUAD) instead of EF_RISCV_{SOFT,HARD}_FLOAT. gas/ * config/tc-riscv.h (xlen): Delete. * config/tc-riscv.c (xlen): Make static. (abi_xlen): New variable. (options): Replace OPTION_{M32,M64,MSOFT_FLOAT,MHARD_FLOAT,MRVC} with OPTION_MABI. (md_longopts): Likewise. (md_parse_option): Likewise. (riscv_elf_final_processing): Likewise. * doc/as.texinfo (Target RISC-V options): Likewise. * doc/c-riscv.texi (OPTIONS): Likewise. * config/tc-riscv.c (float_mode): Removed. (float_abi): New type, specifies the floating-point ABI. (riscv_set_abi): New function. (riscv_add_subset): Only allow lower-case ISA names and require them to start with "rv". (riscv_after_parse_args): Likewise. opcodes/ * riscv-dis.c (riscv_disassemble_insn): Default to the ELF's XLEN when none is provided. --- bfd/ChangeLog | 5 ++ bfd/elfnn-riscv.c | 4 +- binutils/ChangeLog | 6 ++ binutils/readelf.c | 21 ++++- gas/ChangeLog | 19 ++++ gas/config/tc-riscv.c | 197 ++++++++++++++++++++---------------------- gas/config/tc-riscv.h | 1 - gas/doc/as.texinfo | 5 +- gas/doc/c-riscv.texi | 23 ++--- include/ChangeLog | 7 ++ include/elf/riscv.h | 16 +++- opcodes/ChangeLog | 5 ++ opcodes/riscv-dis.c | 8 +- 13 files changed, 186 insertions(+), 131 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f2b1707e5a1..259825de7ad 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2016-12-20 Andrew Waterman + + * elfnn-riscv.c (_bfd_riscv_elf_merge_private_bfd_data): Use + EF_RISCV_FLOAT_ABI_SOFT instead of EF_RISCV_SOFT_FLOAT. + 2016-12-20 Andrew Waterman * elfnn-riscv.c (bfd_riscv_get_max_alignment): Return bfd_vma diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index a9b0ac6be09..7f3ca728b92 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -2597,8 +2597,8 @@ _bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) return TRUE; } - /* Disallow linking soft-float and hard-float. */ - if ((old_flags ^ new_flags) & EF_RISCV_SOFT_FLOAT) + /* Disallow linking different float ABIs. */ + if ((old_flags ^ new_flags) & EF_RISCV_FLOAT_ABI) { (*_bfd_error_handler) (_("%B: can't link hard-float modules with soft-float modules"), ibfd); diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 057e309dd97..fd86ed5f33f 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,9 @@ +2016-12-20 Andrew Waterman + + * readelf.c (get_machine_flags): Use + EF_RISCV_FLOAT_ABI_{SOFT,SINGLE,DOBULE,QUAD) instead of + EF_RISCV_{SOFT,HARD}_FLOAT. + 2016-12-14 Maciej W. Rozycki * testsuite/binutils-all/mips/mips-ase-1.d: New test. diff --git a/binutils/readelf.c b/binutils/readelf.c index c8e97269036..873a4710294 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -3317,8 +3317,25 @@ get_machine_flags (unsigned e_flags, unsigned e_machine) case EM_RISCV: if (e_flags & EF_RISCV_RVC) strcat (buf, ", RVC"); - if (e_flags & EF_RISCV_SOFT_FLOAT) - strcat (buf, ", soft-float ABI"); + + switch (e_flags & EF_RISCV_FLOAT_ABI) + { + case EF_RISCV_FLOAT_ABI_SOFT: + strcat (buf, ", soft-float ABI"); + break; + + case EF_RISCV_FLOAT_ABI_SINGLE: + strcat (buf, ", single-float ABI"); + break; + + case EF_RISCV_FLOAT_ABI_DOUBLE: + strcat (buf, ", double-float ABI"); + break; + + case EF_RISCV_FLOAT_ABI_QUAD: + strcat (buf, ", quad-float ABI"); + break; + } break; case EM_SH: diff --git a/gas/ChangeLog b/gas/ChangeLog index 0e652b13469..a603984e698 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,22 @@ +2016-12-20 Andrew Waterman + + * config/tc-riscv.h (xlen): Delete. + * config/tc-riscv.c (xlen): Make static. + (abi_xlen): New variable. + (options): Replace OPTION_{M32,M64,MSOFT_FLOAT,MHARD_FLOAT,MRVC} + with OPTION_MABI. + (md_longopts): Likewise. + (md_parse_option): Likewise. + (riscv_elf_final_processing): Likewise. + * doc/as.texinfo (Target RISC-V options): Likewise. + * doc/c-riscv.texi (OPTIONS): Likewise. + * config/tc-riscv.c (float_mode): Removed. + (float_abi): New type, specifies the floating-point ABI. + (riscv_set_abi): New function. + (riscv_add_subset): Only allow lower-case ISA names and require + them to start with "rv". + (riscv_after_parse_args): Likewise. + 2016-12-20 Andrew Waterman Kuan-Lin Chen diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index d011864fd70..77c92cfac30 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -61,9 +61,10 @@ struct riscv_cl_insn static const char default_arch[] = DEFAULT_ARCH; -unsigned xlen = 0; /* width of an x-register */ +static unsigned xlen = 0; /* width of an x-register */ +static unsigned abi_xlen = 0; /* width of a pointer in the ABI */ -#define LOAD_ADDRESS_INSN (xlen == 64 ? "ld" : "lw") +#define LOAD_ADDRESS_INSN (abi_xlen == 64 ? "ld" : "lw") #define ADD32_INSN (xlen == 64 ? "addiw" : "addi") static unsigned elf_flags = 0; @@ -129,56 +130,49 @@ riscv_add_subset (const char *subset) riscv_subsets = s; } -/* Set which ISA and extensions are available. Formally, ISA strings must - begin with RV32 or RV64, but we allow the prefix to be omitted. +/* Set which ISA and extensions are available. */ - FIXME: Version numbers are not supported yet. */ static void -riscv_set_arch (const char *p) +riscv_set_arch (const char *s) { - const char *all_subsets = "IMAFDC"; + const char *all_subsets = "imafdc"; const char *extension = NULL; - int rvc = 0; - int i; + const char *p = s; - if (strncasecmp (p, "RV32", 4) == 0) + if (strncmp (p, "rv32", 4) == 0) { xlen = 32; p += 4; } - else if (strncasecmp (p, "RV64", 4) == 0) + else if (strncmp (p, "rv64", 4) == 0) { xlen = 64; p += 4; } - else if (strncasecmp (p, "RV", 2) == 0) - p += 2; + else + as_fatal ("-march=%s: ISA string must begin with rv32 or rv64", s); - switch (TOUPPER(*p)) + switch (*p) { - case 'I': + case 'i': break; - case 'G': + case 'g': p++; - /* Fall through. */ - - case '\0': - for (i = 0; all_subsets[i] != '\0'; i++) + for ( ; *all_subsets != 'c'; all_subsets++) { - const char subset[] = {all_subsets[i], '\0'}; + const char subset[] = {*all_subsets, '\0'}; riscv_add_subset (subset); } break; default: - as_fatal ("`I' must be the first ISA subset name specified (got %c)", - *p); + as_fatal ("-march=%s: first ISA subset must be `i' or `g'", s); } while (*p) { - if (TOUPPER(*p) == 'X') + if (*p == 'x') { char *subset = xstrdup (p), *q = subset; @@ -187,8 +181,8 @@ riscv_set_arch (const char *p) *q = '\0'; if (extension) - as_fatal ("only one eXtension is supported (found %s and %s)", - extension, subset); + as_fatal ("-march=%s: only one non-standard extension is supported" + " (found `%s' and `%s')", s, extension, subset); extension = subset; riscv_add_subset (subset); p += strlen (subset); @@ -200,24 +194,11 @@ riscv_set_arch (const char *p) { const char subset[] = {*p, 0}; riscv_add_subset (subset); - if (TOUPPER(*p) == 'C') - rvc = 1; all_subsets++; p++; } else - as_fatal ("unsupported ISA subset %c", *p); - } - - if (rvc) - { - /* Override -m[no-]rvc setting if C was explicitly listed. */ - riscv_set_rvc (TRUE); - } - else - { - /* Add RVC anyway. -m[no-]rvc toggles its availability. */ - riscv_add_subset ("C"); + as_fatal ("-march=%s: unsupported ISA subset `%c'", s, *p); } } @@ -604,8 +585,9 @@ void md_begin (void) { int i = 0; + unsigned long mach = xlen == 64 ? bfd_mach_riscv64 : bfd_mach_riscv32; - if (! bfd_set_arch_mach (stdoutput, bfd_arch_riscv, 0)) + if (! bfd_set_arch_mach (stdoutput, bfd_arch_riscv, mach)) as_warn (_("Could not set architecture and machine")); op_hash = hash_new (); @@ -1717,72 +1699,46 @@ const char *md_shortopts = "O::g::G:"; enum options { - OPTION_M32 = OPTION_MD_BASE, - OPTION_M64, - OPTION_MARCH, + OPTION_MARCH = OPTION_MD_BASE, OPTION_PIC, OPTION_NO_PIC, - OPTION_MSOFT_FLOAT, - OPTION_MHARD_FLOAT, - OPTION_MRVC, - OPTION_MNO_RVC, + OPTION_MABI, OPTION_END_OF_ENUM }; struct option md_longopts[] = { - {"m32", no_argument, NULL, OPTION_M32}, - {"m64", no_argument, NULL, OPTION_M64}, {"march", required_argument, NULL, OPTION_MARCH}, {"fPIC", no_argument, NULL, OPTION_PIC}, {"fpic", no_argument, NULL, OPTION_PIC}, {"fno-pic", no_argument, NULL, OPTION_NO_PIC}, - {"mrvc", no_argument, NULL, OPTION_MRVC}, - {"mno-rvc", no_argument, NULL, OPTION_MNO_RVC}, - {"msoft-float", no_argument, NULL, OPTION_MSOFT_FLOAT}, - {"mhard-float", no_argument, NULL, OPTION_MHARD_FLOAT}, + {"mabi", required_argument, NULL, OPTION_MABI}, {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); -enum float_mode -{ - FLOAT_MODE_DEFAULT, - FLOAT_MODE_SOFT, - FLOAT_MODE_HARD +enum float_abi { + FLOAT_ABI_DEFAULT = -1, + FLOAT_ABI_SOFT, + FLOAT_ABI_SINGLE, + FLOAT_ABI_DOUBLE, + FLOAT_ABI_QUAD }; -static enum float_mode float_mode = FLOAT_MODE_DEFAULT; +static enum float_abi float_abi = FLOAT_ABI_DEFAULT; + +static void +riscv_set_abi (unsigned new_xlen, enum float_abi new_float_abi) +{ + abi_xlen = new_xlen; + float_abi = new_float_abi; +} int md_parse_option (int c, const char *arg) { switch (c) { - case OPTION_MRVC: - riscv_set_rvc (TRUE); - break; - - case OPTION_MNO_RVC: - riscv_set_rvc (FALSE); - break; - - case OPTION_MSOFT_FLOAT: - float_mode = FLOAT_MODE_SOFT; - break; - - case OPTION_MHARD_FLOAT: - float_mode = FLOAT_MODE_HARD; - break; - - case OPTION_M32: - xlen = 32; - break; - - case OPTION_M64: - xlen = 64; - break; - case OPTION_MARCH: riscv_set_arch (arg); break; @@ -1795,6 +1751,27 @@ md_parse_option (int c, const char *arg) riscv_opts.pic = TRUE; break; + case OPTION_MABI: + if (strcmp (arg, "ilp32") == 0) + riscv_set_abi (32, FLOAT_ABI_SOFT); + else if (strcmp (arg, "ilp32f") == 0) + riscv_set_abi (32, FLOAT_ABI_SINGLE); + else if (strcmp (arg, "ilp32d") == 0) + riscv_set_abi (32, FLOAT_ABI_DOUBLE); + else if (strcmp (arg, "ilp32q") == 0) + riscv_set_abi (32, FLOAT_ABI_QUAD); + else if (strcmp (arg, "lp64") == 0) + riscv_set_abi (64, FLOAT_ABI_SOFT); + else if (strcmp (arg, "lp64f") == 0) + riscv_set_abi (64, FLOAT_ABI_SINGLE); + else if (strcmp (arg, "lp64d") == 0) + riscv_set_abi (64, FLOAT_ABI_DOUBLE); + else if (strcmp (arg, "lp64q") == 0) + riscv_set_abi (64, FLOAT_ABI_QUAD); + else + return 0; + break; + default: return 0; } @@ -1805,9 +1782,6 @@ md_parse_option (int c, const char *arg) void riscv_after_parse_args (void) { - if (riscv_subsets == NULL) - riscv_set_arch ("RVIMAFD"); - if (xlen == 0) { if (strcmp (default_arch, "riscv32") == 0) @@ -1817,6 +1791,38 @@ riscv_after_parse_args (void) else as_bad ("unknown default architecture `%s'", default_arch); } + + if (riscv_subsets == NULL) + riscv_set_arch (xlen == 64 ? "rv64g" : "rv32g"); + + /* Add the RVC extension, regardless of -march, to support .option rvc. */ + if (riscv_subset_supports ("c")) + riscv_set_rvc (TRUE); + else + riscv_add_subset ("c"); + + /* Infer ABI from ISA if not specified on command line. */ + if (abi_xlen == 0) + abi_xlen = xlen; + else if (abi_xlen > xlen) + as_bad ("can't have %d-bit ABI on %d-bit ISA", abi_xlen, xlen); + else if (abi_xlen < xlen) + as_bad ("%d-bit ABI not yet supported on %d-bit ISA", abi_xlen, xlen); + + if (float_abi == FLOAT_ABI_DEFAULT) + { + struct riscv_subset *subset; + + /* Assume soft-float unless D extension is present. */ + float_abi = FLOAT_ABI_SOFT; + + for (subset = riscv_subsets; subset != NULL; subset = subset->next) + if (strcasecmp (subset->name, "D") == 0) + float_abi = FLOAT_ABI_DOUBLE; + } + + /* Insert float_abi into the EF_RISCV_FLOAT_ABI field of elf_flags. */ + elf_flags |= float_abi * (EF_RISCV_FLOAT_ABI & ~(EF_RISCV_FLOAT_ABI << 1)); } long @@ -2449,24 +2455,7 @@ tc_riscv_regname_to_dw2regnum (char *regname) void riscv_elf_final_processing (void) { - enum float_mode elf_float_mode = float_mode; - elf_elfheader (stdoutput)->e_flags |= elf_flags; - - if (elf_float_mode == FLOAT_MODE_DEFAULT) - { - struct riscv_subset *subset; - - /* Assume soft-float unless D extension is present. */ - elf_float_mode = FLOAT_MODE_SOFT; - - for (subset = riscv_subsets; subset != NULL; subset = subset->next) - if (strcasecmp (subset->name, "D") == 0) - elf_float_mode = FLOAT_MODE_HARD; - } - - if (elf_float_mode == FLOAT_MODE_SOFT) - elf_elfheader (stdoutput)->e_flags |= EF_RISCV_SOFT_FLOAT; } /* Parse the .sleb128 and .uleb128 pseudos. Only allow constant expressions, diff --git a/gas/config/tc-riscv.h b/gas/config/tc-riscv.h index 32cf3eea403..5e07fdae643 100644 --- a/gas/config/tc-riscv.h +++ b/gas/config/tc-riscv.h @@ -94,7 +94,6 @@ extern void riscv_cfi_frame_initial_instructions (void); #define tc_regname_to_dw2regnum tc_riscv_regname_to_dw2regnum extern int tc_riscv_regname_to_dw2regnum (char *); -extern unsigned xlen; #define DWARF2_DEFAULT_RETURN_COLUMN X_RA /* Even on RV64, use 4-byte alignment, as F registers may be only 32 bits. */ diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo index 2b00accc1f2..4b14e081fb5 100644 --- a/gas/doc/as.texinfo +++ b/gas/doc/as.texinfo @@ -514,9 +514,8 @@ gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}. @ifset RISCV @emph{Target RISC-V options:} - [@b{-m32}|@b{-m64}] - [@b{-mrvc}] - [@b{-mhard-float}|@b{-msoft-float}] + [@b{-march}=@var{ISA}] + [@b{-mabi}=@var{ABI}] @end ifset @ifset S390 diff --git a/gas/doc/c-riscv.texi b/gas/doc/c-riscv.texi index 8674ff2eb96..25e4486baa9 100644 --- a/gas/doc/c-riscv.texi +++ b/gas/doc/c-riscv.texi @@ -25,24 +25,17 @@ The following table lists all availiable RISC-V specific options @c man begin OPTIONS @table @gcctabopt -@cindex @samp{-m32} option, RISC-V -@cindex @samp{-m64} option, RISC-V -@item -m32 | -m64 -Select the base ISA, either RV32 or RV64. - -@cindex @samp{-mrvc} option, RISC-V -@item -mrvc -Enables the C ISA subset for compressed instructions. - -@cindex @samp{-msoft-float} option, RISC-V -@cindex @samp{-mhard-float} option, RISC-V -@item -msoft-float | -mhard-float -Select the floating-point ABI, hard-float has F registers while soft-float -doesn't. @cindex @samp{-march=ISA} option, RISC-V @item -march=ISA -Select the base isa, as specified by ISA. For example -march=RV32IMA. +Select the base isa, as specified by ISA. For example -march=rv32ima. + +@cindex @samp{-mabi=ABI} option, RISC-V +@item -mabi=ABI +Selects the ABI, which is either "ilp32" or "lp64", optionally followed +by "f", "d", or "q" to indicate single-precision, double-precision, or +quad-precision floating-point calling convention, or none to indicate +the soft-float calling convention. @end table @c man end diff --git a/include/ChangeLog b/include/ChangeLog index 51792be23bc..ffefe6550e1 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,10 @@ +2016-12-20 Andrew Waterman + + * elf/riscv.h (EF_RISCV_SOFT_FLOAT): Don't define. + (EF_RISCV_FLOAT_ABI, EF_RISCV_FLOAT_ABI_SOFT): Define. + (EF_RISCV_FLOAT_ABI_SINGLE, EF_RISCV_FLOAT_ABI_DOUBLE): Define. + (EF_RISCV_FLOAT_ABI_QUAD): Define. + 2016-12-20 Andrew Waterman Kuan-Lin Chen diff --git a/include/elf/riscv.h b/include/elf/riscv.h index 44076119400..5303bd9c160 100644 --- a/include/elf/riscv.h +++ b/include/elf/riscv.h @@ -94,7 +94,19 @@ END_RELOC_NUMBERS (R_RISCV_max) /* File may contain compressed instructions. */ #define EF_RISCV_RVC 0x0001 -/* File uses the soft-float calling convention. */ -#define EF_RISCV_SOFT_FLOAT 0x0002 +/* Which floating-point ABI a file uses. */ +#define EF_RISCV_FLOAT_ABI 0x0006 + +/* File uses the soft-float ABI. */ +#define EF_RISCV_FLOAT_ABI_SOFT 0x0000 + +/* File uses the single-float ABI. */ +#define EF_RISCV_FLOAT_ABI_SINGLE 0x0002 + +/* File uses the double-float ABI. */ +#define EF_RISCV_FLOAT_ABI_DOUBLE 0x0004 + +/* File uses the quad-float ABI. */ +#define EF_RISCV_FLOAT_ABI_QUAD 0x0006 #endif /* _ELF_RISCV_H */ diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index df466ef12cf..92d2516bc07 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,8 @@ +2016-12-20 Andrew Waterman + + * riscv-dis.c (riscv_disassemble_insn): Default to the ELF's + XLEN when none is provided. + 2016-12-20 Andrew Waterman * riscv-opc.c: Formatting fixes. diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c index 3b4e1e01ef4..cb263505d16 100644 --- a/opcodes/riscv-dis.c +++ b/opcodes/riscv-dis.c @@ -406,8 +406,12 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info) { int xlen = 0; - /* The incoming section might not always be complete. */ - if (info->section != NULL) + /* If XLEN is not known, get its value from the ELF class. */ + if (info->mach == bfd_mach_riscv64) + xlen = 64; + else if (info->mach == bfd_mach_riscv32) + xlen = 32; + else if (info->section != NULL) { Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner); xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32; -- 2.30.2