aboutsummaryrefslogtreecommitdiff
path: root/bfd/elfxx-riscv.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elfxx-riscv.c')
-rw-r--r--bfd/elfxx-riscv.c142
1 files changed, 76 insertions, 66 deletions
diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index 43d3c0d..1200032 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1178,9 +1178,20 @@ static bool
check_implicit_for_zcf (riscv_parse_subset_t *rps,
const riscv_subset_t *subset ATTRIBUTE_UNUSED)
{
- riscv_subset_t *tmp = NULL;
- return *rps->xlen == 32
- && riscv_lookup_subset (rps->subset_list, "f", &tmp);
+ return (rps != NULL
+ && rps->xlen != NULL
+ && *rps->xlen == 32
+ && riscv_subset_supports (rps, "f"));
+}
+
+/* Add the implicit only when 'd' extension is also available. */
+
+static bool
+check_implicit_for_zcd (riscv_parse_subset_t *rps,
+ const riscv_subset_t *subset ATTRIBUTE_UNUSED)
+{
+ return (rps != NULL
+ && riscv_subset_supports (rps, "d"));
}
/* Record all implicit information for the subsets. */
@@ -1237,15 +1248,6 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
{"zvl128b", "+zvl64b", check_implicit_always},
{"zvl64b", "+zvl32b", check_implicit_always},
- {"zce", "+zca,+zcb,+zcmp,+zcmt", check_implicit_always},
- {"zce", "+zcf", check_implicit_for_zcf},
- {"zcb", "+zca", check_implicit_always},
- {"zcd", "+d,+zca", check_implicit_always},
- {"zcf", "+f,+zca", check_implicit_always},
- {"zcmp", "+zca", check_implicit_always},
- {"zcmop", "+zca", check_implicit_always},
- {"zcmt", "+zca,+zicsr", check_implicit_always},
-
{"zicfilp", "+zicsr", check_implicit_always},
{"zicfiss", "+zimop,+zicsr", check_implicit_always},
{"zclsd", "+zca,+zilsd", check_implicit_always},
@@ -1262,6 +1264,9 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
{"zhinx", "+zhinxmin", check_implicit_always},
{"zhinxmin", "+zfinx", check_implicit_always},
+ {"zcd", "+d,+zca", check_implicit_always},
+ {"zcf", "+f,+zca", check_implicit_always},
+
{"q", "+d", check_implicit_always},
{"zqinx", "+zdinx", check_implicit_always},
@@ -1275,6 +1280,16 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
{"zfinx", "+zicsr", check_implicit_always},
{"f", "+zicsr", check_implicit_always},
+ {"zce", "+zcb,+zcmp,+zcmt", check_implicit_always},
+ {"zce", "+zcf", check_implicit_for_zcf},
+ {"zcb", "+zca", check_implicit_always},
+ {"zcmp", "+zca", check_implicit_always},
+ {"zcmop", "+zca", check_implicit_always},
+ {"zcmt", "+zca,+zicsr", check_implicit_always},
+ {"c", "+zcf", check_implicit_for_zcf},
+ {"c", "+zcd", check_implicit_for_zcd},
+ {"c", "+zca", check_implicit_always},
+
{"b", "+zba,+zbb,+zbs", check_implicit_always},
{"zk", "+zkn,+zkr,+zkt", check_implicit_always},
@@ -2208,7 +2223,7 @@ riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
&& riscv_subset_supports (rps, "zcd"))
{
rps->error_handler
- (_("zcmp' is incompatible with `d/zcd' extension"));
+ (_("zcmp' is incompatible with `d' and `c', or `zcd' extension"));
no_conflict = false;
}
if (riscv_lookup_subset (rps->subset_list, "zcf", &subset)
@@ -2602,7 +2617,7 @@ riscv_remove_subset (riscv_subset_list_t *subset_list,
called from riscv_update_subset./
The IMPLICIT_EXTS, +extension[version] [,...,+extension_n[version_n]]
- -extension [,...,-extension_n],
+ (Deprecated) -extension [,...,-extension_n],
full ISA. */
static bool
@@ -2694,16 +2709,26 @@ riscv_update_subset1 (riscv_parse_subset_t *rps,
return false;
}
- if (explicit_subset == NULL
- && (strcmp (subset, "i") == 0
- || strcmp (subset, "e") == 0
- || strcmp (subset, "g") == 0))
+ if (explicit_subset == NULL)
{
- rps->error_handler
- (_("%scannot + or - base extension `%s' in %s `%s'"),
- errmsg_internal, subset, errmsg_caller, implicit_exts);
- free (subset);
- return false;
+ if (removed)
+ {
+ rps->error_handler
+ (_("%sdeprecated - extension `%s' in %s `%s'"),
+ errmsg_internal, subset, errmsg_caller, implicit_exts);
+ free (subset);
+ return false;
+ }
+ else if (strcmp (subset, "i") == 0
+ || strcmp (subset, "e") == 0
+ || strcmp (subset, "g") == 0)
+ {
+ rps->error_handler
+ (_("%scannot + base extension `%s' in %s `%s'"),
+ errmsg_internal, subset, errmsg_caller, implicit_exts);
+ free (subset);
+ return false;
+ }
}
if (removed)
@@ -2729,8 +2754,8 @@ riscv_update_subset1 (riscv_parse_subset_t *rps,
return no_conflict;
}
-/* Add/Remove an extension to/from the subset list. This is used for
- the .option rvc or norvc, and .option arch directives. */
+/* Add an extension to/from the subset list. This is used for the .option rvc
+ and .option arch directives. */
bool
riscv_update_subset (riscv_parse_subset_t *rps,
@@ -2739,6 +2764,16 @@ riscv_update_subset (riscv_parse_subset_t *rps,
return riscv_update_subset1 (rps, NULL, str);
}
+/* Called from .option norvc directives. */
+
+bool
+riscv_update_subset_norvc (riscv_parse_subset_t *rps)
+{
+ return riscv_update_subset1 (rps, rps->subset_list->head,
+ "-c,-zca,-zcd,-zcf,-zcb,-zce,-zcmp,-zcmt,"
+ "-zcmop,-zclsd");
+}
+
/* Check if the FEATURE subset is supported or not in the subset list.
Return true if it is supported; Otherwise, return false. */
@@ -2775,10 +2810,9 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
return riscv_subset_supports (rps, "zifencei");
case INSN_CLASS_ZIHINTNTL:
return riscv_subset_supports (rps, "zihintntl");
- case INSN_CLASS_ZIHINTNTL_AND_C:
- return (riscv_subset_supports (rps, "zihintntl")
- && (riscv_subset_supports (rps, "c")
- || riscv_subset_supports (rps, "zca")));
+ case INSN_CLASS_ZIHINTNTL_AND_ZCA:
+ return riscv_subset_supports (rps, "zihintntl")
+ && riscv_subset_supports (rps, "zca");
case INSN_CLASS_ZIHINTPAUSE:
return riscv_subset_supports (rps, "zihintpause");
case INSN_CLASS_ZIMOP:
@@ -2813,17 +2847,12 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
return riscv_subset_supports (rps, "d");
case INSN_CLASS_Q:
return riscv_subset_supports (rps, "q");
- case INSN_CLASS_C:
- return (riscv_subset_supports (rps, "c")
- || riscv_subset_supports (rps, "zca"));
- case INSN_CLASS_F_AND_C:
- return (riscv_subset_supports (rps, "f")
- && (riscv_subset_supports (rps, "c")
- || riscv_subset_supports (rps, "zcf")));
- case INSN_CLASS_D_AND_C:
- return (riscv_subset_supports (rps, "d")
- && (riscv_subset_supports (rps, "c")
- || riscv_subset_supports (rps, "zcd")));
+ case INSN_CLASS_ZCA:
+ return riscv_subset_supports (rps, "zca");
+ case INSN_CLASS_ZCF:
+ return riscv_subset_supports (rps, "zcf");
+ case INSN_CLASS_ZCD:
+ return riscv_subset_supports (rps, "zcd");
case INSN_CLASS_F_INX:
return (riscv_subset_supports (rps, "f")
|| riscv_subset_supports (rps, "zfinx"));
@@ -3070,11 +3099,10 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
return "zicfilp";
case INSN_CLASS_ZIHINTNTL:
return "zihintntl";
- case INSN_CLASS_ZIHINTNTL_AND_C:
+ case INSN_CLASS_ZIHINTNTL_AND_ZCA:
if (!riscv_subset_supports (rps, "zihintntl"))
{
- if (!riscv_subset_supports (rps, "c")
- && !riscv_subset_supports (rps, "zca"))
+ if (!riscv_subset_supports (rps, "zca"))
return _("zihintntl' and `c', or `zihintntl' and `zca");
else
return "zihintntl";
@@ -3105,30 +3133,12 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
return "d";
case INSN_CLASS_Q:
return "q";
- case INSN_CLASS_C:
+ case INSN_CLASS_ZCA:
return _("c' or `zca");
- case INSN_CLASS_F_AND_C:
- if (!riscv_subset_supports (rps, "f"))
- {
- if (!riscv_subset_supports (rps, "c")
- && !riscv_subset_supports (rps, "zcf"))
- return _("f' and `c', or `f' and `zcf");
- else
- return "f";
- }
- else
- return _("c' or `zcf");
- case INSN_CLASS_D_AND_C:
- if (!riscv_subset_supports (rps, "d"))
- {
- if (!riscv_subset_supports (rps, "c")
- && !riscv_subset_supports (rps, "zcd"))
- return _("d' and `c', or `d' and `zcd");
- else
- return "d";
- }
- else
- return _("c' or `zcd");
+ case INSN_CLASS_ZCF:
+ return _("f' and `c', or `zcf");
+ case INSN_CLASS_ZCD:
+ return _("d' and `c', or `zcd");
case INSN_CLASS_F_INX:
return _("f' or `zfinx");
case INSN_CLASS_D_INX: