RISC-V: Accept version, supervisor ext and more than one NSE for -march.

This patch moves all -march parsing logic into bfd, because we will use this
code in ELF attributes.

	bfd/
	* elfxx-riscv.h (RISCV_DONT_CARE_VERSION): New macro.
	(struct riscv_subset_t): New structure.
	(riscv_subset_t): New typedef.
	(riscv_subset_list_t): New structure.
	(riscv_release_subset_list): New prototype.
	(riscv_add_subset): Likewise.
	(riscv_lookup_subset): Likewise.
	(riscv_lookup_subset_version): Likewise.
	(riscv_release_subset_list): Likewise.
	* elfxx-riscv.c: Include safe-ctype.h.
	(riscv_parsing_subset_version): New function.
	(riscv_supported_std_ext): Likewise.
	(riscv_parse_std_ext): Likewise.
	(riscv_parse_sv_or_non_std_ext): Likewise.
	(riscv_parse_subset): Likewise.
	(riscv_add_subset): Likewise.
	(riscv_lookup_subset): Likewise.
	(riscv_lookup_subset_version): Likewise.
	(riscv_release_subset_list): Likewise.
	gas/
	* config/tc-riscv.c: Include elfxx-riscv.h.
	(struct riscv_subset): Removed.
	(riscv_subsets): Change type to riscv_subset_list_t.
	(riscv_subset_supports): Removed argument: xlen_required and move
	logic into libbfd.
	(riscv_multi_subset_supports): Removed argument: xlen_required.
	(riscv_clear_subsets): Removed.
	(riscv_add_subset): Ditto.
	(riscv_set_arch): Extract parsing logic into libbfd.
	(riscv_ip): Update argument for riscv_multi_subset_supports and
	riscv_subset_supports. Update riscv_subsets due to struct definition
	changed.
	(riscv_after_parse_args): Update riscv_subsets due to struct
	definition changed, update and argument for riscv_subset_supports.
	* testsuite/gas/riscv/empty.s: New.
	* testsuite/gas/riscv/march-fail-rv32ef.d: Likewise.
	* testsuite/gas/riscv/march-fail-rv32ef.l: Likewise.
	* testsuite/gas/riscv/march-fail-rv32i.d: Likewise.
	* testsuite/gas/riscv/march-fail-rv32i.l: Likewise.
	* testsuite/gas/riscv/march-fail-rv32iam.d: Likewise.
	* testsuite/gas/riscv/march-fail-rv32iam.l: Likewise.
	* testsuite/gas/riscv/march-fail-rv32ic.d: Likewise.
	* testsuite/gas/riscv/march-fail-rv32ic.l: Likewise.
	* testsuite/gas/riscv/march-fail-rv32icx2p.d: Likewise.
	* testsuite/gas/riscv/march-fail-rv32icx2p.l: Likewise.
	* testsuite/gas/riscv/march-fail-rv32imc.d: Likewise.
	* testsuite/gas/riscv/march-fail-rv32imc.l: Likewise.
	* testsuite/gas/riscv/march-fail-rv64I.d: Likewise.
	* testsuite/gas/riscv/march-fail-rv64I.l: Likewise.
	* testsuite/gas/riscv/march-fail-rv64e.d: Likewise.
	* testsuite/gas/riscv/march-fail-rv64e.l: Likewise.
	* testsuite/gas/riscv/march-ok-g2.d: Likewise.
	* testsuite/gas/riscv/march-ok-g2p0.d: Likewise.
	* testsuite/gas/riscv/march-ok-i2p0.d: Likewise.
	* testsuite/gas/riscv/march-ok-nse-with-version.: Likewise.d
	* testsuite/gas/riscv/march-ok-s-with-version.d: Likewise.
	* testsuite/gas/riscv/march-ok-s.d: Likewise.
	* testsuite/gas/riscv/march-ok-sx.d: Likewise.
	* testsuite/gas/riscv/march-ok-two-nse.d: Likewise.
	* testsuite/gas/riscv/march-ok-g2_p1.d: Likewise.
	* testsuite/gas/riscv/march-ok-i2p0m2_a2f2.d: Likewise.
	include/
	* opcode/riscv.h (riscv_opcode): Change type of xlen_requirement to
	unsigned.
	opcodes/
	* riscv-opc.c: Change the type of xlen, because type of
	xlen_requirement changed.
