mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-19 22:44:16 +08:00
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.
This commit is contained in:
parent
53c4e37bb1
commit
6a95962e25
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -328,6 +328,15 @@ static inline unsigned int riscv_insn_length (insn_t insn)
|
||||
#define OP_MASK_VWD 0x1
|
||||
#define OP_SH_VWD 26
|
||||
|
||||
#define OP_MASK_XTHEADVLMUL 0x3
|
||||
#define OP_SH_XTHEADVLMUL 0
|
||||
#define OP_MASK_XTHEADVSEW 0x7
|
||||
#define OP_SH_XTHEADVSEW 2
|
||||
#define OP_MASK_XTHEADVEDIV 0x3
|
||||
#define OP_SH_XTHEADVEDIV 5
|
||||
#define OP_MASK_XTHEADVTYPE_RES 0xf
|
||||
#define OP_SH_XTHEADVTYPE_RES 7
|
||||
|
||||
#define NVECR 32
|
||||
#define NVECM 1
|
||||
|
||||
@ -595,6 +604,8 @@ extern const char * const riscv_vsew[8];
|
||||
extern const char * const riscv_vlmul[8];
|
||||
extern const char * const riscv_vta[2];
|
||||
extern const char * const riscv_vma[2];
|
||||
extern const char * const riscv_th_vlen[4];
|
||||
extern const char * const riscv_th_vediv[4];
|
||||
extern const char * const riscv_fli_symval[32];
|
||||
extern const float riscv_fli_numval[32];
|
||||
|
||||
|
@ -653,6 +653,28 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
|
||||
bool sign;
|
||||
switch (*++oparg)
|
||||
{
|
||||
case 'V':
|
||||
++oparg;
|
||||
if (*oparg != 'c')
|
||||
goto undefined_modifier;
|
||||
|
||||
int imm = (*oparg == 'b') ? EXTRACT_RVV_VB_IMM (l)
|
||||
: EXTRACT_RVV_VC_IMM (l);
|
||||
unsigned int imm_vediv = EXTRACT_OPERAND (XTHEADVEDIV, imm);
|
||||
unsigned int imm_vlmul = EXTRACT_OPERAND (XTHEADVLMUL, imm);
|
||||
unsigned int imm_vsew = EXTRACT_OPERAND (XTHEADVSEW, imm);
|
||||
unsigned int imm_vtype_res
|
||||
= EXTRACT_OPERAND (XTHEADVTYPE_RES, imm);
|
||||
if (imm_vsew < ARRAY_SIZE (riscv_vsew)
|
||||
&& imm_vlmul < ARRAY_SIZE (riscv_th_vlen)
|
||||
&& imm_vediv < ARRAY_SIZE (riscv_th_vediv)
|
||||
&& ! imm_vtype_res)
|
||||
print (info->stream, dis_style_text, "%s,%s,%s",
|
||||
riscv_vsew[imm_vsew], riscv_th_vlen[imm_vlmul],
|
||||
riscv_th_vediv[imm_vediv]);
|
||||
else
|
||||
print (info->stream, dis_style_immediate, "%d", imm);
|
||||
break;
|
||||
case 'l': /* Integer immediate, literal. */
|
||||
oparg++;
|
||||
while (*oparg && *oparg != ',')
|
||||
|
@ -110,6 +110,18 @@ const char * const riscv_vma[2] =
|
||||
"mu", "ma"
|
||||
};
|
||||
|
||||
/* XTheadVector, List of vsetvli vlmul constants. */
|
||||
const char * const riscv_th_vlen[4] =
|
||||
{
|
||||
"m1", "m2", "m4", "m8"
|
||||
};
|
||||
|
||||
/* XTheadVector, List of vsetvli vediv constants. */
|
||||
const char * const riscv_th_vediv[4] =
|
||||
{
|
||||
"d1", "d2", "d4", "d8"
|
||||
};
|
||||
|
||||
/* The FLI.[HSDQ] symbolic constants (NULL for numeric constant). */
|
||||
const char * const riscv_fli_symval[32] =
|
||||
{
|
||||
@ -2236,7 +2248,7 @@ const struct riscv_opcode riscv_opcodes[] =
|
||||
|
||||
/* Vendor-specific (T-Head) XTheadVector instructions. */
|
||||
{"th.vsetvl", 0, INSN_CLASS_XTHEADVECTOR, "d,s,t", MATCH_VSETVL, MASK_VSETVL, match_opcode, 0},
|
||||
{"th.vsetvli", 0, INSN_CLASS_XTHEADVECTOR, "d,s,Vc", MATCH_VSETVLI, MASK_VSETVLI, match_opcode, 0},
|
||||
{"th.vsetvli", 0, INSN_CLASS_XTHEADVECTOR, "d,s,XtVc", MATCH_VSETVLI, MASK_VSETVLI, match_opcode, 0},
|
||||
{"th.vlb.v", 0, INSN_CLASS_XTHEADVECTOR, "Vd,0(s)Vm", MATCH_TH_VLBV, MASK_TH_VLBV, match_opcode, INSN_DREF },
|
||||
{"th.vlh.v", 0, INSN_CLASS_XTHEADVECTOR, "Vd,0(s)Vm", MATCH_TH_VLHV, MASK_TH_VLHV, match_opcode, INSN_DREF },
|
||||
{"th.vlw.v", 0, INSN_CLASS_XTHEADVECTOR, "Vd,0(s)Vm", MATCH_TH_VLWV, MASK_TH_VLWV, match_opcode, INSN_DREF },
|
||||
|
Loading…
Reference in New Issue
Block a user