diff options
| author | Mark Hatle <mark.hatle@amd.com> | 2024-05-27 14:58:33 -0500 |
|---|---|---|
| committer | Steve Sakoman <steve@sakoman.com> | 2024-06-14 05:19:22 -0700 |
| commit | 0efe15c5ba29ba4d8599b5d151e6e8ffbf9b253d (patch) | |
| tree | 18ef5fdbfbe851a81ac18371ba81ad884fdbf16d | |
| parent | 6a8b1d85e7ec93704e6476dd4ee45bbbace7983a (diff) | |
| download | poky-0efe15c5ba29ba4d8599b5d151e6e8ffbf9b253d.tar.gz | |
binutils: Fix aarch64 disassembly abort
Code backported from binutils development tree.
aarch64: Remove asserts from operand qualifier decoders [PR31595]
Given that the disassembler should never abort when decoding
(potentially random) data, assertion statements in the
`get_*reg_qualifier_from_value' function family prove problematic.
...
(From OE-Core rev: 3b070fc3963d04ce8c13b5b78c3b7ae95e26c435)
Signed-off-by: Mark Hatle <mark.hatle@amd.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit 00f3d8495a1d8fe44336b53c5a9d9a5f8a8d5664)
Signed-off-by: Steve Sakoman <steve@sakoman.com>
| -rw-r--r-- | meta/recipes-devtools/binutils/binutils-2.42.inc | 1 | ||||
| -rw-r--r-- | meta/recipes-devtools/binutils/binutils/0016-aarch64-Remove-asserts-from-operand-qualifier-decode.patch | 382 |
2 files changed, 383 insertions, 0 deletions
diff --git a/meta/recipes-devtools/binutils/binutils-2.42.inc b/meta/recipes-devtools/binutils/binutils-2.42.inc index 3b6f47d4ce..d2f49560f3 100644 --- a/meta/recipes-devtools/binutils/binutils-2.42.inc +++ b/meta/recipes-devtools/binutils/binutils-2.42.inc | |||
| @@ -36,5 +36,6 @@ SRC_URI = "\ | |||
| 36 | file://0013-Define-alignof-using-_Alignof-when-using-C11-or-newe.patch \ | 36 | file://0013-Define-alignof-using-_Alignof-when-using-C11-or-newe.patch \ |
| 37 | file://0014-Remove-duplicate-pe-dll.o-entry-deom-targ_extra_ofil.patch \ | 37 | file://0014-Remove-duplicate-pe-dll.o-entry-deom-targ_extra_ofil.patch \ |
| 38 | file://0015-gprofng-change-use-of-bignum-to-bigint.patch \ | 38 | file://0015-gprofng-change-use-of-bignum-to-bigint.patch \ |
| 39 | file://0016-aarch64-Remove-asserts-from-operand-qualifier-decode.patch \ | ||
| 39 | " | 40 | " |
| 40 | S = "${WORKDIR}/git" | 41 | S = "${WORKDIR}/git" |
diff --git a/meta/recipes-devtools/binutils/binutils/0016-aarch64-Remove-asserts-from-operand-qualifier-decode.patch b/meta/recipes-devtools/binutils/binutils/0016-aarch64-Remove-asserts-from-operand-qualifier-decode.patch new file mode 100644 index 0000000000..7b52425a38 --- /dev/null +++ b/meta/recipes-devtools/binutils/binutils/0016-aarch64-Remove-asserts-from-operand-qualifier-decode.patch | |||
| @@ -0,0 +1,382 @@ | |||
| 1 | From 5b1c70bfe0d8f84dc28237d6150b7b9d57c791a8 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Victor Do Nascimento <victor.donascimento@arm.com> | ||
| 3 | Date: Tue, 16 Apr 2024 11:49:15 +0100 | ||
| 4 | Subject: [PATCH] aarch64: Remove asserts from operand qualifier decoders | ||
| 5 | [PR31595] | ||
| 6 | |||
| 7 | Given that the disassembler should never abort when decoding | ||
| 8 | (potentially random) data, assertion statements in the | ||
| 9 | `get_*reg_qualifier_from_value' function family prove problematic. | ||
| 10 | |||
| 11 | Consider the random 32-bit word W, encoded in a data segment and | ||
| 12 | encountered on execution of `objdump -D <obj_name>'. | ||
| 13 | |||
| 14 | If: | ||
| 15 | |||
| 16 | (W & ~opcode_mask) == valid instruction | ||
| 17 | |||
| 18 | Then before `print_insn_aarch64_word' has a chance to report the | ||
| 19 | instruction as potentially undefined, an attempt will be made to have | ||
| 20 | the qualifiers for the instruction's register operands (if any) | ||
| 21 | decoded. If the relevant bits do not map onto a valid qualifier for | ||
| 22 | the matched instruction-like word, an abort will be triggered and the | ||
| 23 | execution of objdump aborted. | ||
| 24 | |||
| 25 | As this scenario is perfectly feasible and, in light of the fact that | ||
| 26 | objdump must successfully decode all sections of a given object file, | ||
| 27 | it is not appropriate to assert in this family of functions. | ||
| 28 | |||
| 29 | Therefore, we add a new pseudo-qualifier `AARCH64_OPND_QLF_ERR' for | ||
| 30 | handling invalid qualifier-associated values and re-purpose the | ||
| 31 | assertion conditions in qualifier-retrieving functions to be the | ||
| 32 | predicate guarding the returning of the calculated qualifier type. | ||
| 33 | If the predicate fails, we return this new qualifier and allow the | ||
| 34 | caller to handle the error as appropriate. | ||
| 35 | |||
| 36 | As these functions are called either from within | ||
| 37 | `aarch64_extract_operand' or `do_special_decoding', both of which are | ||
| 38 | expected to return non-zero values, it suffices that callers return | ||
| 39 | zero upon encountering `AARCH64_OPND_QLF_ERR'. | ||
| 40 | |||
| 41 | Ar present the error presented in the hypothetical scenario has been | ||
| 42 | encountered in `get_sreg_qualifier_from_value', but the change is made | ||
| 43 | to the whole family to keep the interface consistent. | ||
| 44 | |||
| 45 | Bug: https://sourceware.org/PR31595 | ||
| 46 | |||
| 47 | Upstream-Status: Backport [commit 2601b201e95ea0edab89342ee7137c74e88a8a79] | ||
| 48 | |||
| 49 | Signed-off-by: Mark Hatle <mark.hatle@amd.com> | ||
| 50 | --- | ||
| 51 | .../testsuite/binutils-all/aarch64/illegal.d | 1 + | ||
| 52 | .../testsuite/binutils-all/aarch64/illegal.s | 3 + | ||
| 53 | include/opcode/aarch64.h | 3 + | ||
| 54 | opcodes/aarch64-dis.c | 98 +++++++++++++++---- | ||
| 55 | 4 files changed, 87 insertions(+), 18 deletions(-) | ||
| 56 | |||
| 57 | diff --git a/binutils/testsuite/binutils-all/aarch64/illegal.d b/binutils/testsuite/binutils-all/aarch64/illegal.d | ||
| 58 | index 4b90a1d9f39..b69318aec85 100644 | ||
| 59 | --- a/binutils/testsuite/binutils-all/aarch64/illegal.d | ||
| 60 | +++ b/binutils/testsuite/binutils-all/aarch64/illegal.d | ||
| 61 | @@ -8,5 +8,6 @@ Disassembly of section \.text: | ||
| 62 | |||
| 63 | 0+000 <.*>: | ||
| 64 | [ ]+0:[ ]+68ea18cc[ ]+.inst[ ]+0x68ea18cc ; undefined | ||
| 65 | +[ ]+4:[ ]+9dc39839[ ]+.inst[ ]+0x9dc39839 ; undefined | ||
| 66 | #pass | ||
| 67 | |||
| 68 | diff --git a/binutils/testsuite/binutils-all/aarch64/illegal.s b/binutils/testsuite/binutils-all/aarch64/illegal.s | ||
| 69 | index 216cbe6f265..43668c6db55 100644 | ||
| 70 | --- a/binutils/testsuite/binutils-all/aarch64/illegal.s | ||
| 71 | +++ b/binutils/testsuite/binutils-all/aarch64/illegal.s | ||
| 72 | @@ -4,4 +4,7 @@ | ||
| 73 | # ldpsw x12, x6, [x6],#-8 ; illegal because one of the dest regs is also the address reg | ||
| 74 | .inst 0x68ea18cc | ||
| 75 | |||
| 76 | + # illegal, resembles the opcode `ldapur' with invalid qualifier bits | ||
| 77 | + .inst 0x9dc39839 | ||
| 78 | + | ||
| 79 | # FIXME: Add more illegal instructions here. | ||
| 80 | diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h | ||
| 81 | index 2fca9528c20..e8fe93ef127 100644 | ||
| 82 | --- a/include/opcode/aarch64.h | ||
| 83 | +++ b/include/opcode/aarch64.h | ||
| 84 | @@ -894,6 +894,9 @@ enum aarch64_opnd_qualifier | ||
| 85 | /* Special qualifier helping retrieve qualifier information during the | ||
| 86 | decoding time (currently not in use). */ | ||
| 87 | AARCH64_OPND_QLF_RETRIEVE, | ||
| 88 | + | ||
| 89 | + /* Special qualifier used for indicating error in qualifier retrieval. */ | ||
| 90 | + AARCH64_OPND_QLF_ERR, | ||
| 91 | }; | ||
| 92 | |||
| 93 | /* Instruction class. */ | ||
| 94 | diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c | ||
| 95 | index 96f42ae862a..b70e6da9eb7 100644 | ||
| 96 | --- a/opcodes/aarch64-dis.c | ||
| 97 | +++ b/opcodes/aarch64-dis.c | ||
| 98 | @@ -219,9 +219,10 @@ static inline enum aarch64_opnd_qualifier | ||
| 99 | get_greg_qualifier_from_value (aarch64_insn value) | ||
| 100 | { | ||
| 101 | enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_W + value; | ||
| 102 | - assert (value <= 0x1 | ||
| 103 | - && aarch64_get_qualifier_standard_value (qualifier) == value); | ||
| 104 | - return qualifier; | ||
| 105 | + if (value <= 0x1 | ||
| 106 | + && aarch64_get_qualifier_standard_value (qualifier) == value) | ||
| 107 | + return qualifier; | ||
| 108 | + return AARCH64_OPND_QLF_ERR; | ||
| 109 | } | ||
| 110 | |||
| 111 | /* Given VALUE, return qualifier for a vector register. This does not support | ||
| 112 | @@ -237,9 +238,10 @@ get_vreg_qualifier_from_value (aarch64_insn value) | ||
| 113 | if (qualifier >= AARCH64_OPND_QLF_V_2H) | ||
| 114 | qualifier += 1; | ||
| 115 | |||
| 116 | - assert (value <= 0x8 | ||
| 117 | - && aarch64_get_qualifier_standard_value (qualifier) == value); | ||
| 118 | - return qualifier; | ||
| 119 | + if (value <= 0x8 | ||
| 120 | + && aarch64_get_qualifier_standard_value (qualifier) == value) | ||
| 121 | + return qualifier; | ||
| 122 | + return AARCH64_OPND_QLF_ERR; | ||
| 123 | } | ||
| 124 | |||
| 125 | /* Given VALUE, return qualifier for an FP or AdvSIMD scalar register. */ | ||
| 126 | @@ -248,9 +250,10 @@ get_sreg_qualifier_from_value (aarch64_insn value) | ||
| 127 | { | ||
| 128 | enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_S_B + value; | ||
| 129 | |||
| 130 | - assert (value <= 0x4 | ||
| 131 | - && aarch64_get_qualifier_standard_value (qualifier) == value); | ||
| 132 | - return qualifier; | ||
| 133 | + if (value <= 0x4 | ||
| 134 | + && aarch64_get_qualifier_standard_value (qualifier) == value) | ||
| 135 | + return qualifier; | ||
| 136 | + return AARCH64_OPND_QLF_ERR; | ||
| 137 | } | ||
| 138 | |||
| 139 | /* Given the instruction in *INST which is probably half way through the | ||
| 140 | @@ -263,13 +266,17 @@ get_expected_qualifier (const aarch64_inst *inst, int i) | ||
| 141 | { | ||
| 142 | aarch64_opnd_qualifier_seq_t qualifiers; | ||
| 143 | /* Should not be called if the qualifier is known. */ | ||
| 144 | - assert (inst->operands[i].qualifier == AARCH64_OPND_QLF_NIL); | ||
| 145 | - int invalid_count; | ||
| 146 | - if (aarch64_find_best_match (inst, inst->opcode->qualifiers_list, | ||
| 147 | - i, qualifiers, &invalid_count)) | ||
| 148 | - return qualifiers[i]; | ||
| 149 | + if (inst->operands[i].qualifier == AARCH64_OPND_QLF_NIL) | ||
| 150 | + { | ||
| 151 | + int invalid_count; | ||
| 152 | + if (aarch64_find_best_match (inst, inst->opcode->qualifiers_list, | ||
| 153 | + i, qualifiers, &invalid_count)) | ||
| 154 | + return qualifiers[i]; | ||
| 155 | + else | ||
| 156 | + return AARCH64_OPND_QLF_NIL; | ||
| 157 | + } | ||
| 158 | else | ||
| 159 | - return AARCH64_OPND_QLF_NIL; | ||
| 160 | + return AARCH64_OPND_QLF_ERR; | ||
| 161 | } | ||
| 162 | |||
| 163 | /* Operand extractors. */ | ||
| 164 | @@ -355,6 +362,8 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info, | ||
| 165 | aarch64_insn value = extract_field (FLD_imm4_11, code, 0); | ||
| 166 | /* Depend on AARCH64_OPND_Ed to determine the qualifier. */ | ||
| 167 | info->qualifier = get_expected_qualifier (inst, info->idx); | ||
| 168 | + if (info->qualifier == AARCH64_OPND_QLF_ERR) | ||
| 169 | + return 0; | ||
| 170 | shift = get_logsz (aarch64_get_qualifier_esize (info->qualifier)); | ||
| 171 | info->reglane.index = value >> shift; | ||
| 172 | } | ||
| 173 | @@ -374,6 +383,8 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info, | ||
| 174 | if (pos > 3) | ||
| 175 | return false; | ||
| 176 | info->qualifier = get_sreg_qualifier_from_value (pos); | ||
| 177 | + if (info->qualifier == AARCH64_OPND_QLF_ERR) | ||
| 178 | + return 0; | ||
| 179 | info->reglane.index = (unsigned) (value >> 1); | ||
| 180 | } | ||
| 181 | } | ||
| 182 | @@ -381,6 +392,8 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info, | ||
| 183 | { | ||
| 184 | /* Need information in other operand(s) to help decoding. */ | ||
| 185 | info->qualifier = get_expected_qualifier (inst, info->idx); | ||
| 186 | + if (info->qualifier == AARCH64_OPND_QLF_ERR) | ||
| 187 | + return 0; | ||
| 188 | switch (info->qualifier) | ||
| 189 | { | ||
| 190 | case AARCH64_OPND_QLF_S_4B: | ||
| 191 | @@ -405,6 +418,8 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info, | ||
| 192 | |||
| 193 | /* Need information in other operand(s) to help decoding. */ | ||
| 194 | info->qualifier = get_expected_qualifier (inst, info->idx); | ||
| 195 | + if (info->qualifier == AARCH64_OPND_QLF_ERR) | ||
| 196 | + return 0; | ||
| 197 | switch (info->qualifier) | ||
| 198 | { | ||
| 199 | case AARCH64_OPND_QLF_S_H: | ||
| 200 | @@ -644,9 +659,15 @@ aarch64_ext_advsimd_imm_shift (const aarch64_operand *self ATTRIBUTE_UNUSED, | ||
| 201 | 1xxx 1 2D */ | ||
| 202 | info->qualifier = | ||
| 203 | get_vreg_qualifier_from_value ((pos << 1) | (int) Q); | ||
| 204 | + if (info->qualifier == AARCH64_OPND_QLF_ERR) | ||
| 205 | + return false; | ||
| 206 | } | ||
| 207 | else | ||
| 208 | - info->qualifier = get_sreg_qualifier_from_value (pos); | ||
| 209 | + { | ||
| 210 | + info->qualifier = get_sreg_qualifier_from_value (pos); | ||
| 211 | + if (info->qualifier == AARCH64_OPND_QLF_ERR) | ||
| 212 | + return 0; | ||
| 213 | + } | ||
| 214 | |||
| 215 | if (info->type == AARCH64_OPND_IMM_VLSR) | ||
| 216 | /* immh <shift> | ||
| 217 | @@ -773,6 +794,8 @@ aarch64_ext_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED, | ||
| 218 | |||
| 219 | /* cmode */ | ||
| 220 | info->qualifier = get_expected_qualifier (inst, info->idx); | ||
| 221 | + if (info->qualifier == AARCH64_OPND_QLF_ERR) | ||
| 222 | + return 0; | ||
| 223 | switch (info->qualifier) | ||
| 224 | { | ||
| 225 | case AARCH64_OPND_QLF_NIL: | ||
| 226 | @@ -1014,6 +1037,8 @@ aarch64_ext_ft (const aarch64_operand *self ATTRIBUTE_UNUSED, | ||
| 227 | if (value > 0x4) | ||
| 228 | return false; | ||
| 229 | info->qualifier = get_sreg_qualifier_from_value (value); | ||
| 230 | + if (info->qualifier == AARCH64_OPND_QLF_ERR) | ||
| 231 | + return 0; | ||
| 232 | } | ||
| 233 | |||
| 234 | return true; | ||
| 235 | @@ -1086,6 +1111,8 @@ aarch64_ext_rcpc3_addr_offset (const aarch64_operand *self ATTRIBUTE_UNUSED, | ||
| 236 | aarch64_operand_error *errors ATTRIBUTE_UNUSED) | ||
| 237 | { | ||
| 238 | info->qualifier = get_expected_qualifier (inst, info->idx); | ||
| 239 | + if (info->qualifier == AARCH64_OPND_QLF_ERR) | ||
| 240 | + return 0; | ||
| 241 | |||
| 242 | /* Rn */ | ||
| 243 | info->addr.base_regno = extract_field (self->fields[0], code, 0); | ||
| 244 | @@ -1105,6 +1132,8 @@ aarch64_ext_addr_offset (const aarch64_operand *self ATTRIBUTE_UNUSED, | ||
| 245 | aarch64_operand_error *errors ATTRIBUTE_UNUSED) | ||
| 246 | { | ||
| 247 | info->qualifier = get_expected_qualifier (inst, info->idx); | ||
| 248 | + if (info->qualifier == AARCH64_OPND_QLF_ERR) | ||
| 249 | + return 0; | ||
| 250 | |||
| 251 | /* Rn */ | ||
| 252 | info->addr.base_regno = extract_field (self->fields[0], code, 0); | ||
| 253 | @@ -1154,6 +1183,8 @@ aarch64_ext_addr_regoff (const aarch64_operand *self ATTRIBUTE_UNUSED, | ||
| 254 | /* Need information in other operand(s) to help achieve the decoding | ||
| 255 | from 'S' field. */ | ||
| 256 | info->qualifier = get_expected_qualifier (inst, info->idx); | ||
| 257 | + if (info->qualifier == AARCH64_OPND_QLF_ERR) | ||
| 258 | + return 0; | ||
| 259 | /* Get the size of the data element that is accessed, which may be | ||
| 260 | different from that of the source register size, e.g. in strb/ldrb. */ | ||
| 261 | size = aarch64_get_qualifier_esize (info->qualifier); | ||
| 262 | @@ -1172,6 +1203,8 @@ aarch64_ext_addr_simm (const aarch64_operand *self, aarch64_opnd_info *info, | ||
| 263 | { | ||
| 264 | aarch64_insn imm; | ||
| 265 | info->qualifier = get_expected_qualifier (inst, info->idx); | ||
| 266 | + if (info->qualifier == AARCH64_OPND_QLF_ERR) | ||
| 267 | + return 0; | ||
| 268 | |||
| 269 | /* Rn */ | ||
| 270 | info->addr.base_regno = extract_field (FLD_Rn, code, 0); | ||
| 271 | @@ -1210,6 +1243,8 @@ aarch64_ext_addr_uimm12 (const aarch64_operand *self, aarch64_opnd_info *info, | ||
| 272 | { | ||
| 273 | int shift; | ||
| 274 | info->qualifier = get_expected_qualifier (inst, info->idx); | ||
| 275 | + if (info->qualifier == AARCH64_OPND_QLF_ERR) | ||
| 276 | + return 0; | ||
| 277 | shift = get_logsz (aarch64_get_qualifier_esize (info->qualifier)); | ||
| 278 | /* Rn */ | ||
| 279 | info->addr.base_regno = extract_field (self->fields[0], code, 0); | ||
| 280 | @@ -1228,6 +1263,8 @@ aarch64_ext_addr_simm10 (const aarch64_operand *self, aarch64_opnd_info *info, | ||
| 281 | aarch64_insn imm; | ||
| 282 | |||
| 283 | info->qualifier = get_expected_qualifier (inst, info->idx); | ||
| 284 | + if (info->qualifier == AARCH64_OPND_QLF_ERR) | ||
| 285 | + return 0; | ||
| 286 | /* Rn */ | ||
| 287 | info->addr.base_regno = extract_field (self->fields[0], code, 0); | ||
| 288 | /* simm10 */ | ||
| 289 | @@ -2467,6 +2504,8 @@ decode_sizeq (aarch64_inst *inst) | ||
| 290 | if (mask == 0x7) | ||
| 291 | { | ||
| 292 | inst->operands[idx].qualifier = get_vreg_qualifier_from_value (value); | ||
| 293 | + if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR) | ||
| 294 | + return 0; | ||
| 295 | return 1; | ||
| 296 | } | ||
| 297 | |||
| 298 | @@ -2649,6 +2688,8 @@ do_special_decoding (aarch64_inst *inst) | ||
| 299 | idx = select_operand_for_sf_field_coding (inst->opcode); | ||
| 300 | value = extract_field (FLD_sf, inst->value, 0); | ||
| 301 | inst->operands[idx].qualifier = get_greg_qualifier_from_value (value); | ||
| 302 | + if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR) | ||
| 303 | + return 0; | ||
| 304 | if ((inst->opcode->flags & F_N) | ||
| 305 | && extract_field (FLD_N, inst->value, 0) != value) | ||
| 306 | return 0; | ||
| 307 | @@ -2659,6 +2700,8 @@ do_special_decoding (aarch64_inst *inst) | ||
| 308 | idx = select_operand_for_sf_field_coding (inst->opcode); | ||
| 309 | value = extract_field (FLD_lse_sz, inst->value, 0); | ||
| 310 | inst->operands[idx].qualifier = get_greg_qualifier_from_value (value); | ||
| 311 | + if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR) | ||
| 312 | + return 0; | ||
| 313 | } | ||
| 314 | /* rcpc3 'size' field. */ | ||
| 315 | if (inst->opcode->flags & F_RCPC3_SIZE) | ||
| 316 | @@ -2670,12 +2713,18 @@ do_special_decoding (aarch64_inst *inst) | ||
| 317 | { | ||
| 318 | if (aarch64_operands[inst->operands[i].type].op_class | ||
| 319 | == AARCH64_OPND_CLASS_INT_REG) | ||
| 320 | - inst->operands[i].qualifier = get_greg_qualifier_from_value (value & 1); | ||
| 321 | + { | ||
| 322 | + inst->operands[i].qualifier = get_greg_qualifier_from_value (value & 1); | ||
| 323 | + if (inst->operands[i].qualifier == AARCH64_OPND_QLF_ERR) | ||
| 324 | + return 0; | ||
| 325 | + } | ||
| 326 | else if (aarch64_operands[inst->operands[i].type].op_class | ||
| 327 | == AARCH64_OPND_CLASS_FP_REG) | ||
| 328 | { | ||
| 329 | value += (extract_field (FLD_opc1, inst->value, 0) << 2); | ||
| 330 | inst->operands[i].qualifier = get_sreg_qualifier_from_value (value); | ||
| 331 | + if (inst->operands[i].qualifier == AARCH64_OPND_QLF_ERR) | ||
| 332 | + return 0; | ||
| 333 | } | ||
| 334 | } | ||
| 335 | } | ||
| 336 | @@ -2709,7 +2758,11 @@ do_special_decoding (aarch64_inst *inst) | ||
| 337 | /* For most related instruciton, the 'size' field is fully available for | ||
| 338 | operand encoding. */ | ||
| 339 | if (mask == 0x3) | ||
| 340 | - inst->operands[idx].qualifier = get_sreg_qualifier_from_value (value); | ||
| 341 | + { | ||
| 342 | + inst->operands[idx].qualifier = get_sreg_qualifier_from_value (value); | ||
| 343 | + if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR) | ||
| 344 | + return 0; | ||
| 345 | + } | ||
| 346 | else | ||
| 347 | { | ||
| 348 | get_operand_possible_qualifiers (idx, inst->opcode->qualifiers_list, | ||
| 349 | @@ -2744,6 +2797,9 @@ do_special_decoding (aarch64_inst *inst) | ||
| 350 | Q = (unsigned) extract_field (FLD_Q, inst->value, inst->opcode->mask); | ||
| 351 | inst->operands[0].qualifier = | ||
| 352 | get_vreg_qualifier_from_value ((num << 1) | Q); | ||
| 353 | + if (inst->operands[0].qualifier == AARCH64_OPND_QLF_ERR) | ||
| 354 | + return 0; | ||
| 355 | + | ||
| 356 | } | ||
| 357 | |||
| 358 | if ((inst->opcode->flags & F_OPD_SIZE) && inst->opcode->iclass == sve2_urqvs) | ||
| 359 | @@ -2753,7 +2809,11 @@ do_special_decoding (aarch64_inst *inst) | ||
| 360 | inst->opcode->mask); | ||
| 361 | inst->operands[0].qualifier | ||
| 362 | = get_vreg_qualifier_from_value (1 + (size << 1)); | ||
| 363 | + if (inst->operands[0].qualifier == AARCH64_OPND_QLF_ERR) | ||
| 364 | + return 0; | ||
| 365 | inst->operands[2].qualifier = get_sreg_qualifier_from_value (size); | ||
| 366 | + if (inst->operands[2].qualifier == AARCH64_OPND_QLF_ERR) | ||
| 367 | + return 0; | ||
| 368 | } | ||
| 369 | |||
| 370 | if (inst->opcode->flags & F_GPRSIZE_IN_Q) | ||
| 371 | @@ -2772,6 +2832,8 @@ do_special_decoding (aarch64_inst *inst) | ||
| 372 | assert (idx == 0 || idx == 1); | ||
| 373 | value = extract_field (FLD_Q, inst->value, 0); | ||
| 374 | inst->operands[idx].qualifier = get_greg_qualifier_from_value (value); | ||
| 375 | + if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR) | ||
| 376 | + return 0; | ||
| 377 | } | ||
| 378 | |||
| 379 | if (inst->opcode->flags & F_LDS_SIZE) | ||
| 380 | -- | ||
| 381 | 2.34.1 | ||
| 382 | |||