This commit is contained in:
Jim Wilson 2018-12-03 13:59:44 -08:00
parent 57b64c4103
commit 1080bf78c0
36 changed files with 720 additions and 143 deletions

View File

@ -1,3 +1,25 @@
2018-12-03 Kito Cheng <kito@andestech.com>
* elfxx-riscv.h (RISCV_DONT_CARE_VERSION): New macro.
(struct riscv_subset_t): New structure.
(riscv_subset_t): New typedef.
(riscv_subset_list_t): New structure.
(riscv_release_subset_list): New prototype.
(riscv_add_subset): Likewise.
(riscv_lookup_subset): Likewise.
(riscv_lookup_subset_version): Likewise.
(riscv_release_subset_list): Likewise.
* elfxx-riscv.c: Include safe-ctype.h.
(riscv_parsing_subset_version): New function.
(riscv_supported_std_ext): Likewise.
(riscv_parse_std_ext): Likewise.
(riscv_parse_sv_or_non_std_ext): Likewise.
(riscv_parse_subset): Likewise.
(riscv_add_subset): Likewise.
(riscv_lookup_subset): Likewise.
(riscv_lookup_subset_version): Likewise.
(riscv_release_subset_list): Likewise.
2018-12-01 H.J. Lu <hongjiu.lu@intel.com>
PR ld/23930

View File

