@@ -1717,6 +1717,14 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
1717
1717
goto unknown_validate_operand ;
1718
1718
}
1719
1719
break ;
1720
+ case 'a' : /* Vendor-specific (ARC-V) operands. */
1721
+ switch (* ++ oparg )
1722
+ {
1723
+ case 'v' : USE_BITS (OP_MASK_FUNCT3 , OP_SH_FUNCT3 ); break ;
1724
+ default :
1725
+ goto unknown_validate_operand ;
1726
+ }
1727
+ break ;
1720
1728
default :
1721
1729
goto unknown_validate_operand ;
1722
1730
}
@@ -2685,6 +2693,97 @@ my_getThVsetvliExpression (expressionS *ep, char *str)
2685
2693
}
2686
2694
}
2687
2695
2696
+ static struct arcv_udsp_insn_vtype_combination {
2697
+ const char * insn ;
2698
+ int sew ;
2699
+ int lmul ;
2700
+ } arcv_udsp_insn_vtype_combinations [] = {
2701
+ { "arcv.xvadd.vv" , 0x1 , 0 },
2702
+ { "arcv.xvsub.vv" , 0x1 , 0 },
2703
+ { "arcv.xvsadd.vv" , 0x1 , 0 },
2704
+ { "arcv.xvsadd.vv" , 0x2 , 0 },
2705
+ { "arcv.xvssub.vv" , 0x1 , 0 },
2706
+ { "arcv.xvssub.vv" , 0x2 , 0 },
2707
+ { "arcv.xvsll.vx" , 0x1 , 0 },
2708
+ { "arcv.xvsra.vx" , 0x1 , 0 },
2709
+ { "arcv.xvnclip.wx" , 0x1 , 0 },
2710
+ { "arcv.xvnclip.wx" , 0x1 , 0x7 },
2711
+ { "arcv.xvwmul.vv" , 0x1 , 0 },
2712
+ { "arcv.xvwmul.vv" , 0x1 , 0x7 },
2713
+ { "arcv.xvwsrdot.vv" , 0x1 , 0 },
2714
+ { "arcv.xvscmul.vv" , 0x1 , 0 },
2715
+ { "arcv.xvscjmul.vv" , 0x1 , 0 },
2716
+ { "arcv.xvwscmul.vv" , 0x1 , 0 },
2717
+ { "arcv.xvwscjmul.vv" , 0x1 , 0 },
2718
+ { "arcv.xvwscrdot.vv" , 0x1 , 0 },
2719
+ { "arcv.xvwscjrdot.vv" , 0x1 , 0 },
2720
+ { 0 },
2721
+ };
2722
+
2723
+ static bool
2724
+ arcv_udsp_opcode_supports_sew_lmul (char * insn , int sew , int lmul )
2725
+ {
2726
+ for (struct arcv_udsp_insn_vtype_combination * ivc =
2727
+ arcv_udsp_insn_vtype_combinations ;
2728
+ ivc -> insn ;
2729
+ ivc ++ )
2730
+ if (!strcmp (ivc -> insn , insn ) && ivc -> sew == sew && ivc -> lmul == lmul )
2731
+ return true;
2732
+
2733
+ as_bad (_ ("bad ARC-V UDSP instruction: "
2734
+ "combination of SEW and LMUL not supported for opcode" ));
2735
+
2736
+ return false;
2737
+ }
2738
+
2739
+ /* Parse string STR as a set of "vtype" operands of an ARC-V UDSP instruction
2740
+ (the format is "eXX, mf?X"). Check legality of operands depending on the
2741
+ instruction. Store the expression in *EP.
2742
+ On exit, EXPR_PARSE_END points to the first character after the
2743
+ expression. */
2744
+
2745
+ static void
2746
+ my_getArcvVtypeExpression (expressionS * ep , char * str , char * insn )
2747
+ {
2748
+ unsigned int sew = 0 , lmul = 0 ;
2749
+ bfd_boolean vsew_found = FALSE, vlmul_found = FALSE;
2750
+
2751
+ if (arg_lookup (& str , riscv_vsew , ARRAY_SIZE (riscv_vsew ),
2752
+ & sew ))
2753
+ {
2754
+ if (* str == ',' )
2755
+ ++ str ;
2756
+ vsew_found = TRUE;
2757
+ }
2758
+ else as_bad (_ ("bad ARC-V UDSP instruction: SEW not specified" ));
2759
+
2760
+ if (arg_lookup (& str , riscv_vlmul , ARRAY_SIZE (riscv_vlmul ), & lmul ))
2761
+ {
2762
+ if (* str == ',' )
2763
+ ++ str ;
2764
+ vlmul_found = TRUE;
2765
+ }
2766
+ else as_bad (_ ("bad ARC-V UDSP instruction: LMUL not specified" ));
2767
+
2768
+ if (!vsew_found || !vlmul_found
2769
+ || !arcv_udsp_opcode_supports_sew_lmul (insn , sew , lmul ))
2770
+ {
2771
+ my_getExpression (ep , str );
2772
+ str = expr_parse_end ;
2773
+ }
2774
+ else
2775
+ {
2776
+ gas_assert ((sew == 0x2 && lmul == 0 )
2777
+ || (sew == 0x1 && (lmul == 0 || lmul == 0x7 )));
2778
+
2779
+ ep -> X_op = O_constant ;
2780
+ ep -> X_add_number = (sew == 0x2 ? 0x4 :
2781
+ (lmul == 0 ? 0x2 : 0x1 ));
2782
+ expr_parse_end = str ;
2783
+ }
2784
+ }
2785
+
2786
+
2688
2787
/* Detect and handle implicitly zero load-store offsets. For example,
2689
2788
"lw t0, (t1)" is shorthand for "lw t0, 0(t1)". Return true if such
2690
2789
an implicit offset was detected. */
@@ -4070,6 +4169,21 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
4070
4169
#undef ENCODE_UIMM_BIT_FIELD
4071
4170
break ;
4072
4171
4172
+ case 'a' : /* Vendor-specific (ARC-V) operands. */
4173
+ switch (* ++ oparg )
4174
+ {
4175
+ case 'v' :
4176
+ my_getArcvVtypeExpression (imm_expr , asarg , insn -> name );
4177
+ asarg = expr_parse_end ;
4178
+ ip -> insn_opcode
4179
+ |= (imm_expr -> X_add_number & OP_MASK_FUNCT3 )
4180
+ << OP_SH_FUNCT3 ;
4181
+ continue ;
4182
+ default :
4183
+ goto unknown_riscv_ip_operand ;
4184
+ }
4185
+ break ;
4186
+
4073
4187
default :
4074
4188
goto unknown_riscv_ip_operand ;
4075
4189
}
0 commit comments