aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorJin Ma <jinma@linux.alibaba.com>2024-01-04 10:17:40 +0800
committerNelson Chu <nelson@rivosinc.com>2024-01-05 09:59:48 +0800
commit6a95962e258f9ef06050f11c049771a865250c6f (patch)
tree287f74274d39575ef8311047dbb4df2a8a783f17 /gas
parent53c4e37bb18cb8d13dbe2f595bc2ebb453673771 (diff)
downloadfsf-binutils-gdb-6a95962e258f9ef06050f11c049771a865250c6f.zip
fsf-binutils-gdb-6a95962e258f9ef06050f11c049771a865250c6f.tar.gz
fsf-binutils-gdb-6a95962e258f9ef06050f11c049771a865250c6f.tar.bz2
RISC-V: T-HEAD: Fix wrong instruction encoding for th.vsetvli
Since the particularity of "th.vsetvli" was not taken into account in the initial support patches for XTheadVector, the program operation failed due to instruction coding errors. According to T-Head SPEC ([1]), the "vsetvl" in the XTheadVector extension consists of SEW, LMUL and EDIV, which is quite different from the "V" extension. Therefore, we cannot simply reuse the processing of vsetvl in V extension. We have set up tens of thousands of test cases to ensure that no further encoding issues are there, and and execute all compiled test files on real HW and make sure they don't trigger SIGILL. Ref: [1] https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.3.0/xthead-2023-11-10-2.3.0.pdf Co-developed-by: Lifang Xia <lifang_xia@linux.alibaba.com> Co-developed-by: Christoph Müllner <christoph.muellner@vrull.eu> gas/ChangeLog: * config/tc-riscv.c (validate_riscv_insn): Add handling for th.vsetvli. (my_getThVsetvliExpression): New function. (riscv_ip): Likewise. * testsuite/gas/riscv/x-thead-vector.d: Likewise. * testsuite/gas/riscv/x-thead-vector.s: Likewise. include/ChangeLog: * opcode/riscv.h (OP_MASK_XTHEADVLMUL): New macro. (OP_SH_XTHEADVLMUL): Likewise. (OP_MASK_XTHEADVSEW): Likewise. (OP_SH_XTHEADVSEW): Likewise. (OP_MASK_XTHEADVEDIV): Likewise. (OP_SH_XTHEADVEDIV): Likewise. (OP_MASK_XTHEADVTYPE_RES): Likewise. (OP_SH_XTHEADVTYPE_RES): Likewise. opcodes/ChangeLog: * riscv-dis.c (print_insn_args): Likewise. * riscv-opc.c: Likewise.
Diffstat (limited to 'gas')
-rw-r--r--gas/config/tc-riscv.c79
-rw-r--r--gas/testsuite/gas/riscv/x-thead-vector.d3
-rw-r--r--gas/testsuite/gas/riscv/x-thead-vector.s1
3 files changed, 82 insertions, 1 deletions
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 1d075fd..a416142 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -1467,6 +1467,15 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
size_t s;
switch (*++oparg)
{
+ case 'V':
+ switch (*++oparg)
+ {
+ case 'c': /* Vtypei for th.vsetvli. */
+ used_bits |= ENCODE_RVV_VC_IMM (-1U); break;
+ default:
+ goto unknown_validate_operand;
+ }
+ break;
case 'l': /* Integer immediate, literal. */
oparg += strcspn(oparg, ",") - 1;
break;
@@ -2423,6 +2432,59 @@ my_getVsetvliExpression (expressionS *ep, char *str)
}
}
+/* Parse string STR as a th.vsetvli operand. Store the expression in *EP.
+ On exit, EXPR_PARSE_END points to the first character after the
+ expression. */
+
+static void
+my_getThVsetvliExpression (expressionS *ep, char *str)
+{
+ unsigned int vsew_value = 0, vlen_value = 0, vediv_value = 0;
+ bfd_boolean vsew_found = FALSE, vlen_found = FALSE, vediv_found = FALSE;
+
+ if (arg_lookup (&str, riscv_vsew, ARRAY_SIZE (riscv_vsew),
+ &vsew_value))
+ {
+ if (*str == ',')
+ ++str;
+ if (vsew_found)
+ as_bad (_("multiple vsew constants"));
+ vsew_found = TRUE;
+ }
+
+ if (arg_lookup (&str, riscv_th_vlen, ARRAY_SIZE (riscv_th_vlen),
+ &vlen_value))
+ {
+ if (*str == ',')
+ ++str;
+ if (vlen_found)
+ as_bad (_("multiple vlen constants"));
+ vlen_found = TRUE;
+ }
+ if (arg_lookup (&str, riscv_th_vediv, ARRAY_SIZE (riscv_th_vediv),
+ &vediv_value))
+ {
+ if (*str == ',')
+ ++str;
+ if (vediv_found)
+ as_bad (_("multiple vediv constants"));
+ vediv_found = TRUE;
+ }
+
+ if (vlen_found || vediv_found || vsew_found)
+ {
+ ep->X_op = O_constant;
+ ep->X_add_number
+ = (vediv_value << 5) | (vsew_value << 2) | (vlen_value);
+ expr_parse_end = str;
+ }
+ else
+ {
+ my_getExpression (ep, str);
+ str = expr_parse_end;
+ }
+}
+
/* Detect and handle implicitly zero load-store offsets. For example,
"lw t0, (t1)" is shorthand for "lw t0, 0(t1)". Return true if such
an implicit offset was detected. */
@@ -3624,6 +3686,23 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
bool sign;
switch (*++oparg)
{
+ case 'V':
+ /* Vtypei for th.vsetvli. */
+ ++oparg;
+ if (*oparg != 'c')
+ goto unknown_riscv_ip_operand;
+
+ my_getThVsetvliExpression (imm_expr, asarg);
+ check_absolute_expr (ip, imm_expr, FALSE);
+ if (!VALID_RVV_VC_IMM (imm_expr->X_add_number))
+ as_bad (_("bad value for th.vsetvli immediate field, "
+ "value must be 0..2047"));
+ ip->insn_opcode
+ |= ENCODE_RVV_VC_IMM (imm_expr->X_add_number);
+ imm_expr->X_op = O_absent;
+ asarg = expr_parse_end;
+ continue;
+
case 'l': /* Integer immediate, literal. */
n = strcspn (++oparg, ",");
if (strncmp (oparg, asarg, n))
diff --git a/gas/testsuite/gas/riscv/x-thead-vector.d b/gas/testsuite/gas/riscv/x-thead-vector.d
index 441bd0e6..836150a 100644
--- a/gas/testsuite/gas/riscv/x-thead-vector.d
+++ b/gas/testsuite/gas/riscv/x-thead-vector.d
@@ -8,8 +8,9 @@ Disassembly of section .text:
0+000 <.text>:
[ ]+[0-9a-f]+:[ ]+80c5f557[ ]+th.vsetvl[ ]+a0,a1,a2
-[ ]+[0-9a-f]+:[ ]+0005f557[ ]+th.vsetvli[ ]+a0,a1,e8,m1,tu,mu
+[ ]+[0-9a-f]+:[ ]+0005f557[ ]+th.vsetvli[ ]+a0,a1,e8,m1,d1
[ ]+[0-9a-f]+:[ ]+7ff5f557[ ]+th.vsetvli[ ]+a0,a1,2047
+[ ]+[0-9a-f]+:[ ]+0455f557[ ]+th.vsetvli[ ]+a0,a1,e16,m2,d4
[ ]+[0-9a-f]+:[ ]+12050207[ ]+th.vlb.v[ ]+v4,\(a0\)
[ ]+[0-9a-f]+:[ ]+12050207[ ]+th.vlb.v[ ]+v4,\(a0\)
[ ]+[0-9a-f]+:[ ]+10050207[ ]+th.vlb.v[ ]+v4,\(a0\),v0.t
diff --git a/gas/testsuite/gas/riscv/x-thead-vector.s b/gas/testsuite/gas/riscv/x-thead-vector.s
index 413f4a8..92315b5 100644
--- a/gas/testsuite/gas/riscv/x-thead-vector.s
+++ b/gas/testsuite/gas/riscv/x-thead-vector.s
@@ -1,6 +1,7 @@
th.vsetvl a0, a1, a2
th.vsetvli a0, a1, 0
th.vsetvli a0, a1, 0x7ff
+ th.vsetvli a0, a1, e16,m2,d4
th.vlb.v v4, (a0)
th.vlb.v v4, 0(a0)