@ -28,6 +28,7 @@
#include "opcode/riscv.h"
#include "libiberty.h"
#include "elfxx-riscv.h"
#include "safe-ctype.h"
#include <stdint.h>
#define MINUS_ONE ((bfd_vma)0 - 1)
@ -1010,3 +1011,477 @@ riscv_elf_add_sub_reloc (bfd *abfd,
return bfd_reloc_ok;
}
/* Parsing subset version.
Return Value:
Points to the end of version
Arguments:
`rps`: Hooks and status for parsing subset.
`march`: Full arch string.
`p`: Curent parsing position.
`major_version`: Parsing result of major version, using
default_major_version if version is not present in arch string.
`minor_version`: Parsing result of minor version, set to 0 if version is
not present in arch string, but set to `default_minor_version` if
`major_version` using default_major_version.
`default_major_version`: Default major version.
`default_minor_version`: Default minor version.
`std_ext_p`: True if parsing std extension. */
static const char *
riscv_parsing_subset_version (riscv_parse_subset_t *rps,
const char *march,
const char *p,
unsigned *major_version,
unsigned *minor_version,
unsigned default_major_version,
unsigned default_minor_version,
bfd_boolean std_ext_p)
{
bfd_boolean major_p = TRUE;
unsigned version = 0;
unsigned major = 0;
unsigned minor = 0;
char np;
for (;*p; ++p)
{
if (*p == 'p')
{
np = *(p + 1);
if (!ISDIGIT (np))
{
/* Might be beginning of `p` extension. */
if (std_ext_p)
{
*major_version = version;
*minor_version = 0;
return p;
}
else
{
rps->error_handler ("-march=%s: Expect number after `%dp'.",
march, version);
return NULL;
}
}
major = version;
major_p = FALSE;
version = 0;
}
else if (ISDIGIT (*p))
version = (version * 10) + (*p - '0');
else
break;
}
if (major_p)
major = version;
else
minor = version;
if (major == 0 && minor == 0)
{
/* We don't found any version string, use default version. */
*major_version = default_major_version;
*minor_version = default_minor_version;
}
else
{
*major_version = major;
*minor_version = minor;
}
return p;
}
/* Return string which contain all supported standard extensions in
canonical order. */
const char *
riscv_supported_std_ext (void)
{
return "mafdqlcbjtpvn";
}
/* Parsing function for standard extensions.
Return Value:
Points to the end of extensions.
Arguments:
`rps`: Hooks and status for parsing subset.
`march`: Full arch string.
`p`: Curent parsing position. */
static const char *
riscv_parse_std_ext (riscv_parse_subset_t *rps,
const char *march, const char *p)
{
const char *all_std_exts = riscv_supported_std_ext ();
const char *std_exts = all_std_exts;
unsigned major_version = 0;
unsigned minor_version = 0;
char std_ext = '\0';
/* First letter must start with i, e or g. */
switch (*p)
{
case 'i':
p++;
p = riscv_parsing_subset_version (
rps,
march,
p, &major_version, &minor_version,
/* default_major_version= */ 2,
/* default_minor_version= */ 0,
/* std_ext_p= */TRUE);
riscv_add_subset (rps->subset_list, "i", major_version, minor_version);
break;
case 'e':
p++;
p = riscv_parsing_subset_version (
rps,
march,
p, &major_version, &minor_version,
/* default_major_version= */ 1,
/* default_minor_version= */ 9,
/* std_ext_p= */TRUE);
riscv_add_subset (rps->subset_list, "e", major_version, minor_version);
riscv_add_subset (rps->subset_list, "i", 2, 0);
if (*rps->xlen > 32)
{
rps->error_handler ("-march=%s: rv%de is not a valid base ISA",
march, *rps->xlen);
return NULL;
}
break;
case 'g':
p++;
p = riscv_parsing_subset_version (
rps,
march,
p, &major_version, &minor_version,
/* default_major_version= */ 2,
/* default_minor_version= */ 0,
/* std_ext_p= */TRUE);
riscv_add_subset (rps->subset_list, "i", major_version, minor_version);
for ( ; *std_exts != 'q'; std_exts++)
{
const char subset[] = {*std_exts, '\0'};
riscv_add_subset (
rps->subset_list, subset, major_version, minor_version);
}
break;
default:
rps->error_handler (
"-march=%s: first ISA subset must be `e', `i' or `g'", march);
return NULL;
}
while (*p)
{
char subset[2] = {0, 0};
if (*p == 'x' || *p == 's')
break;
if (*p == '_')
{
p++;
continue;
}
std_ext = *p;
/* Checking canonical order. */
while (*std_exts && std_ext != *std_exts) std_exts++;
if (std_ext != *std_exts)
{
if (strchr (all_std_exts, std_ext) == NULL)
rps->error_handler (
"-march=%s: unsupported ISA subset `%c'", march, *p);
else
rps->error_handler (
"-march=%s: ISA string is not in canonical order. `%c'",
march, *p);
return NULL;
}
std_exts++;
p++;
p = riscv_parsing_subset_version (
rps,
march,
p, &major_version, &minor_version,
/* default_major_version= */ 2,
/* default_minor_version= */ 0,
/* std_ext_p= */TRUE);
subset[0] = std_ext;
riscv_add_subset (rps->subset_list, subset, major_version, minor_version);
}
return p;
}
/* Parsing function for non-standard and supervisor extensions.
Return Value:
Points to the end of extensions.
Arguments:
`rps`: Hooks and status for parsing subset.
`march`: Full arch string.
`p`: Curent parsing position.
`ext_type`: What kind of extensions, 'x', 's' or 'sx'.
`ext_type_str`: Full name for kind of extension. */
static const char *
riscv_parse_sv_or_non_std_ext (riscv_parse_subset_t *rps,
const char *march,
const char *p,
const char *ext_type,
const char *ext_type_str)
{
unsigned major_version = 0;
unsigned minor_version = 0;
size_t ext_type_len = strlen (ext_type);
while (*p)
{
if (*p == '_')
{
p++;
continue;
}
if (strncmp (p, ext_type, ext_type_len) != 0)
break;
/* It's non-standard supervisor extension if it prefix with sx. */
if ((ext_type[0] == 's') && (ext_type_len == 1)
&& (*(p + 1) == 'x'))
break;
char *subset = xstrdup (p);
char *q = subset;
const char *end_of_version;
while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
;
end_of_version =
riscv_parsing_subset_version (
rps,
march,
q, &major_version, &minor_version,
/* default_major_version= */ 2,
/* default_minor_version= */ 0,
/* std_ext_p= */FALSE);
*q = '\0';
riscv_add_subset (rps->subset_list, subset, major_version, minor_version);
free (subset);
p += end_of_version - subset;
if (*p != '\0' && *p != '_')
{
rps->error_handler ("-march=%s: %s must seperate with _",
march, ext_type_str);
return NULL;
}
}
return p;
}
/* Function for parsing arch string.
Return Value:
Return TRUE on success.
Arguments:
`rps`: Hooks and status for parsing subset.
`arch`: Arch string. */
bfd_boolean
riscv_parse_subset (riscv_parse_subset_t *rps,
const char *arch)
{
const char *p = arch;
if (strncmp (p, "rv32", 4) == 0)
{
*rps->xlen = 32;
p += 4;
}
else if (strncmp (p, "rv64", 4) == 0)
{
*rps->xlen = 64;
p += 4;
}
else
{
rps->error_handler ("-march=%s: ISA string must begin with rv32 or rv64",
arch);
return FALSE;
}
/* Parsing standard extension. */
p = riscv_parse_std_ext (rps, arch, p);
if (p == NULL)
return FALSE;
/* Parsing non-standard extension. */
p = riscv_parse_sv_or_non_std_ext (
rps, arch, p, "x", "non-standard extension");
if (p == NULL)
return FALSE;
/* Parsing supervisor extension. */
p = riscv_parse_sv_or_non_std_ext (
rps, arch, p, "s", "supervisor extension");
if (p == NULL)
return FALSE;
/* Parsing non-standard supervisor extension. */
p = riscv_parse_sv_or_non_std_ext (
rps, arch, p, "sx", "non-standard supervisor extension");
if (p == NULL)
return FALSE;
if (*p != '\0')
{
rps->error_handler ("-march=%s: unexpected ISA string at end: %s",
arch, p);
return FALSE;
}
if (riscv_lookup_subset (rps->subset_list, "e")
&& riscv_lookup_subset (rps->subset_list, "f"))
{
rps->error_handler ("-march=%s: rv32e does not support the `f' extension",
arch);
return FALSE;
}
if (riscv_lookup_subset (rps->subset_list, "d")
&& !riscv_lookup_subset (rps->subset_list, "f"))
{
rps->error_handler ("-march=%s: `d' extension requires `f' extension",
arch);
return FALSE;
}
if (riscv_lookup_subset (rps->subset_list, "q")
&& !riscv_lookup_subset (rps->subset_list, "d"))
{
rps->error_handler ("-march=%s: `q' extension requires `d' extension",
arch);
return FALSE;
}
if (riscv_lookup_subset (rps->subset_list, "q") && *rps->xlen < 64)
{
rps->error_handler ("-march=%s: rv32 does not support the `q' extension",
arch);
return FALSE;
}
return TRUE;
}
/* Add new subset to list. */
void
riscv_add_subset (riscv_subset_list_t *subset_list,
const char *subset,
int major, int minor)
{
riscv_subset_t *s = xmalloc (sizeof *s);
if (subset_list->head == NULL)
subset_list->head = s;
s->name = xstrdup (subset);
s->major_version = major;
s->minor_version = minor;
s->next = NULL;
if (subset_list->tail != NULL)
subset_list->tail->next = s;
subset_list->tail = s;
}
/* Find subset in list without version checking, return NULL if not found. */
riscv_subset_t *
riscv_lookup_subset (const riscv_subset_list_t *subset_list,
const char *subset)
{
return riscv_lookup_subset_version (
subset_list, subset,
RISCV_DONT_CARE_VERSION,
RISCV_DONT_CARE_VERSION);
}
/* Find subset in list with version checking, return NULL if not found. */
riscv_subset_t *
riscv_lookup_subset_version (const riscv_subset_list_t *subset_list,
const char *subset,
int major, int minor)
{
riscv_subset_t *s;
for (s = subset_list->head; s != NULL; s = s->next)
if (strcasecmp (s->name, subset) == 0)
{
if ((major != RISCV_DONT_CARE_VERSION)
&& (s->major_version != major))
return NULL;
if ((minor != RISCV_DONT_CARE_VERSION)
&& (s->minor_version != minor))
return NULL;
return s;
}
return NULL;
}
/* Release subset list. */
void
riscv_release_subset_list (riscv_subset_list_t *subset_list)
{
while (subset_list->head != NULL)
{
riscv_subset_t *next = subset_list->head->next;
free ((void *)subset_list->head->name);
free (subset_list->head);
subset_list->head = next;
}
subset_list->tail = NULL;
}

View File

@ -31,3 +31,55 @@ riscv_reloc_type_lookup (bfd *, bfd_reloc_code_real_type);
extern reloc_howto_type *
riscv_elf_rtype_to_howto (bfd *, unsigned int r_type);
#define RISCV_DONT_CARE_VERSION -1
/* The information of architecture attribute. */
struct riscv_subset_t
{
const char *name;
int major_version;
int minor_version;
struct riscv_subset_t *next;
};
typedef struct riscv_subset_t riscv_subset_t;
typedef struct {
riscv_subset_t *head;
riscv_subset_t *tail;
} riscv_subset_list_t;
extern void
riscv_release_subset_list (riscv_subset_list_t *);
extern void
riscv_add_subset (riscv_subset_list_t *,
const char *,
int, int);
extern riscv_subset_t *
riscv_lookup_subset (const riscv_subset_list_t *,
const char *);
extern riscv_subset_t *
riscv_lookup_subset_version (const riscv_subset_list_t *,
const char *,
int, int);
typedef struct {
riscv_subset_list_t *subset_list;
void (*error_handler) (const char *,
...) ATTRIBUTE_PRINTF_1;
unsigned *xlen;
} riscv_parse_subset_t;
extern bfd_boolean
riscv_parse_subset (riscv_parse_subset_t *,
const char *);
extern const char *
riscv_supported_std_ext (void);
extern void
riscv_release_subset_list (riscv_subset_list_t *);

