/* RISC-V-specific support for ELF.
- Copyright (C) 2011-2022 Free Software Foundation, Inc.
+ Copyright (C) 2011-2023 Free Software Foundation, Inc.
Contributed by Andrew Waterman (andrew@sifive.com).
Based on TILE-Gx and MIPS targets.
relocations for the debug info. */
static bfd_reloc_status_type riscv_elf_add_sub_reloc
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+static bfd_reloc_status_type riscv_elf_ignore_reloc
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
/* The relocation table used for SHT_RELA sections. */
MINUS_ONE, /* dst_mask */
false), /* pcrel_offset */
- /* GNU extension to record C++ vtable hierarchy */
- HOWTO (R_RISCV_GNU_VTINHERIT, /* type */
- 0, /* rightshift */
- 8, /* size */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- NULL, /* special_function */
- "R_RISCV_GNU_VTINHERIT", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false), /* pcrel_offset */
-
- /* GNU extension to record C++ vtable member usage */
- HOWTO (R_RISCV_GNU_VTENTRY, /* type */
- 0, /* rightshift */
- 8, /* size */
- 0, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- _bfd_elf_rel_vtable_reloc_fn, /* special_function */
- "R_RISCV_GNU_VTENTRY", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
- 0, /* dst_mask */
- false), /* pcrel_offset */
+ /* 41 and 42 are reserved. */
+ EMPTY_HOWTO (0),
+ EMPTY_HOWTO (0),
/* Indicates an alignment statement. The addend field encodes how many
bytes of NOPs follow the statement. The desired alignment is the
0, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
+
+ /* Reserved for R_RISCV_PLT32. */
+ EMPTY_HOWTO (59),
+
+ /* N-bit in-place setting, for unsigned-leb128 local label subtraction. */
+ HOWTO (R_RISCV_SET_ULEB128, /* type */
+ 0, /* rightshift */
+ 0, /* size */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ riscv_elf_ignore_reloc, /* special_function */
+ "R_RISCV_SET_ULEB128", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* N-bit in-place addition, for unsigned-leb128 local label subtraction. */
+ HOWTO (R_RISCV_SUB_ULEB128, /* type */
+ 0, /* rightshift */
+ 0, /* size */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ riscv_elf_ignore_reloc, /* special_function */
+ "R_RISCV_SUB_ULEB128", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
};
/* A mapping from BFD reloc types to RISC-V ELF reloc types. */
{ BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
{ BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
{ BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
+ { BFD_RELOC_RISCV_SET_ULEB128, R_RISCV_SET_ULEB128 },
+ { BFD_RELOC_RISCV_SUB_ULEB128, R_RISCV_SUB_ULEB128 },
};
/* Given a BFD reloc type, return a howto structure. */
relocation = old_value + relocation;
break;
case R_RISCV_SUB6:
+ relocation = (old_value & ~howto->dst_mask)
+ | (((old_value & howto->dst_mask) - relocation)
+ & howto->dst_mask);
+ break;
case R_RISCV_SUB8:
case R_RISCV_SUB16:
case R_RISCV_SUB32:
return bfd_reloc_ok;
}
+/* Special handler for relocations which don't have to be relocated.
+ This function just simply return bfd_reloc_ok. */
+
+static bfd_reloc_status_type
+riscv_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+ arelent *reloc_entry,
+ asymbol *symbol ATTRIBUTE_UNUSED,
+ void *data ATTRIBUTE_UNUSED,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message ATTRIBUTE_UNUSED)
+{
+ if (output_bfd != NULL)
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+}
+
/* Always add the IMPLICIT for the SUBSET. */
static bool
{"g", "d", check_implicit_always},
{"g", "zicsr", check_implicit_always},
{"g", "zifencei", check_implicit_always},
+ {"m", "zmmul", check_implicit_always},
+ {"h", "zicsr", check_implicit_always},
{"q", "d", check_implicit_always},
{"v", "d", check_implicit_always},
{"v", "zve64d", check_implicit_always},
{"zvl256b", "zvl128b", check_implicit_always},
{"zvl128b", "zvl64b", check_implicit_always},
{"zvl64b", "zvl32b", check_implicit_always},
+ {"zfa", "f", check_implicit_always},
{"d", "f", check_implicit_always},
{"zfh", "zfhmin", check_implicit_always},
{"zfhmin", "f", check_implicit_always},
{"zks", "zbkx", check_implicit_always},
{"zks", "zksed", check_implicit_always},
{"zks", "zksh", check_implicit_always},
+ {"zvkn", "zvkned", check_implicit_always},
+ {"zvkn", "zvknha", check_implicit_always},
+ {"zvkn", "zvknhb", check_implicit_always},
+ {"zvkn", "zvbb", check_implicit_always},
+ {"zvkn", "zvkt", check_implicit_always},
+ {"zvkng", "zvkn", check_implicit_always},
+ {"zvkng", "zvkg", check_implicit_always},
+ {"zvknc", "zvkn", check_implicit_always},
+ {"zvknc", "zvbc", check_implicit_always},
+ {"zvks", "zvksed", check_implicit_always},
+ {"zvks", "zvksh", check_implicit_always},
+ {"zvks", "zvbb", check_implicit_always},
+ {"zvks", "zvkt", check_implicit_always},
+ {"zvksg", "zvks", check_implicit_always},
+ {"zvksg", "zvkg", check_implicit_always},
+ {"zvksc", "zvks", check_implicit_always},
+ {"zvksc", "zvbc", check_implicit_always},
+ {"smaia", "ssaia", check_implicit_always},
+ {"smstateen", "ssstateen", check_implicit_always},
+ {"smepmp", "zicsr", check_implicit_always},
+ {"ssaia", "zicsr", check_implicit_always},
+ {"sscofpmf", "zicsr", check_implicit_always},
+ {"ssstateen", "zicsr", check_implicit_always},
+ {"sstc", "zicsr", check_implicit_always},
{NULL, NULL, NULL}
};
{"zicbom", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zicbop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zicboz", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zicond", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
{"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
{"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
{"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
{"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
+ {"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zfa", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
{"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zfinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zve64x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zve64f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zve64d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zvbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zvbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zvkg", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zvkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zvkng", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zvknc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zvkned", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zvknha", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zvknhb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zvksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zvksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zvks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zvksg", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zvksc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zvkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvl32b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvl64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvl128b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvl16384b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvl32768b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"ztso", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
{NULL, 0, 0, 0, 0}
};
static struct riscv_supported_ext riscv_supported_std_s_ext[] =
{
+ {"smaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"smepmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"smstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"ssaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"sscofpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"ssstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"sstc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"svinval", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"svnapot", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"svpbmt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{NULL, 0, 0, 0, 0}
};
{NULL, 0, 0, 0, 0}
};
+static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
+{
+ {"xtheadba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"xtheadbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"xtheadbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"xtheadcmo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"xtheadcondmov", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"xtheadfmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"xtheadfmv", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"xtheadint", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"xtheadmac", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"xtheadmemidx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"xtheadmempair", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"xtheadsync", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ /* XVentanaCondOps: https://github.com/ventanamicro/ventana-custom-extensions/releases/download/v1.0.0/ventana-custom-extensions-v1.0.0.pdf */
+ {"xventanacondops", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {NULL, 0, 0, 0, 0}
+};
+
const struct riscv_supported_ext *riscv_all_supported_ext[] =
{
riscv_supported_std_ext,
riscv_supported_std_z_ext,
riscv_supported_std_s_ext,
riscv_supported_std_zxm_ext,
+ riscv_supported_vendor_x_ext,
NULL
};
RV_ISA_CLASS_S,
RV_ISA_CLASS_ZXM,
RV_ISA_CLASS_X,
- RV_ISA_CLASS_UNKNOWN
+ RV_ISA_CLASS_SINGLE
};
/* Record the strings of the prefixed extensions, and their corresponding
{RV_ISA_CLASS_Z, "z"},
{RV_ISA_CLASS_S, "s"},
{RV_ISA_CLASS_X, "x"},
- {RV_ISA_CLASS_UNKNOWN, NULL}
+ {RV_ISA_CLASS_SINGLE, NULL}
};
/* Get the prefixed name class for the extensions, the class also
riscv_get_prefix_class (const char *arch)
{
int i = 0;
- while (parse_config[i].class != RV_ISA_CLASS_UNKNOWN)
+ while (parse_config[i].class != RV_ISA_CLASS_SINGLE)
{
if (strncmp (arch, parse_config[i].prefix,
strlen (parse_config[i].prefix)) == 0)
return parse_config[i].class;
i++;
}
- return RV_ISA_CLASS_UNKNOWN;
+ return RV_ISA_CLASS_SINGLE;
}
/* Check KNOWN_EXTS to see if the EXT is supported. */
enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1);
enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2);
- if (class1 != RV_ISA_CLASS_UNKNOWN)
+ if (class1 != RV_ISA_CLASS_SINGLE)
order1 = - (int) class1;
- if (class2 != RV_ISA_CLASS_UNKNOWN)
+ if (class2 != RV_ISA_CLASS_SINGLE)
order2 = - (int) class2;
if (order1 == order2)
case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
- case RV_ISA_CLASS_X:
- break;
+ case RV_ISA_CLASS_X: table = riscv_supported_vendor_x_ext; break;
default:
table = riscv_supported_std_ext;
}
}
subset_list->tail = NULL;
+
+ if (subset_list->arch_str != NULL)
+ {
+ free ((void*) subset_list->arch_str);
+ subset_list->arch_str = NULL;
+ }
}
/* Parsing extension version.
return p;
}
-/* Parsing function for standard extensions.
+/* Parsing function for both standard and prefixed extensions.
Return Value:
Points to the end of extensions.
`p`: Curent parsing position. */
static const char *
-riscv_parse_std_ext (riscv_parse_subset_t *rps,
- const char *arch,
- const char *p)
+riscv_parse_extensions (riscv_parse_subset_t *rps,
+ const char *arch,
+ const char *p)
{
/* First letter must start with i, e or g. */
if (*p != 'e' && *p != 'i' && *p != 'g')
return NULL;
}
- while (p != NULL && *p != '\0')
+ while (*p != '\0')
{
- /* Stop when we parsed the known prefix class. */
- enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
- if (class != RV_ISA_CLASS_UNKNOWN)
- break;
-
if (*p == '_')
{
p++;
continue;
}
- bool implicit = false;
- int major = RISCV_UNKNOWN_VERSION;
- int minor = RISCV_UNKNOWN_VERSION;
- char subset[2] = {0, 0};
-
- subset[0] = *p;
-
- /* Check if the standard extension is supported. */
- if (riscv_ext_order[(subset[0] - 'a')] == 0)
- {
- rps->error_handler
- (_("%s: unknown standard ISA extension `%c'"),
- arch, subset[0]);
- return NULL;
- }
-
- /* Checking canonical order. */
- if (rps->subset_list->tail != NULL
- && riscv_compare_subsets (rps->subset_list->tail->name, subset) > 0)
- {
- rps->error_handler
- (_("%s: standard ISA extension `%c' is not "
- "in canonical order"), arch, subset[0]);
- return NULL;
- }
-
- p = riscv_parsing_subset_version (++p, &major, &minor);
- /* Added g as an implicit extension. */
- if (subset[0] == 'g')
- {
- implicit = true;
- major = RISCV_UNKNOWN_VERSION;
- minor = RISCV_UNKNOWN_VERSION;
- }
- riscv_parse_add_subset (rps, subset, major, minor, implicit);
- }
-
- return p;
-}
-
-/* Parsing function for prefixed extensions.
-
- Return Value:
- Points to the end of extension.
-
- Arguments:
- `rps`: Hooks and status for parsing extensions.
- `arch`: Full ISA string.
- `p`: Curent parsing position. */
-
-static const char *
-riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
- const char *arch,
- const char *p)
-{
- int major_version;
- int minor_version;
- enum riscv_prefix_ext_class class;
-
- while (*p)
- {
- if (*p == '_')
- {
- p++;
- continue;
- }
-
- class = riscv_get_prefix_class (p);
- if (class == RV_ISA_CLASS_UNKNOWN)
- {
- rps->error_handler
- (_("%s: unknown prefix class for the ISA extension `%s'"),
- arch, p);
- return NULL;
- }
-
char *subset = xstrdup (p);
- char *q = subset;
+ char *q = subset; /* Start of version. */
const char *end_of_version;
+ bool implicit = false;
- /* Extract the whole prefixed extension by '_'. */
- while (*++q != '\0' && *q != '_')
- ;
- /* Look forward to the first letter which is not <major>p<minor>. */
- bool find_any_version = false;
- bool find_minor_version = false;
- while (1)
+ enum riscv_prefix_ext_class class = riscv_get_prefix_class (p);
+ if (class == RV_ISA_CLASS_SINGLE)
{
- q--;
- if (ISDIGIT (*q))
- find_any_version = true;
- else if (find_any_version
- && !find_minor_version
- && *q == 'p'
- && ISDIGIT (*(q - 1)))
- find_minor_version = true;
- else
- break;
+ if (riscv_ext_order[(*subset - 'a')] == 0)
+ {
+ rps->error_handler
+ (_("%s: unknown standard ISA extension or prefix class `%c'"),
+ arch, *subset);
+ free (subset);
+ return NULL;
+ }
+ q++;
}
- q++;
-
- /* Check if the end of extension is 'p' or not. If yes, then
- the second letter from the end cannot be number. */
- if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
+ else
{
- *q = '\0';
- rps->error_handler
- (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
- arch, subset);
- free (subset);
- return NULL;
+ /* Extract the whole prefixed extension by '_'. */
+ while (*++q != '\0' && *q != '_')
+ ;
+ /* Look forward to the first letter which is not <major>p<minor>. */
+ bool find_any_version = false;
+ bool find_minor_version = false;
+ while (1)
+ {
+ q--;
+ if (ISDIGIT (*q))
+ find_any_version = true;
+ else if (find_any_version
+ && !find_minor_version
+ && *q == 'p'
+ && ISDIGIT (*(q - 1)))
+ find_minor_version = true;
+ else
+ break;
+ }
+ q++;
+
+ /* Check if the end of extension is 'p' or not. If yes, then
+ the second letter from the end cannot be number. */
+ if (*(q - 1) == 'p' && ISDIGIT (*(q - 2)))
+ {
+ *q = '\0';
+ rps->error_handler
+ (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"),
+ arch, subset);
+ free (subset);
+ return NULL;
+ }
}
+ int major_version = RISCV_UNKNOWN_VERSION;
+ int minor_version = RISCV_UNKNOWN_VERSION;
end_of_version =
riscv_parsing_subset_version (q, &major_version, &minor_version);
*q = '\0';
return NULL;
}
- /* Check that the extension name is well-formed. */
- if (rps->check_unknown_prefixed_ext
+ /* Check if the prefixed extension name is well-formed. */
+ if (class != RV_ISA_CLASS_SINGLE
+ && rps->check_unknown_prefixed_ext
&& !riscv_recognized_prefixed_ext (subset))
{
rps->error_handler
return NULL;
}
+ /* Added g as an implicit extension. */
+ if (class == RV_ISA_CLASS_SINGLE
+ && strcmp (subset, "g") == 0)
+ {
+ implicit = true;
+ major_version = RISCV_UNKNOWN_VERSION;
+ minor_version = RISCV_UNKNOWN_VERSION;
+ }
riscv_parse_add_subset (rps, subset,
major_version,
- minor_version, false);
+ minor_version, implicit);
p += end_of_version - subset;
free (subset);
- if (*p != '\0' && *p != '_')
+ if (class != RV_ISA_CLASS_SINGLE
+ && *p != '\0' && *p != '_')
{
rps->error_handler
(_("%s: prefixed ISA extension must separate with _"),
riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
{
struct riscv_implicit_subset *t = riscv_implicit_subsets;
- for (; t->subset_name; t++)
+ bool finished = false;
+ while (!finished)
{
- riscv_subset_t *subset = NULL;
- if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
- && t->check_func (t->implicit_name, subset))
- riscv_parse_add_subset (rps, t->implicit_name,
- RISCV_UNKNOWN_VERSION,
- RISCV_UNKNOWN_VERSION, true);
+ finished = true;
+ for (; t->subset_name; t++)
+ {
+ riscv_subset_t *subset = NULL;
+ riscv_subset_t *implicit_subset = NULL;
+ if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset)
+ && !riscv_lookup_subset (rps->subset_list, t->implicit_name,
+ &implicit_subset)
+ && t->check_func (t->implicit_name, subset))
+ {
+ riscv_parse_add_subset (rps, t->implicit_name,
+ RISCV_UNKNOWN_VERSION,
+ RISCV_UNKNOWN_VERSION, true);
+
+ /* Restart the loop and pick up any new implications. */
+ finished = false;
+ t = riscv_implicit_subsets;
+ break;
+ }
+ }
}
}
rps->error_handler (_("rv%d does not support the `q' extension"), xlen);
no_conflict = false;
}
- if (riscv_lookup_subset (rps->subset_list, "e", &subset)
- && riscv_lookup_subset (rps->subset_list, "f", &subset))
- {
- rps->error_handler
- (_("rv32e does not support the `f' extension"));
- no_conflict = false;
- }
if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset)
&& riscv_lookup_subset (rps->subset_list, "f", &subset))
{
return false;
}
- /* Parsing standard extension. */
- p = riscv_parse_std_ext (rps, arch, p);
-
- if (p == NULL)
- return false;
-
- /* Parse prefixed extensions. */
- p = riscv_parse_prefixed_ext (rps, arch, p);
-
- if (p == NULL)
+ /* Parse single standard and prefixed extensions. */
+ if (riscv_parse_extensions (rps, arch, p) == NULL)
return false;
/* Finally add implicit extensions according to the current
{
riscv_subset_list_t *new = xmalloc (sizeof *new);
new->head = riscv_copy_subset (new, subset_list->head);
+ new->arch_str = strdup (subset_list->arch_str);
return new;
}
return riscv_subset_supports (rps, "zicbop");
case INSN_CLASS_ZICBOZ:
return riscv_subset_supports (rps, "zicboz");
+ case INSN_CLASS_ZICOND:
+ return riscv_subset_supports (rps, "zicond");
case INSN_CLASS_ZICSR:
return riscv_subset_supports (rps, "zicsr");
case INSN_CLASS_ZIFENCEI:
return riscv_subset_supports (rps, "zihintpause");
case INSN_CLASS_M:
return riscv_subset_supports (rps, "m");
+ case INSN_CLASS_ZMMUL:
+ return riscv_subset_supports (rps, "zmmul");
case INSN_CLASS_A:
return riscv_subset_supports (rps, "a");
+ case INSN_CLASS_ZAWRS:
+ return riscv_subset_supports (rps, "zawrs");
case INSN_CLASS_F:
return riscv_subset_supports (rps, "f");
case INSN_CLASS_D:
case INSN_CLASS_D_AND_C:
return (riscv_subset_supports (rps, "d")
&& riscv_subset_supports (rps, "c"));
- case INSN_CLASS_F_OR_ZFINX:
+ case INSN_CLASS_F_INX:
return (riscv_subset_supports (rps, "f")
|| riscv_subset_supports (rps, "zfinx"));
- case INSN_CLASS_D_OR_ZDINX:
+ case INSN_CLASS_D_INX:
return (riscv_subset_supports (rps, "d")
|| riscv_subset_supports (rps, "zdinx"));
- case INSN_CLASS_Q_OR_ZQINX:
+ case INSN_CLASS_Q_INX:
return (riscv_subset_supports (rps, "q")
|| riscv_subset_supports (rps, "zqinx"));
- case INSN_CLASS_ZFH_OR_ZHINX:
+ case INSN_CLASS_ZFH_INX:
return (riscv_subset_supports (rps, "zfh")
|| riscv_subset_supports (rps, "zhinx"));
case INSN_CLASS_ZFHMIN:
return riscv_subset_supports (rps, "zfhmin");
- case INSN_CLASS_ZFHMIN_OR_ZHINXMIN:
+ case INSN_CLASS_ZFHMIN_INX:
return (riscv_subset_supports (rps, "zfhmin")
|| riscv_subset_supports (rps, "zhinxmin"));
- case INSN_CLASS_ZFHMIN_AND_D:
+ case INSN_CLASS_ZFHMIN_AND_D_INX:
return ((riscv_subset_supports (rps, "zfhmin")
&& riscv_subset_supports (rps, "d"))
|| (riscv_subset_supports (rps, "zhinxmin")
&& riscv_subset_supports (rps, "zdinx")));
- case INSN_CLASS_ZFHMIN_AND_Q:
+ case INSN_CLASS_ZFHMIN_AND_Q_INX:
return ((riscv_subset_supports (rps, "zfhmin")
&& riscv_subset_supports (rps, "q"))
|| (riscv_subset_supports (rps, "zhinxmin")
&& riscv_subset_supports (rps, "zqinx")));
+ case INSN_CLASS_ZFA:
+ return riscv_subset_supports (rps, "zfa");
+ case INSN_CLASS_D_AND_ZFA:
+ return riscv_subset_supports (rps, "d")
+ && riscv_subset_supports (rps, "zfa");
+ case INSN_CLASS_Q_AND_ZFA:
+ return riscv_subset_supports (rps, "q")
+ && riscv_subset_supports (rps, "zfa");
+ case INSN_CLASS_ZFH_AND_ZFA:
+ return riscv_subset_supports (rps, "zfh")
+ && riscv_subset_supports (rps, "zfa");
case INSN_CLASS_ZBA:
return riscv_subset_supports (rps, "zba");
case INSN_CLASS_ZBB:
|| riscv_subset_supports (rps, "zve64d")
|| riscv_subset_supports (rps, "zve64f")
|| riscv_subset_supports (rps, "zve32f"));
+ case INSN_CLASS_ZVBB:
+ return riscv_subset_supports (rps, "zvbb");
+ case INSN_CLASS_ZVBC:
+ return riscv_subset_supports (rps, "zvbc");
+ case INSN_CLASS_ZVKG:
+ return riscv_subset_supports (rps, "zvkg");
+ case INSN_CLASS_ZVKNED:
+ return riscv_subset_supports (rps, "zvkned");
+ case INSN_CLASS_ZVKNHA:
+ return riscv_subset_supports (rps, "zvknha");
+ case INSN_CLASS_ZVKNHB:
+ return riscv_subset_supports (rps, "zvknhb");
+ case INSN_CLASS_ZVKNHA_OR_ZVKNHB:
+ return (riscv_subset_supports (rps, "zvknha")
+ || riscv_subset_supports (rps, "zvknhb"));
+ case INSN_CLASS_ZVKSED:
+ return riscv_subset_supports (rps, "zvksed");
+ case INSN_CLASS_ZVKSH:
+ return riscv_subset_supports (rps, "zvksh");
case INSN_CLASS_SVINVAL:
return riscv_subset_supports (rps, "svinval");
case INSN_CLASS_H:
return riscv_subset_supports (rps, "h");
+ case INSN_CLASS_XTHEADBA:
+ return riscv_subset_supports (rps, "xtheadba");
+ case INSN_CLASS_XTHEADBB:
+ return riscv_subset_supports (rps, "xtheadbb");
+ case INSN_CLASS_XTHEADBS:
+ return riscv_subset_supports (rps, "xtheadbs");
+ case INSN_CLASS_XTHEADCMO:
+ return riscv_subset_supports (rps, "xtheadcmo");
+ case INSN_CLASS_XTHEADCONDMOV:
+ return riscv_subset_supports (rps, "xtheadcondmov");
+ case INSN_CLASS_XTHEADFMEMIDX:
+ return riscv_subset_supports (rps, "xtheadfmemidx");
+ case INSN_CLASS_XTHEADFMV:
+ return riscv_subset_supports (rps, "xtheadfmv");
+ case INSN_CLASS_XTHEADINT:
+ return riscv_subset_supports (rps, "xtheadint");
+ case INSN_CLASS_XTHEADMAC:
+ return riscv_subset_supports (rps, "xtheadmac");
+ case INSN_CLASS_XTHEADMEMIDX:
+ return riscv_subset_supports (rps, "xtheadmemidx");
+ case INSN_CLASS_XTHEADMEMPAIR:
+ return riscv_subset_supports (rps, "xtheadmempair");
+ case INSN_CLASS_XTHEADSYNC:
+ return riscv_subset_supports (rps, "xtheadsync");
+ case INSN_CLASS_XVENTANACONDOPS:
+ return riscv_subset_supports (rps, "xventanacondops");
default:
rps->error_handler
(_("internal: unreachable INSN_CLASS_*"));
{
case INSN_CLASS_I:
return "i";
+ case INSN_CLASS_ZICBOM:
+ return "zicbom";
+ case INSN_CLASS_ZICBOP:
+ return "zicbop";
+ case INSN_CLASS_ZICBOZ:
+ return "zicboz";
+ case INSN_CLASS_ZICOND:
+ return "zicond";
case INSN_CLASS_ZICSR:
return "zicsr";
case INSN_CLASS_ZIFENCEI:
return "zihintpause";
case INSN_CLASS_M:
return "m";
+ case INSN_CLASS_ZMMUL:
+ return _ ("m' or `zmmul");
case INSN_CLASS_A:
return "a";
+ case INSN_CLASS_ZAWRS:
+ return "zawrs";
case INSN_CLASS_F:
return "f";
case INSN_CLASS_D:
return "d";
else
return "c";
- case INSN_CLASS_F_OR_ZFINX:
- /* i18n: Formatted like "extension `f' or `zfinx' required". */
+ case INSN_CLASS_F_INX:
return _("f' or `zfinx");
- case INSN_CLASS_D_OR_ZDINX:
+ case INSN_CLASS_D_INX:
return _("d' or `zdinx");
- case INSN_CLASS_Q_OR_ZQINX:
+ case INSN_CLASS_Q_INX:
return _("q' or `zqinx");
- case INSN_CLASS_ZFH_OR_ZHINX:
+ case INSN_CLASS_ZFH_INX:
return _("zfh' or `zhinx");
case INSN_CLASS_ZFHMIN:
return "zfhmin";
- case INSN_CLASS_ZFHMIN_OR_ZHINXMIN:
+ case INSN_CLASS_ZFHMIN_INX:
return _("zfhmin' or `zhinxmin");
- case INSN_CLASS_ZFHMIN_AND_D:
+ case INSN_CLASS_ZFHMIN_AND_D_INX:
if (riscv_subset_supports (rps, "zfhmin"))
return "d";
else if (riscv_subset_supports (rps, "d"))
return "zhinxmin";
else
return _("zfhmin' and `d', or `zhinxmin' and `zdinx");
- case INSN_CLASS_ZFHMIN_AND_Q:
+ case INSN_CLASS_ZFHMIN_AND_Q_INX:
if (riscv_subset_supports (rps, "zfhmin"))
return "q";
else if (riscv_subset_supports (rps, "q"))
return "zhinxmin";
else
return _("zfhmin' and `q', or `zhinxmin' and `zqinx");
+ case INSN_CLASS_ZFA:
+ return "zfa";
+ case INSN_CLASS_D_AND_ZFA:
+ if (!riscv_subset_supports (rps, "d")
+ && !riscv_subset_supports (rps, "zfa"))
+ return _("d' and `zfa");
+ else if (!riscv_subset_supports (rps, "d"))
+ return "d";
+ else
+ return "zfa";
+ case INSN_CLASS_Q_AND_ZFA:
+ if (!riscv_subset_supports (rps, "q")
+ && !riscv_subset_supports (rps, "zfa"))
+ return _("q' and `zfa");
+ else if (!riscv_subset_supports (rps, "q"))
+ return "q";
+ else
+ return "zfa";
+ case INSN_CLASS_ZFH_AND_ZFA:
+ if (!riscv_subset_supports (rps, "zfh")
+ && !riscv_subset_supports (rps, "zfa"))
+ return _("zfh' and `zfa");
+ else if (!riscv_subset_supports (rps, "zfh"))
+ return "zfh";
+ else
+ return "zfa";
case INSN_CLASS_ZBA:
return "zba";
case INSN_CLASS_ZBB:
return _("v' or `zve64x' or `zve32x");
case INSN_CLASS_ZVEF:
return _("v' or `zve64d' or `zve64f' or `zve32f");
+ case INSN_CLASS_ZVBB:
+ return _("zvbb");
+ case INSN_CLASS_ZVBC:
+ return _("zvbc");
+ case INSN_CLASS_ZVKG:
+ return _("zvkg");
+ case INSN_CLASS_ZVKNED:
+ return _("zvkned");
+ case INSN_CLASS_ZVKNHA:
+ return _("zvknha");
+ case INSN_CLASS_ZVKNHB:
+ return _("zvknhb");
+ case INSN_CLASS_ZVKSED:
+ return _("zvksed");
+ case INSN_CLASS_ZVKSH:
+ return _("zvksh");
case INSN_CLASS_SVINVAL:
return "svinval";
case INSN_CLASS_H:
return _("h");
+ case INSN_CLASS_XTHEADBA:
+ return "xtheadba";
+ case INSN_CLASS_XTHEADBB:
+ return "xtheadbb";
+ case INSN_CLASS_XTHEADBS:
+ return "xtheadbs";
+ case INSN_CLASS_XTHEADCMO:
+ return "xtheadcmo";
+ case INSN_CLASS_XTHEADCONDMOV:
+ return "xtheadcondmov";
+ case INSN_CLASS_XTHEADFMEMIDX:
+ return "xtheadfmemidx";
+ case INSN_CLASS_XTHEADFMV:
+ return "xtheadfmv";
+ case INSN_CLASS_XTHEADINT:
+ return "xtheadint";
+ case INSN_CLASS_XTHEADMAC:
+ return "xtheadmac";
+ case INSN_CLASS_XTHEADMEMIDX:
+ return "xtheadmemidx";
+ case INSN_CLASS_XTHEADMEMPAIR:
+ return "xtheadmempair";
+ case INSN_CLASS_XTHEADSYNC:
+ return "xtheadsync";
default:
rps->error_handler
(_("internal: unreachable INSN_CLASS_*"));