diff options
author | Andrew Waterman <andrew@sifive.com> | 2016-12-18 22:53:50 -0800 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2016-12-20 12:26:34 +1030 |
commit | 2922d21da14b4711872371abacb16e8ab7c70894 (patch) | |
tree | 42987b9714a1c6641f3bc74c4a7e7230936545ff /gas | |
parent | 1d61f7949f77796ee407466f3ca7f42dcde9251b (diff) | |
download | fsf-binutils-gdb-2922d21da14b4711872371abacb16e8ab7c70894.zip fsf-binutils-gdb-2922d21da14b4711872371abacb16e8ab7c70894.tar.gz fsf-binutils-gdb-2922d21da14b4711872371abacb16e8ab7c70894.tar.bz2 |
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.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 19 | ||||
-rw-r--r-- | gas/config/tc-riscv.c | 197 | ||||
-rw-r--r-- | gas/config/tc-riscv.h | 1 | ||||
-rw-r--r-- | gas/doc/as.texinfo | 5 | ||||
-rw-r--r-- | gas/doc/c-riscv.texi | 23 |
5 files changed, 122 insertions, 123 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 0e652b1..a603984 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,4 +1,23 @@ 2016-12-20 Andrew Waterman <andrew@sifive.com> + + * 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 <andrew@sifive.com> Kuan-Lin Chen <kuanlinchentw@gmail.com> * config/tc-riscv.c (riscv_set_options): Add relax. diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index d011864..77c92cf 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 32cf3ee..5e07fda 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 2b00acc..4b14e08 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 8674ff2..25e4486 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 |