View File

@ -1,4 +1,48 @@
2018-12-03 Egeyar Bagcioglu <egeyar.bagcioglu@oracle.com>
2018-12-03 Kito Cheng <kito@andestech.com>
* config/tc-riscv.c: Include elfxx-riscv.h.
(struct riscv_subset): Removed.
(riscv_subsets): Change type to riscv_subset_list_t.
(riscv_subset_supports): Removed argument: xlen_required and move
logic into libbfd.
(riscv_multi_subset_supports): Removed argument: xlen_required.
(riscv_clear_subsets): Removed.
(riscv_add_subset): Ditto.
(riscv_set_arch): Extract parsing logic into libbfd.
(riscv_ip): Update argument for riscv_multi_subset_supports and
riscv_subset_supports. Update riscv_subsets due to struct definition
changed.
(riscv_after_parse_args): Update riscv_subsets due to struct
definition changed, update and argument for riscv_subset_supports.
* testsuite/gas/riscv/empty.s: New.
* testsuite/gas/riscv/march-fail-rv32ef.d: Likewise.
* testsuite/gas/riscv/march-fail-rv32ef.l: Likewise.
* testsuite/gas/riscv/march-fail-rv32i.d: Likewise.
* testsuite/gas/riscv/march-fail-rv32i.l: Likewise.
* testsuite/gas/riscv/march-fail-rv32iam.d: Likewise.
* testsuite/gas/riscv/march-fail-rv32iam.l: Likewise.
* testsuite/gas/riscv/march-fail-rv32ic.d: Likewise.
* testsuite/gas/riscv/march-fail-rv32ic.l: Likewise.
* testsuite/gas/riscv/march-fail-rv32icx2p.d: Likewise.
* testsuite/gas/riscv/march-fail-rv32icx2p.l: Likewise.
* testsuite/gas/riscv/march-fail-rv32imc.d: Likewise.
* testsuite/gas/riscv/march-fail-rv32imc.l: Likewise.
* testsuite/gas/riscv/march-fail-rv64I.d: Likewise.
* testsuite/gas/riscv/march-fail-rv64I.l: Likewise.
* testsuite/gas/riscv/march-fail-rv64e.d: Likewise.
* testsuite/gas/riscv/march-fail-rv64e.l: Likewise.
* testsuite/gas/riscv/march-ok-g2.d: Likewise.
* testsuite/gas/riscv/march-ok-g2p0.d: Likewise.
* testsuite/gas/riscv/march-ok-i2p0.d: Likewise.
* testsuite/gas/riscv/march-ok-nse-with-version.: Likewise.d
* testsuite/gas/riscv/march-ok-s-with-version.d: Likewise.
* testsuite/gas/riscv/march-ok-s.d: Likewise.
* testsuite/gas/riscv/march-ok-sx.d: Likewise.
* testsuite/gas/riscv/march-ok-two-nse.d: Likewise.
* testsuite/gas/riscv/march-ok-g2_p1.d: Likewise.
* testsuite/gas/riscv/march-ok-i2p0m2_a2f2.d: Likewise.
018-12-03 Egeyar Bagcioglu <egeyar.bagcioglu@oracle.com>
PR 23193
PR 19721

