[v2,1/2] RISC-V: Add support for RISC-V Profiles 20/22.
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_binutils_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_binutils_check--master-arm |
success
|
Test passed
|
Commit Message
This patch introduces support for RISC-V Profiles RV20 and RV22 [1],
enabling developers to utilize these profiles through the -march option.
[1] https://github.com/riscv/riscv-profiles/releases/tag/v1.0
Version log:
1. Add check and error info between profiles and other extensions.
2. Update -march error info, when input is not start with rv32/rv64/profile.
bfd/ChangeLog:
* elfxx-riscv.c (struct riscv_profiles): New struct.
(riscv_handle_profiles): New hadnle function.
(riscv_parse_subset): New parser.
* elfxx-riscv.h (riscv_handle_profiles): New def.
gas/ChangeLog:
* NEWS: Add RISC-V Profiles.
* doc/as.texi: Update -march input type.
* doc/c-riscv.texi: Ditto.
* testsuite/gas/riscv/option-arch-fail.l: Modify error info.
* testsuite/gas/riscv/attribute-15.d: New test.
* testsuite/gas/riscv/attribute-16.d: New test.
* testsuite/gas/riscv/march-fail-rvi20u64v.d: New test.
* testsuite/gas/riscv/march-fail-rvi20u64v.l: New test.
---
bfd/elfxx-riscv.c | 86 +++++++++++++++++--
bfd/elfxx-riscv.h | 3 +
gas/NEWS | 2 +
gas/doc/as.texi | 2 +-
gas/doc/c-riscv.texi | 14 ++-
gas/testsuite/gas/riscv/attribute-15.d | 6 ++
gas/testsuite/gas/riscv/attribute-16.d | 6 ++
.../gas/riscv/march-fail-rvi20u64v.d | 3 +
.../gas/riscv/march-fail-rvi20u64v.l | 2 +
gas/testsuite/gas/riscv/option-arch-fail.l | 2 +-
10 files changed, 115 insertions(+), 11 deletions(-)
create mode 100644 gas/testsuite/gas/riscv/attribute-15.d
create mode 100644 gas/testsuite/gas/riscv/attribute-16.d
create mode 100644 gas/testsuite/gas/riscv/march-fail-rvi20u64v.d
create mode 100644 gas/testsuite/gas/riscv/march-fail-rvi20u64v.l
Comments
On Thu, Jan 23, 2025 at 1:30 PM Jiawei <jiawei@iscas.ac.cn> wrote:
> +const char *
> +riscv_handle_profiles (riscv_parse_subset_t *rps, const char *p)
> +{
> + /* Checking if input string contains a Profiles.
> + There are two cases use Profiles in -march option:
> +
> + 1. Only use Profiles in '-march' as input
> + 2. Mixed Profiles with other extensions
> +
> + Use '_' to split Profiles and other extensions. */
> + for (int i = 0; riscv_profiles_table[i].profile_name != NULL; ++i)
> + {
> + const char *match = strstr (p,
> riscv_profiles_table[i].profile_name);
> + const char *plus_ext = strchr (p, '_');
> + /* Find profile at the beginning. */
> + if (match != NULL && match == p)
> + {
> + /* If only have profile, return the profile_string directly. */
> + if (*(match + strlen(riscv_profiles_table[i].profile_name)) ==
> '\0')
> + return riscv_profiles_table[i].profile_string;
> + /* If there's a '_' sign, need to add profiles with other ext.
> */
> + else if (*(match + strlen(riscv_profiles_table[i].profile_name))
> == '_')
> + {
> + size_t arch_len = (strlen
> (riscv_profiles_table[i].profile_string)
> + + strlen (plus_ext));
> + /* Reset the input string with Profiles mandatory extensions,
> + end with '_' to connect other additional extensions. */
> + char *result = (char *) malloc (arch_len + 2);
>
Well, malloc spaces need to be free, so see the caller riscv_parse_subset
...
> + strcpy (result, riscv_profiles_table[i].profile_string);
> + strcat (result, plus_ext); /* Add other extensions after
> '_'. */
> + return result;
> + }
> + else
> + {
> + rps->error_handler (
> + _("%s: should use '_' between profile and other
> extesnions"),
> + p);
> + return riscv_profiles_table[i].profile_string;
>
Return NULL for the error case?
> + }
> + }
> + }
> + return p;
> +}
> +
> /* Function for parsing ISA string.
>
> Return Value:
> @@ -2198,18 +2273,19 @@ riscv_parse_subset (riscv_parse_subset_t *rps,
> return riscv_parse_check_conflicts (rps);
> }
>
> - for (p = arch; *p != '\0'; p++)
> + p = riscv_handle_profiles (rps, arch);
> +
> + for (const char *q = p; *q != '\0'; q++)
> {
>
... The p may point to a malloc profile string from riscv_handle_profiles,
or normal input const architecture string. The former needs free, but the
latter does not need to care about this in this function. It's hard to
know which one is it from the current code, so I think we can ...
> - if (ISUPPER (*p))
> + if (ISUPPER (*q))
> {
> rps->error_handler
> (_("%s: ISA string cannot contain uppercase letters"),
> - arch);
> + q);
> return false;
> }
> }
>
> - p = arch;
> if (startswith (p, "rv32"))
> {
> *rps->xlen = 32;
> @@ -2231,7 +2307,7 @@ riscv_parse_subset (riscv_parse_subset_t *rps,
> string is empty. */
> if (strlen (arch))
> rps->error_handler (
> - _("%s: ISA string must begin with rv32 or rv64"),
> + _("%s: ISA string must begin with rv32, rv64 or a profile"),
> arch);
> return false;
> }
>
... Here, Don't malloc new spaces to parse profile string, instead,
something probably like,
if (startswith (p, "rv32"))
{ *rps->xlen = 32; p += 4; }
else if (startswith (p, "rv64"))
{ *rps->xlen = 64; p += 4; }
else if (riscv_handle_profiles (...))
{ riscv_parse_subset (rps, profile_replaced_string);
p += length of profile name; }
The riscv_handle_profiles only compare the profile name, and then return
the corresponding str without malloc.
Also, maybe a new argument in riscv_parse_extensions (..., boolean
base_eig), that only checks the base is e/i/g for non-profile cases.
diff --git a/bfd/elfxx-riscv.h b/bfd/elfxx-riscv.h
> index 19e04adfa6a..d8bb61825fc 100644
> --- a/bfd/elfxx-riscv.h
> +++ b/bfd/elfxx-riscv.h
> @@ -121,6 +121,9 @@ riscv_multi_subset_supports (riscv_parse_subset_t *,
> enum riscv_insn_class);
> extern const char *
> riscv_multi_subset_supports_ext (riscv_parse_subset_t *, enum
> riscv_insn_class);
>
> +extern const char *
> +riscv_handle_profiles(riscv_parse_subset_t *, const char*);
> +
>
Can this be static so that it doesn't need extern?
> extern void
> riscv_print_extensions (void);
>
> diff --git a/gas/NEWS b/gas/NEWS
> index 70f3ad40dba..f62e59bdd64 100644
> --- a/gas/NEWS
> +++ b/gas/NEWS
> @@ -34,6 +34,8 @@ Changes in 2.44:
> CORE-V, xcvbitmanip v1.0 and xcvsimd v1.0.
> SiFive, xsfvqmaccdod v1.0, xsfvqmaccqoqv1.0 and xsfvfnrclipxfqf v1.0.
>
> +* Add support for RISC-V Profiles.
> +
>
Should be 2.45.
> * Add support for 4 formats of .cfi directives register aliases for
> LoongArch,
> for example, .cfi_offset r1,8, .cfi_offset ra,8, .cfi_offset $r1,8,
> .cfi_offset $ra,8.
> diff --git a/gas/doc/as.texi b/gas/doc/as.texi
> index afe1737f4ce..ad096fc02c8 100644
> --- a/gas/doc/as.texi
> +++ b/gas/doc/as.texi
> @@ -552,7 +552,7 @@ gcc(1), ld(1), and the Info entries for
> @file{binutils} and @file{ld}.
>
> @emph{Target RISC-V options:}
> [@b{-fpic}|@b{-fPIC}|@b{-fno-pic}]
> - [@b{-march}=@var{ISA}]
> + [@b{-march}=@var{ISA/Profiles/Profiles+ISA}]
>
Maybe,
[@b{-march}=@var{ISA}|@var{Profile}[+@var{ISA}] ?
> [@b{-mabi}=@var{ABI}]
> [@b{-mlittle-endian}|@b{-mbig-endian}]
> @end ifset
> diff --git a/gas/doc/c-riscv.texi b/gas/doc/c-riscv.texi
> index d2e47455e7c..f5f13a976e5 100644
> --- a/gas/doc/c-riscv.texi
> +++ b/gas/doc/c-riscv.texi
> @@ -41,9 +41,10 @@ Generate position-independent code
> @item -fno-pic
> Don't generate position-independent code (default)
>
> -@cindex @samp{-march=ISA} option, RISC-V
> -@item -march=ISA
> -Select the base isa, as specified by ISA. For example -march=rv32ima.
> +@cindex @samp{-march=ISA/Profiles/Profies+ISA} option, RISC-V
> +@item -march=ISA/Profiles/Profiles+ISA
+Select the base isa, as specified by ISA or Profiles or Profies+ISA.
>
@samp{-march=[ISA|Profiles|Profies+ISA]}, I think we need regular
expression here.
Btw, "profiles" seem to allow adding multiple profiles?
> +For example -march=rv32ima -march=RVI20U64 -march=RVI20U64+d.
>
Comma to separate?
Thanks
Nelson
@@ -1022,6 +1022,12 @@ static const struct elf_reloc_map riscv_reloc_map[] =
{ BFD_RELOC_RISCV_SUB_ULEB128, R_RISCV_SUB_ULEB128 },
};
+struct riscv_profiles
+{
+ const char *profile_name;
+ const char *profile_string;
+};
+
/* Given a BFD reloc type, return a howto structure. */
reloc_howto_type *
@@ -1285,6 +1291,31 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
{NULL, NULL, NULL}
};
+/* This table records the mapping form RISC-V Profiles into march string. */
+static struct riscv_profiles riscv_profiles_table[] =
+{
+ /* RVI20U only contains the base extension 'i' as mandatory extension. */
+ {"rvi20u64", "rv64i"},
+ {"rvi20u32", "rv32i"},
+
+ /* RVA20U contains the 'i,m,a,f,d,c,zicsr,zicntr,ziccif,ziccrse,ziccamoa,
+ zicclsm,za128rs' as mandatory extensions. */
+ {"rva20u64", "rv64imafdc_zicsr_zicntr_ziccif_ziccrse_ziccamoa"
+ "_zicclsm_za128rs"},
+
+ /* RVA22U contains the 'i,m,a,f,d,c,zicsr,zihintpause,zba,zbb,zbs,zicntr,
+ zihpm,ziccif,ziccrse,ziccamoa, zicclsm,zic64b,za64rs,zicbom,zicbop,zicboz,
+ zfhmin,zkt' as mandatory extensions. */
+ {"rva22u64", "rv64imafdc_zicsr_zicntr_ziccif_ziccrse_ziccamoa"
+ "_zicclsm_zic64b_za64rs_zihintpause_zba_zbb_zbs_zicbom_zicbop"
+ "_zicboz_zfhmin_zkt"},
+
+ /* Currently we do not define S/M mode Profiles. */
+
+ /* Terminate the list. */
+ {NULL, NULL}
+};
+
/* For default_enable field, decide if the extension should
be enbaled by default. */
@@ -2172,6 +2203,50 @@ riscv_set_default_arch (riscv_parse_subset_t *rps)
}
}
+const char *
+riscv_handle_profiles (riscv_parse_subset_t *rps, const char *p)
+{
+ /* Checking if input string contains a Profiles.
+ There are two cases use Profiles in -march option:
+
+ 1. Only use Profiles in '-march' as input
+ 2. Mixed Profiles with other extensions
+
+ Use '_' to split Profiles and other extensions. */
+ for (int i = 0; riscv_profiles_table[i].profile_name != NULL; ++i)
+ {
+ const char *match = strstr (p, riscv_profiles_table[i].profile_name);
+ const char *plus_ext = strchr (p, '_');
+ /* Find profile at the beginning. */
+ if (match != NULL && match == p)
+ {
+ /* If only have profile, return the profile_string directly. */
+ if (*(match + strlen(riscv_profiles_table[i].profile_name)) == '\0')
+ return riscv_profiles_table[i].profile_string;
+ /* If there's a '_' sign, need to add profiles with other ext. */
+ else if (*(match + strlen(riscv_profiles_table[i].profile_name)) == '_')
+ {
+ size_t arch_len = (strlen (riscv_profiles_table[i].profile_string)
+ + strlen (plus_ext));
+ /* Reset the input string with Profiles mandatory extensions,
+ end with '_' to connect other additional extensions. */
+ char *result = (char *) malloc (arch_len + 2);
+ strcpy (result, riscv_profiles_table[i].profile_string);
+ strcat (result, plus_ext); /* Add other extensions after '_'. */
+ return result;
+ }
+ else
+ {
+ rps->error_handler (
+ _("%s: should use '_' between profile and other extesnions"),
+ p);
+ return riscv_profiles_table[i].profile_string;
+ }
+ }
+ }
+ return p;
+}
+
/* Function for parsing ISA string.
Return Value:
@@ -2198,18 +2273,19 @@ riscv_parse_subset (riscv_parse_subset_t *rps,
return riscv_parse_check_conflicts (rps);
}
- for (p = arch; *p != '\0'; p++)
+ p = riscv_handle_profiles (rps, arch);
+
+ for (const char *q = p; *q != '\0'; q++)
{
- if (ISUPPER (*p))
+ if (ISUPPER (*q))
{
rps->error_handler
(_("%s: ISA string cannot contain uppercase letters"),
- arch);
+ q);
return false;
}
}
- p = arch;
if (startswith (p, "rv32"))
{
*rps->xlen = 32;
@@ -2231,7 +2307,7 @@ riscv_parse_subset (riscv_parse_subset_t *rps,
string is empty. */
if (strlen (arch))
rps->error_handler (
- _("%s: ISA string must begin with rv32 or rv64"),
+ _("%s: ISA string must begin with rv32, rv64 or a profile"),
arch);
return false;
}
@@ -121,6 +121,9 @@ riscv_multi_subset_supports (riscv_parse_subset_t *, enum riscv_insn_class);
extern const char *
riscv_multi_subset_supports_ext (riscv_parse_subset_t *, enum riscv_insn_class);
+extern const char *
+riscv_handle_profiles(riscv_parse_subset_t *, const char*);
+
extern void
riscv_print_extensions (void);
@@ -34,6 +34,8 @@ Changes in 2.44:
CORE-V, xcvbitmanip v1.0 and xcvsimd v1.0.
SiFive, xsfvqmaccdod v1.0, xsfvqmaccqoqv1.0 and xsfvfnrclipxfqf v1.0.
+* Add support for RISC-V Profiles.
+
* Add support for 4 formats of .cfi directives register aliases for LoongArch,
for example, .cfi_offset r1,8, .cfi_offset ra,8, .cfi_offset $r1,8,
.cfi_offset $ra,8.
@@ -552,7 +552,7 @@ gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}.
@emph{Target RISC-V options:}
[@b{-fpic}|@b{-fPIC}|@b{-fno-pic}]
- [@b{-march}=@var{ISA}]
+ [@b{-march}=@var{ISA/Profiles/Profiles+ISA}]
[@b{-mabi}=@var{ABI}]
[@b{-mlittle-endian}|@b{-mbig-endian}]
@end ifset
@@ -41,9 +41,10 @@ Generate position-independent code
@item -fno-pic
Don't generate position-independent code (default)
-@cindex @samp{-march=ISA} option, RISC-V
-@item -march=ISA
-Select the base isa, as specified by ISA. For example -march=rv32ima.
+@cindex @samp{-march=ISA/Profiles/Profies+ISA} option, RISC-V
+@item -march=ISA/Profiles/Profiles+ISA
+Select the base isa, as specified by ISA or Profiles or Profies+ISA.
+For example -march=rv32ima -march=RVI20U64 -march=RVI20U64+d.
If this option and the architecture attributes aren't set, then assembler
will check the default configure setting --with-arch=ISA.
@@ -720,7 +721,12 @@ to be recorded in the attribute as @code{RV32I2P0} in which @code{2P0} stands
for the default version of its base ISA. On the other hand, the architecture
@code{RV32G} has to be presented as @code{RV32I2P0_M2P0_A2P0_F2P0_D2P0} in
which the abbreviation @code{G} is expanded to the @code{IMAFD} combination
-with default versions of the standard extensions.
+with default versions of the standard extensions. All Profiles are expanded
+ to the mandatory extensions it includes then processing. For example,
+@code{RVI20U32} is expanded to @code{RV32I2P0} for processing, which contains
+the mandatory extensions @code{I} as it defined. And you can also combine
+Profiles with ISA use +, like @code{RVI20U32_D} is expanded to the
+@code{RV32I2P0_F2P0_D2P0}.
@item Tag_RISCV_unaligned_access (6)
Tag_RISCV_unaligned_access is 0 for files that do not allow any unaligned
new file mode 100644
@@ -0,0 +1,6 @@
+#as: -march=rva20u64
+#readelf: -A
+#source: empty.s
+Attribute Section: riscv
+File Attributes
+ Tag_RISCV_arch: "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_ziccamoa1p0_ziccif1p0_zicclsm1p0_ziccrse1p0_zicntr2p0_zicsr2p0_zmmul1p0_za128rs1p0_zaamo1p0_zalrsc1p0"
new file mode 100644
@@ -0,0 +1,6 @@
+#as: -march=rvi20u32_d
+#readelf: -A
+#source: empty.s
+Attribute Section: riscv
+File Attributes
+ Tag_RISCV_arch: "rv32i2p1_f2p2_d2p2_zicsr2p0"
new file mode 100644
@@ -0,0 +1,3 @@
+#as: -march=rvi20u64v
+#source: empty.s
+#error_output: march-fail-rvi20u64v.l
new file mode 100644
@@ -0,0 +1,2 @@
+.*Assembler messages:
+.*Error: .*rvi20u64v: should use '_' between profile and other extesnions
@@ -1,5 +1,5 @@
.*Assembler messages:
-.*Error: m2p0: ISA string must begin with rv32 or rv64
+.*Error: m2p0: ISA string must begin with rv32, rv64 or a profile
.*Error: cannot \+ or \- base extension `i' in .option arch `\-i'
.*Error: cannot \+ or \- base extension `e' in .option arch `\+e'
.*Error: cannot \+ or \- base extension `g' in .option arch `\-g'