Skip to content
This repository has been archived by the owner on Aug 17, 2022. It is now read-only.

Add p-ext support with spec v0.94 #257

Open
wants to merge 13 commits into
base: riscv-binutils-experiment
Choose a base branch
from
15 changes: 14 additions & 1 deletion bfd/elfxx-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1598,7 +1598,8 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,

static const char * const riscv_std_z_ext_strtab[] =
{
"zicsr", "zifencei", "zihintpause", "zba", "zbb", "zbc", NULL
"zicsr", "zifencei", "zihintpause", "zba", "zbb", "zbc",
"zbpbo", "zpn", "zpsf",NULL
};

static const char * const riscv_std_s_ext_strtab[] =
Expand Down Expand Up @@ -1770,6 +1771,18 @@ riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps)
RISCV_UNKNOWN_VERSION,
RISCV_UNKNOWN_VERSION, TRUE);
}
if (riscv_lookup_subset (rps->subset_list, "p", &subset))
{
riscv_parse_add_subset (rps, "zpn",
RISCV_UNKNOWN_VERSION,
RISCV_UNKNOWN_VERSION, TRUE);
riscv_parse_add_subset (rps, "zpsf",
RISCV_UNKNOWN_VERSION,
RISCV_UNKNOWN_VERSION, TRUE);
riscv_parse_add_subset (rps, "zbpbo",
RISCV_UNKNOWN_VERSION,
RISCV_UNKNOWN_VERSION, TRUE);
}
}

/* Function for parsing ISA string.
Expand Down
164 changes: 163 additions & 1 deletion gas/config/tc-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ enum riscv_csr_class
CSR_CLASS_I,
CSR_CLASS_I_32, /* rv32 only */
CSR_CLASS_F, /* f-ext only */
CSR_CLASS_P, /* rvp only */
CSR_CLASS_DEBUG /* debug CSR */
};

Expand Down Expand Up @@ -131,6 +132,8 @@ static const struct riscv_ext_version ext_version_table[] =
{"c", ISA_SPEC_CLASS_20190608, 2, 0},
{"c", ISA_SPEC_CLASS_2P2, 2, 0},

{"p", ISA_SPEC_CLASS_DRAFT, 2, 0},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the g and k expansions, but we don't need to care about this here.


{"zicsr", ISA_SPEC_CLASS_20191213, 2, 0},
{"zicsr", ISA_SPEC_CLASS_20190608, 2, 0},

Expand All @@ -142,7 +145,10 @@ static const struct riscv_ext_version ext_version_table[] =
{"zbb", ISA_SPEC_CLASS_DRAFT, 0, 93},
{"zba", ISA_SPEC_CLASS_DRAFT, 0, 93},
{"zbc", ISA_SPEC_CLASS_DRAFT, 0, 93},


{"zpn", ISA_SPEC_CLASS_DRAFT, 2, 0},
{"zpsf", ISA_SPEC_CLASS_DRAFT, 2, 0},
{"zbpbo", ISA_SPEC_CLASS_DRAFT, 2, 0},
/* Terminate the list. */
{NULL, 0, 0, 0}
};
Expand Down Expand Up @@ -340,6 +346,13 @@ riscv_multi_subset_supports (enum riscv_insn_class insn_class)
return riscv_subset_supports ("zba");
case INSN_CLASS_ZBC:
return riscv_subset_supports ("zbc");

case INSN_CLASS_ZPN:
return riscv_subset_supports ("zpn");
case INSN_CLASS_ZPSF:
return riscv_subset_supports ("zpsf");
case INSN_CLASS_ZBPBO:
return riscv_subset_supports ("zbpbo");

default:
as_fatal ("internal: unreachable");
Expand Down Expand Up @@ -856,6 +869,10 @@ riscv_csr_address (const char *csr_name,
result = riscv_subset_supports ("f");
need_check_version = FALSE;
break;
case CSR_CLASS_P:
result = riscv_subset_supports ("zpn");
need_check_version = FALSE;
break;
case CSR_CLASS_DEBUG:
need_check_version = FALSE;
break;
Expand Down Expand Up @@ -973,6 +990,29 @@ arg_lookup (char **s, const char *const *array, size_t size, unsigned *regnop)
return FALSE;
}

#define RVP_MAX_KEYWORD_LEN 32