View File

@ -29,6 +29,7 @@
#include "dwarf2dbg.h"
#include "dw2gencfi.h"
#include "bfd/elfxx-riscv.h"
#include "elf/riscv.h"
#include "opcode/riscv.h"
@ -102,160 +103,41 @@ riscv_set_rve (bfd_boolean rve_value)
riscv_opts.rve = rve_value;
}
struct riscv_subset
{
const char *name;
struct riscv_subset *next;
};
static struct riscv_subset *riscv_subsets;
static riscv_subset_list_t riscv_subsets;
static bfd_boolean
riscv_subset_supports (unsigned xlen_required, const char *feature)
riscv_subset_supports (const char *feature)
{
struct riscv_subset *s;
if (riscv_opts.rvc && (strcasecmp (feature, "c") == 0))
return TRUE;
if (xlen_required && xlen != xlen_required)
return FALSE;
for (s = riscv_subsets; s != NULL; s = s->next)
if (strcasecmp (s->name, feature) == 0)
return TRUE;
return FALSE;
return riscv_lookup_subset (&riscv_subsets, feature) != NULL;
}
static bfd_boolean
riscv_multi_subset_supports (unsigned xlen_required, const char *features[])
riscv_multi_subset_supports (const char *features[])
{
unsigned i = 0;
bfd_boolean supported = TRUE;
for (;features[i]; ++i)
supported = supported && riscv_subset_supports (xlen_required, features[i]);
supported = supported && riscv_subset_supports (features[i]);
return supported;
}
static void
riscv_clear_subsets (void)
{
while (riscv_subsets != NULL)
{
struct riscv_subset *next = riscv_subsets->next;
free ((void *) riscv_subsets->name);
free (riscv_subsets);
riscv_subsets = next;
}
}
static void
riscv_add_subset (const char *subset)
{
struct riscv_subset *s = xmalloc (sizeof *s);
s->name = xstrdup (subset);
s->next = riscv_subsets;
riscv_subsets = s;
}
/* Set which ISA and extensions are available. */
static void
riscv_set_arch (const char *s)
{
const char *all_subsets = "imafdqc";
char *extension = NULL;
const char *p = s;
riscv_parse_subset_t rps;
rps.subset_list = &riscv_subsets;
rps.error_handler = as_fatal;
rps.xlen = &xlen;
riscv_clear_subsets();
if (strncmp (p, "rv32", 4) == 0)
{
xlen = 32;
p += 4;
}
else if (strncmp (p, "rv64", 4) == 0)
{
xlen = 64;
p += 4;
}
else
as_fatal ("-march=%s: ISA string must begin with rv32 or rv64", s);
switch (*p)
{
case 'i':
break;
case 'e':
p++;
riscv_add_subset ("e");
riscv_add_subset ("i");
if (xlen > 32)
as_fatal ("-march=%s: rv%de is not a valid base ISA", s, xlen);
break;
case 'g':
p++;
for ( ; *all_subsets != 'q'; all_subsets++)
{
const char subset[] = {*all_subsets, '\0'};
riscv_add_subset (subset);
}
break;
default:
as_fatal ("-march=%s: first ISA subset must be `e', `i' or `g'", s);
}
while (*p)
{
if (*p == 'x')
{
char *subset = xstrdup (p);
char *q = subset;
while (*++q != '\0' && *q != '_')
;
*q = '\0';
if (extension)
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);
}
else if (*p == '_')
p++;
else if ((all_subsets = strchr (all_subsets, *p)) != NULL)
{
const char subset[] = {*p, 0};
riscv_add_subset (subset);
all_subsets++;
p++;
}
else
as_fatal ("-march=%s: unsupported ISA subset `%c'", s, *p);
}
if (riscv_subset_supports (0, "e") && riscv_subset_supports (0, "f"))
as_fatal ("-march=%s: rv32e does not support the `f' extension", s);
if (riscv_subset_supports (0, "d") && !riscv_subset_supports (0, "f"))
as_fatal ("-march=%s: `d' extension requires `f' extension", s);
if (riscv_subset_supports (0, "q") && !riscv_subset_supports (0, "d"))
as_fatal ("-march=%s: `q' extension requires `d' extension", s);
if (riscv_subset_supports (0, "q") && xlen < 64)
as_fatal ("-march=%s: rv32 does not support the `q' extension", s);
free (extension);
riscv_release_subset_list (&riscv_subsets);
riscv_parse_subset (&rps, s);
}
/* Handle of the OPCODE hash table. */
@ -1491,7 +1373,10 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
argsStart = s;
for ( ; insn && insn->name && strcmp (insn->name, str) == 0; insn++)
{
if (!riscv_multi_subset_supports (insn->xlen_requirement, insn->subset))
if ((insn->xlen_requirement != 0) && (xlen != insn->xlen_requirement))
continue;
if (!riscv_multi_subset_supports (insn->subset))
continue;
create_insn (ip, insn);
@ -2332,19 +2217,17 @@ riscv_after_parse_args (void)
as_bad ("unknown default architecture `%s'", default_arch);
}
if (riscv_subsets == NULL)
if (riscv_subsets.head == NULL)
riscv_set_arch (xlen == 64 ? "rv64g" : "rv32g");
/* Add the RVC extension, regardless of -march, to support .option rvc. */
riscv_set_rvc (FALSE);
if (riscv_subset_supports (0, "c"))
if (riscv_subset_supports ("c"))
riscv_set_rvc (TRUE);
else
riscv_add_subset ("c");
/* Enable RVE if specified by the -march option. */
riscv_set_rve (FALSE);
if (riscv_subset_supports (0, "e"))
if (riscv_subset_supports ("e"))
riscv_set_rve (TRUE);
/* Infer ABI from ISA if not specified on command line. */
@ -2357,12 +2240,12 @@ riscv_after_parse_args (void)
if (float_abi == FLOAT_ABI_DEFAULT)
{
struct riscv_subset *subset;
riscv_subset_t *subset;
/* Assume soft-float unless D extension is present. */
float_abi = FLOAT_ABI_SOFT;
for (subset = riscv_subsets; subset != NULL; subset = subset->next)
for (subset = riscv_subsets.head; subset != NULL; subset = subset->next)
{
if (strcasecmp (subset->name, "D") == 0)
float_abi = FLOAT_ABI_DOUBLE;

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,3 @@
#as: -march=rv32ef
#source: empty.s
#error_output: march-fail-rv32ef.l

View File

@ -0,0 +1,2 @@
Assembler messages:
Fatal error: -march=rv32ef: rv32e does not support the `f' extension

View File

@ -0,0 +1,3 @@
#as: -march=rv32I
#source: empty.s
#error_output: march-fail-rv32i.l

View File

@ -0,0 +1,2 @@
Assembler messages:
Fatal error: -march=rv32I: first ISA subset must be `e', `i' or `g'

View File

@ -0,0 +1,3 @@
#as: -march=rv32iam
#source: empty.s
#error_output: march-fail-rv32iam.l

View File

@ -0,0 +1,2 @@
Assembler messages:
Fatal error: -march=rv32iam: ISA string is not in canonical order. `m'

View File

@ -0,0 +1,3 @@
#as: -march=rv32iC
#source: empty.s
#error_output: march-fail-rv32ic.l

View File

@ -0,0 +1,2 @@
Assembler messages:
Fatal error: -march=rv32iC: unsupported ISA subset `C'

View File

@ -0,0 +1,3 @@
#as: -march=rv32icx2p
#source: empty.s
#error_output: march-fail-rv32icx2p.l

View File

@ -0,0 +1,2 @@
Assembler messages:
Fatal error: -march=rv32icx2p: Expect number after `2p'.

View File

@ -0,0 +1,3 @@
#as: -march=rv32iamfd
#source: empty.s
#error_output: march-fail-rv32imc.l

View File

@ -0,0 +1,2 @@
Assembler messages:
Fatal error: -march=rv32iamfd: ISA string is not in canonical order. `m'

View File

@ -0,0 +1,3 @@
#as: -march=rv64I
#source: empty.s
#error_output: march-fail-rv64I.l

View File

@ -0,0 +1,2 @@
Assembler messages:
Fatal error: -march=rv64I: first ISA subset must be `e', `i' or `g'

View File

@ -0,0 +1,3 @@
#as: -march=rv64e
#source: empty.s
#error_output: march-fail-rv64e.l

View File

@ -0,0 +1,2 @@
Assembler messages:
Fatal error: -march=rv64e: rv64e is not a valid base ISA

View File

@ -0,0 +1,5 @@
#as: -march=rv32g2
#objdump: -dr
#source: empty.s
.*: file format elf32-littleriscv

View File

@ -0,0 +1,5 @@
#as: -march=rv32g2_p1
#objdump: -dr
#source: empty.s
.*: file format elf32-littleriscv

View File

@ -0,0 +1,5 @@
#as: -march=rv32g2p0
#objdump: -dr
#source: empty.s
.*: file format elf32-littleriscv

View File

@ -0,0 +1,5 @@
#as: -march=rv32i2p0
#objdump: -dr
#source: empty.s
.*: file format elf32-littleriscv

View File

@ -0,0 +1,5 @@
#as: -march=rv32i2p0m2_a2f2
#objdump: -dr
#source: empty.s
.*: file format elf32-littleriscv

View File

@ -0,0 +1,5 @@
#as: -march=rv32imafd_xargle2p0
#objdump: -dr
#source: empty.s
.*: file format elf32-littleriscv

View File

@ -0,0 +1,5 @@
#as: -march=rv32isfoo3p4
#objdump: -dr
#source: empty.s
.*: file format elf32-littleriscv

View File

@ -0,0 +1,5 @@
#as: -march=rv32isfoo
#objdump: -dr
#source: empty.s
.*: file format elf32-littleriscv

View File

@ -0,0 +1,5 @@
#as: -march=rv32isfoo_sxbar
#objdump: -dr
#source: empty.s
.*: file format elf32-littleriscv

View File

@ -0,0 +1,5 @@
#as: -march=rv32imafd_xargle_xbargle
#objdump: -dr
#source: empty.s
.*: file format elf32-littleriscv

View File

@ -1,3 +1,8 @@
2018-12-03 Kito Cheng <kito@andestech.com>
* opcode/riscv.h (riscv_opcode): Change type of xlen_requirement to
unsigned.
2018-11-27 Jim Wilson <jimw@sifive.com>
* opcode/riscv.h (OP_MASK_CFUNCT6, OP_SH_CFUNCT6): New.

View File

@ -295,7 +295,7 @@ struct riscv_opcode
/* The name of the instruction. */
const char *name;
/* The requirement of xlen for the instruction, 0 if no requirement. */
int xlen_requirement;
unsigned xlen_requirement;
/* An array of ISA subset name (I, M, A, F, D, Xextension), must ended
with a NULL pointer sential. */
const char *subset[MAX_SUBSET_NUM];

View File

@ -1,3 +1,8 @@
2018-12-03 Kito Cheng <kito@andestech.com>
* riscv-opc.c: Change the type of xlen, because type of
xlen_requirement changed.
2018-12-03 Egeyar Bagcioglu <egeyar.bagcioglu@oracle.com>
PR 23193

View File

@ -408,7 +408,7 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
op = riscv_hash[OP_HASH_IDX (word)];
if (op != NULL)
{
int xlen = 0;
unsigned xlen = 0;
/* If XLEN is not known, get its value from the ELF class. */
if (info->mach == bfd_mach_riscv64)