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;
}
}
+/* 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. */
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))
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
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)
#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
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];
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 != ',')
"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] =
{
/* 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 },