From a214c80612ee7be0c867ad95e7171c9dc817c507 Mon Sep 17 00:00:00 2001 From: Cutie Deng Date: Wed, 2 Jul 2025 17:48:48 +0800 Subject: [PATCH] Enable support in gas for the AArch64 instruction set on the ARMv9.2-A architecture. --- .../binutils-aarch64-support-armv9.2-a.patch | 166090 +++++++++++++++ SPECS/binutils.spec | 7 +- 2 files changed, 166096 insertions(+), 1 deletion(-) create mode 100644 SOURCES/binutils-aarch64-support-armv9.2-a.patch diff --git a/SOURCES/binutils-aarch64-support-armv9.2-a.patch b/SOURCES/binutils-aarch64-support-armv9.2-a.patch new file mode 100644 index 0000000..7a35d65 --- /dev/null +++ b/SOURCES/binutils-aarch64-support-armv9.2-a.patch @@ -0,0 +1,166090 @@ +diff --git a/bfd/archures.c b/bfd/archures.c +index 78658314b..69da9a4a5 100644 +--- a/bfd/archures.c ++++ b/bfd/archures.c +@@ -349,19 +349,6 @@ DESCRIPTION + .#define bfd_mach_arm_ep9312 11 + .#define bfd_mach_arm_iWMMXt 12 + .#define bfd_mach_arm_iWMMXt2 13 +-.#define bfd_mach_arm_5TEJ 14 +-.#define bfd_mach_arm_6 15 +-.#define bfd_mach_arm_6KZ 16 +-.#define bfd_mach_arm_6T2 17 +-.#define bfd_mach_arm_6K 18 +-.#define bfd_mach_arm_7 19 +-.#define bfd_mach_arm_6M 20 +-.#define bfd_mach_arm_6SM 21 +-.#define bfd_mach_arm_7EM 22 +-.#define bfd_mach_arm_8 23 +-.#define bfd_mach_arm_8R 24 +-.#define bfd_mach_arm_8M_BASE 25 +-.#define bfd_mach_arm_8M_MAIN 26 + . bfd_arch_nds32, {* Andes NDS32. *} + .#define bfd_mach_n1 1 + .#define bfd_mach_n1h 2 +@@ -539,6 +526,7 @@ DESCRIPTION + .#define bfd_mach_tilegx32 2 + . bfd_arch_aarch64, {* AArch64. *} + .#define bfd_mach_aarch64 0 ++.#define bfd_mach_aarch64_8R 1 + .#define bfd_mach_aarch64_ilp32 32 + . bfd_arch_nios2, {* Nios II. *} + .#define bfd_mach_nios2 0 +diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h +index 750a6d544..39df7807b 100644 +--- a/bfd/bfd-in2.h ++++ b/bfd/bfd-in2.h +@@ -2213,19 +2213,6 @@ enum bfd_architecture + #define bfd_mach_arm_ep9312 11 + #define bfd_mach_arm_iWMMXt 12 + #define bfd_mach_arm_iWMMXt2 13 +-#define bfd_mach_arm_5TEJ 14 +-#define bfd_mach_arm_6 15 +-#define bfd_mach_arm_6KZ 16 +-#define bfd_mach_arm_6T2 17 +-#define bfd_mach_arm_6K 18 +-#define bfd_mach_arm_7 19 +-#define bfd_mach_arm_6M 20 +-#define bfd_mach_arm_6SM 21 +-#define bfd_mach_arm_7EM 22 +-#define bfd_mach_arm_8 23 +-#define bfd_mach_arm_8R 24 +-#define bfd_mach_arm_8M_BASE 25 +-#define bfd_mach_arm_8M_MAIN 26 + bfd_arch_nds32, /* Andes NDS32. */ + #define bfd_mach_n1 1 + #define bfd_mach_n1h 2 +@@ -2403,6 +2390,7 @@ enum bfd_architecture + #define bfd_mach_tilegx32 2 + bfd_arch_aarch64, /* AArch64. */ + #define bfd_mach_aarch64 0 ++#define bfd_mach_aarch64_8R 1 + #define bfd_mach_aarch64_ilp32 32 + bfd_arch_nios2, /* Nios II. */ + #define bfd_mach_nios2 0 +diff --git a/bfd/cpu-aarch64.c b/bfd/cpu-aarch64.c +index 44cee6c98..79831d99c 100644 +--- a/bfd/cpu-aarch64.c ++++ b/bfd/cpu-aarch64.c +@@ -105,8 +105,12 @@ scan (const struct bfd_arch_info *info, const char *string) + "aarch64", PRINT, 4, DEFAULT, compatible, scan, \ + bfd_arch_default_fill, NEXT } + ++static const bfd_arch_info_type bfd_aarch64_arch_v8_r = ++ N (bfd_mach_aarch64_8R, "aarch64:armv8-r", 64, FALSE, NULL); ++ + static const bfd_arch_info_type bfd_aarch64_arch_ilp32 = +- N (bfd_mach_aarch64_ilp32, "aarch64:ilp32", 32, FALSE, NULL); ++ N (bfd_mach_aarch64_ilp32, "aarch64:ilp32", 32, FALSE, ++ &bfd_aarch64_arch_v8_r); + + const bfd_arch_info_type bfd_aarch64_arch = + N (0, "aarch64", 64, TRUE, &bfd_aarch64_arch_ilp32); +diff --git a/bfd/cpu-arm.c b/bfd/cpu-arm.c +index 4c4dfbe1d..151f27367 100644 +--- a/bfd/cpu-arm.c ++++ b/bfd/cpu-arm.c +@@ -129,33 +129,20 @@ scan (const struct bfd_arch_info *info, const char *string) + + static const bfd_arch_info_type arch_info_struct[] = + { +- N (bfd_mach_arm_2, "armv2", FALSE, & arch_info_struct[1]), +- N (bfd_mach_arm_2a, "armv2a", FALSE, & arch_info_struct[2]), +- N (bfd_mach_arm_3, "armv3", FALSE, & arch_info_struct[3]), +- N (bfd_mach_arm_3M, "armv3m", FALSE, & arch_info_struct[4]), +- N (bfd_mach_arm_4, "armv4", FALSE, & arch_info_struct[5]), +- N (bfd_mach_arm_4T, "armv4t", FALSE, & arch_info_struct[6]), +- N (bfd_mach_arm_5, "armv5", FALSE, & arch_info_struct[7]), +- N (bfd_mach_arm_5T, "armv5t", FALSE, & arch_info_struct[8]), +- N (bfd_mach_arm_5TE, "armv5te", FALSE, & arch_info_struct[9]), +- N (bfd_mach_arm_XScale, "xscale", FALSE, & arch_info_struct[10]), +- N (bfd_mach_arm_ep9312, "ep9312", FALSE, & arch_info_struct[11]), +- N (bfd_mach_arm_iWMMXt, "iwmmxt", FALSE, & arch_info_struct[12]), +- N (bfd_mach_arm_iWMMXt2, "iwmmxt2", FALSE, & arch_info_struct[13]), +- N (bfd_mach_arm_5TEJ, "armv5tej", FALSE, & arch_info_struct[14]), +- N (bfd_mach_arm_6, "armv6", FALSE, & arch_info_struct[15]), +- N (bfd_mach_arm_6KZ, "armv6kz", FALSE, & arch_info_struct[16]), +- N (bfd_mach_arm_6T2, "armv6t2", FALSE, & arch_info_struct[17]), +- N (bfd_mach_arm_6K, "armv6k", FALSE, & arch_info_struct[18]), +- N (bfd_mach_arm_7, "armv7", FALSE, & arch_info_struct[19]), +- N (bfd_mach_arm_6M, "armv6-m", FALSE, & arch_info_struct[20]), +- N (bfd_mach_arm_6SM, "armv6s-m", FALSE, & arch_info_struct[21]), +- N (bfd_mach_arm_7EM, "armv7e-m", FALSE, & arch_info_struct[22]), +- N (bfd_mach_arm_8, "armv8-a", FALSE, & arch_info_struct[23]), +- N (bfd_mach_arm_8R, "armv8-r", FALSE, & arch_info_struct[24]), +- N (bfd_mach_arm_8M_BASE, "armv8-m.base", FALSE, & arch_info_struct[25]), +- N (bfd_mach_arm_8M_MAIN, "armv8-m.main", FALSE, & arch_info_struct[26]), +- N (bfd_mach_arm_unknown, "arm_any", FALSE, NULL) ++ N (bfd_mach_arm_2, "armv2", FALSE, & arch_info_struct[1]), ++ N (bfd_mach_arm_2a, "armv2a", FALSE, & arch_info_struct[2]), ++ N (bfd_mach_arm_3, "armv3", FALSE, & arch_info_struct[3]), ++ N (bfd_mach_arm_3M, "armv3m", FALSE, & arch_info_struct[4]), ++ N (bfd_mach_arm_4, "armv4", FALSE, & arch_info_struct[5]), ++ N (bfd_mach_arm_4T, "armv4t", FALSE, & arch_info_struct[6]), ++ N (bfd_mach_arm_5, "armv5", FALSE, & arch_info_struct[7]), ++ N (bfd_mach_arm_5T, "armv5t", FALSE, & arch_info_struct[8]), ++ N (bfd_mach_arm_5TE, "armv5te", FALSE, & arch_info_struct[9]), ++ N (bfd_mach_arm_XScale, "xscale", FALSE, & arch_info_struct[10]), ++ N (bfd_mach_arm_ep9312, "ep9312", FALSE, & arch_info_struct[11]), ++ N (bfd_mach_arm_iWMMXt, "iwmmxt", FALSE, & arch_info_struct[12]), ++ N (bfd_mach_arm_iWMMXt2, "iwmmxt2", FALSE, & arch_info_struct[13]), ++ N (bfd_mach_arm_unknown, "arm_any", FALSE, NULL) + }; + + const bfd_arch_info_type bfd_arm_arch = +diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c +index c408dd561..0b250cea2 100644 +--- a/bfd/elf32-arm.c ++++ b/bfd/elf32-arm.c +@@ -12980,38 +12980,7 @@ bfd_arm_get_mach_from_attributes (bfd * abfd) + return bfd_mach_arm_5TE; + } + +- case TAG_CPU_ARCH_V5TEJ: +- return bfd_mach_arm_5TEJ; +- case TAG_CPU_ARCH_V6: +- return bfd_mach_arm_6; +- case TAG_CPU_ARCH_V6KZ: +- return bfd_mach_arm_6KZ; +- case TAG_CPU_ARCH_V6T2: +- return bfd_mach_arm_6T2; +- case TAG_CPU_ARCH_V6K: +- return bfd_mach_arm_6K; +- case TAG_CPU_ARCH_V7: +- return bfd_mach_arm_7; +- case TAG_CPU_ARCH_V6_M: +- return bfd_mach_arm_6M; +- case TAG_CPU_ARCH_V6S_M: +- return bfd_mach_arm_6SM; +- case TAG_CPU_ARCH_V7E_M: +- return bfd_mach_arm_7EM; +- case TAG_CPU_ARCH_V8: +- return bfd_mach_arm_8; +- case TAG_CPU_ARCH_V8R: +- return bfd_mach_arm_8R; +- case TAG_CPU_ARCH_V8M_BASE: +- return bfd_mach_arm_8M_BASE; +- case TAG_CPU_ARCH_V8M_MAIN: +- return bfd_mach_arm_8M_MAIN; +- + default: +- /* Force entry to be added for any new known Tag_CPU_arch value. */ +- BFD_ASSERT (arch > MAX_TAG_CPU_ARCH); +- +- /* Unknown Tag_CPU_arch value. */ + return bfd_mach_arm_unknown; + } + } +diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c +index 68dc02335..e4504321e 100644 +--- a/bfd/elfnn-aarch64.c ++++ b/bfd/elfnn-aarch64.c +@@ -3727,8 +3727,10 @@ _bfd_aarch64_resize_stubs (struct elf_aarch64_link_hash_table *htab) + if (!strstr (section->name, STUB_SUFFIX)) + continue; + ++ /* Add space for a branch. Add 8 bytes to keep section 8 byte aligned, ++ as long branch stubs contain a 64-bit address. */ + if (section->size) +- section->size += 4; ++ section->size += 8; + + /* Ensure all stub sections have a size which is a multiple of + 4096. This is important in order to ensure that the insertion +@@ -3740,9 +3742,7 @@ _bfd_aarch64_resize_stubs (struct elf_aarch64_link_hash_table *htab) + } + } + +- +-/* Construct an erratum 843419 workaround stub name. +- */ ++/* Construct an erratum 843419 workaround stub name. */ + + static char * + _bfd_aarch64_erratum_843419_stub_name (asection *input_section, +@@ -4284,8 +4284,11 @@ elfNN_aarch64_build_stubs (struct bfd_link_info *info) + return FALSE; + stub_sec->size = 0; + ++ /* Add a branch around the stub section, and a nop, to keep it 8 byte ++ aligned, as long branch stubs contain a 64-bit address. */ + bfd_putl32 (0x14000000 | (size >> 2), stub_sec->contents); +- stub_sec->size += 4; ++ bfd_putl32 (INSN_NOP, stub_sec->contents + 4); ++ stub_sec->size += 8; + } + + /* Build the stubs as directed by the stub hash table. */ +diff --git a/binutils/NEWS b/binutils/NEWS +index 8022ce77f..0231f5441 100644 +--- a/binutils/NEWS ++++ b/binutils/NEWS +@@ -22,6 +22,14 @@ + + * Add support for disassembling netronome Flow Processor (NFP) firmware files. + ++* The AArch64 port now supports showing disassembly notes which are emitted ++ when inconsistencies are found with the instruction that may result in the ++ instruction being invalid. These can be turned on with the option -M notes ++ to objdump. ++ ++* The AArch64 port now emits warnings when a combination of an instruction and ++ a named register could be invalid. ++ + Changes in 2.30: + + * Add --debug-dump=links option to readelf and --dwarf=links option to objdump +diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi +index 81b6564f8..bb869d133 100644 +--- a/binutils/doc/binutils.texi ++++ b/binutils/doc/binutils.texi +@@ -2399,6 +2399,11 @@ using the switch @option{--disassembler-options=force-thumb}. This can be + useful when attempting to disassemble thumb code produced by other + compilers. + ++For AArch64 targets this switch can be used to set whether instructions are ++disassembled as the most general instruction using the @option{-M no-aliases} ++option or whether instruction notes should be generated as comments in the ++disasssembly using @option{-M notes}. ++ + For the x86, some of the options duplicate functions of the @option{-m} + switch, but allow finer grained control. Multiple selections from the + following may be specified as a comma separated string. +diff --git a/gas/as.h b/gas/as.h +index 6261d156d..55d781884 100644 +--- a/gas/as.h ++++ b/gas/as.h +@@ -470,6 +470,7 @@ void as_bad_value_out_of_range (const char *, offsetT, offsetT, offsetT, + void print_version_id (void); + char * app_push (void); + char * atof_ieee (char *, int, LITTLENUM_TYPE *); ++char * atof_ieee_detail (char *, int, int, LITTLENUM_TYPE *, FLONUM_TYPE *); + const char * ieee_md_atof (int, char *, int *, bfd_boolean); + const char * vax_md_atof (int, char *, int *); + char * input_scrub_include_file (const char *, char *); +diff --git a/gas/config/atof-ieee.c b/gas/config/atof-ieee.c +index 8d8c95236..41ac17fec 100644 +--- a/gas/config/atof-ieee.c ++++ b/gas/config/atof-ieee.c +@@ -26,6 +26,7 @@ extern FLONUM_TYPE generic_floating_point_number; + /* Precision in LittleNums. */ + /* Don't count the gap in the m68k extended precision format. */ + #define MAX_PRECISION 5 ++#define H_PRECISION 1 + #define F_PRECISION 2 + #define D_PRECISION 4 + #define X_PRECISION 5 +@@ -145,29 +146,30 @@ make_invalid_floating_point_number (LITTLENUM_TYPE *words) + words[4] = (LITTLENUM_TYPE) -1; + words[5] = (LITTLENUM_TYPE) -1; + } +- +-/* Warning: This returns 16-bit LITTLENUMs. It is up to the caller to +- figure out any alignment problems and to conspire for the +- bytes/word to be emitted in the right order. Bigendians beware! */ + +-/* Note that atof-ieee always has X and P precisions enabled. it is up +- to md_atof to filter them out if the target machine does not support +- them. */ ++/* Build a floating point constant at str into a IEEE floating ++ point number. This function does the same thing as atof_ieee ++ however it allows more control over the exact format, i.e. ++ explicitly specifying the precision and number of exponent bits ++ instead of relying on this infomation being deduced from a given type. + +-/* Returns pointer past text consumed. */ ++ If generic_float_info is not NULL then it will be set to contain generic ++ infomation about the parsed floating point number. + ++ Returns pointer past text consumed. */ + char * +-atof_ieee (char *str, /* Text to convert to binary. */ +- int what_kind, /* 'd', 'f', 'x', 'p'. */ +- LITTLENUM_TYPE *words) /* Build the binary here. */ ++atof_ieee_detail (char * str, ++ int precision, ++ int exponent_bits, ++ LITTLENUM_TYPE * words, ++ FLONUM_TYPE * generic_float_info) + { + /* Extra bits for zeroed low-order bits. + The 1st MAX_PRECISION are zeroed, the last contain flonum bits. */ + static LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD]; + char *return_value; ++ + /* Number of 16-bit words in the format. */ +- int precision; +- long exponent_bits; + FLONUM_TYPE save_gen_flonum; + + /* We have to save the generic_floating_point_number because it +@@ -188,8 +190,53 @@ atof_ieee (char *str, /* Text to convert to binary. */ + + memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION); + ++ generic_floating_point_number.high ++ = generic_floating_point_number.low + precision - 1 + GUARD; ++ ++ if (atof_generic (&return_value, ".", EXP_CHARS, ++ &generic_floating_point_number)) ++ { ++ make_invalid_floating_point_number (words); ++ return NULL; ++ } ++ ++ if (generic_float_info) ++ *generic_float_info = generic_floating_point_number; ++ ++ gen_to_words (words, precision, exponent_bits); ++ ++ /* Restore the generic_floating_point_number's storage alloc (and ++ everything else). */ ++ generic_floating_point_number = save_gen_flonum; ++ ++ return return_value; ++} ++ ++/* Warning: This returns 16-bit LITTLENUMs. It is up to the caller to ++ figure out any alignment problems and to conspire for the ++ bytes/word to be emitted in the right order. Bigendians beware! */ ++ ++/* Note that atof-ieee always has X and P precisions enabled. it is up ++ to md_atof to filter them out if the target machine does not support ++ them. */ ++ ++/* Returns pointer past text consumed. */ ++char * ++atof_ieee (char *str, /* Text to convert to binary. */ ++ int what_kind, /* 'd', 'f', 'x', 'p'. */ ++ LITTLENUM_TYPE *words) /* Build the binary here. */ ++{ ++ int precision; ++ long exponent_bits; ++ + switch (what_kind) + { ++ case 'h': ++ case 'H': ++ precision = H_PRECISION; ++ exponent_bits = 5; ++ break; ++ + case 'f': + case 'F': + case 's': +@@ -225,22 +272,7 @@ atof_ieee (char *str, /* Text to convert to binary. */ + return (NULL); + } + +- generic_floating_point_number.high +- = generic_floating_point_number.low + precision - 1 + GUARD; +- +- if (atof_generic (&return_value, ".", EXP_CHARS, +- &generic_floating_point_number)) +- { +- make_invalid_floating_point_number (words); +- return NULL; +- } +- gen_to_words (words, precision, exponent_bits); +- +- /* Restore the generic_floating_point_number's storage alloc (and +- everything else). */ +- generic_floating_point_number = save_gen_flonum; +- +- return return_value; ++ return atof_ieee_detail (str, precision, exponent_bits, words, NULL); + } + + /* Turn generic_floating_point_number into a real float/double/extended. */ +@@ -283,8 +315,13 @@ gen_to_words (LITTLENUM_TYPE *words, int precision, long exponent_bits) + if (generic_floating_point_number.sign == 0) + { + if (TC_LARGEST_EXPONENT_IS_NORMAL (precision)) +- as_warn (_("NaNs are not supported by this target\n")); +- if (precision == F_PRECISION) ++ as_warn (_("NaNs are not supported by this target")); ++ ++ if (precision == H_PRECISION) ++ { ++ words[0] = 0x7fff; ++ } ++ else if (precision == F_PRECISION) + { + words[0] = 0x7fff; + words[1] = 0xffff; +@@ -322,10 +359,14 @@ gen_to_words (LITTLENUM_TYPE *words, int precision, long exponent_bits) + else if (generic_floating_point_number.sign == 'P') + { + if (TC_LARGEST_EXPONENT_IS_NORMAL (precision)) +- as_warn (_("Infinities are not supported by this target\n")); ++ as_warn (_("Infinities are not supported by this target")); + + /* +INF: Do the right thing. */ +- if (precision == F_PRECISION) ++ if (precision == H_PRECISION) ++ { ++ words[0] = 0x7c00; ++ } ++ else if (precision == F_PRECISION) + { + words[0] = 0x7f80; + words[1] = 0; +@@ -363,10 +404,14 @@ gen_to_words (LITTLENUM_TYPE *words, int precision, long exponent_bits) + else if (generic_floating_point_number.sign == 'N') + { + if (TC_LARGEST_EXPONENT_IS_NORMAL (precision)) +- as_warn (_("Infinities are not supported by this target\n")); ++ as_warn (_("Infinities are not supported by this target")); + + /* Negative INF. */ +- if (precision == F_PRECISION) ++ if (precision == H_PRECISION) ++ { ++ words[0] = 0xfc00; ++ } ++ else if (precision == F_PRECISION) + { + words[0] = 0xff80; + words[1] = 0x0; +@@ -723,6 +768,11 @@ ieee_md_atof (int type, + { + switch (type) + { ++ case 'H': ++ case 'h': ++ prec = H_PRECISION; ++ break; ++ + case 'f': + case 'F': + case 's': +diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c +index e0e33f7da..0ac618d8a 100644 +--- a/gas/config/tc-aarch64.c ++++ b/gas/config/tc-aarch64.c +@@ -55,6 +55,9 @@ static const aarch64_feature_set *march_cpu_opt = NULL; + /* Constants for known architecture features. */ + static const aarch64_feature_set cpu_default = CPU_DEFAULT; + ++/* Currently active instruction sequence. */ ++static aarch64_instr_sequence *insn_sequence = NULL; ++ + #ifdef OBJ_ELF + /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */ + static symbolS *GOT_symbol; +@@ -439,6 +442,7 @@ get_reg_expected_msg (aarch64_reg_type reg_type) + + /* Some well known registers that we refer to directly elsewhere. */ + #define REG_SP 31 ++#define REG_ZR 31 + + /* Instructions take 4 bytes in the object file. */ + #define INSN_SIZE 4 +@@ -521,7 +525,7 @@ const char EXP_CHARS[] = "eE"; + /* As in 0f12.456 */ + /* or 0d1.2345e12 */ + +-const char FLT_CHARS[] = "rRsSfFdDxXeEpP"; ++const char FLT_CHARS[] = "rRsSfFdDxXeEpPhH"; + + /* Prefix character that indicates the start of an immediate value. */ + #define is_immediate_prefix(C) ((C) == '#') +@@ -627,6 +631,54 @@ my_get_expression (expressionS * ep, char **str, int prefix_mode, + const char * + md_atof (int type, char *litP, int *sizeP) + { ++ /* If this is a bfloat16 type, then parse it slightly differently - ++ as it does not follow the IEEE standard exactly. */ ++ if (type == 'b') ++ { ++ char * t; ++ LITTLENUM_TYPE words[MAX_LITTLENUMS]; ++ FLONUM_TYPE generic_float; ++ ++ t = atof_ieee_detail (input_line_pointer, 1, 8, words, &generic_float); ++ ++ if (t) ++ input_line_pointer = t; ++ else ++ return _("invalid floating point number"); ++ ++ switch (generic_float.sign) ++ { ++ /* Is +Inf. */ ++ case 'P': ++ words[0] = 0x7f80; ++ break; ++ ++ /* Is -Inf. */ ++ case 'N': ++ words[0] = 0xff80; ++ break; ++ ++ /* Is NaN. */ ++ /* bfloat16 has two types of NaN - quiet and signalling. ++ Quiet NaN has bit[6] == 1 && faction != 0, whereas ++ signalling Nan's have bit[0] == 0 && fraction != 0. ++ Chose this specific encoding as it is the same form ++ as used by other IEEE 754 encodings in GAS. */ ++ case 0: ++ words[0] = 0x7fff; ++ break; ++ ++ default: ++ break; ++ } ++ ++ *sizeP = 2; ++ ++ md_number_to_chars (litP, (valueT) words[0], sizeof (LITTLENUM_TYPE)); ++ ++ return NULL; ++ } ++ + return ieee_md_atof (type, litP, sizeP, target_big_endian); + } + +@@ -2089,6 +2141,8 @@ const pseudo_typeS md_pseudo_table[] = { + {"dword", s_aarch64_elf_cons, 8}, + {"variant_pcs", s_variant_pcs, 0}, + #endif ++ {"float16", float_cons, 'h'}, ++ {"bfloat16", float_cons, 'b'}, + {0, 0, 0} + }; + +@@ -3339,7 +3393,6 @@ parse_shifter_operand_reloc (char **str, aarch64_opnd_info *operand, + [base,Wm,(S|U)XTW {#imm}] + Pre-indexed + [base,#imm]! +- [base]! // in ld/stgv + Post-indexed + [base],#imm + [base],Xm // in SIMD ld/st structure +@@ -3352,6 +3405,7 @@ parse_shifter_operand_reloc (char **str, aarch64_opnd_info *operand, + [base,Zm.D,(S|U)XTW {#imm}] // ignores top 32 bits of Zm.D elements + [Zn.S,#imm] + [Zn.D,#imm] ++ [Zn.S{, Xm}] + [Zn.S,Zm.S{,LSL #imm}] // in ADR + [Zn.D,Zm.D{,LSL #imm}] // in ADR + [Zn.D,Zm.D,(S|U)XTW {#imm}] // in ADR +@@ -3517,6 +3571,7 @@ parse_address_main (char **str, aarch64_opnd_info *operand, + return FALSE; + } + /* We only accept: ++ [base,Xm] # For vector plus scalar SVE2 indexing. + [base,Xm{,LSL #imm}] + [base,Xm,SXTX {#imm}] + [base,Wm,(S|U)XTW {#imm}] */ +@@ -3530,7 +3585,10 @@ parse_address_main (char **str, aarch64_opnd_info *operand, + return FALSE; + } + if (aarch64_get_qualifier_esize (*base_qualifier) +- != aarch64_get_qualifier_esize (*offset_qualifier)) ++ != aarch64_get_qualifier_esize (*offset_qualifier) ++ && (operand->type != AARCH64_OPND_SVE_ADDR_ZX ++ || *base_qualifier != AARCH64_OPND_QLF_S_S ++ || *offset_qualifier != AARCH64_OPND_QLF_X)) + { + set_syntax_error (_("offset has different size from base")); + return FALSE; +@@ -3648,19 +3706,30 @@ parse_address_main (char **str, aarch64_opnd_info *operand, + } + + /* If at this point neither .preind nor .postind is set, we have a +- bare [Rn]{!}; reject [Rn]! except for ld/stgv but accept [Rn] +- as a shorthand for [Rn,#0]. */ ++ bare [Rn]{!}; reject [Rn]! accept [Rn] as a shorthand for [Rn,#0]. ++ For SVE2 vector plus scalar offsets, allow [Zn.] as shorthand for ++ [Zn., xzr]. */ + if (operand->addr.preind == 0 && operand->addr.postind == 0) + { +- if (operand->type != AARCH64_OPND_ADDR_SIMPLE_2 && operand->addr.writeback) ++ if (operand->addr.writeback) + { + /* Reject [Rn]! */ + set_syntax_error (_("missing offset in the pre-indexed address")); + return FALSE; + } ++ + operand->addr.preind = 1; +- inst.reloc.exp.X_op = O_constant; +- inst.reloc.exp.X_add_number = 0; ++ if (operand->type == AARCH64_OPND_SVE_ADDR_ZX) ++ { ++ operand->addr.offset.is_reg = 1; ++ operand->addr.offset.regno = REG_ZR; ++ *offset_qualifier = AARCH64_OPND_QLF_X; ++ } ++ else ++ { ++ inst.reloc.exp.X_op = O_constant; ++ inst.reloc.exp.X_add_number = 0; ++ } + } + + *str = p; +@@ -3690,6 +3759,22 @@ parse_sve_address (char **str, aarch64_opnd_info *operand, + SHIFTED_MUL_VL); + } + ++/* Parse a register X0-X30. The register must be 64-bit and register 31 ++ is unallocated. */ ++static bfd_boolean ++parse_x0_to_x30 (char **str, aarch64_opnd_info *operand) ++{ ++ const reg_entry *reg = parse_reg (str); ++ if (!reg || !aarch64_check_reg_type (reg, REG_TYPE_R_64)) ++ { ++ set_syntax_error (_(get_reg_expected_msg (REG_TYPE_R_64))); ++ return FALSE; ++ } ++ operand->reg.regno = reg->number; ++ operand->qualifier = AARCH64_OPND_QLF_X; ++ return TRUE; ++} ++ + /* Parse an operand for a MOVZ, MOVN or MOVK instruction. + Return TRUE on success; otherwise return FALSE. */ + static bfd_boolean +@@ -3884,7 +3969,7 @@ parse_barrier_psb (char **str, + if (!o) + { + set_fatal_syntax_error +- ( _("unknown or missing option to PSB")); ++ ( _("unknown or missing option to PSB/TSB")); + return PARSE_FAIL; + } + +@@ -3892,7 +3977,7 @@ parse_barrier_psb (char **str, + { + /* PSB only accepts option name 'CSYNC'. */ + set_syntax_error +- (_("the specified option is not accepted for PSB")); ++ (_("the specified option is not accepted for PSB/TSB")); + return PARSE_FAIL; + } + +@@ -3901,6 +3986,29 @@ parse_barrier_psb (char **str, + return 0; + } + ++/* Parse an operand for CSR (CSRE instruction). */ ++ ++static int ++parse_csr_operand (char **str) ++{ ++ char *p, *q; ++ ++ p = q = *str; ++ while (ISALPHA (*q)) ++ q++; ++ ++ /* Instruction has only one operand PDEC which encodes Rt field of the ++ operation to 0b11111. */ ++ if (strcasecmp(p, "pdec")) ++ { ++ set_syntax_error (_("CSR instruction accepts only PDEC")); ++ return PARSE_FAIL; ++ } ++ ++ *str = q; ++ return 0; ++} ++ + /* Parse an operand for BTI. Set *HINT_OPT to the hint-option record + return 0 if successful. Otherwise return PARSE_FAIL. */ + +@@ -3954,7 +4062,8 @@ parse_bti_operand (char **str, + + static int + parse_sys_reg (char **str, struct hash_control *sys_regs, +- int imple_defined_p, int pstatefield_p) ++ int imple_defined_p, int pstatefield_p, ++ uint32_t* flags) + { + char *p, *q; + char buf[32]; +@@ -3985,6 +4094,8 @@ parse_sys_reg (char **str, struct hash_control *sys_regs, + if (op0 > 3 || op1 > 7 || cn > 15 || cm > 15 || op2 > 7) + return PARSE_FAIL; + value = (op0 << 14) | (op1 << 11) | (cn << 7) | (cm << 3) | op2; ++ if (flags) ++ *flags = 0; + } + } + else +@@ -3999,6 +4110,8 @@ parse_sys_reg (char **str, struct hash_control *sys_regs, + as_warn (_("system register name '%s' is deprecated and may be " + "removed in a future release"), buf); + value = o->value; ++ if (flags) ++ *flags = o->flags; + } + + *str = q; +@@ -4214,6 +4327,8 @@ const char* operand_mismatch_kind_names[] = + { + "AARCH64_OPDE_NIL", + "AARCH64_OPDE_RECOVERABLE", ++ "AARCH64_OPDE_A_SHOULD_FOLLOW_B", ++ "AARCH64_OPDE_EXPECTED_A_AFTER_B", + "AARCH64_OPDE_SYNTAX_ERROR", + "AARCH64_OPDE_FATAL_SYNTAX_ERROR", + "AARCH64_OPDE_INVALID_VARIANT", +@@ -4235,7 +4350,10 @@ operand_error_higher_severity_p (enum aarch64_operand_error_kind lhs, + enum aarch64_operand_error_kind rhs) + { + gas_assert (AARCH64_OPDE_RECOVERABLE > AARCH64_OPDE_NIL); +- gas_assert (AARCH64_OPDE_SYNTAX_ERROR > AARCH64_OPDE_RECOVERABLE); ++ gas_assert (AARCH64_OPDE_A_SHOULD_FOLLOW_B > AARCH64_OPDE_RECOVERABLE); ++ gas_assert (AARCH64_OPDE_EXPECTED_A_AFTER_B > AARCH64_OPDE_RECOVERABLE); ++ gas_assert (AARCH64_OPDE_SYNTAX_ERROR > AARCH64_OPDE_A_SHOULD_FOLLOW_B); ++ gas_assert (AARCH64_OPDE_SYNTAX_ERROR > AARCH64_OPDE_EXPECTED_A_AFTER_B); + gas_assert (AARCH64_OPDE_FATAL_SYNTAX_ERROR > AARCH64_OPDE_SYNTAX_ERROR); + gas_assert (AARCH64_OPDE_INVALID_VARIANT > AARCH64_OPDE_FATAL_SYNTAX_ERROR); + gas_assert (AARCH64_OPDE_OUT_OF_RANGE > AARCH64_OPDE_INVALID_VARIANT); +@@ -4415,6 +4533,7 @@ record_operand_error (const aarch64_opcode *opcode, int idx, + info.index = idx; + info.kind = kind; + info.error = error; ++ info.non_fatal = FALSE; + record_operand_error_info (opcode, &info); + } + +@@ -4427,9 +4546,10 @@ record_operand_error_with_data (const aarch64_opcode *opcode, int idx, + info.index = idx; + info.kind = kind; + info.error = error; +- info.data[0] = extra_data[0]; +- info.data[1] = extra_data[1]; +- info.data[2] = extra_data[2]; ++ info.data[0].i = extra_data[0]; ++ info.data[1].i = extra_data[1]; ++ info.data[2].i = extra_data[2]; ++ info.non_fatal = FALSE; + record_operand_error_info (opcode, &info); + } + +@@ -4548,7 +4668,8 @@ print_operands (char *buf, const aarch64_opcode *opcode, + break; + + /* Generate the operand string in STR. */ +- aarch64_print_operand (str, sizeof (str), 0, opcode, opnds, i, NULL, NULL); ++ aarch64_print_operand (str, sizeof (str), 0, opcode, opnds, i, NULL, NULL, ++ NULL); + + /* Delimiter. */ + if (str[0] != '\0') +@@ -4594,12 +4715,27 @@ output_operand_error_record (const operand_error_record *record, char *str) + enum aarch64_opnd opd_code = (idx >= 0 ? opcode->operands[idx] + : AARCH64_OPND_NIL); + ++ typedef void (*handler_t)(const char *format, ...); ++ handler_t handler = detail->non_fatal ? as_warn : as_bad; ++ + switch (detail->kind) + { + case AARCH64_OPDE_NIL: + gas_assert (0); + break; + ++ case AARCH64_OPDE_A_SHOULD_FOLLOW_B: ++ handler (_("this `%s' should have an immediately preceding `%s'" ++ " -- `%s'"), ++ detail->data[0].s, detail->data[1].s, str); ++ break; ++ ++ case AARCH64_OPDE_EXPECTED_A_AFTER_B: ++ handler (_("the preceding `%s' should be followed by `%s` rather" ++ " than `%s` -- `%s'"), ++ detail->data[1].s, detail->data[0].s, opcode->name, str); ++ break; ++ + case AARCH64_OPDE_SYNTAX_ERROR: + case AARCH64_OPDE_RECOVERABLE: + case AARCH64_OPDE_FATAL_SYNTAX_ERROR: +@@ -4609,21 +4745,21 @@ output_operand_error_record (const operand_error_record *record, char *str) + if (detail->error != NULL) + { + if (idx < 0) +- as_bad (_("%s -- `%s'"), detail->error, str); ++ handler (_("%s -- `%s'"), detail->error, str); + else +- as_bad (_("%s at operand %d -- `%s'"), +- detail->error, idx + 1, str); ++ handler (_("%s at operand %d -- `%s'"), ++ detail->error, idx + 1, str); + } + else + { + gas_assert (idx >= 0); +- as_bad (_("operand %d must be %s -- `%s'"), idx + 1, +- aarch64_get_operand_desc (opd_code), str); ++ handler (_("operand %d must be %s -- `%s'"), idx + 1, ++ aarch64_get_operand_desc (opd_code), str); + } + break; + + case AARCH64_OPDE_INVALID_VARIANT: +- as_bad (_("operand mismatch -- `%s'"), str); ++ handler (_("operand mismatch -- `%s'"), str); + if (verbose_error_p) + { + /* We will try to correct the erroneous instruction and also provide +@@ -4671,7 +4807,7 @@ output_operand_error_record (const operand_error_record *record, char *str) + && programmer_friendly_fixup (&inst); + gas_assert (result); + result = aarch64_opcode_encode (opcode, inst_base, &inst_base->value, +- NULL, NULL); ++ NULL, NULL, insn_sequence); + gas_assert (!result); + + /* Find the most matched qualifier sequence. */ +@@ -4720,36 +4856,36 @@ output_operand_error_record (const operand_error_record *record, char *str) + break; + + case AARCH64_OPDE_UNTIED_OPERAND: +- as_bad (_("operand %d must be the same register as operand 1 -- `%s'"), +- detail->index + 1, str); ++ handler (_("operand %d must be the same register as operand 1 -- `%s'"), ++ detail->index + 1, str); + break; + + case AARCH64_OPDE_OUT_OF_RANGE: +- if (detail->data[0] != detail->data[1]) +- as_bad (_("%s out of range %d to %d at operand %d -- `%s'"), +- detail->error ? detail->error : _("immediate value"), +- detail->data[0], detail->data[1], idx + 1, str); ++ if (detail->data[0].i != detail->data[1].i) ++ handler (_("%s out of range %d to %d at operand %d -- `%s'"), ++ detail->error ? detail->error : _("immediate value"), ++ detail->data[0].i, detail->data[1].i, idx + 1, str); + else +- as_bad (_("%s must be %d at operand %d -- `%s'"), +- detail->error ? detail->error : _("immediate value"), +- detail->data[0], idx + 1, str); ++ handler (_("%s must be %d at operand %d -- `%s'"), ++ detail->error ? detail->error : _("immediate value"), ++ detail->data[0].i, idx + 1, str); + break; + + case AARCH64_OPDE_REG_LIST: +- if (detail->data[0] == 1) +- as_bad (_("invalid number of registers in the list; " +- "only 1 register is expected at operand %d -- `%s'"), +- idx + 1, str); ++ if (detail->data[0].i == 1) ++ handler (_("invalid number of registers in the list; " ++ "only 1 register is expected at operand %d -- `%s'"), ++ idx + 1, str); + else +- as_bad (_("invalid number of registers in the list; " +- "%d registers are expected at operand %d -- `%s'"), +- detail->data[0], idx + 1, str); ++ handler (_("invalid number of registers in the list; " ++ "%d registers are expected at operand %d -- `%s'"), ++ detail->data[0].i, idx + 1, str); + break; + + case AARCH64_OPDE_UNALIGNED: +- as_bad (_("immediate value must be a multiple of " +- "%d at operand %d -- `%s'"), +- detail->data[0], idx + 1, str); ++ handler (_("immediate value must be a multiple of " ++ "%d at operand %d -- `%s'"), ++ detail->data[0].i, idx + 1, str); + break; + + default: +@@ -4763,10 +4899,15 @@ output_operand_error_record (const operand_error_record *record, char *str) + When this function is called, the operand error information had + been collected for an assembly line and there will be multiple + errors in the case of multiple instruction templates; output the +- error message that most closely describes the problem. */ ++ error message that most closely describes the problem. ++ ++ The errors to be printed can be filtered on printing all errors ++ or only non-fatal errors. This distinction has to be made because ++ the error buffer may already be filled with fatal errors we don't want to ++ print due to the different instruction templates. */ + + static void +-output_operand_error_report (char *str) ++output_operand_error_report (char *str, bfd_boolean non_fatal_only) + { + int largest_error_pos; + const char *msg = NULL; +@@ -4784,9 +4925,14 @@ output_operand_error_report (char *str) + /* Only one error. */ + if (head == operand_error_report.tail) + { +- DEBUG_TRACE ("single opcode entry with error kind: %s", +- operand_mismatch_kind_names[head->detail.kind]); +- output_operand_error_record (head, str); ++ /* If the only error is a non-fatal one and we don't want to print it, ++ just exit. */ ++ if (!non_fatal_only || head->detail.non_fatal) ++ { ++ DEBUG_TRACE ("single opcode entry with error kind: %s", ++ operand_mismatch_kind_names[head->detail.kind]); ++ output_operand_error_record (head, str); ++ } + return; + } + +@@ -4797,16 +4943,21 @@ output_operand_error_report (char *str) + { + gas_assert (curr->detail.kind != AARCH64_OPDE_NIL); + DEBUG_TRACE ("\t%s", operand_mismatch_kind_names[curr->detail.kind]); +- if (operand_error_higher_severity_p (curr->detail.kind, kind)) ++ if (operand_error_higher_severity_p (curr->detail.kind, kind) ++ && (!non_fatal_only || (non_fatal_only && curr->detail.non_fatal))) + kind = curr->detail.kind; + } +- gas_assert (kind != AARCH64_OPDE_NIL); ++ ++ gas_assert (kind != AARCH64_OPDE_NIL || non_fatal_only); + + /* Pick up one of errors of KIND to report. */ + largest_error_pos = -2; /* Index can be -1 which means unknown index. */ + for (curr = head; curr != NULL; curr = curr->next) + { +- if (curr->detail.kind != kind) ++ /* If we don't want to print non-fatal errors then don't consider them ++ at all. */ ++ if (curr->detail.kind != kind ++ || (non_fatal_only && !curr->detail.non_fatal)) + continue; + /* If there are multiple errors, pick up the one with the highest + mismatching operand index. In the case of multiple errors with +@@ -4822,6 +4973,17 @@ output_operand_error_report (char *str) + } + } + ++ /* The way errors are collected in the back-end is a bit non-intuitive. But ++ essentially, because each operand template is tried recursively you may ++ always have errors collected from the previous tried OPND. These are ++ usually skipped if there is one successful match. However now with the ++ non-fatal errors we have to ignore those previously collected hard errors ++ when we're only interested in printing the non-fatal ones. This condition ++ prevents us from printing errors that are not appropriate, since we did ++ match a condition, but it also has warnings that it wants to print. */ ++ if (non_fatal_only && !record) ++ return; ++ + gas_assert (largest_error_pos != -2 && record != NULL); + DEBUG_TRACE ("Pick up error kind %s to report", + operand_mismatch_kind_names[record->detail.kind]); +@@ -5001,6 +5163,10 @@ vectype_to_qualifier (const struct vector_type_el *vectype) + if (vectype->type == NT_b && vectype->width == 4) + return AARCH64_OPND_QLF_S_4B; + ++ /* Special case S_2H. */ ++ if (vectype->type == NT_h && vectype->width == 2) ++ return AARCH64_OPND_QLF_S_2H; ++ + /* Vector element register. */ + return AARCH64_OPND_QLF_S_B + vectype->type; + } +@@ -5058,6 +5224,7 @@ process_omitted_operand (enum aarch64_opnd type, const aarch64_opcode *opcode, + case AARCH64_OPND_Rm: + case AARCH64_OPND_Rt: + case AARCH64_OPND_Rt2: ++ case AARCH64_OPND_Rt_SP: + case AARCH64_OPND_Rs: + case AARCH64_OPND_Ra: + case AARCH64_OPND_Rt_SYS: +@@ -5085,6 +5252,7 @@ process_omitted_operand (enum aarch64_opnd type, const aarch64_opcode *opcode, + case AARCH64_OPND_Ed: + case AARCH64_OPND_En: + case AARCH64_OPND_Em: ++ case AARCH64_OPND_Em16: + case AARCH64_OPND_SM3_IMM2: + operand->reglane.regno = default_value; + break; +@@ -5402,6 +5570,7 @@ parse_operands (char *str, const aarch64_opcode *opcode) + + case AARCH64_OPND_Rd_SP: + case AARCH64_OPND_Rn_SP: ++ case AARCH64_OPND_Rt_SP: + case AARCH64_OPND_SVE_Rn_SP: + case AARCH64_OPND_Rm_SP: + po_int_reg_or_fail (REG_TYPE_R_SP); +@@ -5526,6 +5695,8 @@ parse_operands (char *str, const aarch64_opcode *opcode) + + case AARCH64_OPND_SVE_Zm3_INDEX: + case AARCH64_OPND_SVE_Zm3_22_INDEX: ++ case AARCH64_OPND_SVE_Zm3_11_INDEX: ++ case AARCH64_OPND_SVE_Zm4_11_INDEX: + case AARCH64_OPND_SVE_Zm4_INDEX: + case AARCH64_OPND_SVE_Zn_INDEX: + reg_type = REG_TYPE_ZN; +@@ -5534,6 +5705,7 @@ parse_operands (char *str, const aarch64_opcode *opcode) + case AARCH64_OPND_Ed: + case AARCH64_OPND_En: + case AARCH64_OPND_Em: ++ case AARCH64_OPND_Em16: + case AARCH64_OPND_SM3_IMM2: + reg_type = REG_TYPE_VN; + vector_reg_index: +@@ -5640,6 +5812,7 @@ parse_operands (char *str, const aarch64_opcode *opcode) + case AARCH64_OPND_CCMP_IMM: + case AARCH64_OPND_SIMM5: + case AARCH64_OPND_FBITS: ++ case AARCH64_OPND_TME_UIMM16: + case AARCH64_OPND_UIMM4: + case AARCH64_OPND_UIMM4_ADDG: + case AARCH64_OPND_UIMM10: +@@ -5654,8 +5827,10 @@ parse_operands (char *str, const aarch64_opcode *opcode) + case AARCH64_OPND_SVE_LIMM_MOV: + case AARCH64_OPND_SVE_SHLIMM_PRED: + case AARCH64_OPND_SVE_SHLIMM_UNPRED: ++ case AARCH64_OPND_SVE_SHLIMM_UNPRED_22: + case AARCH64_OPND_SVE_SHRIMM_PRED: + case AARCH64_OPND_SVE_SHRIMM_UNPRED: ++ case AARCH64_OPND_SVE_SHRIMM_UNPRED_22: + case AARCH64_OPND_SVE_SIMM5: + case AARCH64_OPND_SVE_SIMM5B: + case AARCH64_OPND_SVE_SIMM6: +@@ -5669,6 +5844,7 @@ parse_operands (char *str, const aarch64_opcode *opcode) + case AARCH64_OPND_IMM_ROT3: + case AARCH64_OPND_SVE_IMM_ROT1: + case AARCH64_OPND_SVE_IMM_ROT2: ++ case AARCH64_OPND_SVE_IMM_ROT3: + po_imm_nc_or_fail (); + info->imm.value = val; + break; +@@ -5916,6 +6092,7 @@ parse_operands (char *str, const aarch64_opcode *opcode) + break; + + case AARCH64_OPND_EXCEPTION: ++ case AARCH64_OPND_UNDEFINED: + po_misc_or_fail (parse_immediate_expression (&str, &inst.reloc.exp, + imm_reg_type)); + assign_imm_if_const_or_fixup_later (&inst.reloc, info, +@@ -6036,7 +6213,6 @@ parse_operands (char *str, const aarch64_opcode *opcode) + break; + + case AARCH64_OPND_ADDR_SIMPLE: +- case AARCH64_OPND_ADDR_SIMPLE_2: + case AARCH64_OPND_SIMD_ADDR_SIMPLE: + { + /* [{, #}] */ +@@ -6046,8 +6222,7 @@ parse_operands (char *str, const aarch64_opcode *opcode) + po_misc_or_fail (parse_address (&str, info)); + if (info->addr.pcrel || info->addr.offset.is_reg + || !info->addr.preind || info->addr.postind +- || (info->addr.writeback +- && operands[i] != AARCH64_OPND_ADDR_SIMPLE_2)) ++ || info->addr.writeback) + { + set_syntax_error (_("invalid addressing mode")); + goto failure; +@@ -6070,8 +6245,6 @@ parse_operands (char *str, const aarch64_opcode *opcode) + } + } + po_char_or_fail (']'); +- if (operands[i] == AARCH64_OPND_ADDR_SIMPLE_2) +- po_char_or_fail ('!'); + break; + } + +@@ -6201,6 +6374,7 @@ parse_operands (char *str, const aarch64_opcode *opcode) + break; + + case AARCH64_OPND_SVE_ADDR_RI_S4x16: ++ case AARCH64_OPND_SVE_ADDR_RI_S4x32: + case AARCH64_OPND_SVE_ADDR_RI_S4xVL: + case AARCH64_OPND_SVE_ADDR_RI_S4x2xVL: + case AARCH64_OPND_SVE_ADDR_RI_S4x3xVL: +@@ -6239,6 +6413,25 @@ parse_operands (char *str, const aarch64_opcode *opcode) + info->addr.offset.imm = inst.reloc.exp.X_add_number; + break; + ++ case AARCH64_OPND_SVE_ADDR_R: ++ /* [{, }] ++ but recognizing SVE registers. */ ++ po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier, ++ &offset_qualifier)); ++ if (offset_qualifier == AARCH64_OPND_QLF_NIL) ++ { ++ offset_qualifier = AARCH64_OPND_QLF_X; ++ info->addr.offset.is_reg = 1; ++ info->addr.offset.regno = 31; ++ } ++ else if (base_qualifier != AARCH64_OPND_QLF_X ++ || offset_qualifier != AARCH64_OPND_QLF_X) ++ { ++ set_syntax_error (_("invalid addressing mode")); ++ goto failure; ++ } ++ goto regoff_addr; ++ + case AARCH64_OPND_SVE_ADDR_RR: + case AARCH64_OPND_SVE_ADDR_RR_LSL1: + case AARCH64_OPND_SVE_ADDR_RR_LSL2: +@@ -6285,6 +6478,33 @@ parse_operands (char *str, const aarch64_opcode *opcode) + info->qualifier = offset_qualifier; + goto regoff_addr; + ++ case AARCH64_OPND_SVE_ADDR_ZX: ++ /* [Zn.{, }]. */ ++ po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier, ++ &offset_qualifier)); ++ /* Things to check: ++ base_qualifier either S_S or S_D ++ offset_qualifier must be X ++ */ ++ if ((base_qualifier != AARCH64_OPND_QLF_S_S ++ && base_qualifier != AARCH64_OPND_QLF_S_D) ++ || offset_qualifier != AARCH64_OPND_QLF_X) ++ { ++ set_syntax_error (_("invalid addressing mode")); ++ goto failure; ++ } ++ info->qualifier = base_qualifier; ++ if (!info->addr.offset.is_reg || info->addr.pcrel ++ || !info->addr.preind || info->addr.writeback ++ || info->shifter.operator_present != 0) ++ { ++ set_syntax_error (_("invalid addressing mode")); ++ goto failure; ++ } ++ info->shifter.kind = AARCH64_MOD_LSL; ++ break; ++ ++ + case AARCH64_OPND_SVE_ADDR_ZI_U5: + case AARCH64_OPND_SVE_ADDR_ZI_U5x2: + case AARCH64_OPND_SVE_ADDR_ZI_U5x4: +@@ -6326,17 +6546,21 @@ parse_operands (char *str, const aarch64_opcode *opcode) + goto regoff_addr; + + case AARCH64_OPND_SYSREG: +- if ((val = parse_sys_reg (&str, aarch64_sys_regs_hsh, 1, 0)) +- == PARSE_FAIL) +- { +- set_syntax_error (_("unknown or missing system register name")); +- goto failure; +- } +- inst.base.operands[i].sysreg = val; +- break; ++ { ++ uint32_t sysreg_flags; ++ if ((val = parse_sys_reg (&str, aarch64_sys_regs_hsh, 1, 0, ++ &sysreg_flags)) == PARSE_FAIL) ++ { ++ set_syntax_error (_("unknown or missing system register name")); ++ goto failure; ++ } ++ inst.base.operands[i].sysreg.value = val; ++ inst.base.operands[i].sysreg.flags = sysreg_flags; ++ break; ++ } + + case AARCH64_OPND_PSTATEFIELD: +- if ((val = parse_sys_reg (&str, aarch64_pstatefield_hsh, 0, 1)) ++ if ((val = parse_sys_reg (&str, aarch64_pstatefield_hsh, 0, 1, NULL)) + == PARSE_FAIL) + { + set_syntax_error (_("unknown or missing PSTATE field name")); +@@ -6389,12 +6613,49 @@ sys_reg_ins: + backtrack_pos = 0; + goto failure; + } ++ if (val != PARSE_FAIL ++ && operands[i] == AARCH64_OPND_BARRIER) ++ { ++ /* Regular barriers accept options CRm (C0-C15). ++ DSB nXS barrier variant accepts values > 15. */ ++ po_imm_or_fail (0, 15); ++ } + /* This is an extension to accept a 0..15 immediate. */ + if (val == PARSE_FAIL) + po_imm_or_fail (0, 15); + info->barrier = aarch64_barrier_options + val; + break; + ++ case AARCH64_OPND_BARRIER_DSB_NXS: ++ val = parse_barrier (&str); ++ if (val != PARSE_FAIL) ++ { ++ /* DSB nXS barrier variant accept only