static bfd_boolean
parse_rvp_field (const char **str, char name[RVP_MAX_KEYWORD_LEN])
{
char *p = name;
const char *str_t;

str_t = *str;
str_t--;
while (ISALNUM (*str_t) || *str_t == '.' || *str_t == '_')
*p++ = *str_t++;
*p = '\0';

if (strncmp (name, "nds_", 4) == 0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is minor, so it is OK here. But once it becomes to one of the stable standard extensions, then I think we should give them new operand names.

{
*str = str_t;
return TRUE;
}
else
return FALSE;
}

/* For consistency checking, verify that all bits are specified either
by the match/mask part of the instruction definition, or by the
operand list. The `length` could be 0, 4 or 8, 0 for auto detection. */
Expand Down Expand Up @@ -1071,6 +1111,7 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
case 'Z': /* RS1, CSR number. */
case 'S': /* RS1, floating point. */
case 's': USE_BITS (OP_MASK_RS1, OP_SH_RS1); break;
case 'g': /* RS1 and RS2 are the same. */
case 'U': /* RS1 and RS2 are the same, floating point. */
USE_BITS (OP_MASK_RS1, OP_SH_RS1);
/* Fall through. */
Expand All @@ -1083,6 +1124,7 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
case 'P': USE_BITS (OP_MASK_PRED, OP_SH_PRED); break;
case 'Q': USE_BITS (OP_MASK_SUCC, OP_SH_SUCC); break;
case 'o': /* ITYPE immediate, load displacement. */
case 'l': /* IMM6L */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks strange. We encode it as ENCODE_ITYPE_IMM here (validate_riscv_insn), but will use ENCODE_SBTYPE_IMM6L to encode it later in the riscv_ip.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing it out. Fixed it the latest commit.

case 'j': used_bits |= ENCODE_ITYPE_IMM (-1U); break;
case 'a': used_bits |= ENCODE_JTYPE_IMM (-1U); break;
case 'p': used_bits |= ENCODE_BTYPE_IMM (-1U); break;
Expand Down Expand Up @@ -1118,6 +1160,36 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
return FALSE;
}
break;
case 'n':
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should renamed the operands eventually. Rename to `p' prefix is more reasonable and easy to understand, just like what vector instructions did, but we already have p operand for another usage. Maybe we can file an issue to discuss the problem.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked 'p', 'P', 'r'(for rvp), but they are taken by others. so I used the old prefix 'nds'. It would be great to have a discussion on that. Thanks!

{
char field_name[RVP_MAX_KEYWORD_LEN];
if (parse_rvp_field (&p, field_name))
{
if (strcmp (field_name, "nds_rdp") == 0)
USE_BITS (OP_MASK_RD, OP_SH_RD);
else if (strcmp (field_name, "nds_rsp") == 0)
USE_BITS (OP_MASK_RD, OP_SH_RS1);
else if (strcmp (field_name, "nds_rtp") == 0)
USE_BITS (OP_MASK_RD, OP_SH_RS2);
else if (strcmp (field_name, "nds_i3u") == 0)
used_bits |= ENCODE_PTYPE_IMM3U (-1U);
else if (strcmp (field_name, "nds_i4u") == 0)
used_bits |= ENCODE_PTYPE_IMM4U (-1U);
else if (strcmp (field_name, "nds_i5u") == 0)
used_bits |= ENCODE_PTYPE_IMM5U (-1U);
else if (strcmp (field_name, "nds_i6u") == 0)
used_bits |= ENCODE_PTYPE_IMM6U (-1U);
else
as_bad (_("internal: bad RISC-V opcode "
"(unknown operand type `%s'): %s %s"),
field_name, opc->name, opc->args);
}
else
as_bad (_("internal: bad RISC-V opcode "
"(unknown operand type `%c'): %s %s"),
c, opc->name, opc->args);
}
break;
default:
as_bad (_("internal: bad RISC-V opcode "
"(unknown operand type `%c'): %s %s"),
Expand Down Expand Up @@ -2402,6 +2474,17 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
}
continue;

case 'l':
my_getExpression (imm_expr, s);
if (imm_expr->X_op != O_constant
|| imm_expr->X_add_number >= xlen
|| imm_expr->X_add_number < 0)
break;
ip->insn_opcode |= ENCODE_ITYPE_IMM6L (imm_expr->X_add_number);
s = expr_end;
imm_expr->X_op = O_absent;
continue;

case 'm': /* Rounding mode. */
if (arg_lookup (&s, riscv_rm, ARRAY_SIZE (riscv_rm), &regno))
{
Expand All @@ -2410,6 +2493,81 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
}
break;

