GNU Binutils with patches for OS216
修訂 | 6b1bf5e62fddaa3a503c5fd303f2c8e767393ab2 (tree) |
---|---|
時間 | 2016-08-23 17:41:03 |
作者 | Richard Sandiford <richard.sandiford@arm....> |
Commiter | Richard Sandiford |
[AArch64][SVE 22/32] Add qualifiers for merging and zeroing predication
This patch adds qualifiers to represent /z and /m suffixes on
predicate registers.
include/opcode/
* aarch64.h (AARCH64_OPND_QLF_P_Z): New aarch64_opnd_qualifier.
(AARCH64_OPND_QLF_P_M): Likewise.
opcodes/
* aarch64-opc.c (aarch64_opnd_qualifiers): Add entries for
AARCH64_OPND_QLF_P_[ZM].
(aarch64_print_operand): Print /z and /m where appropriate.
gas/
* config/tc-aarch64.c (vector_el_type): Add NT_zero and NT_merge.
(parse_vector_type_for_operand): Assert that the skipped character
is a '.'.
(parse_predication_for_operand): New function.
(parse_typed_reg): Parse /z and /m suffixes for predicate registers.
(vectype_to_qualifier): Handle NT_zero and NT_merge.
Change-Id: I0e1463f446feeb2051ee9e4c832bbb31318ff05d
@@ -83,7 +83,9 @@ enum vector_el_type | ||
83 | 83 | NT_h, |
84 | 84 | NT_s, |
85 | 85 | NT_d, |
86 | - NT_q | |
86 | + NT_q, | |
87 | + NT_zero, | |
88 | + NT_merge | |
87 | 89 | }; |
88 | 90 | |
89 | 91 | /* Bits for DEFINED field in vector_type_el. */ |
@@ -780,6 +782,7 @@ parse_vector_type_for_operand (aarch64_reg_type reg_type, | ||
780 | 782 | enum vector_el_type type; |
781 | 783 | |
782 | 784 | /* skip '.' */ |
785 | + gas_assert (*ptr == '.'); | |
783 | 786 | ptr++; |
784 | 787 | |
785 | 788 | if (reg_type == REG_TYPE_ZN || reg_type == REG_TYPE_PN || !ISDIGIT (*ptr)) |
@@ -846,6 +849,38 @@ elt_size: | ||
846 | 849 | return TRUE; |
847 | 850 | } |
848 | 851 | |
852 | +/* *STR contains an SVE zero/merge predication suffix. Parse it into | |
853 | + *PARSED_TYPE and point *STR at the end of the suffix. */ | |
854 | + | |
855 | +static bfd_boolean | |
856 | +parse_predication_for_operand (struct vector_type_el *parsed_type, char **str) | |
857 | +{ | |
858 | + char *ptr = *str; | |
859 | + | |
860 | + /* Skip '/'. */ | |
861 | + gas_assert (*ptr == '/'); | |
862 | + ptr++; | |
863 | + switch (TOLOWER (*ptr)) | |
864 | + { | |
865 | + case 'z': | |
866 | + parsed_type->type = NT_zero; | |
867 | + break; | |
868 | + case 'm': | |
869 | + parsed_type->type = NT_merge; | |
870 | + break; | |
871 | + default: | |
872 | + if (*ptr != '\0' && *ptr != ',') | |
873 | + first_error_fmt (_("unexpected character `%c' in predication type"), | |
874 | + *ptr); | |
875 | + else | |
876 | + first_error (_("missing predication type")); | |
877 | + return FALSE; | |
878 | + } | |
879 | + parsed_type->width = 0; | |
880 | + *str = ptr + 1; | |
881 | + return TRUE; | |
882 | +} | |
883 | + | |
849 | 884 | /* Parse a register of the type TYPE. |
850 | 885 | |
851 | 886 | Return PARSE_FAIL if the string pointed by *CCP is not a valid register |
@@ -890,10 +925,18 @@ parse_typed_reg (char **ccp, aarch64_reg_type type, aarch64_reg_type *rtype, | ||
890 | 925 | type = reg->type; |
891 | 926 | |
892 | 927 | if ((type == REG_TYPE_VN || type == REG_TYPE_ZN || type == REG_TYPE_PN) |
893 | - && *str == '.') | |
928 | + && (*str == '.' || (type == REG_TYPE_PN && *str == '/'))) | |
894 | 929 | { |
895 | - if (!parse_vector_type_for_operand (type, &parsetype, &str)) | |
896 | - return PARSE_FAIL; | |
930 | + if (*str == '.') | |
931 | + { | |
932 | + if (!parse_vector_type_for_operand (type, &parsetype, &str)) | |
933 | + return PARSE_FAIL; | |
934 | + } | |
935 | + else | |
936 | + { | |
937 | + if (!parse_predication_for_operand (&parsetype, &str)) | |
938 | + return PARSE_FAIL; | |
939 | + } | |
897 | 940 | |
898 | 941 | /* Register if of the form Vn.[bhsdq]. */ |
899 | 942 | is_typed_vecreg = TRUE; |
@@ -4706,6 +4749,11 @@ vectype_to_qualifier (const struct vector_type_el *vectype) | ||
4706 | 4749 | if (!vectype->defined || vectype->type == NT_invtype) |
4707 | 4750 | goto vectype_conversion_fail; |
4708 | 4751 | |
4752 | + if (vectype->type == NT_zero) | |
4753 | + return AARCH64_OPND_QLF_P_Z; | |
4754 | + if (vectype->type == NT_merge) | |
4755 | + return AARCH64_OPND_QLF_P_M; | |
4756 | + | |
4709 | 4757 | gas_assert (vectype->type >= NT_b && vectype->type <= NT_q); |
4710 | 4758 | |
4711 | 4759 | if (vectype->defined & (NTA_HASINDEX | NTA_HASVARWIDTH)) |
@@ -315,6 +315,9 @@ enum aarch64_opnd_qualifier | ||
315 | 315 | AARCH64_OPND_QLF_V_2D, |
316 | 316 | AARCH64_OPND_QLF_V_1Q, |
317 | 317 | |
318 | + AARCH64_OPND_QLF_P_Z, | |
319 | + AARCH64_OPND_QLF_P_M, | |
320 | + | |
318 | 321 | /* Constraint on value. */ |
319 | 322 | AARCH64_OPND_QLF_imm_0_7, |
320 | 323 | AARCH64_OPND_QLF_imm_0_15, |
@@ -603,6 +603,9 @@ struct operand_qualifier_data aarch64_opnd_qualifiers[] = | ||
603 | 603 | {8, 2, 0x7, "2d", OQK_OPD_VARIANT}, |
604 | 604 | {16, 1, 0x8, "1q", OQK_OPD_VARIANT}, |
605 | 605 | |
606 | + {0, 0, 0, "z", OQK_OPD_VARIANT}, | |
607 | + {0, 0, 0, "m", OQK_OPD_VARIANT}, | |
608 | + | |
606 | 609 | /* Qualifiers constraining the value range. |
607 | 610 | First 3 fields: |
608 | 611 | Lower bound, higher bound, unused. */ |
@@ -2623,6 +2626,10 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc, | ||
2623 | 2626 | case AARCH64_OPND_SVE_Pt: |
2624 | 2627 | if (opnd->qualifier == AARCH64_OPND_QLF_NIL) |
2625 | 2628 | snprintf (buf, size, "p%d", opnd->reg.regno); |
2629 | + else if (opnd->qualifier == AARCH64_OPND_QLF_P_Z | |
2630 | + || opnd->qualifier == AARCH64_OPND_QLF_P_M) | |
2631 | + snprintf (buf, size, "p%d/%s", opnd->reg.regno, | |
2632 | + aarch64_get_qualifier_name (opnd->qualifier)); | |
2626 | 2633 | else |
2627 | 2634 | snprintf (buf, size, "p%d.%s", opnd->reg.regno, |
2628 | 2635 | aarch64_get_qualifier_name (opnd->qualifier)); |