case 'n':
{
char field_name[RVP_MAX_KEYWORD_LEN];
args++;
if (parse_rvp_field (&args, field_name))
{
if (strcmp (field_name, "nds_rdp") == 0
&& reg_lookup (&s, RCLASS_GPR, &regno))
{
if (xlen == 32 && (regno % 2) != 0)
{
as_bad (_("the number of Rd must be even "
"(limitation of register pair)"));
break;
}
INSERT_OPERAND (RD, *ip, regno);
args--;
continue;
}
else if (strcmp (field_name, "nds_rsp") == 0
&& reg_lookup (&s, RCLASS_GPR, &regno))
{
if (xlen == 32 && (regno % 2) != 0)
{
as_bad (_("the number of Rs1 must be even "
"(limitation of register pair)"));
break;
}
INSERT_OPERAND (RS1, *ip, regno);
args--;
continue;
}
else if (strcmp (field_name, "nds_rtp") == 0
&& reg_lookup (&s, RCLASS_GPR, &regno))
{
if (xlen == 32 && (regno % 2) != 0)
{
as_bad (_("the number of Rs2 must be even "
"(limitation of register pair)"));
break;
}
INSERT_OPERAND (RS2, *ip, regno);
args--;
continue;
}

my_getExpression (imm_expr, s);
if (imm_expr->X_op != O_constant
|| imm_expr->X_add_number >= xlen
|| imm_expr->X_add_number < 0)
break;

if (strcmp (field_name, "nds_i3u") == 0
&& VALID_PTYPE_IMM3U (imm_expr->X_add_number))
ip->insn_opcode |= ENCODE_PTYPE_IMM3U (imm_expr->X_add_number);
else if (strcmp (field_name, "nds_i4u") == 0
&& VALID_PTYPE_IMM4U (imm_expr->X_add_number))
ip->insn_opcode |= ENCODE_PTYPE_IMM4U (imm_expr->X_add_number);
else if (strcmp (field_name, "nds_i5u") == 0
&& VALID_PTYPE_IMM5U (imm_expr->X_add_number))
ip->insn_opcode |= ENCODE_PTYPE_IMM5U (imm_expr->X_add_number);
else if (strcmp (field_name, "nds_i6u") == 0
&& VALID_PTYPE_IMM6U (imm_expr->X_add_number))
ip->insn_opcode |= ENCODE_PTYPE_IMM6U (imm_expr->X_add_number);
else
break;

s = expr_end;
imm_expr->X_op = O_absent;
args--;
continue;
}
break;
}

case 'P':
case 'Q': /* Fence predecessor/successor. */
if (arg_lookup (&s, riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ),
Expand All @@ -2425,6 +2583,7 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,

case 'd': /* Destination register. */
case 's': /* Source register. */
case 'g': /* RS1 and RS2. */
case 't': /* Target register. */
case 'r': /* RS3 */
if (reg_lookup (&s, RCLASS_GPR, &regno))
Expand All @@ -2443,6 +2602,9 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
case 'd':
INSERT_OPERAND (RD, *ip, regno);
break;
case 'g':
INSERT_OPERAND (RS1, *ip, regno);
/* Fall through. */
case 't':
INSERT_OPERAND (RS2, *ip, regno);
break;
Expand Down
24 changes: 24 additions & 0 deletions gas/testsuite/gas/riscv/insn-dsp-zbpbo.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#as: -march=rv32gc_zbpbo_zpn_zpsf
#source: insn-dsp-zbpbo.s
#objdump: -d

.*:[ ]+file format .*


Disassembly of section .text:

0+000 <dsp>:
[ ]+.*:[ ]+.*[ ]+clz[ ]+a1,a2
[ ]+.*:[ ]+.*[ ]+clz[ ]+a1,a2
[ ]+.*:[ ]+.*[ ]+cmix[ ]+a1,a2,a3,a4
[ ]+.*:[ ]+.*[ ]+fsr[ ]+a1,a2,a3,a4
[ ]+.*:[ ]+.*[ ]+fsri[ ]+a1,a2,a3,0x5
[ ]+.*:[ ]+.*[ ]+max[ ]+a1,a2,a3
[ ]+.*:[ ]+.*[ ]+min[ ]+a1,a2,a3
[ ]+.*:[ ]+.*[ ]+pack[ ]+a1,a2,a3
[ ]+.*:[ ]+.*[ ]+packu[ ]+a1,a2,a3
[ ]+.*:[ ]+.*[ ]+pack[ ]+a1,a2,a3
[ ]+.*:[ ]+.*[ ]+packu[ ]+a1,a2,a3
[ ]+.*:[ ]+.*[ ]+rev[ ]+a1,a2
[ ]+.*:[ ]+.*[ ]+rev8.h[ ]+a1,a2
[ ]+.*:[ ]+.*[ ]+rev8.h[ ]+a1,a2
15 changes: 15 additions & 0 deletions gas/testsuite/gas/riscv/insn-dsp-zbpbo.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
dsp:
clz a1,a2
clz32 a1,a2
cmix a1,a2,a3,a4
fsr a1,a2,a3,a4
fsri a1,a2,a3,5
max a1,a2,a3
min a1,a2,a3
pack a1,a2,a3
packu a1,a2,a3
pktt16 a1,a2,a3
pkbb16 a1,a2,a3
rev a1,a2
rev8.h a1,a2
swap8 a1,a2
Loading