1 1.1 christos /* aarch64-dis.c -- AArch64 disassembler. 2 1.10 christos Copyright (C) 2009-2025 Free Software Foundation, Inc. 3 1.1 christos Contributed by ARM Ltd. 4 1.1 christos 5 1.1 christos This file is part of the GNU opcodes library. 6 1.1 christos 7 1.1 christos This library is free software; you can redistribute it and/or modify 8 1.1 christos it under the terms of the GNU General Public License as published by 9 1.1 christos the Free Software Foundation; either version 3, or (at your option) 10 1.1 christos any later version. 11 1.1 christos 12 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT 13 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 1.1 christos License for more details. 16 1.1 christos 17 1.1 christos You should have received a copy of the GNU General Public License 18 1.1 christos along with this program; see the file COPYING3. If not, 19 1.1 christos see <http://www.gnu.org/licenses/>. */ 20 1.1 christos 21 1.1 christos #include "sysdep.h" 22 1.8 christos #include <stdint.h> 23 1.6 christos #include "disassemble.h" 24 1.1 christos #include "libiberty.h" 25 1.1 christos #include "opintl.h" 26 1.1 christos #include "aarch64-dis.h" 27 1.1 christos #include "elf-bfd.h" 28 1.9 christos #include "safe-ctype.h" 29 1.9 christos #include "obstack.h" 30 1.9 christos 31 1.9 christos #define obstack_chunk_alloc xmalloc 32 1.9 christos #define obstack_chunk_free free 33 1.1 christos 34 1.1 christos #define INSNLEN 4 35 1.1 christos 36 1.9 christos /* This character is used to encode style information within the output 37 1.9 christos buffers. See get_style_text and print_operands for more details. */ 38 1.9 christos #define STYLE_MARKER_CHAR '\002' 39 1.9 christos 40 1.1 christos /* Cached mapping symbol state. */ 41 1.1 christos enum map_type 42 1.1 christos { 43 1.1 christos MAP_INSN, 44 1.1 christos MAP_DATA 45 1.1 christos }; 46 1.1 christos 47 1.8 christos static aarch64_feature_set arch_variant; /* See select_aarch64_variant. */ 48 1.1 christos static enum map_type last_type; 49 1.1 christos static int last_mapping_sym = -1; 50 1.7 christos static bfd_vma last_stop_offset = 0; 51 1.1 christos static bfd_vma last_mapping_addr = 0; 52 1.1 christos 53 1.1 christos /* Other options */ 54 1.1 christos static int no_aliases = 0; /* If set disassemble as most general inst. */ 55 1.6 christos static int no_notes = 1; /* If set do not print disassemble notes in the 57 1.1 christos output as comments. */ 58 1.7 christos 59 1.7 christos /* Currently active instruction sequence. */ 60 1.7 christos static aarch64_instr_sequence insn_sequence; 61 1.1 christos 62 1.1 christos static void 63 1.1 christos set_default_aarch64_dis_options (struct disassemble_info *info ATTRIBUTE_UNUSED) 64 1.1 christos { 65 1.1 christos } 66 1.1 christos 67 1.1 christos static void 68 1.1 christos parse_aarch64_dis_option (const char *option, unsigned int len ATTRIBUTE_UNUSED) 69 1.1 christos { 70 1.8 christos /* Try to match options that are simple flags */ 71 1.1 christos if (startswith (option, "no-aliases")) 72 1.1 christos { 73 1.1 christos no_aliases = 1; 74 1.1 christos return; 75 1.1 christos } 76 1.8 christos 77 1.1 christos if (startswith (option, "aliases")) 78 1.1 christos { 79 1.1 christos no_aliases = 0; 80 1.1 christos return; 81 1.1 christos } 82 1.8 christos 83 1.6 christos if (startswith (option, "no-notes")) 84 1.6 christos { 85 1.6 christos no_notes = 1; 86 1.6 christos return; 87 1.6 christos } 88 1.8 christos 89 1.6 christos if (startswith (option, "notes")) 90 1.6 christos { 91 1.6 christos no_notes = 0; 92 1.6 christos return; 93 1.6 christos } 94 1.1 christos 95 1.8 christos #ifdef DEBUG_AARCH64 96 1.1 christos if (startswith (option, "debug_dump")) 97 1.1 christos { 98 1.1 christos debug_dump = 1; 99 1.1 christos return; 100 1.1 christos } 101 1.1 christos #endif /* DEBUG_AARCH64 */ 102 1.1 christos 103 1.6 christos /* Invalid option. */ 104 1.1 christos opcodes_error_handler (_("unrecognised disassembler option: %s"), option); 105 1.1 christos } 106 1.1 christos 107 1.1 christos static void 108 1.1 christos parse_aarch64_dis_options (const char *options) 109 1.1 christos { 110 1.1 christos const char *option_end; 111 1.1 christos 112 1.1 christos if (options == NULL) 113 1.1 christos return; 114 1.1 christos 115 1.1 christos while (*options != '\0') 116 1.1 christos { 117 1.1 christos /* Skip empty options. */ 118 1.1 christos if (*options == ',') 119 1.1 christos { 120 1.1 christos options++; 121 1.1 christos continue; 122 1.1 christos } 123 1.1 christos 124 1.1 christos /* We know that *options is neither NUL or a comma. */ 125 1.1 christos option_end = options + 1; 126 1.1 christos while (*option_end != ',' && *option_end != '\0') 127 1.1 christos option_end++; 128 1.1 christos 129 1.1 christos parse_aarch64_dis_option (options, option_end - options); 130 1.1 christos 131 1.1 christos /* Go on to the next one. If option_end points to a comma, it 132 1.1 christos will be skipped above. */ 133 1.1 christos options = option_end; 134 1.1 christos } 135 1.1 christos } 136 1.1 christos 137 1.1 christos /* Functions doing the instruction disassembling. */ 139 1.1 christos 140 1.1 christos /* The unnamed arguments consist of the number of fields and information about 141 1.1 christos these fields where the VALUE will be extracted from CODE and returned. 142 1.1 christos MASK can be zero or the base mask of the opcode. 143 1.1 christos 144 1.1 christos N.B. the fields are required to be in such an order than the most signficant 145 1.3 christos field for VALUE comes the first, e.g. the <index> in 146 1.1 christos SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>] 147 1.1 christos is encoded in H:L:M in some cases, the fields H:L:M should be passed in 148 1.6 christos the order of H, L, M. */ 149 1.1 christos 150 1.1 christos aarch64_insn 151 1.1 christos extract_fields (aarch64_insn code, aarch64_insn mask, ...) 152 1.1 christos { 153 1.1 christos uint32_t num; 154 1.1 christos const aarch64_field *field; 155 1.3 christos enum aarch64_field_kind kind; 156 1.1 christos va_list va; 157 1.1 christos 158 1.1 christos va_start (va, mask); 159 1.1 christos num = va_arg (va, uint32_t); 160 1.1 christos assert (num <= 5); 161 1.1 christos aarch64_insn value = 0x0; 162 1.1 christos while (num--) 163 1.1 christos { 164 1.1 christos kind = va_arg (va, enum aarch64_field_kind); 165 1.1 christos field = &fields[kind]; 166 1.1 christos value <<= field->width; 167 1.8 christos value |= extract_field (kind, code, mask); 168 1.1 christos } 169 1.1 christos va_end (va); 170 1.1 christos return value; 171 1.9 christos } 172 1.9 christos 173 1.6 christos /* Extract the value of all fields in SELF->fields after START from 174 1.6 christos instruction CODE. The least significant bit comes from the final field. */ 175 1.9 christos 176 1.9 christos static aarch64_insn 177 1.6 christos extract_all_fields_after (const aarch64_operand *self, unsigned int start, 178 1.6 christos aarch64_insn code) 179 1.6 christos { 180 1.6 christos aarch64_insn value; 181 1.6 christos unsigned int i; 182 1.6 christos enum aarch64_field_kind kind; 183 1.9 christos 184 1.9 christos value = 0; 185 1.6 christos for (i = start; 186 1.6 christos i < ARRAY_SIZE (self->fields) && self->fields[i] != FLD_NIL; ++i) 187 1.6 christos { 188 1.6 christos kind = self->fields[i]; 189 1.6 christos value <<= fields[kind].width; 190 1.6 christos value |= extract_field (kind, code, 0); 191 1.6 christos } 192 1.6 christos return value; 193 1.9 christos } 194 1.9 christos 195 1.9 christos /* Extract the value of all fields in SELF->fields from instruction CODE. 196 1.9 christos The least significant bit comes from the final field. */ 197 1.9 christos 198 1.9 christos static aarch64_insn 199 1.9 christos extract_all_fields (const aarch64_operand *self, aarch64_insn code) 200 1.9 christos { 201 1.9 christos return extract_all_fields_after (self, 0, code); 202 1.1 christos } 203 1.7 christos 204 1.1 christos /* Sign-extend bit I of VALUE. */ 205 1.1 christos static inline uint64_t 206 1.7 christos sign_extend (aarch64_insn value, unsigned i) 207 1.3 christos { 208 1.1 christos uint64_t ret, sign; 209 1.7 christos 210 1.7 christos assert (i < 32); 211 1.7 christos ret = value; 212 1.1 christos sign = (uint64_t) 1 << i; 213 1.1 christos return ((ret & (sign + sign - 1)) ^ sign) - sign; 214 1.1 christos } 215 1.1 christos 216 1.1 christos /* N.B. the following inline helpfer functions create a dependency on the 217 1.1 christos order of operand qualifier enumerators. */ 218 1.1 christos 219 1.1 christos /* Given VALUE, return qualifier for a general purpose register. */ 220 1.1 christos static inline enum aarch64_opnd_qualifier 221 1.1 christos get_greg_qualifier_from_value (aarch64_insn value) 222 1.10 christos { 223 1.10 christos enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_W + value; 224 1.10 christos if (value <= 0x1 225 1.10 christos && aarch64_get_qualifier_standard_value (qualifier) == value) 226 1.1 christos return qualifier; 227 1.1 christos return AARCH64_OPND_QLF_ERR; 228 1.3 christos } 229 1.3 christos 230 1.3 christos /* Given VALUE, return qualifier for a vector register. This does not support 231 1.1 christos decoding instructions that accept the 2H vector type. */ 232 1.1 christos 233 1.1 christos static inline enum aarch64_opnd_qualifier 234 1.1 christos get_vreg_qualifier_from_value (aarch64_insn value) 235 1.3 christos { 236 1.3 christos enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_V_8B + value; 237 1.3 christos 238 1.3 christos /* Instructions using vector type 2H should not call this function. Skip over 239 1.3 christos the 2H qualifier. */ 240 1.3 christos if (qualifier >= AARCH64_OPND_QLF_V_2H) 241 1.10 christos qualifier += 1; 242 1.10 christos 243 1.10 christos if (value <= 0x8 244 1.10 christos && aarch64_get_qualifier_standard_value (qualifier) == value) 245 1.1 christos return qualifier; 246 1.1 christos return AARCH64_OPND_QLF_ERR; 247 1.1 christos } 248 1.1 christos 249 1.1 christos /* Given VALUE, return qualifier for an FP or AdvSIMD scalar register. */ 250 1.1 christos static inline enum aarch64_opnd_qualifier 251 1.1 christos get_sreg_qualifier_from_value (aarch64_insn value) 252 1.3 christos { 253 1.10 christos enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_S_B + value; 254 1.10 christos 255 1.10 christos if (value <= 0x4 256 1.10 christos && aarch64_get_qualifier_standard_value (qualifier) == value) 257 1.1 christos return qualifier; 258 1.1 christos return AARCH64_OPND_QLF_ERR; 259 1.1 christos } 260 1.1 christos 261 1.1 christos /* Given the instruction in *INST which is probably half way through the 262 1.1 christos decoding and our caller wants to know the expected qualifier for operand 263 1.1 christos I. Return such a qualifier if we can establish it; otherwise return 264 1.1 christos AARCH64_OPND_QLF_NIL. */ 265 1.1 christos 266 1.1 christos static aarch64_opnd_qualifier_t 267 1.1 christos get_expected_qualifier (const aarch64_inst *inst, int i) 268 1.1 christos { 269 1.10 christos aarch64_opnd_qualifier_seq_t qualifiers; 270 1.10 christos /* Should not be called if the qualifier is known. */ 271 1.10 christos if (inst->operands[i].qualifier == AARCH64_OPND_QLF_NIL) 272 1.10 christos { 273 1.10 christos int invalid_count; 274 1.10 christos if (aarch64_find_best_match (inst, inst->opcode->qualifiers_list, 275 1.10 christos i, qualifiers, &invalid_count)) 276 1.10 christos return qualifiers[i]; 277 1.10 christos else 278 1.1 christos return AARCH64_OPND_QLF_NIL; 279 1.10 christos } 280 1.1 christos else 281 1.1 christos return AARCH64_OPND_QLF_ERR; 282 1.1 christos } 283 1.1 christos 284 1.8 christos /* Operand extractors. */ 285 1.8 christos 286 1.8 christos bool 287 1.8 christos aarch64_ext_none (const aarch64_operand *self ATTRIBUTE_UNUSED, 288 1.8 christos aarch64_opnd_info *info ATTRIBUTE_UNUSED, 289 1.8 christos const aarch64_insn code ATTRIBUTE_UNUSED, 290 1.8 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 291 1.8 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 292 1.8 christos { 293 1.8 christos return true; 294 1.8 christos } 295 1.1 christos 296 1.1 christos bool 297 1.6 christos aarch64_ext_regno (const aarch64_operand *self, aarch64_opnd_info *info, 298 1.6 christos const aarch64_insn code, 299 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 300 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 301 1.9 christos { 302 1.8 christos info->reg.regno = (extract_field (self->fields[0], code, 0) 303 1.1 christos + get_operand_specific_data (self)); 304 1.1 christos return true; 305 1.8 christos } 306 1.3 christos 307 1.3 christos bool 308 1.6 christos aarch64_ext_regno_pair (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info, 309 1.6 christos const aarch64_insn code ATTRIBUTE_UNUSED, 310 1.3 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 311 1.3 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 312 1.9 christos { 313 1.9 christos assert (info->idx == 1 314 1.9 christos || info->idx == 2 315 1.9 christos || info->idx == 3 316 1.9 christos || info->idx == 5); 317 1.9 christos 318 1.9 christos unsigned prev_regno = inst->operands[info->idx - 1].reg.regno; 319 1.8 christos info->reg.regno = (prev_regno == 0x1f) ? 0x1f 320 1.3 christos : prev_regno + 1; 321 1.3 christos return true; 322 1.1 christos } 323 1.8 christos 324 1.1 christos /* e.g. IC <ic_op>{, <Xt>}. */ 325 1.1 christos bool 326 1.6 christos aarch64_ext_regrt_sysins (const aarch64_operand *self, aarch64_opnd_info *info, 327 1.6 christos const aarch64_insn code, 328 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 329 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 330 1.1 christos { 331 1.1 christos info->reg.regno = extract_field (self->fields[0], code, 0); 332 1.1 christos assert (info->idx == 1 333 1.1 christos && (aarch64_get_operand_class (inst->operands[0].type) 334 1.1 christos == AARCH64_OPND_CLASS_SYSTEM)); 335 1.1 christos /* This will make the constraint checking happy and more importantly will 336 1.3 christos help the disassembler determine whether this operand is optional or 337 1.1 christos not. */ 338 1.8 christos info->present = aarch64_sys_ins_reg_has_xt (inst->operands[0].sysins_op); 339 1.1 christos 340 1.1 christos return true; 341 1.1 christos } 342 1.8 christos 343 1.1 christos /* e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */ 344 1.1 christos bool 345 1.6 christos aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info, 346 1.6 christos const aarch64_insn code, 347 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 348 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 349 1.1 christos { 350 1.1 christos /* regno */ 351 1.1 christos info->reglane.regno = extract_field (self->fields[0], code, 352 1.3 christos inst->opcode->mask); 353 1.1 christos 354 1.1 christos /* Index and/or type. */ 355 1.1 christos if (inst->opcode->iclass == asisdone 356 1.1 christos || inst->opcode->iclass == asimdins) 357 1.1 christos { 358 1.1 christos if (info->type == AARCH64_OPND_En 359 1.1 christos && inst->opcode->operands[0] == AARCH64_OPND_Ed) 360 1.1 christos { 361 1.1 christos unsigned shift; 362 1.9 christos /* index2 for e.g. INS <Vd>.<Ts>[<index1>], <Vn>.<Ts>[<index2>]. */ 363 1.1 christos assert (info->idx == 1); /* Vn */ 364 1.1 christos aarch64_insn value = extract_field (FLD_imm4_11, code, 0); 365 1.10 christos /* Depend on AARCH64_OPND_Ed to determine the qualifier. */ 366 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx); 367 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR) 368 1.1 christos return 0; 369 1.1 christos shift = get_logsz (aarch64_get_qualifier_esize (info->qualifier)); 370 1.1 christos info->reglane.index = value >> shift; 371 1.1 christos } 372 1.1 christos else 373 1.1 christos { 374 1.1 christos /* index and type for e.g. DUP <V><d>, <Vn>.<T>[<index>]. 375 1.1 christos imm5<3:0> <V> 376 1.1 christos 0000 RESERVED 377 1.1 christos xxx1 B 378 1.1 christos xx10 H 379 1.1 christos x100 S 380 1.1 christos 1000 D */ 381 1.1 christos int pos = -1; 382 1.1 christos aarch64_insn value = extract_field (FLD_imm5, code, 0); 383 1.1 christos while (++pos <= 3 && (value & 0x1) == 0) 384 1.8 christos value >>= 1; 385 1.1 christos if (pos > 3) 386 1.10 christos return false; 387 1.10 christos info->qualifier = get_sreg_qualifier_from_value (pos); 388 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR) 389 1.1 christos return 0; 390 1.1 christos info->reglane.index = (unsigned) (value >> 1); 391 1.6 christos } 392 1.6 christos } 393 1.6 christos else if (inst->opcode->iclass == dotproduct) 394 1.6 christos { 395 1.10 christos /* Need information in other operand(s) to help decoding. */ 396 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx); 397 1.6 christos if (info->qualifier == AARCH64_OPND_QLF_ERR) 398 1.6 christos return 0; 399 1.6 christos switch (info->qualifier) 400 1.7 christos { 401 1.6 christos case AARCH64_OPND_QLF_S_4B: 402 1.6 christos case AARCH64_OPND_QLF_S_2H: 403 1.6 christos /* L:H */ 404 1.6 christos info->reglane.index = extract_fields (code, 0, 2, FLD_H, FLD_L); 405 1.10 christos info->reglane.regno &= 0x1f; 406 1.10 christos break; 407 1.10 christos case AARCH64_OPND_QLF_S_2B: 408 1.10 christos /* h:l:m */ 409 1.10 christos info->reglane.index = extract_fields (code, 0, 3, FLD_H, FLD_L, 410 1.10 christos FLD_M); 411 1.6 christos info->reglane.regno &= 0xf; 412 1.8 christos break; 413 1.6 christos default: 414 1.6 christos return false; 415 1.6 christos } 416 1.6 christos } 417 1.6 christos else if (inst->opcode->iclass == cryptosm3) 418 1.6 christos { 419 1.6 christos /* index for e.g. SM3TT2A <Vd>.4S, <Vn>.4S, <Vm>S[<imm2>]. */ 420 1.1 christos info->reglane.index = extract_field (FLD_SM3_imm2, code, 0); 421 1.1 christos } 422 1.3 christos else 423 1.1 christos { 424 1.1 christos /* Index only for e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>] 425 1.1 christos or SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */ 426 1.1 christos 427 1.10 christos /* Need information in other operand(s) to help decoding. */ 428 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx); 429 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR) 430 1.1 christos return 0; 431 1.10 christos switch (info->qualifier) 432 1.10 christos { 433 1.10 christos case AARCH64_OPND_QLF_S_B: 434 1.10 christos /* H:imm3 */ 435 1.10 christos info->reglane.index = extract_fields (code, 0, 2, FLD_H, 436 1.10 christos FLD_imm3_19); 437 1.10 christos info->reglane.regno &= 0x7; 438 1.1 christos break; 439 1.10 christos 440 1.6 christos case AARCH64_OPND_QLF_S_H: 441 1.6 christos case AARCH64_OPND_QLF_S_2B: 442 1.6 christos if (info->type == AARCH64_OPND_Em16) 443 1.6 christos { 444 1.6 christos /* h:l:m */ 445 1.6 christos info->reglane.index = extract_fields (code, 0, 3, FLD_H, FLD_L, 446 1.6 christos FLD_M); 447 1.6 christos info->reglane.regno &= 0xf; 448 1.6 christos } 449 1.6 christos else 450 1.6 christos { 451 1.6 christos /* h:l */ 452 1.1 christos info->reglane.index = extract_fields (code, 0, 2, FLD_H, FLD_L); 453 1.1 christos } 454 1.10 christos break; 455 1.1 christos case AARCH64_OPND_QLF_S_S: 456 1.1 christos case AARCH64_OPND_QLF_S_4B: 457 1.1 christos /* h:l */ 458 1.1 christos info->reglane.index = extract_fields (code, 0, 2, FLD_H, FLD_L); 459 1.1 christos break; 460 1.1 christos case AARCH64_OPND_QLF_S_D: 461 1.1 christos /* H */ 462 1.1 christos info->reglane.index = extract_field (FLD_H, code, 0); 463 1.8 christos break; 464 1.6 christos default: 465 1.6 christos return false; 466 1.6 christos } 467 1.6 christos 468 1.6 christos if (inst->opcode->op == OP_FCMLA_ELEM 469 1.6 christos && info->qualifier != AARCH64_OPND_QLF_S_H) 470 1.6 christos { 471 1.8 christos /* Complex operand takes two elements. */ 472 1.6 christos if (info->reglane.index & 1) 473 1.1 christos return false; 474 1.1 christos info->reglane.index /= 2; 475 1.1 christos } 476 1.8 christos } 477 1.1 christos 478 1.1 christos return true; 479 1.8 christos } 480 1.1 christos 481 1.1 christos bool 482 1.6 christos aarch64_ext_reglist (const aarch64_operand *self, aarch64_opnd_info *info, 483 1.6 christos const aarch64_insn code, 484 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 485 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 486 1.1 christos { 487 1.1 christos /* R */ 488 1.1 christos info->reglist.first_regno = extract_field (self->fields[0], code, 0); 489 1.9 christos /* len */ 490 1.8 christos info->reglist.num_regs = extract_field (FLD_len, code, 0) + 1; 491 1.1 christos info->reglist.stride = 1; 492 1.1 christos return true; 493 1.1 christos } 494 1.8 christos 495 1.1 christos /* Decode Rt and opcode fields of Vt in AdvSIMD load/store instructions. */ 496 1.1 christos bool 497 1.6 christos aarch64_ext_ldst_reglist (const aarch64_operand *self ATTRIBUTE_UNUSED, 498 1.6 christos aarch64_opnd_info *info, const aarch64_insn code, 499 1.1 christos const aarch64_inst *inst, 500 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 501 1.1 christos { 502 1.1 christos aarch64_insn value; 503 1.1 christos /* Number of elements in each structure to be loaded/stored. */ 504 1.1 christos unsigned expected_num = get_opcode_dependent_value (inst->opcode); 505 1.1 christos 506 1.1 christos struct 507 1.1 christos { 508 1.1 christos unsigned is_reserved; 509 1.1 christos unsigned num_regs; 510 1.1 christos unsigned num_elements; 511 1.1 christos } data [] = 512 1.1 christos { {0, 4, 4}, 513 1.1 christos {1, 4, 4}, 514 1.1 christos {0, 4, 1}, 515 1.1 christos {0, 4, 2}, 516 1.1 christos {0, 3, 3}, 517 1.1 christos {1, 3, 3}, 518 1.1 christos {0, 3, 1}, 519 1.1 christos {0, 1, 1}, 520 1.1 christos {0, 2, 2}, 521 1.1 christos {1, 2, 2}, 522 1.1 christos {0, 2, 1}, 523 1.1 christos }; 524 1.1 christos 525 1.1 christos /* Rt */ 526 1.1 christos info->reglist.first_regno = extract_field (FLD_Rt, code, 0); 527 1.6 christos /* opcode */ 528 1.6 christos value = extract_field (FLD_opcode, code, 0); 529 1.8 christos /* PR 21595: Check for a bogus value. */ 530 1.1 christos if (value >= ARRAY_SIZE (data)) 531 1.8 christos return false; 532 1.1 christos if (expected_num != data[value].num_elements || data[value].is_reserved) 533 1.9 christos return false; 534 1.1 christos info->reglist.num_regs = data[value].num_regs; 535 1.8 christos info->reglist.stride = 1; 536 1.1 christos 537 1.1 christos return true; 538 1.1 christos } 539 1.1 christos 540 1.8 christos /* Decode Rt and S fields of Vt in AdvSIMD load single structure to all 541 1.1 christos lanes instructions. */ 542 1.1 christos bool 543 1.6 christos aarch64_ext_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED, 544 1.6 christos aarch64_opnd_info *info, const aarch64_insn code, 545 1.1 christos const aarch64_inst *inst, 546 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 547 1.1 christos { 548 1.1 christos aarch64_insn value; 549 1.1 christos 550 1.1 christos /* Rt */ 551 1.1 christos info->reglist.first_regno = extract_field (FLD_Rt, code, 0); 552 1.1 christos /* S */ 553 1.1 christos value = extract_field (FLD_S, code, 0); 554 1.1 christos 555 1.1 christos /* Number of registers is equal to the number of elements in 556 1.1 christos each structure to be loaded/stored. */ 557 1.1 christos info->reglist.num_regs = get_opcode_dependent_value (inst->opcode); 558 1.1 christos assert (info->reglist.num_regs >= 1 && info->reglist.num_regs <= 4); 559 1.1 christos 560 1.1 christos /* Except when it is LD1R. */ 561 1.1 christos if (info->reglist.num_regs == 1 && value == (aarch64_insn) 1) 562 1.9 christos info->reglist.num_regs = 2; 563 1.8 christos 564 1.1 christos info->reglist.stride = 1; 565 1.1 christos return true; 566 1.10 christos } 567 1.10 christos 568 1.10 christos /* Decode AdvSIMD vector register list for AdvSIMD lut instructions. 569 1.10 christos The number of of registers in the list is determined by the opcode 570 1.10 christos flag. */ 571 1.10 christos bool 572 1.10 christos aarch64_ext_lut_reglist (const aarch64_operand *self, aarch64_opnd_info *info, 573 1.10 christos const aarch64_insn code, 574 1.10 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 575 1.10 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 576 1.10 christos { 577 1.10 christos info->reglist.first_regno = extract_field (self->fields[0], code, 0); 578 1.10 christos info->reglist.num_regs = get_opcode_dependent_value (inst->opcode); 579 1.10 christos info->reglist.stride = 1; 580 1.10 christos return true; 581 1.1 christos } 582 1.1 christos 583 1.8 christos /* Decode Q, opcode<2:1>, S, size and Rt fields of Vt in AdvSIMD 584 1.1 christos load/store single element instructions. */ 585 1.1 christos bool 586 1.6 christos aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED, 587 1.6 christos aarch64_opnd_info *info, const aarch64_insn code, 588 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 589 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 590 1.1 christos { 591 1.1 christos aarch64_field field = {0, 0}; 592 1.1 christos aarch64_insn QSsize; /* fields Q:S:size. */ 593 1.1 christos aarch64_insn opcodeh2; /* opcode<2:1> */ 594 1.1 christos 595 1.1 christos /* Rt */ 596 1.1 christos info->reglist.first_regno = extract_field (FLD_Rt, code, 0); 597 1.1 christos 598 1.1 christos /* Decode the index, opcode<2:1> and size. */ 599 1.1 christos gen_sub_field (FLD_asisdlso_opcode, 1, 2, &field); 600 1.1 christos opcodeh2 = extract_field_2 (&field, code, 0); 601 1.1 christos QSsize = extract_fields (code, 0, 3, FLD_Q, FLD_S, FLD_vldst_size); 602 1.1 christos switch (opcodeh2) 603 1.1 christos { 604 1.1 christos case 0x0: 605 1.1 christos info->qualifier = AARCH64_OPND_QLF_S_B; 606 1.1 christos /* Index encoded in "Q:S:size". */ 607 1.1 christos info->reglist.index = QSsize; 608 1.3 christos break; 609 1.3 christos case 0x1: 610 1.8 christos if (QSsize & 0x1) 611 1.1 christos /* UND. */ 612 1.1 christos return false; 613 1.1 christos info->qualifier = AARCH64_OPND_QLF_S_H; 614 1.1 christos /* Index encoded in "Q:S:size<1>". */ 615 1.1 christos info->reglist.index = QSsize >> 1; 616 1.3 christos break; 617 1.3 christos case 0x2: 618 1.8 christos if ((QSsize >> 1) & 0x1) 619 1.1 christos /* UND. */ 620 1.1 christos return false; 621 1.1 christos if ((QSsize & 0x1) == 0) 622 1.1 christos { 623 1.1 christos info->qualifier = AARCH64_OPND_QLF_S_S; 624 1.1 christos /* Index encoded in "Q:S". */ 625 1.1 christos info->reglist.index = QSsize >> 2; 626 1.1 christos } 627 1.3 christos else 628 1.3 christos { 629 1.8 christos if (extract_field (FLD_S, code, 0)) 630 1.1 christos /* UND */ 631 1.1 christos return false; 632 1.1 christos info->qualifier = AARCH64_OPND_QLF_S_D; 633 1.1 christos /* Index encoded in "Q". */ 634 1.1 christos info->reglist.index = QSsize >> 3; 635 1.1 christos } 636 1.8 christos break; 637 1.1 christos default: 638 1.1 christos return false; 639 1.1 christos } 640 1.1 christos 641 1.9 christos info->reglist.has_index = 1; 642 1.1 christos info->reglist.num_regs = 0; 643 1.1 christos info->reglist.stride = 1; 644 1.1 christos /* Number of registers is equal to the number of elements in 645 1.1 christos each structure to be loaded/stored. */ 646 1.1 christos info->reglist.num_regs = get_opcode_dependent_value (inst->opcode); 647 1.8 christos assert (info->reglist.num_regs >= 1 && info->reglist.num_regs <= 4); 648 1.1 christos 649 1.1 christos return true; 650 1.1 christos } 651 1.1 christos 652 1.1 christos /* Decode fields immh:immb and/or Q for e.g. 653 1.1 christos SSHR <Vd>.<T>, <Vn>.<T>, #<shift> 654 1.8 christos or SSHR <V><d>, <V><n>, #<shift>. */ 655 1.1 christos 656 1.1 christos bool 657 1.6 christos aarch64_ext_advsimd_imm_shift (const aarch64_operand *self ATTRIBUTE_UNUSED, 658 1.6 christos aarch64_opnd_info *info, const aarch64_insn code, 659 1.1 christos const aarch64_inst *inst, 660 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 661 1.1 christos { 662 1.1 christos int pos; 663 1.1 christos aarch64_insn Q, imm, immh; 664 1.1 christos enum aarch64_insn_class iclass = inst->opcode->iclass; 665 1.1 christos 666 1.8 christos immh = extract_field (FLD_immh, code, 0); 667 1.1 christos if (immh == 0) 668 1.1 christos return false; 669 1.1 christos imm = extract_fields (code, 0, 2, FLD_immh, FLD_immb); 670 1.1 christos pos = 4; 671 1.1 christos /* Get highest set bit in immh. */ 672 1.1 christos while (--pos >= 0 && (immh & 0x8) == 0) 673 1.1 christos immh <<= 1; 674 1.1 christos 675 1.1 christos assert ((iclass == asimdshf || iclass == asisdshf) 676 1.1 christos && (info->type == AARCH64_OPND_IMM_VLSR 677 1.1 christos || info->type == AARCH64_OPND_IMM_VLSL)); 678 1.1 christos 679 1.1 christos if (iclass == asimdshf) 680 1.1 christos { 681 1.1 christos Q = extract_field (FLD_Q, code, 0); 682 1.1 christos /* immh Q <T> 683 1.1 christos 0000 x SEE AdvSIMD modified immediate 684 1.1 christos 0001 0 8B 685 1.1 christos 0001 1 16B 686 1.1 christos 001x 0 4H 687 1.1 christos 001x 1 8H 688 1.1 christos 01xx 0 2S 689 1.1 christos 01xx 1 4S 690 1.1 christos 1xxx 0 RESERVED 691 1.1 christos 1xxx 1 2D */ 692 1.10 christos info->qualifier = 693 1.10 christos get_vreg_qualifier_from_value ((pos << 1) | (int) Q); 694 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR) 695 1.1 christos return false; 696 1.10 christos } 697 1.10 christos else 698 1.10 christos { 699 1.10 christos info->qualifier = get_sreg_qualifier_from_value (pos); 700 1.10 christos if (info->qualifier == AARCH64_OPND_QLF_ERR) 701 1.1 christos return 0; 702 1.1 christos } 703 1.1 christos 704 1.1 christos if (info->type == AARCH64_OPND_IMM_VLSR) 705 1.1 christos /* immh <shift> 706 1.1 christos 0000 SEE AdvSIMD modified immediate 707 1.1 christos 0001 (16-UInt(immh:immb)) 708 1.1 christos 001x (32-UInt(immh:immb)) 709 1.1 christos 01xx (64-UInt(immh:immb)) 710 1.1 christos 1xxx (128-UInt(immh:immb)) */ 711 1.1 christos info->imm.value = (16 << pos) - imm; 712 1.1 christos else 713 1.1 christos /* immh:immb 714 1.1 christos immh <shift> 715 1.1 christos 0000 SEE AdvSIMD modified immediate 716 1.1 christos 0001 (UInt(immh:immb)-8) 717 1.1 christos 001x (UInt(immh:immb)-16) 718 1.1 christos 01xx (UInt(immh:immb)-32) 719 1.1 christos 1xxx (UInt(immh:immb)-64) */ 720 1.8 christos info->imm.value = imm - (8 << pos); 721 1.1 christos 722 1.1 christos return true; 723 1.1 christos } 724 1.8 christos 725 1.1 christos /* Decode shift immediate for e.g. sshr (imm). */ 726 1.1 christos bool 727 1.6 christos aarch64_ext_shll_imm (const aarch64_operand *self ATTRIBUTE_UNUSED, 728 1.6 christos aarch64_opnd_info *info, const aarch64_insn code, 729 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 730 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 731 1.1 christos { 732 1.1 christos int64_t imm; 733 1.1 christos aarch64_insn val; 734 1.1 christos val = extract_field (FLD_size, code, 0); 735 1.1 christos switch (val) 736 1.1 christos { 737 1.1 christos case 0: imm = 8; break; 738 1.8 christos case 1: imm = 16; break; 739 1.1 christos case 2: imm = 32; break; 740 1.1 christos default: return false; 741 1.8 christos } 742 1.1 christos info->imm.value = imm; 743 1.1 christos return true; 744 1.1 christos } 745 1.1 christos 746 1.8 christos /* Decode imm for e.g. BFM <Wd>, <Wn>, #<immr>, #<imms>. 747 1.1 christos value in the field(s) will be extracted as unsigned immediate value. */ 748 1.1 christos bool 749 1.8 christos aarch64_ext_imm (const aarch64_operand *self, aarch64_opnd_info *info, 750 1.6 christos const aarch64_insn code, 751 1.1 christos const aarch64_inst *inst, 752 1.7 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 753 1.1 christos { 754 1.6 christos uint64_t imm; 755 1.1 christos 756 1.1 christos imm = extract_all_fields (self, code); 757 1.1 christos 758 1.1 christos if (operand_need_sign_extension (self)) 759 1.1 christos imm = sign_extend (imm, get_operand_fields_width (self) - 1); 760 1.1 christos 761 1.9 christos if (operand_need_shift_by_two (self)) 762 1.9 christos imm <<= 2; 763 1.7 christos else if (operand_need_shift_by_three (self)) 764 1.7 christos imm <<= 3; 765 1.1 christos else if (operand_need_shift_by_four (self)) 766 1.1 christos imm <<= 4; 767 1.1 christos 768 1.1 christos if (info->type == AARCH64_OPND_ADDR_ADRP) 769 1.8 christos imm <<= 12; 770 1.8 christos 771 1.8 christos if (inst->operands[0].type == AARCH64_OPND_PSTATEFIELD 772 1.8 christos && inst->operands[0].sysreg.flags & F_IMM_IN_CRM) 773 1.1 christos imm &= PSTATE_DECODE_CRM_IMM (inst->operands[0].sysreg.flags); 774 1.8 christos 775 1.1 christos info->imm.value = imm; 776 1.1 christos return true; 777 1.1 christos } 778 1.8 christos 779 1.1 christos /* Decode imm and its shifter for e.g. MOVZ <Wd>, #<imm16>{, LSL #<shift>}. */ 780 1.1 christos bool 781 1.6 christos aarch64_ext_imm_half (const aarch64_operand *self, aarch64_opnd_info *info, 782 1.6 christos const aarch64_insn code, 783 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 784 1.6 christos aarch64_operand_error *errors) 785 1.1 christos { 786 1.1 christos aarch64_ext_imm (self, info, code, inst, errors); 787 1.8 christos info->shifter.kind = AARCH64_MOD_LSL; 788 1.1 christos info->shifter.amount = extract_field (FLD_hw, code, 0) << 4; 789 1.1 christos return true; 790 1.1 christos } 791 1.1 christos 792 1.8 christos /* Decode cmode and "a:b:c:d:e:f:g:h" for e.g. 793 1.1 christos MOVI <Vd>.<T>, #<imm8> {, LSL #<amount>}. */ 794 1.1 christos bool 795 1.1 christos aarch64_ext_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED, 796 1.6 christos aarch64_opnd_info *info, 797 1.6 christos const aarch64_insn code, 798 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 799 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 800 1.1 christos { 801 1.1 christos uint64_t imm; 802 1.1 christos enum aarch64_opnd_qualifier opnd0_qualifier = inst->operands[0].qualifier; 803 1.1 christos aarch64_field field = {0, 0}; 804 1.1 christos 805 1.1 christos assert (info->idx == 1); 806 1.1 christos 807 1.1 christos if (info->type == AARCH64_OPND_SIMD_FPIMM) 808 1.1 christos info->imm.is_fp = 1; 809 1.1 christos 810 1.1 christos /* a:b:c:d:e:f:g:h */ 811 1.1 christos imm = extract_fields (code, 0, 2, FLD_abc, FLD_defgh); 812 1.1 christos if (!info->imm.is_fp && aarch64_get_qualifier_esize (opnd0_qualifier) == 8) 813 1.1 christos { 814 1.1 christos /* Either MOVI <Dd>, #<imm> 815 1.1 christos or MOVI <Vd>.2D, #<imm>. 816 1.1 christos <imm> is a 64-bit immediate 817 1.1 christos 'aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh', 818 1.1 christos encoded in "a:b:c:d:e:f:g:h". */ 819 1.1 christos int i; 820 1.1 christos unsigned abcdefgh = imm; 821 1.1 christos for (imm = 0ull, i = 0; i < 8; i++) 822 1.1 christos if (((abcdefgh >> i) & 0x1) != 0) 823 1.1 christos imm |= 0xffull << (8 * i); 824 1.1 christos } 825 1.1 christos info->imm.value = imm; 826 1.1 christos 827 1.10 christos /* cmode */ 828 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx); 829 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR) 830 1.1 christos return 0; 831 1.1 christos switch (info->qualifier) 832 1.1 christos { 833 1.1 christos case AARCH64_OPND_QLF_NIL: 834 1.1 christos /* no shift */ 835 1.1 christos info->shifter.kind = AARCH64_MOD_NONE; 836 1.1 christos return 1; 837 1.1 christos case AARCH64_OPND_QLF_LSL: 838 1.1 christos /* shift zeros */ 839 1.1 christos info->shifter.kind = AARCH64_MOD_LSL; 840 1.1 christos switch (aarch64_get_qualifier_esize (opnd0_qualifier)) 841 1.1 christos { 842 1.3 christos case 4: gen_sub_field (FLD_cmode, 1, 2, &field); break; /* per word */ 843 1.8 christos case 2: gen_sub_field (FLD_cmode, 1, 1, &field); break; /* per half */ 844 1.1 christos case 1: gen_sub_field (FLD_cmode, 1, 0, &field); break; /* per byte */ 845 1.1 christos default: return false; 846 1.1 christos } 847 1.1 christos /* 00: 0; 01: 8; 10:16; 11:24. */ 848 1.1 christos info->shifter.amount = extract_field_2 (&field, code, 0) << 3; 849 1.1 christos break; 850 1.1 christos case AARCH64_OPND_QLF_MSL: 851 1.1 christos /* shift ones */ 852 1.1 christos info->shifter.kind = AARCH64_MOD_MSL; 853 1.1 christos gen_sub_field (FLD_cmode, 0, 1, &field); /* per word */ 854 1.1 christos info->shifter.amount = extract_field_2 (&field, code, 0) ? 16 : 8; 855 1.8 christos break; 856 1.1 christos default: 857 1.1 christos return false; 858 1.8 christos } 859 1.6 christos 860 1.6 christos return true; 861 1.6 christos } 862 1.8 christos 863 1.6 christos /* Decode an 8-bit floating-point immediate. */ 864 1.6 christos bool 865 1.6 christos aarch64_ext_fpimm (const aarch64_operand *self, aarch64_opnd_info *info, 866 1.6 christos const aarch64_insn code, 867 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 868 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 869 1.6 christos { 870 1.8 christos info->imm.value = extract_all_fields (self, code); 871 1.6 christos info->imm.is_fp = 1; 872 1.6 christos return true; 873 1.6 christos } 874 1.8 christos 875 1.6 christos /* Decode a 1-bit rotate immediate (#90 or #270). */ 876 1.6 christos bool 877 1.6 christos aarch64_ext_imm_rotate1 (const aarch64_operand *self, aarch64_opnd_info *info, 878 1.6 christos const aarch64_insn code, 879 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 880 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 881 1.6 christos { 882 1.6 christos uint64_t rot = extract_field (self->fields[0], code, 0); 883 1.8 christos assert (rot < 2U); 884 1.6 christos info->imm.value = rot * 180 + 90; 885 1.6 christos return true; 886 1.6 christos } 887 1.8 christos 888 1.6 christos /* Decode a 2-bit rotate immediate (#0, #90, #180 or #270). */ 889 1.6 christos bool 890 1.6 christos aarch64_ext_imm_rotate2 (const aarch64_operand *self, aarch64_opnd_info *info, 891 1.6 christos const aarch64_insn code, 892 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 893 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 894 1.6 christos { 895 1.6 christos uint64_t rot = extract_field (self->fields[0], code, 0); 896 1.8 christos assert (rot < 4U); 897 1.1 christos info->imm.value = rot * 90; 898 1.1 christos return true; 899 1.1 christos } 900 1.8 christos 901 1.1 christos /* Decode scale for e.g. SCVTF <Dd>, <Wn>, #<fbits>. */ 902 1.1 christos bool 903 1.6 christos aarch64_ext_fbits (const aarch64_operand *self ATTRIBUTE_UNUSED, 904 1.6 christos aarch64_opnd_info *info, const aarch64_insn code, 905 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 906 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 907 1.8 christos { 908 1.1 christos info->imm.value = 64- extract_field (FLD_scale, code, 0); 909 1.1 christos return true; 910 1.1 christos } 911 1.1 christos 912 1.8 christos /* Decode arithmetic immediate for e.g. 913 1.1 christos SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}. */ 914 1.1 christos bool 915 1.6 christos aarch64_ext_aimm (const aarch64_operand *self ATTRIBUTE_UNUSED, 916 1.6 christos aarch64_opnd_info *info, const aarch64_insn code, 917 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 918 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 919 1.1 christos { 920 1.1 christos aarch64_insn value; 921 1.1 christos 922 1.1 christos info->shifter.kind = AARCH64_MOD_LSL; 923 1.1 christos /* shift */ 924 1.8 christos value = extract_field (FLD_shift, code, 0); 925 1.1 christos if (value >= 2) 926 1.1 christos return false; 927 1.1 christos info->shifter.amount = value ? 12 : 0; 928 1.1 christos /* imm12 (unsigned) */ 929 1.8 christos info->imm.value = extract_field (FLD_imm12, code, 0); 930 1.1 christos 931 1.1 christos return true; 932 1.6 christos } 933 1.6 christos 934 1.6 christos /* Return true if VALUE is a valid logical immediate encoding, storing the 935 1.8 christos decoded value in *RESULT if so. ESIZE is the number of bytes in the 936 1.6 christos decoded immediate. */ 937 1.1 christos static bool 938 1.1 christos decode_limm (uint32_t esize, aarch64_insn value, int64_t *result) 939 1.1 christos { 940 1.1 christos uint64_t imm, mask; 941 1.1 christos uint32_t N, R, S; 942 1.1 christos unsigned simd_size; 943 1.1 christos 944 1.1 christos /* value is N:immr:imms. */ 945 1.1 christos S = value & 0x3f; 946 1.1 christos R = (value >> 6) & 0x3f; 947 1.1 christos N = (value >> 12) & 0x1; 948 1.3 christos 949 1.1 christos /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R 950 1.1 christos (in other words, right rotated by R), then replicated. */ 951 1.1 christos if (N != 0) 952 1.1 christos { 953 1.1 christos simd_size = 64; 954 1.1 christos mask = 0xffffffffffffffffull; 955 1.1 christos } 956 1.1 christos else 957 1.1 christos { 958 1.1 christos switch (S) 959 1.1 christos { 960 1.1 christos case 0x00 ... 0x1f: /* 0xxxxx */ simd_size = 32; break; 961 1.1 christos case 0x20 ... 0x2f: /* 10xxxx */ simd_size = 16; S &= 0xf; break; 962 1.1 christos case 0x30 ... 0x37: /* 110xxx */ simd_size = 8; S &= 0x7; break; 963 1.8 christos case 0x38 ... 0x3b: /* 1110xx */ simd_size = 4; S &= 0x3; break; 964 1.1 christos case 0x3c ... 0x3d: /* 11110x */ simd_size = 2; S &= 0x1; break; 965 1.1 christos default: return false; 966 1.1 christos } 967 1.1 christos mask = (1ull << simd_size) - 1; 968 1.1 christos /* Top bits are IGNORED. */ 969 1.6 christos R &= simd_size - 1; 970 1.6 christos } 971 1.8 christos 972 1.6 christos if (simd_size > esize * 8) 973 1.1 christos return false; 974 1.1 christos 975 1.8 christos /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */ 976 1.1 christos if (S == simd_size - 1) 977 1.1 christos return false; 978 1.1 christos /* S+1 consecutive bits to 1. */ 979 1.1 christos /* NOTE: S can't be 63 due to detection above. */ 980 1.1 christos imm = (1ull << (S + 1)) - 1; 981 1.1 christos /* Rotate to the left by simd_size - R. */ 982 1.1 christos if (R != 0) 983 1.1 christos imm = ((imm << (simd_size - R)) & mask) | (imm >> R); 984 1.1 christos /* Replicate the value according to SIMD size. */ 985 1.1 christos switch (simd_size) 986 1.6 christos { 987 1.1 christos case 2: imm = (imm << 2) | imm; 988 1.6 christos /* Fall through. */ 989 1.1 christos case 4: imm = (imm << 4) | imm; 990 1.6 christos /* Fall through. */ 991 1.1 christos case 8: imm = (imm << 8) | imm; 992 1.6 christos /* Fall through. */ 993 1.1 christos case 16: imm = (imm << 16) | imm; 994 1.6 christos /* Fall through. */ 995 1.1 christos case 32: imm = (imm << 32) | imm; 996 1.8 christos /* Fall through. */ 997 1.1 christos case 64: break; 998 1.1 christos default: return 0; 999 1.6 christos } 1000 1.6 christos 1001 1.8 christos *result = imm & ~((uint64_t) -1 << (esize * 4) << (esize * 4)); 1002 1.6 christos 1003 1.6 christos return true; 1004 1.6 christos } 1005 1.8 christos 1006 1.6 christos /* Decode a logical immediate for e.g. ORR <Wd|WSP>, <Wn>, #<imm>. */ 1007 1.6 christos bool 1008 1.6 christos aarch64_ext_limm (const aarch64_operand *self, 1009 1.6 christos aarch64_opnd_info *info, const aarch64_insn code, 1010 1.6 christos const aarch64_inst *inst, 1011 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1012 1.6 christos { 1013 1.6 christos uint32_t esize; 1014 1.6 christos aarch64_insn value; 1015 1.6 christos 1016 1.6 christos value = extract_fields (code, 0, 3, self->fields[0], self->fields[1], 1017 1.6 christos self->fields[2]); 1018 1.6 christos esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier); 1019 1.1 christos return decode_limm (esize, value, &info->imm.value); 1020 1.6 christos } 1021 1.8 christos 1022 1.6 christos /* Decode a logical immediate for the BIC alias of AND (etc.). */ 1023 1.6 christos bool 1024 1.6 christos aarch64_ext_inv_limm (const aarch64_operand *self, 1025 1.6 christos aarch64_opnd_info *info, const aarch64_insn code, 1026 1.6 christos const aarch64_inst *inst, 1027 1.6 christos aarch64_operand_error *errors) 1028 1.8 christos { 1029 1.6 christos if (!aarch64_ext_limm (self, info, code, inst, errors)) 1030 1.8 christos return false; 1031 1.1 christos info->imm.value = ~info->imm.value; 1032 1.1 christos return true; 1033 1.1 christos } 1034 1.1 christos 1035 1.8 christos /* Decode Ft for e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}] 1036 1.1 christos or LDP <Qt1>, <Qt2>, [<Xn|SP>], #<imm>. */ 1037 1.1 christos bool 1038 1.6 christos aarch64_ext_ft (const aarch64_operand *self ATTRIBUTE_UNUSED, 1039 1.6 christos aarch64_opnd_info *info, 1040 1.1 christos const aarch64_insn code, const aarch64_inst *inst, 1041 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1042 1.1 christos { 1043 1.1 christos aarch64_insn value; 1044 1.1 christos 1045 1.1 christos /* Rt */ 1046 1.1 christos info->reg.regno = extract_field (FLD_Rt, code, 0); 1047 1.1 christos 1048 1.1 christos /* size */ 1049 1.1 christos value = extract_field (FLD_ldst_size, code, 0); 1050 1.1 christos if (inst->opcode->iclass == ldstpair_indexed 1051 1.1 christos || inst->opcode->iclass == ldstnapair_offs 1052 1.1 christos || inst->opcode->iclass == ldstpair_off 1053 1.1 christos || inst->opcode->iclass == loadlit) 1054 1.1 christos { 1055 1.1 christos enum aarch64_opnd_qualifier qualifier; 1056 1.1 christos switch (value) 1057 1.1 christos { 1058 1.1 christos case 0: qualifier = AARCH64_OPND_QLF_S_S; break; 1059 1.8 christos case 1: qualifier = AARCH64_OPND_QLF_S_D; break; 1060 1.1 christos case 2: qualifier = AARCH64_OPND_QLF_S_Q; break; 1061 1.1 christos default: return false; 1062 1.1 christos } 1063 1.1 christos info->qualifier = qualifier; 1064 1.1 christos } 1065 1.1 christos else 1066 1.1 christos { 1067 1.1 christos /* opc1:size */ 1068 1.8 christos value = extract_fields (code, 0, 2, FLD_opc1, FLD_ldst_size); 1069 1.1 christos if (value > 0x4) 1070 1.10 christos return false; 1071 1.10 christos info->qualifier = get_sreg_qualifier_from_value (value); 1072 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR) 1073 1.1 christos return false; 1074 1.8 christos } 1075 1.1 christos 1076 1.1 christos return true; 1077 1.1 christos } 1078 1.8 christos 1079 1.1 christos /* Decode the address operand for e.g. STXRB <Ws>, <Wt>, [<Xn|SP>{,#0}]. */ 1080 1.1 christos bool 1081 1.1 christos aarch64_ext_addr_simple (const aarch64_operand *self ATTRIBUTE_UNUSED, 1082 1.6 christos aarch64_opnd_info *info, 1083 1.6 christos aarch64_insn code, 1084 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1085 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1086 1.1 christos { 1087 1.8 christos /* Rn */ 1088 1.6 christos info->addr.base_regno = extract_field (FLD_Rn, code, 0); 1089 1.6 christos return true; 1090 1.9 christos } 1091 1.9 christos 1092 1.9 christos /* Decode the address operand for rcpc3 instructions with optional load/store 1093 1.9 christos datasize offset, e.g. STILPP <Xs>, <Xt>, [<Xn|SP>{,#-16}]! and 1094 1.9 christos LIDAP <Xs>, <Xt>, [<Xn|SP>]{,#-16}. */ 1095 1.9 christos bool 1096 1.9 christos aarch64_ext_rcpc3_addr_opt_offset (const aarch64_operand *self ATTRIBUTE_UNUSED, 1097 1.9 christos aarch64_opnd_info *info, 1098 1.9 christos aarch64_insn code, 1099 1.9 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1100 1.9 christos aarch64_operand_error *err ATTRIBUTE_UNUSED) 1101 1.9 christos { 1102 1.9 christos info->addr.base_regno = extract_field (FLD_Rn, code, 0); 1103 1.9 christos if (!extract_field (FLD_opc2, code, 0)) 1104 1.9 christos { 1105 1.9 christos info->addr.writeback = 1; 1106 1.9 christos 1107 1.9 christos enum aarch64_opnd type; 1108 1.9 christos for (int i = 0; i < AARCH64_MAX_OPND_NUM; i++) 1109 1.9 christos { 1110 1.9 christos aarch64_opnd_info opnd = info[i]; 1111 1.9 christos type = opnd.type; 1112 1.9 christos if (aarch64_operands[type].op_class == AARCH64_OPND_CLASS_ADDRESS) 1113 1.9 christos break; 1114 1.9 christos } 1115 1.9 christos 1116 1.9 christos assert (aarch64_operands[type].op_class == AARCH64_OPND_CLASS_ADDRESS); 1117 1.9 christos int offset = calc_ldst_datasize (inst->operands); 1118 1.9 christos 1119 1.9 christos switch (type) 1120 1.9 christos { 1121 1.9 christos case AARCH64_OPND_RCPC3_ADDR_OPT_PREIND_WB: 1122 1.9 christos case AARCH64_OPND_RCPC3_ADDR_PREIND_WB: 1123 1.9 christos info->addr.offset.imm = -offset; 1124 1.9 christos info->addr.preind = 1; 1125 1.9 christos break; 1126 1.9 christos case AARCH64_OPND_RCPC3_ADDR_OPT_POSTIND: 1127 1.9 christos case AARCH64_OPND_RCPC3_ADDR_POSTIND: 1128 1.9 christos info->addr.offset.imm = offset; 1129 1.9 christos info->addr.postind = 1; 1130 1.9 christos break; 1131 1.9 christos default: 1132 1.9 christos return false; 1133 1.9 christos } 1134 1.9 christos } 1135 1.9 christos return true; 1136 1.9 christos } 1137 1.9 christos 1138 1.9 christos bool 1139 1.9 christos aarch64_ext_rcpc3_addr_offset (const aarch64_operand *self ATTRIBUTE_UNUSED, 1140 1.9 christos aarch64_opnd_info *info, 1141 1.9 christos aarch64_insn code, 1142 1.9 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1143 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1144 1.10 christos { 1145 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx); 1146 1.9 christos if (info->qualifier == AARCH64_OPND_QLF_ERR) 1147 1.9 christos return 0; 1148 1.9 christos 1149 1.9 christos /* Rn */ 1150 1.9 christos info->addr.base_regno = extract_field (self->fields[0], code, 0); 1151 1.9 christos 1152 1.9 christos /* simm9 */ 1153 1.9 christos aarch64_insn imm = extract_fields (code, 0, 1, self->fields[1]); 1154 1.9 christos info->addr.offset.imm = sign_extend (imm, 8); 1155 1.9 christos return true; 1156 1.6 christos } 1157 1.6 christos 1158 1.8 christos /* Decode the address operand for e.g. 1159 1.6 christos stlur <Xt>, [<Xn|SP>{, <amount>}]. */ 1160 1.6 christos bool 1161 1.6 christos aarch64_ext_addr_offset (const aarch64_operand *self ATTRIBUTE_UNUSED, 1162 1.6 christos aarch64_opnd_info *info, 1163 1.6 christos aarch64_insn code, const aarch64_inst *inst, 1164 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1165 1.10 christos { 1166 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx); 1167 1.6 christos if (info->qualifier == AARCH64_OPND_QLF_ERR) 1168 1.6 christos return 0; 1169 1.6 christos 1170 1.6 christos /* Rn */ 1171 1.6 christos info->addr.base_regno = extract_field (self->fields[0], code, 0); 1172 1.6 christos 1173 1.6 christos /* simm9 */ 1174 1.6 christos aarch64_insn imm = extract_fields (code, 0, 1, self->fields[1]); 1175 1.6 christos info->addr.offset.imm = sign_extend (imm, 8); 1176 1.6 christos if (extract_field (self->fields[2], code, 0) == 1) { 1177 1.6 christos info->addr.writeback = 1; 1178 1.8 christos info->addr.preind = 1; 1179 1.1 christos } 1180 1.1 christos return true; 1181 1.1 christos } 1182 1.1 christos 1183 1.8 christos /* Decode the address operand for e.g. 1184 1.1 christos STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */ 1185 1.1 christos bool 1186 1.6 christos aarch64_ext_addr_regoff (const aarch64_operand *self ATTRIBUTE_UNUSED, 1187 1.6 christos aarch64_opnd_info *info, 1188 1.1 christos aarch64_insn code, const aarch64_inst *inst, 1189 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1190 1.1 christos { 1191 1.1 christos aarch64_insn S, value; 1192 1.1 christos 1193 1.1 christos /* Rn */ 1194 1.1 christos info->addr.base_regno = extract_field (FLD_Rn, code, 0); 1195 1.1 christos /* Rm */ 1196 1.1 christos info->addr.offset.regno = extract_field (FLD_Rm, code, 0); 1197 1.1 christos /* option */ 1198 1.8 christos value = extract_field (FLD_option, code, 0); 1199 1.1 christos info->shifter.kind = 1200 1.1 christos aarch64_get_operand_modifier_from_value (value, true /* extend_p */); 1201 1.1 christos /* Fix-up the shifter kind; although the table-driven approach is 1202 1.1 christos efficient, it is slightly inflexible, thus needing this fix-up. */ 1203 1.1 christos if (info->shifter.kind == AARCH64_MOD_UXTX) 1204 1.1 christos info->shifter.kind = AARCH64_MOD_LSL; 1205 1.1 christos /* S */ 1206 1.1 christos S = extract_field (FLD_S, code, 0); 1207 1.1 christos if (S == 0) 1208 1.1 christos { 1209 1.1 christos info->shifter.amount = 0; 1210 1.1 christos info->shifter.amount_present = 0; 1211 1.1 christos } 1212 1.1 christos else 1213 1.1 christos { 1214 1.1 christos int size; 1215 1.1 christos /* Need information in other operand(s) to help achieve the decoding 1216 1.10 christos from 'S' field. */ 1217 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx); 1218 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR) 1219 1.1 christos return 0; 1220 1.1 christos /* Get the size of the data element that is accessed, which may be 1221 1.1 christos different from that of the source register size, e.g. in strb/ldrb. */ 1222 1.1 christos size = aarch64_get_qualifier_esize (info->qualifier); 1223 1.1 christos info->shifter.amount = get_logsz (size); 1224 1.1 christos info->shifter.amount_present = 1; 1225 1.8 christos } 1226 1.1 christos 1227 1.1 christos return true; 1228 1.1 christos } 1229 1.8 christos 1230 1.1 christos /* Decode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>], #<simm>. */ 1231 1.6 christos bool 1232 1.6 christos aarch64_ext_addr_simm (const aarch64_operand *self, aarch64_opnd_info *info, 1233 1.1 christos aarch64_insn code, const aarch64_inst *inst, 1234 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1235 1.1 christos { 1236 1.10 christos aarch64_insn imm; 1237 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx); 1238 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR) 1239 1.1 christos return 0; 1240 1.1 christos 1241 1.1 christos /* Rn */ 1242 1.1 christos info->addr.base_regno = extract_field (FLD_Rn, code, 0); 1243 1.1 christos /* simm (imm9 or imm7) */ 1244 1.7 christos imm = extract_field (self->fields[0], code, 0); 1245 1.7 christos info->addr.offset.imm = sign_extend (imm, fields[self->fields[0]].width - 1); 1246 1.1 christos if (self->fields[0] == FLD_imm7 1247 1.1 christos || info->qualifier == AARCH64_OPND_QLF_imm_tag) 1248 1.1 christos /* scaled immediate in ld/st pair instructions. */ 1249 1.1 christos info->addr.offset.imm *= aarch64_get_qualifier_esize (info->qualifier); 1250 1.1 christos /* qualifier */ 1251 1.1 christos if (inst->opcode->iclass == ldst_unscaled 1252 1.1 christos || inst->opcode->iclass == ldstnapair_offs 1253 1.1 christos || inst->opcode->iclass == ldstpair_off 1254 1.1 christos || inst->opcode->iclass == ldst_unpriv) 1255 1.1 christos info->addr.writeback = 0; 1256 1.1 christos else 1257 1.1 christos { 1258 1.1 christos /* pre/post- index */ 1259 1.1 christos info->addr.writeback = 1; 1260 1.1 christos if (extract_field (self->fields[1], code, 0) == 1) 1261 1.1 christos info->addr.preind = 1; 1262 1.1 christos else 1263 1.1 christos info->addr.postind = 1; 1264 1.8 christos } 1265 1.1 christos 1266 1.1 christos return true; 1267 1.1 christos } 1268 1.8 christos 1269 1.1 christos /* Decode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>{, #<simm>}]. */ 1270 1.1 christos bool 1271 1.6 christos aarch64_ext_addr_uimm12 (const aarch64_operand *self, aarch64_opnd_info *info, 1272 1.6 christos aarch64_insn code, 1273 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1274 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1275 1.1 christos { 1276 1.10 christos int shift; 1277 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx); 1278 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR) 1279 1.1 christos return 0; 1280 1.1 christos shift = get_logsz (aarch64_get_qualifier_esize (info->qualifier)); 1281 1.1 christos /* Rn */ 1282 1.1 christos info->addr.base_regno = extract_field (self->fields[0], code, 0); 1283 1.8 christos /* uimm12 */ 1284 1.6 christos info->addr.offset.imm = extract_field (self->fields[1], code, 0) << shift; 1285 1.6 christos return true; 1286 1.6 christos } 1287 1.8 christos 1288 1.6 christos /* Decode the address operand for e.g. LDRAA <Xt>, [<Xn|SP>{, #<simm>}]. */ 1289 1.6 christos bool 1290 1.6 christos aarch64_ext_addr_simm10 (const aarch64_operand *self, aarch64_opnd_info *info, 1291 1.6 christos aarch64_insn code, 1292 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1293 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1294 1.6 christos { 1295 1.6 christos aarch64_insn imm; 1296 1.10 christos 1297 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx); 1298 1.6 christos if (info->qualifier == AARCH64_OPND_QLF_ERR) 1299 1.6 christos return 0; 1300 1.6 christos /* Rn */ 1301 1.6 christos info->addr.base_regno = extract_field (self->fields[0], code, 0); 1302 1.6 christos /* simm10 */ 1303 1.6 christos imm = extract_fields (code, 0, 2, self->fields[1], self->fields[2]); 1304 1.6 christos info->addr.offset.imm = sign_extend (imm, 9) << 3; 1305 1.6 christos if (extract_field (self->fields[3], code, 0) == 1) { 1306 1.6 christos info->addr.writeback = 1; 1307 1.8 christos info->addr.preind = 1; 1308 1.1 christos } 1309 1.1 christos return true; 1310 1.1 christos } 1311 1.1 christos 1312 1.8 christos /* Decode the address operand for e.g. 1313 1.1 christos LD1 {<Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>}, [<Xn|SP>], <Xm|#<amount>>. */ 1314 1.1 christos bool 1315 1.6 christos aarch64_ext_simd_addr_post (const aarch64_operand *self ATTRIBUTE_UNUSED, 1316 1.6 christos aarch64_opnd_info *info, 1317 1.1 christos aarch64_insn code, const aarch64_inst *inst, 1318 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1319 1.1 christos { 1320 1.1 christos /* The opcode dependent area stores the number of elements in 1321 1.1 christos each structure to be loaded/stored. */ 1322 1.1 christos int is_ld1r = get_opcode_dependent_value (inst->opcode) == 1; 1323 1.1 christos 1324 1.1 christos /* Rn */ 1325 1.1 christos info->addr.base_regno = extract_field (FLD_Rn, code, 0); 1326 1.1 christos /* Rm | #<amount> */ 1327 1.1 christos info->addr.offset.regno = extract_field (FLD_Rm, code, 0); 1328 1.1 christos if (info->addr.offset.regno == 31) 1329 1.1 christos { 1330 1.1 christos if (inst->opcode->operands[0] == AARCH64_OPND_LVt_AL) 1331 1.1 christos /* Special handling of loading single structure to all lane. */ 1332 1.1 christos info->addr.offset.imm = (is_ld1r ? 1 1333 1.1 christos : inst->operands[0].reglist.num_regs) 1334 1.1 christos * aarch64_get_qualifier_esize (inst->operands[0].qualifier); 1335 1.1 christos else 1336 1.1 christos info->addr.offset.imm = inst->operands[0].reglist.num_regs 1337 1.1 christos * aarch64_get_qualifier_esize (inst->operands[0].qualifier) 1338 1.1 christos * aarch64_get_qualifier_nelem (inst->operands[0].qualifier); 1339 1.1 christos } 1340 1.1 christos else 1341 1.1 christos info->addr.offset.is_reg = 1; 1342 1.8 christos info->addr.writeback = 1; 1343 1.1 christos 1344 1.1 christos return true; 1345 1.1 christos } 1346 1.8 christos 1347 1.1 christos /* Decode the condition operand for e.g. CSEL <Xd>, <Xn>, <Xm>, <cond>. */ 1348 1.1 christos bool 1349 1.6 christos aarch64_ext_cond (const aarch64_operand *self ATTRIBUTE_UNUSED, 1350 1.6 christos aarch64_opnd_info *info, 1351 1.1 christos aarch64_insn code, const aarch64_inst *inst ATTRIBUTE_UNUSED, 1352 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1353 1.1 christos { 1354 1.1 christos aarch64_insn value; 1355 1.1 christos /* cond */ 1356 1.8 christos value = extract_field (FLD_cond, code, 0); 1357 1.1 christos info->cond = get_cond_from_value (value); 1358 1.1 christos return true; 1359 1.1 christos } 1360 1.8 christos 1361 1.1 christos /* Decode the system register operand for e.g. MRS <Xt>, <systemreg>. */ 1362 1.1 christos bool 1363 1.1 christos aarch64_ext_sysreg (const aarch64_operand *self ATTRIBUTE_UNUSED, 1364 1.6 christos aarch64_opnd_info *info, 1365 1.6 christos aarch64_insn code, 1366 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1367 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1368 1.6 christos { 1369 1.6 christos /* op0:op1:CRn:CRm:op2 */ 1370 1.6 christos info->sysreg.value = extract_fields (code, 0, 5, FLD_op0, FLD_op1, FLD_CRn, 1371 1.6 christos FLD_CRm, FLD_op2); 1372 1.6 christos info->sysreg.flags = 0; 1373 1.6 christos 1374 1.6 christos /* If a system instruction, check which restrictions should be on the register 1375 1.6 christos value during decoding, these will be enforced then. */ 1376 1.6 christos if (inst->opcode->iclass == ic_system) 1377 1.6 christos { 1378 1.6 christos /* Check to see if it's read-only, else check if it's write only. 1379 1.6 christos if it's both or unspecified don't care. */ 1380 1.6 christos if ((inst->opcode->flags & (F_SYS_READ | F_SYS_WRITE)) == F_SYS_READ) 1381 1.6 christos info->sysreg.flags = F_REG_READ; 1382 1.6 christos else if ((inst->opcode->flags & (F_SYS_READ | F_SYS_WRITE)) 1383 1.6 christos == F_SYS_WRITE) 1384 1.6 christos info->sysreg.flags = F_REG_WRITE; 1385 1.8 christos } 1386 1.1 christos 1387 1.1 christos return true; 1388 1.1 christos } 1389 1.8 christos 1390 1.1 christos /* Decode the PSTATE field operand for e.g. MSR <pstatefield>, #<imm>. */ 1391 1.1 christos bool 1392 1.6 christos aarch64_ext_pstatefield (const aarch64_operand *self ATTRIBUTE_UNUSED, 1393 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 1394 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1395 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1396 1.8 christos { 1397 1.1 christos int i; 1398 1.1 christos aarch64_insn fld_crm = extract_field (FLD_CRm, code, 0); 1399 1.1 christos /* op1:op2 */ 1400 1.1 christos info->pstatefield = extract_fields (code, 0, 2, FLD_op1, FLD_op2); 1401 1.8 christos for (i = 0; aarch64_pstatefields[i].name != NULL; ++i) 1402 1.8 christos if (aarch64_pstatefields[i].value == (aarch64_insn)info->pstatefield) 1403 1.8 christos { 1404 1.8 christos /* PSTATEFIELD name can be encoded partially in CRm[3:1]. */ 1405 1.8 christos uint32_t flags = aarch64_pstatefields[i].flags; 1406 1.8 christos if ((flags & F_REG_IN_CRM) 1407 1.8 christos && ((fld_crm & 0xe) != PSTATE_DECODE_CRM (flags))) 1408 1.8 christos continue; 1409 1.8 christos info->sysreg.flags = flags; 1410 1.1 christos return true; 1411 1.8 christos } 1412 1.1 christos /* Reserved value in <pstatefield>. */ 1413 1.1 christos return false; 1414 1.1 christos } 1415 1.8 christos 1416 1.1 christos /* Decode the system instruction op operand for e.g. AT <at_op>, <Xt>. */ 1417 1.1 christos bool 1418 1.1 christos aarch64_ext_sysins_op (const aarch64_operand *self ATTRIBUTE_UNUSED, 1419 1.6 christos aarch64_opnd_info *info, 1420 1.6 christos aarch64_insn code, 1421 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1422 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1423 1.1 christos { 1424 1.1 christos int i; 1425 1.1 christos aarch64_insn value; 1426 1.1 christos const aarch64_sys_ins_reg *sysins_ops; 1427 1.1 christos /* op0:op1:CRn:CRm:op2 */ 1428 1.1 christos value = extract_fields (code, 0, 5, 1429 1.1 christos FLD_op0, FLD_op1, FLD_CRn, 1430 1.1 christos FLD_CRm, FLD_op2); 1431 1.1 christos 1432 1.1 christos switch (info->type) 1433 1.1 christos { 1434 1.1 christos case AARCH64_OPND_SYSREG_AT: sysins_ops = aarch64_sys_regs_at; break; 1435 1.1 christos case AARCH64_OPND_SYSREG_DC: sysins_ops = aarch64_sys_regs_dc; break; 1436 1.9 christos case AARCH64_OPND_SYSREG_IC: sysins_ops = aarch64_sys_regs_ic; break; 1437 1.7 christos case AARCH64_OPND_SYSREG_TLBI: sysins_ops = aarch64_sys_regs_tlbi; break; 1438 1.7 christos case AARCH64_OPND_SYSREG_TLBIP: sysins_ops = aarch64_sys_regs_tlbi; break; 1439 1.7 christos case AARCH64_OPND_SYSREG_SR: 1440 1.7 christos sysins_ops = aarch64_sys_regs_sr; 1441 1.7 christos /* Let's remove op2 for rctx. Refer to comments in the definition of 1442 1.7 christos aarch64_sys_regs_sr[]. */ 1443 1.8 christos value = value & ~(0x7); 1444 1.1 christos break; 1445 1.1 christos default: return false; 1446 1.3 christos } 1447 1.1 christos 1448 1.1 christos for (i = 0; sysins_ops[i].name != NULL; ++i) 1449 1.1 christos if (sysins_ops[i].value == value) 1450 1.1 christos { 1451 1.3 christos info->sysins_op = sysins_ops + i; 1452 1.1 christos DEBUG_TRACE ("%s found value: %x, has_xt: %d, i: %d.", 1453 1.3 christos info->sysins_op->name, 1454 1.8 christos (unsigned)info->sysins_op->value, 1455 1.1 christos aarch64_sys_ins_reg_has_xt (info->sysins_op), i); 1456 1.1 christos return true; 1457 1.8 christos } 1458 1.1 christos 1459 1.1 christos return false; 1460 1.1 christos } 1461 1.1 christos 1462 1.8 christos /* Decode the memory barrier option operand for e.g. DMB <option>|#<imm>. */ 1463 1.1 christos 1464 1.1 christos bool 1465 1.1 christos aarch64_ext_barrier (const aarch64_operand *self ATTRIBUTE_UNUSED, 1466 1.6 christos aarch64_opnd_info *info, 1467 1.6 christos aarch64_insn code, 1468 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1469 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1470 1.1 christos { 1471 1.8 christos /* CRm */ 1472 1.8 christos info->barrier = aarch64_barrier_options + extract_field (FLD_CRm, code, 0); 1473 1.8 christos return true; 1474 1.8 christos } 1475 1.8 christos 1476 1.8 christos /* Decode the memory barrier option operand for DSB <option>nXS|#<imm>. */ 1477 1.8 christos 1478 1.8 christos bool 1479 1.8 christos aarch64_ext_barrier_dsb_nxs (const aarch64_operand *self ATTRIBUTE_UNUSED, 1480 1.8 christos aarch64_opnd_info *info, 1481 1.8 christos aarch64_insn code, 1482 1.8 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1483 1.8 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1484 1.8 christos { 1485 1.8 christos /* For the DSB nXS barrier variant immediate is encoded in 2-bit field. */ 1486 1.8 christos aarch64_insn field = extract_field (FLD_CRm_dsb_nxs, code, 0); 1487 1.1 christos info->barrier = aarch64_barrier_dsb_nxs_options + field; 1488 1.1 christos return true; 1489 1.1 christos } 1490 1.1 christos 1491 1.1 christos /* Decode the prefetch operation option operand for e.g. 1492 1.8 christos PRFM <prfop>, [<Xn|SP>{, #<pimm>}]. */ 1493 1.1 christos 1494 1.1 christos bool 1495 1.6 christos aarch64_ext_prfop (const aarch64_operand *self ATTRIBUTE_UNUSED, 1496 1.6 christos aarch64_opnd_info *info, 1497 1.1 christos aarch64_insn code, const aarch64_inst *inst ATTRIBUTE_UNUSED, 1498 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1499 1.1 christos { 1500 1.8 christos /* prfop in Rt */ 1501 1.1 christos info->prfop = aarch64_prfops + extract_field (FLD_Rt, code, 0); 1502 1.1 christos return true; 1503 1.3 christos } 1504 1.3 christos 1505 1.3 christos /* Decode the hint number for an alias taking an operand. Set info->hint_option 1506 1.8 christos to the matching name/value pair in aarch64_hint_options. */ 1507 1.3 christos 1508 1.3 christos bool 1509 1.3 christos aarch64_ext_hint (const aarch64_operand *self ATTRIBUTE_UNUSED, 1510 1.6 christos aarch64_opnd_info *info, 1511 1.6 christos aarch64_insn code, 1512 1.3 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1513 1.3 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1514 1.3 christos { 1515 1.3 christos /* CRm:op2. */ 1516 1.3 christos unsigned hint_number; 1517 1.3 christos int i; 1518 1.3 christos 1519 1.3 christos hint_number = extract_fields (code, 0, 2, FLD_CRm, FLD_op2); 1520 1.3 christos 1521 1.7 christos for (i = 0; aarch64_hint_options[i].name != NULL; i++) 1522 1.3 christos { 1523 1.3 christos if (hint_number == HINT_VAL (aarch64_hint_options[i].value)) 1524 1.8 christos { 1525 1.3 christos info->hint_option = &(aarch64_hint_options[i]); 1526 1.3 christos return true; 1527 1.3 christos } 1528 1.8 christos } 1529 1.3 christos 1530 1.3 christos return false; 1531 1.1 christos } 1532 1.1 christos 1533 1.8 christos /* Decode the extended register operand for e.g. 1534 1.1 christos STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */ 1535 1.1 christos bool 1536 1.1 christos aarch64_ext_reg_extended (const aarch64_operand *self ATTRIBUTE_UNUSED, 1537 1.6 christos aarch64_opnd_info *info, 1538 1.6 christos aarch64_insn code, 1539 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1540 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1541 1.1 christos { 1542 1.1 christos aarch64_insn value; 1543 1.1 christos 1544 1.1 christos /* Rm */ 1545 1.1 christos info->reg.regno = extract_field (FLD_Rm, code, 0); 1546 1.1 christos /* option */ 1547 1.8 christos value = extract_field (FLD_option, code, 0); 1548 1.1 christos info->shifter.kind = 1549 1.9 christos aarch64_get_operand_modifier_from_value (value, true /* extend_p */); 1550 1.1 christos /* imm3 */ 1551 1.1 christos info->shifter.amount = extract_field (FLD_imm3_10, code, 0); 1552 1.1 christos 1553 1.1 christos /* This makes the constraint checking happy. */ 1554 1.1 christos info->shifter.operator_present = 1; 1555 1.1 christos 1556 1.1 christos /* Assume inst->operands[0].qualifier has been resolved. */ 1557 1.1 christos assert (inst->operands[0].qualifier != AARCH64_OPND_QLF_NIL); 1558 1.1 christos info->qualifier = AARCH64_OPND_QLF_W; 1559 1.1 christos if (inst->operands[0].qualifier == AARCH64_OPND_QLF_X 1560 1.1 christos && (info->shifter.kind == AARCH64_MOD_UXTX 1561 1.1 christos || info->shifter.kind == AARCH64_MOD_SXTX)) 1562 1.8 christos info->qualifier = AARCH64_OPND_QLF_X; 1563 1.1 christos 1564 1.1 christos return true; 1565 1.1 christos } 1566 1.1 christos 1567 1.8 christos /* Decode the shifted register operand for e.g. 1568 1.1 christos SUBS <Xd>, <Xn>, <Xm> {, <shift> #<amount>}. */ 1569 1.1 christos bool 1570 1.1 christos aarch64_ext_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED, 1571 1.6 christos aarch64_opnd_info *info, 1572 1.6 christos aarch64_insn code, 1573 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1574 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1575 1.1 christos { 1576 1.1 christos aarch64_insn value; 1577 1.1 christos 1578 1.1 christos /* Rm */ 1579 1.1 christos info->reg.regno = extract_field (FLD_Rm, code, 0); 1580 1.1 christos /* shift */ 1581 1.8 christos value = extract_field (FLD_shift, code, 0); 1582 1.1 christos info->shifter.kind = 1583 1.1 christos aarch64_get_operand_modifier_from_value (value, false /* extend_p */); 1584 1.1 christos if (info->shifter.kind == AARCH64_MOD_ROR 1585 1.1 christos && inst->opcode->iclass != log_shift) 1586 1.8 christos /* ROR is not available for the shifted register operand in arithmetic 1587 1.1 christos instructions. */ 1588 1.9 christos return false; 1589 1.1 christos /* imm6 */ 1590 1.1 christos info->shifter.amount = extract_field (FLD_imm6_10, code, 0); 1591 1.1 christos 1592 1.1 christos /* This makes the constraint checking happy. */ 1593 1.8 christos info->shifter.operator_present = 1; 1594 1.6 christos 1595 1.6 christos return true; 1596 1.10 christos } 1597 1.10 christos 1598 1.10 christos /* Decode the LSL-shifted register operand for e.g. 1599 1.10 christos ADDPT <Xd|SP>, <Xn|SP>, <Xm>{, LSL #<amount>}. */ 1600 1.10 christos bool 1601 1.10 christos aarch64_ext_reg_lsl_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED, 1602 1.10 christos aarch64_opnd_info *info, 1603 1.10 christos aarch64_insn code, 1604 1.10 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1605 1.10 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1606 1.10 christos { 1607 1.10 christos /* Rm */ 1608 1.10 christos info->reg.regno = extract_field (FLD_Rm, code, 0); 1609 1.10 christos /* imm3 */ 1610 1.10 christos info->shifter.kind = AARCH64_MOD_LSL; 1611 1.10 christos info->shifter.amount = extract_field (FLD_imm3_10, code, 0); 1612 1.10 christos return true; 1613 1.6 christos } 1614 1.6 christos 1615 1.6 christos /* Decode an SVE address [<base>, #<offset>*<factor>, MUL VL], 1616 1.6 christos where <offset> is given by the OFFSET parameter and where <factor> is 1617 1.8 christos 1 plus SELF's operand-dependent value. fields[0] specifies the field 1618 1.6 christos that holds <base>. */ 1619 1.6 christos static bool 1620 1.6 christos aarch64_ext_sve_addr_reg_mul_vl (const aarch64_operand *self, 1621 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 1622 1.6 christos int64_t offset) 1623 1.6 christos { 1624 1.8 christos info->addr.base_regno = extract_field (self->fields[0], code, 0); 1625 1.8 christos info->addr.offset.imm = offset * (1 + get_operand_specific_data (self)); 1626 1.8 christos info->addr.offset.is_reg = false; 1627 1.6 christos info->addr.writeback = false; 1628 1.6 christos info->addr.preind = true; 1629 1.6 christos if (offset != 0) 1630 1.6 christos info->shifter.kind = AARCH64_MOD_MUL_VL; 1631 1.8 christos info->shifter.amount = 1; 1632 1.8 christos info->shifter.operator_present = (info->addr.offset.imm != 0); 1633 1.6 christos info->shifter.amount_present = false; 1634 1.6 christos return true; 1635 1.6 christos } 1636 1.6 christos 1637 1.6 christos /* Decode an SVE address [<base>, #<simm4>*<factor>, MUL VL], 1638 1.6 christos where <simm4> is a 4-bit signed value and where <factor> is 1 plus 1639 1.8 christos SELF's operand-dependent value. fields[0] specifies the field that 1640 1.6 christos holds <base>. <simm4> is encoded in the SVE_imm4 field. */ 1641 1.6 christos bool 1642 1.6 christos aarch64_ext_sve_addr_ri_s4xvl (const aarch64_operand *self, 1643 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 1644 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1645 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1646 1.6 christos { 1647 1.6 christos int offset; 1648 1.6 christos 1649 1.6 christos offset = extract_field (FLD_SVE_imm4, code, 0); 1650 1.6 christos offset = ((offset + 8) & 15) - 8; 1651 1.6 christos return aarch64_ext_sve_addr_reg_mul_vl (self, info, code, offset); 1652 1.6 christos } 1653 1.6 christos 1654 1.6 christos /* Decode an SVE address [<base>, #<simm6>*<factor>, MUL VL], 1655 1.6 christos where <simm6> is a 6-bit signed value and where <factor> is 1 plus 1656 1.8 christos SELF's operand-dependent value. fields[0] specifies the field that 1657 1.6 christos holds <base>. <simm6> is encoded in the SVE_imm6 field. */ 1658 1.6 christos bool 1659 1.6 christos aarch64_ext_sve_addr_ri_s6xvl (const aarch64_operand *self, 1660 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 1661 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1662 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1663 1.6 christos { 1664 1.6 christos int offset; 1665 1.6 christos 1666 1.6 christos offset = extract_field (FLD_SVE_imm6, code, 0); 1667 1.6 christos offset = (((offset + 32) & 63) - 32); 1668 1.6 christos return aarch64_ext_sve_addr_reg_mul_vl (self, info, code, offset); 1669 1.6 christos } 1670 1.6 christos 1671 1.6 christos /* Decode an SVE address [<base>, #<simm9>*<factor>, MUL VL], 1672 1.6 christos where <simm9> is a 9-bit signed value and where <factor> is 1 plus 1673 1.6 christos SELF's operand-dependent value. fields[0] specifies the field that 1674 1.8 christos holds <base>. <simm9> is encoded in the concatenation of the SVE_imm6 1675 1.6 christos and imm3 fields, with imm3 being the less-significant part. */ 1676 1.6 christos bool 1677 1.6 christos aarch64_ext_sve_addr_ri_s9xvl (const aarch64_operand *self, 1678 1.6 christos aarch64_opnd_info *info, 1679 1.6 christos aarch64_insn code, 1680 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1681 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1682 1.6 christos { 1683 1.9 christos int offset; 1684 1.6 christos 1685 1.6 christos offset = extract_fields (code, 0, 2, FLD_SVE_imm6, FLD_imm3_10); 1686 1.6 christos offset = (((offset + 256) & 511) - 256); 1687 1.6 christos return aarch64_ext_sve_addr_reg_mul_vl (self, info, code, offset); 1688 1.6 christos } 1689 1.6 christos 1690 1.6 christos /* Decode an SVE address [<base>, #<offset> << <shift>], where <offset> 1691 1.8 christos is given by the OFFSET parameter and where <shift> is SELF's operand- 1692 1.6 christos dependent value. fields[0] specifies the base register field <base>. */ 1693 1.6 christos static bool 1694 1.6 christos aarch64_ext_sve_addr_reg_imm (const aarch64_operand *self, 1695 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 1696 1.6 christos int64_t offset) 1697 1.6 christos { 1698 1.8 christos info->addr.base_regno = extract_field (self->fields[0], code, 0); 1699 1.8 christos info->addr.offset.imm = offset * (1 << get_operand_specific_data (self)); 1700 1.8 christos info->addr.offset.is_reg = false; 1701 1.8 christos info->addr.writeback = false; 1702 1.8 christos info->addr.preind = true; 1703 1.8 christos info->shifter.operator_present = false; 1704 1.6 christos info->shifter.amount_present = false; 1705 1.6 christos return true; 1706 1.6 christos } 1707 1.6 christos 1708 1.6 christos /* Decode an SVE address [X<n>, #<SVE_imm4> << <shift>], where <SVE_imm4> 1709 1.8 christos is a 4-bit signed number and where <shift> is SELF's operand-dependent 1710 1.6 christos value. fields[0] specifies the base register field. */ 1711 1.6 christos bool 1712 1.6 christos aarch64_ext_sve_addr_ri_s4 (const aarch64_operand *self, 1713 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 1714 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1715 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1716 1.6 christos { 1717 1.6 christos int offset = sign_extend (extract_field (FLD_SVE_imm4, code, 0), 3); 1718 1.6 christos return aarch64_ext_sve_addr_reg_imm (self, info, code, offset); 1719 1.6 christos } 1720 1.6 christos 1721 1.6 christos /* Decode an SVE address [X<n>, #<SVE_imm6> << <shift>], where <SVE_imm6> 1722 1.8 christos is a 6-bit unsigned number and where <shift> is SELF's operand-dependent 1723 1.6 christos value. fields[0] specifies the base register field. */ 1724 1.6 christos bool 1725 1.6 christos aarch64_ext_sve_addr_ri_u6 (const aarch64_operand *self, 1726 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 1727 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1728 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1729 1.6 christos { 1730 1.6 christos int offset = extract_field (FLD_SVE_imm6, code, 0); 1731 1.6 christos return aarch64_ext_sve_addr_reg_imm (self, info, code, offset); 1732 1.6 christos } 1733 1.6 christos 1734 1.6 christos /* Decode an SVE address [X<n>, X<m>{, LSL #<shift>}], where <shift> 1735 1.8 christos is SELF's operand-dependent value. fields[0] specifies the base 1736 1.6 christos register field and fields[1] specifies the offset register field. */ 1737 1.6 christos bool 1738 1.6 christos aarch64_ext_sve_addr_rr_lsl (const aarch64_operand *self, 1739 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 1740 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1741 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1742 1.6 christos { 1743 1.6 christos int index_regno; 1744 1.6 christos 1745 1.8 christos index_regno = extract_field (self->fields[1], code, 0); 1746 1.6 christos if (index_regno == 31 && (self->flags & OPD_F_NO_ZR) != 0) 1747 1.6 christos return false; 1748 1.6 christos 1749 1.8 christos info->addr.base_regno = extract_field (self->fields[0], code, 0); 1750 1.8 christos info->addr.offset.regno = index_regno; 1751 1.8 christos info->addr.offset.is_reg = true; 1752 1.6 christos info->addr.writeback = false; 1753 1.6 christos info->addr.preind = true; 1754 1.6 christos info->shifter.kind = AARCH64_MOD_LSL; 1755 1.6 christos info->shifter.amount = get_operand_specific_data (self); 1756 1.8 christos info->shifter.operator_present = (info->shifter.amount != 0); 1757 1.6 christos info->shifter.amount_present = (info->shifter.amount != 0); 1758 1.6 christos return true; 1759 1.6 christos } 1760 1.6 christos 1761 1.6 christos /* Decode an SVE address [X<n>, Z<m>.<T>, (S|U)XTW {#<shift>}], where 1762 1.6 christos <shift> is SELF's operand-dependent value. fields[0] specifies the 1763 1.8 christos base register field, fields[1] specifies the offset register field and 1764 1.6 christos fields[2] is a single-bit field that selects SXTW over UXTW. */ 1765 1.6 christos bool 1766 1.6 christos aarch64_ext_sve_addr_rz_xtw (const aarch64_operand *self, 1767 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 1768 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1769 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1770 1.6 christos { 1771 1.8 christos info->addr.base_regno = extract_field (self->fields[0], code, 0); 1772 1.8 christos info->addr.offset.regno = extract_field (self->fields[1], code, 0); 1773 1.8 christos info->addr.offset.is_reg = true; 1774 1.6 christos info->addr.writeback = false; 1775 1.6 christos info->addr.preind = true; 1776 1.6 christos if (extract_field (self->fields[2], code, 0)) 1777 1.6 christos info->shifter.kind = AARCH64_MOD_SXTW; 1778 1.6 christos else 1779 1.8 christos info->shifter.kind = AARCH64_MOD_UXTW; 1780 1.6 christos info->shifter.amount = get_operand_specific_data (self); 1781 1.8 christos info->shifter.operator_present = true; 1782 1.6 christos info->shifter.amount_present = (info->shifter.amount != 0); 1783 1.6 christos return true; 1784 1.6 christos } 1785 1.6 christos 1786 1.6 christos /* Decode an SVE address [Z<n>.<T>, #<imm5> << <shift>], where <imm5> is a 1787 1.8 christos 5-bit unsigned number and where <shift> is SELF's operand-dependent value. 1788 1.6 christos fields[0] specifies the base register field. */ 1789 1.6 christos bool 1790 1.6 christos aarch64_ext_sve_addr_zi_u5 (const aarch64_operand *self, 1791 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 1792 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1793 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1794 1.6 christos { 1795 1.6 christos int offset = extract_field (FLD_imm5, code, 0); 1796 1.6 christos return aarch64_ext_sve_addr_reg_imm (self, info, code, offset); 1797 1.6 christos } 1798 1.6 christos 1799 1.6 christos /* Decode an SVE address [Z<n>.<T>, Z<m>.<T>{, <modifier> {#<msz>}}], 1800 1.6 christos where <modifier> is given by KIND and where <msz> is a 2-bit unsigned 1801 1.8 christos number. fields[0] specifies the base register field and fields[1] 1802 1.6 christos specifies the offset register field. */ 1803 1.6 christos static bool 1804 1.6 christos aarch64_ext_sve_addr_zz (const aarch64_operand *self, aarch64_opnd_info *info, 1805 1.6 christos aarch64_insn code, enum aarch64_modifier_kind kind) 1806 1.6 christos { 1807 1.8 christos info->addr.base_regno = extract_field (self->fields[0], code, 0); 1808 1.8 christos info->addr.offset.regno = extract_field (self->fields[1], code, 0); 1809 1.8 christos info->addr.offset.is_reg = true; 1810 1.6 christos info->addr.writeback = false; 1811 1.6 christos info->addr.preind = true; 1812 1.6 christos info->shifter.kind = kind; 1813 1.6 christos info->shifter.amount = extract_field (FLD_SVE_msz, code, 0); 1814 1.6 christos info->shifter.operator_present = (kind != AARCH64_MOD_LSL 1815 1.8 christos || info->shifter.amount != 0); 1816 1.6 christos info->shifter.amount_present = (info->shifter.amount != 0); 1817 1.6 christos return true; 1818 1.6 christos } 1819 1.6 christos 1820 1.6 christos /* Decode an SVE address [Z<n>.<T>, Z<m>.<T>{, LSL #<msz>}], where 1821 1.8 christos <msz> is a 2-bit unsigned number. fields[0] specifies the base register 1822 1.6 christos field and fields[1] specifies the offset register field. */ 1823 1.6 christos bool 1824 1.6 christos aarch64_ext_sve_addr_zz_lsl (const aarch64_operand *self, 1825 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 1826 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1827 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1828 1.6 christos { 1829 1.6 christos return aarch64_ext_sve_addr_zz (self, info, code, AARCH64_MOD_LSL); 1830 1.6 christos } 1831 1.6 christos 1832 1.6 christos /* Decode an SVE address [Z<n>.<T>, Z<m>.<T>, SXTW {#<msz>}], where 1833 1.8 christos <msz> is a 2-bit unsigned number. fields[0] specifies the base register 1834 1.6 christos field and fields[1] specifies the offset register field. */ 1835 1.6 christos bool 1836 1.6 christos aarch64_ext_sve_addr_zz_sxtw (const aarch64_operand *self, 1837 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 1838 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1839 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1840 1.6 christos { 1841 1.6 christos return aarch64_ext_sve_addr_zz (self, info, code, AARCH64_MOD_SXTW); 1842 1.6 christos } 1843 1.6 christos 1844 1.6 christos /* Decode an SVE address [Z<n>.<T>, Z<m>.<T>, UXTW {#<msz>}], where 1845 1.8 christos <msz> is a 2-bit unsigned number. fields[0] specifies the base register 1846 1.6 christos field and fields[1] specifies the offset register field. */ 1847 1.6 christos bool 1848 1.6 christos aarch64_ext_sve_addr_zz_uxtw (const aarch64_operand *self, 1849 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 1850 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1851 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1852 1.6 christos { 1853 1.6 christos return aarch64_ext_sve_addr_zz (self, info, code, AARCH64_MOD_UXTW); 1854 1.6 christos } 1855 1.6 christos 1856 1.8 christos /* Finish decoding an SVE arithmetic immediate, given that INFO already 1857 1.6 christos has the raw field value and that the low 8 bits decode to VALUE. */ 1858 1.6 christos static bool 1859 1.6 christos decode_sve_aimm (aarch64_opnd_info *info, int64_t value) 1860 1.6 christos { 1861 1.6 christos info->shifter.kind = AARCH64_MOD_LSL; 1862 1.6 christos info->shifter.amount = 0; 1863 1.6 christos if (info->imm.value & 0x100) 1864 1.6 christos { 1865 1.6 christos if (value == 0) 1866 1.6 christos /* Decode 0x100 as #0, LSL #8. */ 1867 1.6 christos info->shifter.amount = 8; 1868 1.6 christos else 1869 1.6 christos value *= 256; 1870 1.6 christos } 1871 1.6 christos info->shifter.operator_present = (info->shifter.amount != 0); 1872 1.8 christos info->shifter.amount_present = (info->shifter.amount != 0); 1873 1.6 christos info->imm.value = value; 1874 1.6 christos return true; 1875 1.6 christos } 1876 1.8 christos 1877 1.6 christos /* Decode an SVE ADD/SUB immediate. */ 1878 1.6 christos bool 1879 1.6 christos aarch64_ext_sve_aimm (const aarch64_operand *self, 1880 1.6 christos aarch64_opnd_info *info, const aarch64_insn code, 1881 1.6 christos const aarch64_inst *inst, 1882 1.6 christos aarch64_operand_error *errors) 1883 1.6 christos { 1884 1.6 christos return (aarch64_ext_imm (self, info, code, inst, errors) 1885 1.6 christos && decode_sve_aimm (info, (uint8_t) info->imm.value)); 1886 1.9 christos } 1887 1.9 christos 1888 1.9 christos bool 1889 1.9 christos aarch64_ext_sve_aligned_reglist (const aarch64_operand *self, 1890 1.9 christos aarch64_opnd_info *info, aarch64_insn code, 1891 1.9 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1892 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1893 1.9 christos { 1894 1.9 christos unsigned int num_regs = get_operand_specific_data (self); 1895 1.9 christos unsigned int val = extract_field (self->fields[0], code, 0); 1896 1.9 christos info->reglist.first_regno = val * num_regs; 1897 1.9 christos info->reglist.num_regs = num_regs; 1898 1.9 christos info->reglist.stride = 1; 1899 1.9 christos return true; 1900 1.6 christos } 1901 1.8 christos 1902 1.6 christos /* Decode an SVE CPY/DUP immediate. */ 1903 1.6 christos bool 1904 1.6 christos aarch64_ext_sve_asimm (const aarch64_operand *self, 1905 1.6 christos aarch64_opnd_info *info, const aarch64_insn code, 1906 1.6 christos const aarch64_inst *inst, 1907 1.6 christos aarch64_operand_error *errors) 1908 1.6 christos { 1909 1.6 christos return (aarch64_ext_imm (self, info, code, inst, errors) 1910 1.6 christos && decode_sve_aimm (info, (int8_t) info->imm.value)); 1911 1.6 christos } 1912 1.6 christos 1913 1.8 christos /* Decode a single-bit immediate that selects between #0.5 and #1.0. 1914 1.6 christos The fields array specifies which field to use. */ 1915 1.6 christos bool 1916 1.6 christos aarch64_ext_sve_float_half_one (const aarch64_operand *self, 1917 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 1918 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1919 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1920 1.6 christos { 1921 1.6 christos if (extract_field (self->fields[0], code, 0)) 1922 1.6 christos info->imm.value = 0x3f800000; 1923 1.8 christos else 1924 1.8 christos info->imm.value = 0x3f000000; 1925 1.6 christos info->imm.is_fp = true; 1926 1.6 christos return true; 1927 1.6 christos } 1928 1.6 christos 1929 1.8 christos /* Decode a single-bit immediate that selects between #0.5 and #2.0. 1930 1.6 christos The fields array specifies which field to use. */ 1931 1.6 christos bool 1932 1.6 christos aarch64_ext_sve_float_half_two (const aarch64_operand *self, 1933 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 1934 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1935 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1936 1.6 christos { 1937 1.6 christos if (extract_field (self->fields[0], code, 0)) 1938 1.6 christos info->imm.value = 0x40000000; 1939 1.8 christos else 1940 1.8 christos info->imm.value = 0x3f000000; 1941 1.6 christos info->imm.is_fp = true; 1942 1.6 christos return true; 1943 1.6 christos } 1944 1.6 christos 1945 1.8 christos /* Decode a single-bit immediate that selects between #0.0 and #1.0. 1946 1.6 christos The fields array specifies which field to use. */ 1947 1.6 christos bool 1948 1.6 christos aarch64_ext_sve_float_zero_one (const aarch64_operand *self, 1949 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 1950 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1951 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1952 1.6 christos { 1953 1.6 christos if (extract_field (self->fields[0], code, 0)) 1954 1.6 christos info->imm.value = 0x3f800000; 1955 1.8 christos else 1956 1.8 christos info->imm.value = 0x0; 1957 1.8 christos info->imm.is_fp = true; 1958 1.8 christos return true; 1959 1.10 christos } 1960 1.10 christos 1961 1.10 christos /* Decode SME instruction such as MOVZA ZA tile slice to vector. */ 1962 1.10 christos bool 1963 1.10 christos aarch64_ext_sme_za_tile_to_vec (const aarch64_operand *self, 1964 1.10 christos aarch64_opnd_info *info, aarch64_insn code, 1965 1.10 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 1966 1.10 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 1967 1.10 christos { 1968 1.10 christos aarch64_insn Qsize; /* fields Q:S:size. */ 1969 1.10 christos int fld_v = extract_field (self->fields[0], code, 0); 1970 1.10 christos int fld_rv = extract_field (self->fields[1], code, 0); 1971 1.10 christos int fld_zan_imm = extract_field (FLD_imm4_5, code, 0); 1972 1.10 christos 1973 1.10 christos Qsize = extract_fields (inst->value, 0, 2, FLD_SME_size_22, FLD_SME_Q); 1974 1.10 christos switch (Qsize) 1975 1.10 christos { 1976 1.10 christos case 0x0: 1977 1.10 christos info->qualifier = AARCH64_OPND_QLF_S_B; 1978 1.10 christos info->indexed_za.regno = 0; 1979 1.10 christos info->indexed_za.index.imm = fld_zan_imm; 1980 1.10 christos break; 1981 1.10 christos case 0x2: 1982 1.10 christos info->qualifier = AARCH64_OPND_QLF_S_H; 1983 1.10 christos info->indexed_za.regno = fld_zan_imm >> 3; 1984 1.10 christos info->indexed_za.index.imm = fld_zan_imm & 0x07; 1985 1.10 christos break; 1986 1.10 christos case 0x4: 1987 1.10 christos info->qualifier = AARCH64_OPND_QLF_S_S; 1988 1.10 christos info->indexed_za.regno = fld_zan_imm >> 2; 1989 1.10 christos info->indexed_za.index.imm = fld_zan_imm & 0x03; 1990 1.10 christos break; 1991 1.10 christos case 0x6: 1992 1.10 christos info->qualifier = AARCH64_OPND_QLF_S_D; 1993 1.10 christos info->indexed_za.regno = fld_zan_imm >> 1; 1994 1.10 christos info->indexed_za.index.imm = fld_zan_imm & 0x01; 1995 1.10 christos break; 1996 1.10 christos case 0x7: 1997 1.10 christos info->qualifier = AARCH64_OPND_QLF_S_Q; 1998 1.10 christos info->indexed_za.regno = fld_zan_imm; 1999 1.10 christos break; 2000 1.10 christos default: 2001 1.10 christos return false; 2002 1.10 christos } 2003 1.10 christos 2004 1.10 christos info->indexed_za.index.regno = fld_rv + 12; 2005 1.10 christos info->indexed_za.v = fld_v; 2006 1.10 christos 2007 1.10 christos return true; 2008 1.8 christos } 2009 1.8 christos 2010 1.8 christos /* Decode ZA tile vector, vector indicator, vector selector, qualifier and 2011 1.8 christos immediate on numerous SME instruction fields such as MOVA. */ 2012 1.8 christos bool 2013 1.8 christos aarch64_ext_sme_za_hv_tiles (const aarch64_operand *self, 2014 1.8 christos aarch64_opnd_info *info, aarch64_insn code, 2015 1.8 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 2016 1.8 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 2017 1.8 christos { 2018 1.8 christos int fld_size = extract_field (self->fields[0], code, 0); 2019 1.8 christos int fld_q = extract_field (self->fields[1], code, 0); 2020 1.8 christos int fld_v = extract_field (self->fields[2], code, 0); 2021 1.8 christos int fld_rv = extract_field (self->fields[3], code, 0); 2022 1.8 christos int fld_zan_imm = extract_field (self->fields[4], code, 0); 2023 1.8 christos 2024 1.9 christos /* Deduce qualifier encoded in size and Q fields. */ 2025 1.9 christos if (fld_size == 0) 2026 1.9 christos { 2027 1.9 christos info->indexed_za.regno = 0; 2028 1.8 christos info->indexed_za.index.imm = fld_zan_imm; 2029 1.9 christos } 2030 1.9 christos else if (fld_size == 1) 2031 1.9 christos { 2032 1.9 christos info->indexed_za.regno = fld_zan_imm >> 3; 2033 1.8 christos info->indexed_za.index.imm = fld_zan_imm & 0x07; 2034 1.9 christos } 2035 1.9 christos else if (fld_size == 2) 2036 1.9 christos { 2037 1.9 christos info->indexed_za.regno = fld_zan_imm >> 2; 2038 1.8 christos info->indexed_za.index.imm = fld_zan_imm & 0x03; 2039 1.9 christos } 2040 1.9 christos else if (fld_size == 3 && fld_q == 0) 2041 1.9 christos { 2042 1.9 christos info->indexed_za.regno = fld_zan_imm >> 1; 2043 1.8 christos info->indexed_za.index.imm = fld_zan_imm & 0x01; 2044 1.9 christos } 2045 1.9 christos else if (fld_size == 3 && fld_q == 1) 2046 1.9 christos { 2047 1.9 christos info->indexed_za.regno = fld_zan_imm; 2048 1.9 christos info->indexed_za.index.imm = 0; 2049 1.9 christos } 2050 1.8 christos else 2051 1.9 christos return false; 2052 1.9 christos 2053 1.9 christos info->indexed_za.index.regno = fld_rv + 12; 2054 1.9 christos info->indexed_za.v = fld_v; 2055 1.9 christos 2056 1.9 christos return true; 2057 1.9 christos } 2058 1.9 christos 2059 1.9 christos bool 2060 1.9 christos aarch64_ext_sme_za_hv_tiles_range (const aarch64_operand *self, 2061 1.9 christos aarch64_opnd_info *info, aarch64_insn code, 2062 1.9 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 2063 1.9 christos aarch64_operand_error *errors 2064 1.9 christos ATTRIBUTE_UNUSED) 2065 1.9 christos { 2066 1.9 christos int ebytes = aarch64_get_qualifier_esize (info->qualifier); 2067 1.9 christos int range_size = get_opcode_dependent_value (inst->opcode); 2068 1.9 christos int fld_v = extract_field (self->fields[0], code, 0); 2069 1.9 christos int fld_rv = extract_field (self->fields[1], code, 0); 2070 1.8 christos int fld_zan_imm = extract_field (self->fields[2], code, 0); 2071 1.9 christos int max_value = 16 / range_size / ebytes; 2072 1.9 christos 2073 1.9 christos if (max_value == 0) 2074 1.9 christos max_value = 1; 2075 1.9 christos 2076 1.9 christos int regno = fld_zan_imm / max_value; 2077 1.9 christos if (regno >= ebytes) 2078 1.9 christos return false; 2079 1.9 christos 2080 1.9 christos info->indexed_za.regno = regno; 2081 1.9 christos info->indexed_za.index.imm = (fld_zan_imm % max_value) * range_size; 2082 1.9 christos info->indexed_za.index.countm1 = range_size - 1; 2083 1.8 christos info->indexed_za.index.regno = fld_rv + 12; 2084 1.8 christos info->indexed_za.v = fld_v; 2085 1.8 christos 2086 1.8 christos return true; 2087 1.8 christos } 2088 1.8 christos 2089 1.8 christos /* Decode in SME instruction ZERO list of up to eight 64-bit element tile names 2090 1.8 christos separated by commas, encoded in the "imm8" field. 2091 1.8 christos 2092 1.8 christos For programmer convenience an assembler must also accept the names of 2093 1.8 christos 32-bit, 16-bit and 8-bit element tiles which are converted into the 2094 1.8 christos corresponding set of 64-bit element tiles. 2095 1.8 christos */ 2096 1.8 christos bool 2097 1.8 christos aarch64_ext_sme_za_list (const aarch64_operand *self, 2098 1.8 christos aarch64_opnd_info *info, aarch64_insn code, 2099 1.8 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 2100 1.8 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 2101 1.8 christos { 2102 1.8 christos int mask = extract_field (self->fields[0], code, 0); 2103 1.8 christos info->imm.value = mask; 2104 1.8 christos return true; 2105 1.8 christos } 2106 1.9 christos 2107 1.8 christos /* Decode ZA array vector select register (Rv field), optional vector and 2108 1.8 christos memory offset (imm4_11 field). 2109 1.8 christos */ 2110 1.8 christos bool 2111 1.9 christos aarch64_ext_sme_za_array (const aarch64_operand *self, 2112 1.8 christos aarch64_opnd_info *info, aarch64_insn code, 2113 1.8 christos const aarch64_inst *inst, 2114 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 2115 1.9 christos { 2116 1.9 christos int regno = extract_field (self->fields[0], code, 0); 2117 1.9 christos if (info->type == AARCH64_OPND_SME_ZA_array_off4) 2118 1.9 christos regno += 12; 2119 1.8 christos else 2120 1.9 christos regno += 8; 2121 1.9 christos int imm = extract_field (self->fields[1], code, 0); 2122 1.9 christos int num_offsets = get_operand_specific_data (self); 2123 1.9 christos if (num_offsets == 0) 2124 1.9 christos num_offsets = 1; 2125 1.9 christos info->indexed_za.index.regno = regno; 2126 1.9 christos info->indexed_za.index.imm = imm * num_offsets; 2127 1.9 christos info->indexed_za.index.countm1 = num_offsets - 1; 2128 1.9 christos info->indexed_za.group_size = get_opcode_dependent_value (inst->opcode); 2129 1.9 christos return true; 2130 1.9 christos } 2131 1.9 christos 2132 1.9 christos /* Decode two ZA tile slice (V, Rv, off3| ZAn ,off2 | ZAn, ol| ZAn) feilds. */ 2133 1.9 christos bool 2134 1.9 christos aarch64_ext_sme_za_vrs1 (const aarch64_operand *self, 2135 1.9 christos aarch64_opnd_info *info, aarch64_insn code, 2136 1.9 christos const aarch64_inst *inst, 2137 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 2138 1.9 christos { 2139 1.9 christos int v = extract_field (self->fields[0], code, 0); 2140 1.9 christos int regno = 12 + extract_field (self->fields[1], code, 0); 2141 1.9 christos int imm, za_reg, num_offset = 2; 2142 1.9 christos 2143 1.9 christos switch (info->qualifier) 2144 1.9 christos { 2145 1.9 christos case AARCH64_OPND_QLF_S_B: 2146 1.9 christos imm = extract_field (self->fields[2], code, 0); 2147 1.9 christos info->indexed_za.index.imm = imm * num_offset; 2148 1.9 christos break; 2149 1.9 christos case AARCH64_OPND_QLF_S_H: 2150 1.9 christos case AARCH64_OPND_QLF_S_S: 2151 1.9 christos za_reg = extract_field (self->fields[2], code, 0); 2152 1.9 christos imm = extract_field (self->fields[3], code, 0); 2153 1.9 christos info->indexed_za.index.imm = imm * num_offset; 2154 1.9 christos info->indexed_za.regno = za_reg; 2155 1.9 christos break; 2156 1.9 christos case AARCH64_OPND_QLF_S_D: 2157 1.9 christos za_reg = extract_field (self->fields[2], code, 0); 2158 1.9 christos info->indexed_za.regno = za_reg; 2159 1.9 christos break; 2160 1.9 christos default: 2161 1.9 christos return false; 2162 1.9 christos } 2163 1.9 christos 2164 1.9 christos info->indexed_za.index.regno = regno; 2165 1.9 christos info->indexed_za.index.countm1 = num_offset - 1; 2166 1.9 christos info->indexed_za.v = v; 2167 1.9 christos info->indexed_za.group_size = get_opcode_dependent_value (inst->opcode); 2168 1.9 christos return true; 2169 1.9 christos } 2170 1.9 christos 2171 1.9 christos /* Decode four ZA tile slice (V, Rv, off3| ZAn ,off2 | ZAn, ol| ZAn) feilds. */ 2172 1.9 christos bool 2173 1.9 christos aarch64_ext_sme_za_vrs2 (const aarch64_operand *self, 2174 1.9 christos aarch64_opnd_info *info, aarch64_insn code, 2175 1.9 christos const aarch64_inst *inst, 2176 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 2177 1.9 christos { 2178 1.9 christos int v = extract_field (self->fields[0], code, 0); 2179 1.9 christos int regno = 12 + extract_field (self->fields[1], code, 0); 2180 1.9 christos int imm, za_reg, num_offset =4; 2181 1.9 christos 2182 1.9 christos switch (info->qualifier) 2183 1.9 christos { 2184 1.9 christos case AARCH64_OPND_QLF_S_B: 2185 1.9 christos imm = extract_field (self->fields[2], code, 0); 2186 1.9 christos info->indexed_za.index.imm = imm * num_offset; 2187 1.9 christos break; 2188 1.9 christos case AARCH64_OPND_QLF_S_H: 2189 1.9 christos za_reg = extract_field (self->fields[2], code, 0); 2190 1.9 christos imm = extract_field (self->fields[3], code, 0); 2191 1.9 christos info->indexed_za.index.imm = imm * num_offset; 2192 1.9 christos info->indexed_za.regno = za_reg; 2193 1.9 christos break; 2194 1.9 christos case AARCH64_OPND_QLF_S_S: 2195 1.9 christos case AARCH64_OPND_QLF_S_D: 2196 1.9 christos za_reg = extract_field (self->fields[2], code, 0); 2197 1.9 christos info->indexed_za.regno = za_reg; 2198 1.9 christos break; 2199 1.9 christos default: 2200 1.9 christos return false; 2201 1.9 christos } 2202 1.9 christos 2203 1.9 christos info->indexed_za.index.regno = regno; 2204 1.9 christos info->indexed_za.index.countm1 = num_offset - 1; 2205 1.8 christos info->indexed_za.v = v; 2206 1.8 christos info->indexed_za.group_size = get_opcode_dependent_value (inst->opcode); 2207 1.8 christos return true; 2208 1.8 christos } 2209 1.8 christos 2210 1.8 christos bool 2211 1.8 christos aarch64_ext_sme_addr_ri_u4xvl (const aarch64_operand *self, 2212 1.8 christos aarch64_opnd_info *info, aarch64_insn code, 2213 1.8 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 2214 1.8 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 2215 1.8 christos { 2216 1.8 christos int regno = extract_field (self->fields[0], code, 0); 2217 1.8 christos int imm = extract_field (self->fields[1], code, 0); 2218 1.8 christos info->addr.base_regno = regno; 2219 1.8 christos info->addr.offset.imm = imm; 2220 1.8 christos /* MUL VL operator is always present for this operand. */ 2221 1.8 christos info->shifter.kind = AARCH64_MOD_MUL_VL; 2222 1.8 christos info->shifter.operator_present = (imm != 0); 2223 1.8 christos return true; 2224 1.8 christos } 2225 1.8 christos 2226 1.8 christos /* Decode {SM|ZA} filed for SMSTART and SMSTOP instructions. */ 2227 1.8 christos bool 2228 1.8 christos aarch64_ext_sme_sm_za (const aarch64_operand *self, 2229 1.8 christos aarch64_opnd_info *info, aarch64_insn code, 2230 1.8 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 2231 1.8 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 2232 1.8 christos { 2233 1.8 christos info->pstatefield = 0x1b; 2234 1.8 christos aarch64_insn fld_crm = extract_field (self->fields[0], code, 0); 2235 1.8 christos fld_crm >>= 1; /* CRm[3:1]. */ 2236 1.8 christos 2237 1.8 christos if (fld_crm == 0x1) 2238 1.8 christos info->reg.regno = 's'; 2239 1.8 christos else if (fld_crm == 0x2) 2240 1.8 christos info->reg.regno = 'z'; 2241 1.8 christos else 2242 1.8 christos return false; 2243 1.8 christos 2244 1.8 christos return true; 2245 1.8 christos } 2246 1.8 christos 2247 1.8 christos bool 2248 1.8 christos aarch64_ext_sme_pred_reg_with_index (const aarch64_operand *self, 2249 1.8 christos aarch64_opnd_info *info, aarch64_insn code, 2250 1.8 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 2251 1.8 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 2252 1.8 christos { 2253 1.8 christos aarch64_insn fld_rm = extract_field (self->fields[0], code, 0); 2254 1.8 christos aarch64_insn fld_pn = extract_field (self->fields[1], code, 0); 2255 1.8 christos aarch64_insn fld_i1 = extract_field (self->fields[2], code, 0); 2256 1.8 christos aarch64_insn fld_tszh = extract_field (self->fields[3], code, 0); 2257 1.8 christos aarch64_insn fld_tszl = extract_field (self->fields[4], code, 0); 2258 1.9 christos int imm; 2259 1.9 christos 2260 1.8 christos info->indexed_za.regno = fld_pn; 2261 1.9 christos info->indexed_za.index.regno = fld_rm + 12; 2262 1.9 christos 2263 1.9 christos if (fld_tszl & 0x1) 2264 1.9 christos imm = (fld_i1 << 3) | (fld_tszh << 2) | (fld_tszl >> 1); 2265 1.9 christos else if (fld_tszl & 0x2) 2266 1.9 christos imm = (fld_i1 << 2) | (fld_tszh << 1) | (fld_tszl >> 2); 2267 1.9 christos else if (fld_tszl & 0x4) 2268 1.9 christos imm = (fld_i1 << 1) | fld_tszh; 2269 1.8 christos else if (fld_tszh) 2270 1.8 christos imm = fld_i1; 2271 1.8 christos else 2272 1.9 christos return false; 2273 1.8 christos 2274 1.6 christos info->indexed_za.index.imm = imm; 2275 1.6 christos return true; 2276 1.6 christos } 2277 1.6 christos 2278 1.6 christos /* Decode Zn[MM], where MM has a 7-bit triangular encoding. The fields 2279 1.6 christos array specifies which field to use for Zn. MM is encoded in the 2280 1.8 christos concatenation of imm5 and SVE_tszh, with imm5 being the less 2281 1.6 christos significant part. */ 2282 1.6 christos bool 2283 1.6 christos aarch64_ext_sve_index (const aarch64_operand *self, 2284 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 2285 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 2286 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 2287 1.6 christos { 2288 1.6 christos int val; 2289 1.10 christos 2290 1.6 christos info->reglane.regno = extract_field (self->fields[0], code, 0); 2291 1.6 christos val = extract_all_fields_after (self, 1, code); 2292 1.6 christos if ((val & 31) == 0) 2293 1.6 christos return 0; 2294 1.6 christos while ((val & 1) == 0) 2295 1.8 christos val /= 2; 2296 1.6 christos info->reglane.index = val / 2; 2297 1.6 christos return true; 2298 1.6 christos } 2299 1.8 christos 2300 1.6 christos /* Decode a logical immediate for the MOV alias of SVE DUPM. */ 2301 1.6 christos bool 2302 1.6 christos aarch64_ext_sve_limm_mov (const aarch64_operand *self, 2303 1.6 christos aarch64_opnd_info *info, const aarch64_insn code, 2304 1.6 christos const aarch64_inst *inst, 2305 1.6 christos aarch64_operand_error *errors) 2306 1.6 christos { 2307 1.6 christos int esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier); 2308 1.6 christos return (aarch64_ext_limm (self, info, code, inst, errors) 2309 1.6 christos && aarch64_sve_dupm_mov_immediate_p (info->imm.value, esize)); 2310 1.6 christos } 2311 1.6 christos 2312 1.6 christos /* Decode Zn[MM], where Zn occupies the least-significant part of the field 2313 1.8 christos and where MM occupies the most-significant part. The operand-dependent 2314 1.6 christos value specifies the number of bits in Zn. */ 2315 1.6 christos bool 2316 1.6 christos aarch64_ext_sve_quad_index (const aarch64_operand *self, 2317 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 2318 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 2319 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 2320 1.6 christos { 2321 1.6 christos unsigned int reg_bits = get_operand_specific_data (self); 2322 1.6 christos unsigned int val = extract_all_fields (self, code); 2323 1.8 christos info->reglane.regno = val & ((1 << reg_bits) - 1); 2324 1.6 christos info->reglane.index = val >> reg_bits; 2325 1.6 christos return true; 2326 1.6 christos } 2327 1.6 christos 2328 1.6 christos /* Decode {Zn.<T> - Zm.<T>}. The fields array specifies which field 2329 1.8 christos to use for Zn. The opcode-dependent value specifies the number 2330 1.6 christos of registers in the list. */ 2331 1.6 christos bool 2332 1.6 christos aarch64_ext_sve_reglist (const aarch64_operand *self, 2333 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 2334 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 2335 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 2336 1.6 christos { 2337 1.9 christos info->reglist.first_regno = extract_field (self->fields[0], code, 0); 2338 1.9 christos info->reglist.num_regs = get_opcode_dependent_value (inst->opcode); 2339 1.9 christos info->reglist.stride = 1; 2340 1.9 christos return true; 2341 1.9 christos } 2342 1.9 christos 2343 1.9 christos /* Decode {Zn.<T> , Zm.<T>}. The fields array specifies which field 2344 1.9 christos to use for Zn. The opcode-dependent value specifies the number 2345 1.9 christos of registers in the list. */ 2346 1.9 christos bool 2347 1.9 christos aarch64_ext_sve_reglist_zt (const aarch64_operand *self, 2348 1.9 christos aarch64_opnd_info *info, aarch64_insn code, 2349 1.9 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 2350 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 2351 1.9 christos { 2352 1.9 christos info->reglist.first_regno = extract_field (self->fields[0], code, 0); 2353 1.9 christos info->reglist.num_regs = get_operand_specific_data (self); 2354 1.9 christos info->reglist.stride = 1; 2355 1.9 christos return true; 2356 1.9 christos } 2357 1.9 christos 2358 1.9 christos /* Decode a strided register list. The first field holds the top bit 2359 1.9 christos (0 or 16) and the second field holds the lower bits. The stride is 2360 1.9 christos 16 divided by the list length. */ 2361 1.9 christos bool 2362 1.9 christos aarch64_ext_sve_strided_reglist (const aarch64_operand *self, 2363 1.9 christos aarch64_opnd_info *info, aarch64_insn code, 2364 1.9 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 2365 1.9 christos aarch64_operand_error *errors 2366 1.9 christos ATTRIBUTE_UNUSED) 2367 1.9 christos { 2368 1.9 christos unsigned int upper = extract_field (self->fields[0], code, 0); 2369 1.9 christos unsigned int lower = extract_field (self->fields[1], code, 0); 2370 1.9 christos info->reglist.first_regno = upper * 16 + lower; 2371 1.8 christos info->reglist.num_regs = get_operand_specific_data (self); 2372 1.6 christos info->reglist.stride = 16 / info->reglist.num_regs; 2373 1.6 christos return true; 2374 1.6 christos } 2375 1.6 christos 2376 1.6 christos /* Decode <pattern>{, MUL #<amount>}. The fields array specifies which 2377 1.8 christos fields to use for <pattern>. <amount> - 1 is encoded in the SVE_imm4 2378 1.6 christos field. */ 2379 1.6 christos bool 2380 1.6 christos aarch64_ext_sve_scale (const aarch64_operand *self, 2381 1.6 christos aarch64_opnd_info *info, aarch64_insn code, 2382 1.6 christos const aarch64_inst *inst, aarch64_operand_error *errors) 2383 1.6 christos { 2384 1.6 christos int val; 2385 1.8 christos 2386 1.6 christos if (!aarch64_ext_imm (self, info, code, inst, errors)) 2387 1.6 christos return false; 2388 1.6 christos val = extract_field (FLD_SVE_imm4, code, 0); 2389 1.6 christos info->shifter.kind = AARCH64_MOD_MUL; 2390 1.6 christos info->shifter.amount = val + 1; 2391 1.8 christos info->shifter.operator_present = (val != 0); 2392 1.6 christos info->shifter.amount_present = (val != 0); 2393 1.6 christos return true; 2394 1.6 christos } 2395 1.6 christos 2396 1.6 christos /* Return the top set bit in VALUE, which is expected to be relatively 2397 1.6 christos small. */ 2398 1.6 christos static uint64_t 2399 1.6 christos get_top_bit (uint64_t value) 2400 1.6 christos { 2401 1.6 christos while ((value & -value) != value) 2402 1.6 christos value -= value & -value; 2403 1.6 christos return value; 2404 1.6 christos } 2405 1.8 christos 2406 1.6 christos /* Decode an SVE shift-left immediate. */ 2407 1.6 christos bool 2408 1.6 christos aarch64_ext_sve_shlimm (const aarch64_operand *self, 2409 1.6 christos aarch64_opnd_info *info, const aarch64_insn code, 2410 1.6 christos const aarch64_inst *inst, aarch64_operand_error *errors) 2411 1.6 christos { 2412 1.8 christos if (!aarch64_ext_imm (self, info, code, inst, errors) 2413 1.6 christos || info->imm.value == 0) 2414 1.6 christos return false; 2415 1.8 christos 2416 1.6 christos info->imm.value -= get_top_bit (info->imm.value); 2417 1.6 christos return true; 2418 1.6 christos } 2419 1.8 christos 2420 1.6 christos /* Decode an SVE shift-right immediate. */ 2421 1.6 christos bool 2422 1.6 christos aarch64_ext_sve_shrimm (const aarch64_operand *self, 2423 1.6 christos aarch64_opnd_info *info, const aarch64_insn code, 2424 1.6 christos const aarch64_inst *inst, aarch64_operand_error *errors) 2425 1.6 christos { 2426 1.8 christos if (!aarch64_ext_imm (self, info, code, inst, errors) 2427 1.6 christos || info->imm.value == 0) 2428 1.6 christos return false; 2429 1.8 christos 2430 1.8 christos info->imm.value = get_top_bit (info->imm.value) * 2 - info->imm.value; 2431 1.8 christos return true; 2432 1.8 christos } 2433 1.8 christos 2434 1.8 christos /* Decode X0-X30. Register 31 is unallocated. */ 2435 1.8 christos bool 2436 1.8 christos aarch64_ext_x0_to_x30 (const aarch64_operand *self, aarch64_opnd_info *info, 2437 1.8 christos const aarch64_insn code, 2438 1.8 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 2439 1.8 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 2440 1.8 christos { 2441 1.1 christos info->reg.regno = extract_field (self->fields[0], code, 0); 2442 1.9 christos return info->reg.regno <= 30; 2443 1.9 christos } 2444 1.9 christos 2445 1.9 christos /* Decode an indexed register, with the first field being the register 2446 1.9 christos number and the remaining fields being the index. */ 2447 1.9 christos bool 2448 1.9 christos aarch64_ext_simple_index (const aarch64_operand *self, aarch64_opnd_info *info, 2449 1.9 christos const aarch64_insn code, 2450 1.9 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 2451 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 2452 1.9 christos { 2453 1.9 christos int bias = get_operand_specific_data (self); 2454 1.9 christos info->reglane.regno = extract_field (self->fields[0], code, 0) + bias; 2455 1.9 christos info->reglane.index = extract_all_fields_after (self, 1, code); 2456 1.9 christos return true; 2457 1.9 christos } 2458 1.9 christos 2459 1.9 christos /* Decode a plain shift-right immediate, when there is only a single 2460 1.9 christos element size. */ 2461 1.9 christos bool 2462 1.9 christos aarch64_ext_plain_shrimm (const aarch64_operand *self, aarch64_opnd_info *info, 2463 1.9 christos const aarch64_insn code, 2464 1.9 christos const aarch64_inst *inst ATTRIBUTE_UNUSED, 2465 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 2466 1.9 christos { 2467 1.9 christos unsigned int base = 1 << get_operand_field_width (self, 0); 2468 1.9 christos info->imm.value = base - extract_field (self->fields[0], code, 0); 2469 1.1 christos return true; 2470 1.1 christos } 2471 1.1 christos 2472 1.1 christos /* Bitfields that are commonly used to encode certain operands' information 2474 1.1 christos may be partially used as part of the base opcode in some instructions. 2475 1.1 christos For example, the bit 1 of the field 'size' in 2476 1.1 christos FCVTXN <Vb><d>, <Va><n> 2477 1.1 christos is actually part of the base opcode, while only size<0> is available 2478 1.1 christos for encoding the register type. Another example is the AdvSIMD 2479 1.1 christos instruction ORR (register), in which the field 'size' is also used for 2480 1.1 christos the base opcode, leaving only the field 'Q' available to encode the 2481 1.1 christos vector register arrangement specifier '8B' or '16B'. 2482 1.1 christos 2483 1.1 christos This function tries to deduce the qualifier from the value of partially 2484 1.1 christos constrained field(s). Given the VALUE of such a field or fields, the 2485 1.1 christos qualifiers CANDIDATES and the MASK (indicating which bits are valid for 2486 1.1 christos operand encoding), the function returns the matching qualifier or 2487 1.1 christos AARCH64_OPND_QLF_NIL if nothing matches. 2488 1.1 christos 2489 1.1 christos N.B. CANDIDATES is a group of possible qualifiers that are valid for 2490 1.1 christos one operand; it has a maximum of AARCH64_MAX_QLF_SEQ_NUM qualifiers and 2491 1.1 christos may end with AARCH64_OPND_QLF_NIL. */ 2492 1.1 christos 2493 1.1 christos static enum aarch64_opnd_qualifier 2494 1.1 christos get_qualifier_from_partial_encoding (aarch64_insn value, 2495 1.1 christos const enum aarch64_opnd_qualifier* \ 2496 1.1 christos candidates, 2497 1.1 christos aarch64_insn mask) 2498 1.1 christos { 2499 1.1 christos int i; 2500 1.1 christos DEBUG_TRACE ("enter with value: %d, mask: %d", (int)value, (int)mask); 2501 1.1 christos for (i = 0; i < AARCH64_MAX_QLF_SEQ_NUM; ++i) 2502 1.1 christos { 2503 1.1 christos aarch64_insn standard_value; 2504 1.1 christos if (candidates[i] == AARCH64_OPND_QLF_NIL) 2505 1.1 christos break; 2506 1.1 christos standard_value = aarch64_get_qualifier_standard_value (candidates[i]); 2507 1.1 christos if ((standard_value & mask) == (value & mask)) 2508 1.1 christos return candidates[i]; 2509 1.1 christos } 2510 1.1 christos return AARCH64_OPND_QLF_NIL; 2511 1.1 christos } 2512 1.1 christos 2513 1.1 christos /* Given a list of qualifier sequences, return all possible valid qualifiers 2514 1.1 christos for operand IDX in QUALIFIERS. 2515 1.1 christos Assume QUALIFIERS is an array whose length is large enough. */ 2516 1.1 christos 2517 1.1 christos static void 2518 1.1 christos get_operand_possible_qualifiers (int idx, 2519 1.1 christos const aarch64_opnd_qualifier_seq_t *list, 2520 1.1 christos enum aarch64_opnd_qualifier *qualifiers) 2521 1.1 christos { 2522 1.1 christos int i; 2523 1.1 christos for (i = 0; i < AARCH64_MAX_QLF_SEQ_NUM; ++i) 2524 1.1 christos if ((qualifiers[i] = list[i][idx]) == AARCH64_OPND_QLF_NIL) 2525 1.1 christos break; 2526 1.1 christos } 2527 1.1 christos 2528 1.1 christos /* Decode the size Q field for e.g. SHADD. 2529 1.1 christos We tag one operand with the qualifer according to the code; 2530 1.1 christos whether the qualifier is valid for this opcode or not, it is the 2531 1.1 christos duty of the semantic checking. */ 2532 1.1 christos 2533 1.1 christos static int 2534 1.1 christos decode_sizeq (aarch64_inst *inst) 2535 1.1 christos { 2536 1.1 christos int idx; 2537 1.1 christos enum aarch64_opnd_qualifier qualifier; 2538 1.1 christos aarch64_insn code; 2539 1.1 christos aarch64_insn value, mask; 2540 1.1 christos enum aarch64_field_kind fld_sz; 2541 1.1 christos enum aarch64_opnd_qualifier candidates[AARCH64_MAX_QLF_SEQ_NUM]; 2542 1.1 christos 2543 1.1 christos if (inst->opcode->iclass == asisdlse 2544 1.1 christos || inst->opcode->iclass == asisdlsep 2545 1.1 christos || inst->opcode->iclass == asisdlso 2546 1.1 christos || inst->opcode->iclass == asisdlsop) 2547 1.1 christos fld_sz = FLD_vldst_size; 2548 1.1 christos else 2549 1.1 christos fld_sz = FLD_size; 2550 1.1 christos 2551 1.1 christos code = inst->value; 2552 1.1 christos value = extract_fields (code, inst->opcode->mask, 2, fld_sz, FLD_Q); 2553 1.1 christos /* Obtain the info that which bits of fields Q and size are actually 2554 1.1 christos available for operand encoding. Opcodes like FMAXNM and FMLA have 2555 1.1 christos size[1] unavailable. */ 2556 1.1 christos mask = extract_fields (~inst->opcode->mask, 0, 2, fld_sz, FLD_Q); 2557 1.1 christos 2558 1.1 christos /* The index of the operand we are going to tag a qualifier and the qualifer 2559 1.1 christos itself are reasoned from the value of the size and Q fields and the 2560 1.1 christos possible valid qualifier lists. */ 2561 1.1 christos idx = aarch64_select_operand_for_sizeq_field_coding (inst->opcode); 2562 1.1 christos DEBUG_TRACE ("key idx: %d", idx); 2563 1.1 christos 2564 1.1 christos /* For most related instruciton, size:Q are fully available for operand 2565 1.1 christos encoding. */ 2566 1.10 christos if (mask == 0x7) 2567 1.10 christos { 2568 1.1 christos inst->operands[idx].qualifier = get_vreg_qualifier_from_value (value); 2569 1.1 christos if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR) 2570 1.1 christos return 0; 2571 1.1 christos return 1; 2572 1.1 christos } 2573 1.1 christos 2574 1.1 christos get_operand_possible_qualifiers (idx, inst->opcode->qualifiers_list, 2575 1.1 christos candidates); 2576 1.1 christos #ifdef DEBUG_AARCH64 2577 1.1 christos if (debug_dump) 2578 1.1 christos { 2579 1.1 christos int i; 2580 1.1 christos for (i = 0; candidates[i] != AARCH64_OPND_QLF_NIL 2581 1.1 christos && i < AARCH64_MAX_QLF_SEQ_NUM; ++i) 2582 1.1 christos DEBUG_TRACE ("qualifier %d: %s", i, 2583 1.1 christos aarch64_get_qualifier_name(candidates[i])); 2584 1.1 christos DEBUG_TRACE ("%d, %d", (int)value, (int)mask); 2585 1.1 christos } 2586 1.1 christos #endif /* DEBUG_AARCH64 */ 2587 1.1 christos 2588 1.1 christos qualifier = get_qualifier_from_partial_encoding (value, candidates, mask); 2589 1.1 christos 2590 1.1 christos if (qualifier == AARCH64_OPND_QLF_NIL) 2591 1.1 christos return 0; 2592 1.1 christos 2593 1.1 christos inst->operands[idx].qualifier = qualifier; 2594 1.1 christos return 1; 2595 1.1 christos } 2596 1.1 christos 2597 1.1 christos /* Decode size[0]:Q, i.e. bit 22 and bit 30, for 2598 1.1 christos e.g. FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */ 2599 1.1 christos 2600 1.1 christos static int 2601 1.1 christos decode_asimd_fcvt (aarch64_inst *inst) 2602 1.1 christos { 2603 1.1 christos aarch64_field field = {0, 0}; 2604 1.1 christos aarch64_insn value; 2605 1.1 christos enum aarch64_opnd_qualifier qualifier; 2606 1.1 christos 2607 1.1 christos gen_sub_field (FLD_size, 0, 1, &field); 2608 1.1 christos value = extract_field_2 (&field, inst->value, 0); 2609 1.1 christos qualifier = value == 0 ? AARCH64_OPND_QLF_V_4S 2610 1.1 christos : AARCH64_OPND_QLF_V_2D; 2611 1.1 christos switch (inst->opcode->op) 2612 1.1 christos { 2613 1.1 christos case OP_FCVTN: 2614 1.1 christos case OP_FCVTN2: 2615 1.1 christos /* FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */ 2616 1.1 christos inst->operands[1].qualifier = qualifier; 2617 1.1 christos break; 2618 1.1 christos case OP_FCVTL: 2619 1.1 christos case OP_FCVTL2: 2620 1.1 christos /* FCVTL<Q> <Vd>.<Ta>, <Vn>.<Tb>. */ 2621 1.1 christos inst->operands[0].qualifier = qualifier; 2622 1.1 christos break; 2623 1.1 christos default: 2624 1.1 christos return 0; 2625 1.1 christos } 2626 1.1 christos 2627 1.1 christos return 1; 2628 1.1 christos } 2629 1.1 christos 2630 1.1 christos /* Decode size[0], i.e. bit 22, for 2631 1.1 christos e.g. FCVTXN <Vb><d>, <Va><n>. */ 2632 1.1 christos 2633 1.1 christos static int 2634 1.1 christos decode_asisd_fcvtxn (aarch64_inst *inst) 2635 1.1 christos { 2636 1.1 christos aarch64_field field = {0, 0}; 2637 1.1 christos gen_sub_field (FLD_size, 0, 1, &field); 2638 1.1 christos if (!extract_field_2 (&field, inst->value, 0)) 2639 1.1 christos return 0; 2640 1.1 christos inst->operands[0].qualifier = AARCH64_OPND_QLF_S_S; 2641 1.1 christos return 1; 2642 1.1 christos } 2643 1.1 christos 2644 1.1 christos /* Decode the 'opc' field for e.g. FCVT <Dd>, <Sn>. */ 2645 1.1 christos static int 2646 1.1 christos decode_fcvt (aarch64_inst *inst) 2647 1.1 christos { 2648 1.1 christos enum aarch64_opnd_qualifier qualifier; 2649 1.1 christos aarch64_insn value; 2650 1.1 christos const aarch64_field field = {15, 2}; 2651 1.1 christos 2652 1.1 christos /* opc dstsize */ 2653 1.1 christos value = extract_field_2 (&field, inst->value, 0); 2654 1.1 christos switch (value) 2655 1.1 christos { 2656 1.1 christos case 0: qualifier = AARCH64_OPND_QLF_S_S; break; 2657 1.1 christos case 1: qualifier = AARCH64_OPND_QLF_S_D; break; 2658 1.1 christos case 3: qualifier = AARCH64_OPND_QLF_S_H; break; 2659 1.1 christos default: return 0; 2660 1.1 christos } 2661 1.1 christos inst->operands[0].qualifier = qualifier; 2662 1.1 christos 2663 1.1 christos return 1; 2664 1.1 christos } 2665 1.1 christos 2666 1.1 christos /* Do miscellaneous decodings that are not common enough to be driven by 2667 1.1 christos flags. */ 2668 1.1 christos 2669 1.6 christos static int 2670 1.1 christos do_misc_decoding (aarch64_inst *inst) 2671 1.1 christos { 2672 1.1 christos unsigned int value; 2673 1.1 christos switch (inst->opcode->op) 2674 1.6 christos { 2675 1.1 christos case OP_FCVT: 2676 1.1 christos return decode_fcvt (inst); 2677 1.1 christos 2678 1.1 christos case OP_FCVTN: 2679 1.1 christos case OP_FCVTN2: 2680 1.6 christos case OP_FCVTL: 2681 1.1 christos case OP_FCVTL2: 2682 1.1 christos return decode_asimd_fcvt (inst); 2683 1.6 christos 2684 1.6 christos case OP_FCVTXN_S: 2685 1.6 christos return decode_asisd_fcvtxn (inst); 2686 1.6 christos 2687 1.6 christos case OP_MOV_P_P: 2688 1.6 christos case OP_MOVS_P_P: 2689 1.6 christos value = extract_field (FLD_SVE_Pn, inst->value, 0); 2690 1.6 christos return (value == extract_field (FLD_SVE_Pm, inst->value, 0) 2691 1.6 christos && value == extract_field (FLD_SVE_Pg4_10, inst->value, 0)); 2692 1.6 christos 2693 1.6 christos case OP_MOV_Z_P_Z: 2694 1.6 christos return (extract_field (FLD_SVE_Zd, inst->value, 0) 2695 1.6 christos == extract_field (FLD_SVE_Zm_16, inst->value, 0)); 2696 1.6 christos 2697 1.6 christos case OP_MOV_Z_V: 2698 1.6 christos /* Index must be zero. */ 2699 1.6 christos value = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_imm5); 2700 1.6 christos return value > 0 && value <= 16 && value == (value & -value); 2701 1.6 christos 2702 1.6 christos case OP_MOV_Z_Z: 2703 1.6 christos return (extract_field (FLD_SVE_Zn, inst->value, 0) 2704 1.6 christos == extract_field (FLD_SVE_Zm_16, inst->value, 0)); 2705 1.6 christos 2706 1.6 christos case OP_MOV_Z_Zi: 2707 1.6 christos /* Index must be nonzero. */ 2708 1.6 christos value = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_imm5); 2709 1.6 christos return value > 0 && value != (value & -value); 2710 1.6 christos 2711 1.6 christos case OP_MOVM_P_P_P: 2712 1.6 christos return (extract_field (FLD_SVE_Pd, inst->value, 0) 2713 1.6 christos == extract_field (FLD_SVE_Pm, inst->value, 0)); 2714 1.6 christos 2715 1.6 christos case OP_MOVZS_P_P_P: 2716 1.6 christos case OP_MOVZ_P_P_P: 2717 1.6 christos return (extract_field (FLD_SVE_Pn, inst->value, 0) 2718 1.6 christos == extract_field (FLD_SVE_Pm, inst->value, 0)); 2719 1.6 christos 2720 1.6 christos case OP_NOTS_P_P_P_Z: 2721 1.6 christos case OP_NOT_P_P_P_Z: 2722 1.1 christos return (extract_field (FLD_SVE_Pm, inst->value, 0) 2723 1.1 christos == extract_field (FLD_SVE_Pg4_10, inst->value, 0)); 2724 1.1 christos 2725 1.1 christos default: 2726 1.1 christos return 0; 2727 1.1 christos } 2728 1.1 christos } 2729 1.1 christos 2730 1.1 christos /* Opcodes that have fields shared by multiple operands are usually flagged 2731 1.1 christos with flags. In this function, we detect such flags, decode the related 2732 1.1 christos field(s) and store the information in one of the related operands. The 2733 1.1 christos 'one' operand is not any operand but one of the operands that can 2734 1.1 christos accommadate all the information that has been decoded. */ 2735 1.1 christos 2736 1.1 christos static int 2737 1.1 christos do_special_decoding (aarch64_inst *inst) 2738 1.1 christos { 2739 1.1 christos int idx; 2740 1.1 christos aarch64_insn value; 2741 1.1 christos /* Condition for truly conditional executed instructions, e.g. b.cond. */ 2742 1.1 christos if (inst->opcode->flags & F_COND) 2743 1.1 christos { 2744 1.1 christos value = extract_field (FLD_cond2, inst->value, 0); 2745 1.1 christos inst->cond = get_cond_from_value (value); 2746 1.1 christos } 2747 1.1 christos /* 'sf' field. */ 2748 1.1 christos if (inst->opcode->flags & F_SF) 2749 1.10 christos { 2750 1.10 christos idx = select_operand_for_sf_field_coding (inst->opcode); 2751 1.10 christos value = extract_field (FLD_sf, inst->value, 0); 2752 1.10 christos if (inst->opcode->iclass == fprcvtfloat2int 2753 1.10 christos || inst->opcode->iclass == fprcvtint2float) 2754 1.10 christos { 2755 1.10 christos if (value == 0) 2756 1.10 christos inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_S; 2757 1.10 christos else 2758 1.10 christos inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_D; 2759 1.10 christos } 2760 1.10 christos else 2761 1.1 christos inst->operands[idx].qualifier = get_greg_qualifier_from_value (value); 2762 1.1 christos if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR) 2763 1.1 christos return 0; 2764 1.1 christos if ((inst->opcode->flags & F_N) 2765 1.3 christos && extract_field (FLD_N, inst->value, 0) != value) 2766 1.3 christos return 0; 2767 1.3 christos } 2768 1.3 christos /* 'sf' field. */ 2769 1.3 christos if (inst->opcode->flags & F_LSE_SZ) 2770 1.3 christos { 2771 1.10 christos idx = select_operand_for_sf_field_coding (inst->opcode); 2772 1.10 christos value = extract_field (FLD_lse_sz, inst->value, 0); 2773 1.3 christos inst->operands[idx].qualifier = get_greg_qualifier_from_value (value); 2774 1.9 christos if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR) 2775 1.9 christos return 0; 2776 1.9 christos } 2777 1.9 christos /* rcpc3 'size' field. */ 2778 1.9 christos if (inst->opcode->flags & F_RCPC3_SIZE) 2779 1.9 christos { 2780 1.9 christos value = extract_field (FLD_rcpc3_size, inst->value, 0); 2781 1.9 christos for (int i = 0; 2782 1.9 christos aarch64_operands[inst->operands[i].type].op_class != AARCH64_OPND_CLASS_ADDRESS; 2783 1.9 christos i++) 2784 1.10 christos { 2785 1.10 christos if (aarch64_operands[inst->operands[i].type].op_class 2786 1.10 christos == AARCH64_OPND_CLASS_INT_REG) 2787 1.10 christos { 2788 1.10 christos inst->operands[i].qualifier = get_greg_qualifier_from_value (value & 1); 2789 1.9 christos if (inst->operands[i].qualifier == AARCH64_OPND_QLF_ERR) 2790 1.9 christos return 0; 2791 1.9 christos } 2792 1.9 christos else if (aarch64_operands[inst->operands[i].type].op_class 2793 1.9 christos == AARCH64_OPND_CLASS_FP_REG) 2794 1.10 christos { 2795 1.10 christos value += (extract_field (FLD_opc1, inst->value, 0) << 2); 2796 1.9 christos inst->operands[i].qualifier = get_sreg_qualifier_from_value (value); 2797 1.9 christos if (inst->operands[i].qualifier == AARCH64_OPND_QLF_ERR) 2798 1.9 christos return 0; 2799 1.9 christos } 2800 1.1 christos } 2801 1.1 christos } 2802 1.1 christos 2803 1.1 christos /* size:Q fields. */ 2804 1.1 christos if (inst->opcode->flags & F_SIZEQ) 2805 1.1 christos return decode_sizeq (inst); 2806 1.1 christos 2807 1.1 christos if (inst->opcode->flags & F_FPTYPE) 2808 1.1 christos { 2809 1.1 christos idx = select_operand_for_fptype_field_coding (inst->opcode); 2810 1.1 christos value = extract_field (FLD_type, inst->value, 0); 2811 1.1 christos switch (value) 2812 1.1 christos { 2813 1.1 christos case 0: inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_S; break; 2814 1.1 christos case 1: inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_D; break; 2815 1.1 christos case 3: inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_H; break; 2816 1.1 christos default: return 0; 2817 1.1 christos } 2818 1.1 christos } 2819 1.1 christos 2820 1.1 christos if (inst->opcode->flags & F_SSIZE) 2821 1.1 christos { 2822 1.1 christos /* N.B. some opcodes like FCMGT <V><d>, <V><n>, #0 have the size[1] as part 2823 1.1 christos of the base opcode. */ 2824 1.1 christos aarch64_insn mask; 2825 1.1 christos enum aarch64_opnd_qualifier candidates[AARCH64_MAX_QLF_SEQ_NUM]; 2826 1.1 christos idx = select_operand_for_scalar_size_field_coding (inst->opcode); 2827 1.1 christos value = extract_field (FLD_size, inst->value, inst->opcode->mask); 2828 1.1 christos mask = extract_field (FLD_size, ~inst->opcode->mask, 0); 2829 1.10 christos /* For most related instruciton, the 'size' field is fully available for 2830 1.10 christos operand encoding. */ 2831 1.10 christos if (mask == 0x3) 2832 1.10 christos { 2833 1.10 christos inst->operands[idx].qualifier = get_sreg_qualifier_from_value (value); 2834 1.1 christos if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR) 2835 1.1 christos return 0; 2836 1.1 christos } 2837 1.1 christos else 2838 1.1 christos { 2839 1.1 christos get_operand_possible_qualifiers (idx, inst->opcode->qualifiers_list, 2840 1.1 christos candidates); 2841 1.1 christos inst->operands[idx].qualifier 2842 1.1 christos = get_qualifier_from_partial_encoding (value, candidates, mask); 2843 1.10 christos } 2844 1.10 christos } 2845 1.10 christos 2846 1.10 christos if (inst->opcode->flags & F_LSFE_SZ) 2847 1.10 christos { 2848 1.10 christos value = extract_field (FLD_ldst_size, inst->value, 0); 2849 1.10 christos 2850 1.10 christos if (value > 0x3) 2851 1.10 christos return 0; 2852 1.10 christos 2853 1.10 christos for (int i = 0; 2854 1.10 christos aarch64_operands[inst->operands[i].type].op_class != AARCH64_OPND_CLASS_ADDRESS; 2855 1.10 christos i++) 2856 1.10 christos { 2857 1.10 christos inst->operands[i].qualifier = get_sreg_qualifier_from_value (value); 2858 1.10 christos if (inst->operands[i].qualifier == AARCH64_OPND_QLF_ERR) 2859 1.10 christos return 0; 2860 1.1 christos } 2861 1.1 christos } 2862 1.1 christos 2863 1.1 christos if (inst->opcode->flags & F_T) 2864 1.1 christos { 2865 1.1 christos /* Num of consecutive '0's on the right side of imm5<3:0>. */ 2866 1.1 christos int num = 0; 2867 1.1 christos unsigned val, Q; 2868 1.1 christos assert (aarch64_get_operand_class (inst->opcode->operands[0]) 2869 1.1 christos == AARCH64_OPND_CLASS_SIMD_REG); 2870 1.1 christos /* imm5<3:0> q <t> 2871 1.1 christos 0000 x reserved 2872 1.1 christos xxx1 0 8b 2873 1.1 christos xxx1 1 16b 2874 1.1 christos xx10 0 4h 2875 1.1 christos xx10 1 8h 2876 1.1 christos x100 0 2s 2877 1.1 christos x100 1 4s 2878 1.1 christos 1000 0 reserved 2879 1.1 christos 1000 1 2d */ 2880 1.1 christos val = extract_field (FLD_imm5, inst->value, 0); 2881 1.1 christos while ((val & 0x1) == 0 && ++num <= 3) 2882 1.1 christos val >>= 1; 2883 1.1 christos if (num > 3) 2884 1.1 christos return 0; 2885 1.10 christos Q = (unsigned) extract_field (FLD_Q, inst->value, inst->opcode->mask); 2886 1.10 christos inst->operands[0].qualifier = 2887 1.10 christos get_vreg_qualifier_from_value ((num << 1) | Q); 2888 1.1 christos if (inst->operands[0].qualifier == AARCH64_OPND_QLF_ERR) 2889 1.1 christos return 0; 2890 1.9 christos 2891 1.9 christos } 2892 1.9 christos 2893 1.9 christos if ((inst->opcode->flags & F_OPD_SIZE) && inst->opcode->iclass == sve2_urqvs) 2894 1.9 christos { 2895 1.9 christos unsigned size; 2896 1.9 christos size = (unsigned) extract_field (FLD_size, inst->value, 2897 1.10 christos inst->opcode->mask); 2898 1.10 christos inst->operands[0].qualifier 2899 1.9 christos = get_vreg_qualifier_from_value (1 + (size << 1)); 2900 1.10 christos if (inst->operands[0].qualifier == AARCH64_OPND_QLF_ERR) 2901 1.10 christos return 0; 2902 1.9 christos inst->operands[2].qualifier = get_sreg_qualifier_from_value (size); 2903 1.9 christos if (inst->operands[2].qualifier == AARCH64_OPND_QLF_ERR) 2904 1.1 christos return 0; 2905 1.1 christos } 2906 1.1 christos 2907 1.1 christos if (inst->opcode->flags & F_GPRSIZE_IN_Q) 2908 1.1 christos { 2909 1.1 christos /* Use Rt to encode in the case of e.g. 2910 1.1 christos STXP <Ws>, <Xt1>, <Xt2>, [<Xn|SP>{,#0}]. */ 2911 1.1 christos idx = aarch64_operand_index (inst->opcode->operands, AARCH64_OPND_Rt); 2912 1.1 christos if (idx == -1) 2913 1.1 christos { 2914 1.1 christos /* Otherwise use the result operand, which has to be a integer 2915 1.1 christos register. */ 2916 1.1 christos assert (aarch64_get_operand_class (inst->opcode->operands[0]) 2917 1.1 christos == AARCH64_OPND_CLASS_INT_REG); 2918 1.1 christos idx = 0; 2919 1.1 christos } 2920 1.10 christos assert (idx == 0 || idx == 1); 2921 1.10 christos value = extract_field (FLD_Q, inst->value, 0); 2922 1.1 christos inst->operands[idx].qualifier = get_greg_qualifier_from_value (value); 2923 1.1 christos if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR) 2924 1.1 christos return 0; 2925 1.1 christos } 2926 1.1 christos 2927 1.1 christos if (inst->opcode->flags & F_LDS_SIZE) 2928 1.1 christos { 2929 1.1 christos aarch64_field field = {0, 0}; 2930 1.1 christos assert (aarch64_get_operand_class (inst->opcode->operands[0]) 2931 1.1 christos == AARCH64_OPND_CLASS_INT_REG); 2932 1.1 christos gen_sub_field (FLD_opc, 0, 1, &field); 2933 1.1 christos value = extract_field_2 (&field, inst->value, 0); 2934 1.1 christos inst->operands[0].qualifier 2935 1.1 christos = value ? AARCH64_OPND_QLF_W : AARCH64_OPND_QLF_X; 2936 1.1 christos } 2937 1.1 christos 2938 1.1 christos /* Miscellaneous decoding; done as the last step. */ 2939 1.1 christos if (inst->opcode->flags & F_MISC) 2940 1.1 christos return do_misc_decoding (inst); 2941 1.1 christos 2942 1.1 christos return 1; 2943 1.1 christos } 2944 1.1 christos 2945 1.1 christos /* Converters converting a real opcode instruction to its alias form. */ 2946 1.1 christos 2947 1.1 christos /* ROR <Wd>, <Ws>, #<shift> 2948 1.1 christos is equivalent to: 2949 1.1 christos EXTR <Wd>, <Ws>, <Ws>, #<shift>. */ 2950 1.1 christos static int 2951 1.1 christos convert_extr_to_ror (aarch64_inst *inst) 2952 1.1 christos { 2953 1.1 christos if (inst->operands[1].reg.regno == inst->operands[2].reg.regno) 2954 1.1 christos { 2955 1.1 christos copy_operand_info (inst, 2, 3); 2956 1.1 christos inst->operands[3].type = AARCH64_OPND_NIL; 2957 1.1 christos return 1; 2958 1.1 christos } 2959 1.1 christos return 0; 2960 1.1 christos } 2961 1.1 christos 2962 1.1 christos /* UXTL<Q> <Vd>.<Ta>, <Vn>.<Tb> 2963 1.1 christos is equivalent to: 2964 1.1 christos USHLL<Q> <Vd>.<Ta>, <Vn>.<Tb>, #0. */ 2965 1.1 christos static int 2966 1.1 christos convert_shll_to_xtl (aarch64_inst *inst) 2967 1.1 christos { 2968 1.1 christos if (inst->operands[2].imm.value == 0) 2969 1.1 christos { 2970 1.1 christos inst->operands[2].type = AARCH64_OPND_NIL; 2971 1.1 christos return 1; 2972 1.1 christos } 2973 1.1 christos return 0; 2974 1.1 christos } 2975 1.1 christos 2976 1.1 christos /* Convert 2977 1.1 christos UBFM <Xd>, <Xn>, #<shift>, #63. 2978 1.1 christos to 2979 1.1 christos LSR <Xd>, <Xn>, #<shift>. */ 2980 1.1 christos static int 2981 1.1 christos convert_bfm_to_sr (aarch64_inst *inst) 2982 1.1 christos { 2983 1.1 christos int64_t imms, val; 2984 1.1 christos 2985 1.1 christos imms = inst->operands[3].imm.value; 2986 1.1 christos val = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 31 : 63; 2987 1.1 christos if (imms == val) 2988 1.1 christos { 2989 1.1 christos inst->operands[3].type = AARCH64_OPND_NIL; 2990 1.1 christos return 1; 2991 1.1 christos } 2992 1.1 christos 2993 1.1 christos return 0; 2994 1.1 christos } 2995 1.1 christos 2996 1.1 christos /* Convert MOV to ORR. */ 2997 1.1 christos static int 2998 1.1 christos convert_orr_to_mov (aarch64_inst *inst) 2999 1.1 christos { 3000 1.1 christos /* MOV <Vd>.<T>, <Vn>.<T> 3001 1.1 christos is equivalent to: 3002 1.1 christos ORR <Vd>.<T>, <Vn>.<T>, <Vn>.<T>. */ 3003 1.1 christos if (inst->operands[1].reg.regno == inst->operands[2].reg.regno) 3004 1.1 christos { 3005 1.1 christos inst->operands[2].type = AARCH64_OPND_NIL; 3006 1.1 christos return 1; 3007 1.1 christos } 3008 1.1 christos return 0; 3009 1.1 christos } 3010 1.1 christos 3011 1.1 christos /* When <imms> >= <immr>, the instruction written: 3012 1.1 christos SBFX <Xd>, <Xn>, #<lsb>, #<width> 3013 1.1 christos is equivalent to: 3014 1.1 christos SBFM <Xd>, <Xn>, #<lsb>, #(<lsb>+<width>-1). */ 3015 1.1 christos 3016 1.1 christos static int 3017 1.1 christos convert_bfm_to_bfx (aarch64_inst *inst) 3018 1.1 christos { 3019 1.1 christos int64_t immr, imms; 3020 1.1 christos 3021 1.1 christos immr = inst->operands[2].imm.value; 3022 1.1 christos imms = inst->operands[3].imm.value; 3023 1.1 christos if (imms >= immr) 3024 1.1 christos { 3025 1.1 christos int64_t lsb = immr; 3026 1.1 christos inst->operands[2].imm.value = lsb; 3027 1.1 christos inst->operands[3].imm.value = imms + 1 - lsb; 3028 1.1 christos /* The two opcodes have different qualifiers for 3029 1.1 christos the immediate operands; reset to help the checking. */ 3030 1.1 christos reset_operand_qualifier (inst, 2); 3031 1.1 christos reset_operand_qualifier (inst, 3); 3032 1.1 christos return 1; 3033 1.1 christos } 3034 1.1 christos 3035 1.1 christos return 0; 3036 1.1 christos } 3037 1.1 christos 3038 1.1 christos /* When <imms> < <immr>, the instruction written: 3039 1.1 christos SBFIZ <Xd>, <Xn>, #<lsb>, #<width> 3040 1.1 christos is equivalent to: 3041 1.1 christos SBFM <Xd>, <Xn>, #((64-<lsb>)&0x3f), #(<width>-1). */ 3042 1.1 christos 3043 1.1 christos static int 3044 1.1 christos convert_bfm_to_bfi (aarch64_inst *inst) 3045 1.1 christos { 3046 1.1 christos int64_t immr, imms, val; 3047 1.1 christos 3048 1.1 christos immr = inst->operands[2].imm.value; 3049 1.1 christos imms = inst->operands[3].imm.value; 3050 1.1 christos val = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 32 : 64; 3051 1.1 christos if (imms < immr) 3052 1.1 christos { 3053 1.1 christos inst->operands[2].imm.value = (val - immr) & (val - 1); 3054 1.1 christos inst->operands[3].imm.value = imms + 1; 3055 1.1 christos /* The two opcodes have different qualifiers for 3056 1.1 christos the immediate operands; reset to help the checking. */ 3057 1.1 christos reset_operand_qualifier (inst, 2); 3058 1.1 christos reset_operand_qualifier (inst, 3); 3059 1.1 christos return 1; 3060 1.1 christos } 3061 1.1 christos 3062 1.1 christos return 0; 3063 1.3 christos } 3064 1.3 christos 3065 1.3 christos /* The instruction written: 3066 1.3 christos BFC <Xd>, #<lsb>, #<width> 3067 1.3 christos is equivalent to: 3068 1.3 christos BFM <Xd>, XZR, #((64-<lsb>)&0x3f), #(<width>-1). */ 3069 1.3 christos 3070 1.3 christos static int 3071 1.3 christos convert_bfm_to_bfc (aarch64_inst *inst) 3072 1.3 christos { 3073 1.3 christos int64_t immr, imms, val; 3074 1.3 christos 3075 1.3 christos /* Should have been assured by the base opcode value. */ 3076 1.3 christos assert (inst->operands[1].reg.regno == 0x1f); 3077 1.3 christos 3078 1.3 christos immr = inst->operands[2].imm.value; 3079 1.3 christos imms = inst->operands[3].imm.value; 3080 1.3 christos val = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 32 : 64; 3081 1.3 christos if (imms < immr) 3082 1.3 christos { 3083 1.3 christos /* Drop XZR from the second operand. */ 3084 1.3 christos copy_operand_info (inst, 1, 2); 3085 1.3 christos copy_operand_info (inst, 2, 3); 3086 1.3 christos inst->operands[3].type = AARCH64_OPND_NIL; 3087 1.3 christos 3088 1.3 christos /* Recalculate the immediates. */ 3089 1.3 christos inst->operands[1].imm.value = (val - immr) & (val - 1); 3090 1.3 christos inst->operands[2].imm.value = imms + 1; 3091 1.3 christos 3092 1.3 christos /* The two opcodes have different qualifiers for the operands; reset to 3093 1.3 christos help the checking. */ 3094 1.3 christos reset_operand_qualifier (inst, 1); 3095 1.3 christos reset_operand_qualifier (inst, 2); 3096 1.3 christos reset_operand_qualifier (inst, 3); 3097 1.3 christos 3098 1.3 christos return 1; 3099 1.3 christos } 3100 1.3 christos 3101 1.3 christos return 0; 3102 1.1 christos } 3103 1.1 christos 3104 1.1 christos /* The instruction written: 3105 1.1 christos LSL <Xd>, <Xn>, #<shift> 3106 1.1 christos is equivalent to: 3107 1.1 christos UBFM <Xd>, <Xn>, #((64-<shift>)&0x3f), #(63-<shift>). */ 3108 1.1 christos 3109 1.1 christos static int 3110 1.1 christos convert_ubfm_to_lsl (aarch64_inst *inst) 3111 1.1 christos { 3112 1.1 christos int64_t immr = inst->operands[2].imm.value; 3113 1.1 christos int64_t imms = inst->operands[3].imm.value; 3114 1.1 christos int64_t val 3115 1.1 christos = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 31 : 63; 3116 1.1 christos 3117 1.1 christos if ((immr == 0 && imms == val) || immr == imms + 1) 3118 1.1 christos { 3119 1.1 christos inst->operands[3].type = AARCH64_OPND_NIL; 3120 1.1 christos inst->operands[2].imm.value = val - imms; 3121 1.1 christos return 1; 3122 1.1 christos } 3123 1.1 christos 3124 1.1 christos return 0; 3125 1.1 christos } 3126 1.3 christos 3127 1.3 christos /* CINC <Wd>, <Wn>, <cond> 3128 1.1 christos is equivalent to: 3129 1.1 christos CSINC <Wd>, <Wn>, <Wn>, invert(<cond>) 3130 1.1 christos where <cond> is not AL or NV. */ 3131 1.1 christos 3132 1.3 christos static int 3133 1.3 christos convert_from_csel (aarch64_inst *inst) 3134 1.1 christos { 3135 1.1 christos if (inst->operands[1].reg.regno == inst->operands[2].reg.regno 3136 1.1 christos && (inst->operands[3].cond->value & 0xe) != 0xe) 3137 1.1 christos { 3138 1.1 christos copy_operand_info (inst, 2, 3); 3139 1.1 christos inst->operands[2].cond = get_inverted_cond (inst->operands[3].cond); 3140 1.1 christos inst->operands[3].type = AARCH64_OPND_NIL; 3141 1.1 christos return 1; 3142 1.1 christos } 3143 1.1 christos return 0; 3144 1.1 christos } 3145 1.3 christos 3146 1.3 christos /* CSET <Wd>, <cond> 3147 1.1 christos is equivalent to: 3148 1.1 christos CSINC <Wd>, WZR, WZR, invert(<cond>) 3149 1.1 christos where <cond> is not AL or NV. */ 3150 1.1 christos 3151 1.1 christos static int 3152 1.3 christos convert_csinc_to_cset (aarch64_inst *inst) 3153 1.3 christos { 3154 1.1 christos if (inst->operands[1].reg.regno == 0x1f 3155 1.1 christos && inst->operands[2].reg.regno == 0x1f 3156 1.1 christos && (inst->operands[3].cond->value & 0xe) != 0xe) 3157 1.1 christos { 3158 1.1 christos copy_operand_info (inst, 1, 3); 3159 1.1 christos inst->operands[1].cond = get_inverted_cond (inst->operands[3].cond); 3160 1.1 christos inst->operands[3].type = AARCH64_OPND_NIL; 3161 1.1 christos inst->operands[2].type = AARCH64_OPND_NIL; 3162 1.1 christos return 1; 3163 1.1 christos } 3164 1.1 christos return 0; 3165 1.1 christos } 3166 1.9 christos 3167 1.1 christos /* MOV <Wd>, #<imm> 3168 1.1 christos is equivalent to: 3169 1.1 christos MOVZ <Wd>, #<imm16_5>, LSL #<shift>. 3170 1.1 christos 3171 1.1 christos A disassembler may output ORR, MOVZ and MOVN as a MOV mnemonic, except when 3172 1.1 christos ORR has an immediate that could be generated by a MOVZ or MOVN instruction, 3173 1.1 christos or where a MOVN has an immediate that could be encoded by MOVZ, or where 3174 1.1 christos MOVZ/MOVN #0 have a shift amount other than LSL #0, in which case the 3175 1.1 christos machine-instruction mnemonic must be used. */ 3176 1.1 christos 3177 1.1 christos static int 3178 1.1 christos convert_movewide_to_mov (aarch64_inst *inst) 3179 1.1 christos { 3180 1.1 christos uint64_t value = inst->operands[1].imm.value; 3181 1.1 christos /* MOVZ/MOVN #0 have a shift amount other than LSL #0. */ 3182 1.1 christos if (value == 0 && inst->operands[1].shifter.amount != 0) 3183 1.1 christos return 0; 3184 1.1 christos inst->operands[1].type = AARCH64_OPND_IMM_MOV; 3185 1.1 christos inst->operands[1].shifter.kind = AARCH64_MOD_NONE; 3186 1.1 christos value <<= inst->operands[1].shifter.amount; 3187 1.1 christos /* As an alias convertor, it has to be clear that the INST->OPCODE 3188 1.1 christos is the opcode of the real instruction. */ 3189 1.1 christos if (inst->opcode->op == OP_MOVN) 3190 1.1 christos { 3191 1.6 christos int is32 = inst->operands[0].qualifier == AARCH64_OPND_QLF_W; 3192 1.1 christos value = ~value; 3193 1.1 christos /* A MOVN has an immediate that could be encoded by MOVZ. */ 3194 1.1 christos if (aarch64_wide_constant_p (value, is32, NULL)) 3195 1.1 christos return 0; 3196 1.1 christos } 3197 1.1 christos inst->operands[1].imm.value = value; 3198 1.1 christos inst->operands[1].shifter.amount = 0; 3199 1.1 christos return 1; 3200 1.1 christos } 3201 1.1 christos 3202 1.1 christos /* MOV <Wd>, #<imm> 3203 1.1 christos is equivalent to: 3204 1.1 christos ORR <Wd>, WZR, #<imm>. 3205 1.1 christos 3206 1.1 christos A disassembler may output ORR, MOVZ and MOVN as a MOV mnemonic, except when 3207 1.1 christos ORR has an immediate that could be generated by a MOVZ or MOVN instruction, 3208 1.1 christos or where a MOVN has an immediate that could be encoded by MOVZ, or where 3209 1.1 christos MOVZ/MOVN #0 have a shift amount other than LSL #0, in which case the 3210 1.1 christos machine-instruction mnemonic must be used. */ 3211 1.1 christos 3212 1.1 christos static int 3213 1.1 christos convert_movebitmask_to_mov (aarch64_inst *inst) 3214 1.1 christos { 3215 1.1 christos int is32; 3216 1.1 christos uint64_t value; 3217 1.1 christos 3218 1.1 christos /* Should have been assured by the base opcode value. */ 3219 1.1 christos assert (inst->operands[1].reg.regno == 0x1f); 3220 1.1 christos copy_operand_info (inst, 1, 2); 3221 1.1 christos is32 = inst->operands[0].qualifier == AARCH64_OPND_QLF_W; 3222 1.1 christos inst->operands[1].type = AARCH64_OPND_IMM_MOV; 3223 1.1 christos value = inst->operands[1].imm.value; 3224 1.6 christos /* ORR has an immediate that could be generated by a MOVZ or MOVN 3225 1.6 christos instruction. */ 3226 1.1 christos if (inst->operands[0].reg.regno != 0x1f 3227 1.1 christos && (aarch64_wide_constant_p (value, is32, NULL) 3228 1.1 christos || aarch64_wide_constant_p (~value, is32, NULL))) 3229 1.1 christos return 0; 3230 1.1 christos 3231 1.1 christos inst->operands[2].type = AARCH64_OPND_NIL; 3232 1.1 christos return 1; 3233 1.1 christos } 3234 1.1 christos 3235 1.1 christos /* Some alias opcodes are disassembled by being converted from their real-form. 3236 1.1 christos N.B. INST->OPCODE is the real opcode rather than the alias. */ 3237 1.1 christos 3238 1.1 christos static int 3239 1.1 christos convert_to_alias (aarch64_inst *inst, const aarch64_opcode *alias) 3240 1.1 christos { 3241 1.1 christos switch (alias->op) 3242 1.1 christos { 3243 1.1 christos case OP_ASR_IMM: 3244 1.1 christos case OP_LSR_IMM: 3245 1.1 christos return convert_bfm_to_sr (inst); 3246 1.1 christos case OP_LSL_IMM: 3247 1.1 christos return convert_ubfm_to_lsl (inst); 3248 1.1 christos case OP_CINC: 3249 1.1 christos case OP_CINV: 3250 1.1 christos case OP_CNEG: 3251 1.1 christos return convert_from_csel (inst); 3252 1.1 christos case OP_CSET: 3253 1.1 christos case OP_CSETM: 3254 1.1 christos return convert_csinc_to_cset (inst); 3255 1.1 christos case OP_UBFX: 3256 1.1 christos case OP_BFXIL: 3257 1.1 christos case OP_SBFX: 3258 1.1 christos return convert_bfm_to_bfx (inst); 3259 1.1 christos case OP_SBFIZ: 3260 1.3 christos case OP_BFI: 3261 1.3 christos case OP_UBFIZ: 3262 1.1 christos return convert_bfm_to_bfi (inst); 3263 1.1 christos case OP_BFC: 3264 1.1 christos return convert_bfm_to_bfc (inst); 3265 1.1 christos case OP_MOV_V: 3266 1.1 christos return convert_orr_to_mov (inst); 3267 1.1 christos case OP_MOV_IMM_WIDE: 3268 1.1 christos case OP_MOV_IMM_WIDEN: 3269 1.1 christos return convert_movewide_to_mov (inst); 3270 1.1 christos case OP_MOV_IMM_LOG: 3271 1.1 christos return convert_movebitmask_to_mov (inst); 3272 1.1 christos case OP_ROR_IMM: 3273 1.1 christos return convert_extr_to_ror (inst); 3274 1.1 christos case OP_SXTL: 3275 1.1 christos case OP_SXTL2: 3276 1.1 christos case OP_UXTL: 3277 1.1 christos case OP_UXTL2: 3278 1.1 christos return convert_shll_to_xtl (inst); 3279 1.1 christos default: 3280 1.1 christos return 0; 3281 1.8 christos } 3282 1.6 christos } 3283 1.6 christos 3284 1.1 christos static bool 3285 1.1 christos aarch64_opcode_decode (const aarch64_opcode *, const aarch64_insn, 3286 1.1 christos aarch64_inst *, int, aarch64_operand_error *errors); 3287 1.1 christos 3288 1.1 christos /* Given the instruction information in *INST, check if the instruction has 3289 1.1 christos any alias form that can be used to represent *INST. If the answer is yes, 3290 1.1 christos update *INST to be in the form of the determined alias. */ 3291 1.1 christos 3292 1.1 christos /* In the opcode description table, the following flags are used in opcode 3293 1.1 christos entries to help establish the relations between the real and alias opcodes: 3294 1.1 christos 3295 1.1 christos F_ALIAS: opcode is an alias 3296 1.1 christos F_HAS_ALIAS: opcode has alias(es) 3297 1.1 christos F_P1 3298 1.1 christos F_P2 3299 1.1 christos F_P3: Disassembly preference priority 1-3 (the larger the 3300 1.1 christos higher). If nothing is specified, it is the priority 3301 1.1 christos 0 by default, i.e. the lowest priority. 3302 1.1 christos 3303 1.1 christos Although the relation between the machine and the alias instructions are not 3304 1.1 christos explicitly described, it can be easily determined from the base opcode 3305 1.1 christos values, masks and the flags F_ALIAS and F_HAS_ALIAS in their opcode 3306 1.1 christos description entries: 3307 1.1 christos 3308 1.1 christos The mask of an alias opcode must be equal to or a super-set (i.e. more 3309 1.1 christos constrained) of that of the aliased opcode; so is the base opcode value. 3310 1.1 christos 3311 1.1 christos if (opcode_has_alias (real) && alias_opcode_p (opcode) 3312 1.1 christos && (opcode->mask & real->mask) == real->mask 3313 1.1 christos && (real->mask & opcode->opcode) == (real->mask & real->opcode)) 3314 1.1 christos then OPCODE is an alias of, and only of, the REAL instruction 3315 1.1 christos 3316 1.1 christos The alias relationship is forced flat-structured to keep related algorithm 3317 1.1 christos simple; an opcode entry cannot be flagged with both F_ALIAS and F_HAS_ALIAS. 3318 1.1 christos 3319 1.1 christos During the disassembling, the decoding decision tree (in 3320 1.1 christos opcodes/aarch64-dis-2.c) always returns an machine instruction opcode entry; 3321 1.1 christos if the decoding of such a machine instruction succeeds (and -Mno-aliases is 3322 1.1 christos not specified), the disassembler will check whether there is any alias 3323 1.1 christos instruction exists for this real instruction. If there is, the disassembler 3324 1.1 christos will try to disassemble the 32-bit binary again using the alias's rule, or 3325 1.1 christos try to convert the IR to the form of the alias. In the case of the multiple 3326 1.1 christos aliases, the aliases are tried one by one from the highest priority 3327 1.1 christos (currently the flag F_P3) to the lowest priority (no priority flag), and the 3328 1.1 christos first succeeds first adopted. 3329 1.1 christos 3330 1.1 christos You may ask why there is a need for the conversion of IR from one form to 3331 1.1 christos another in handling certain aliases. This is because on one hand it avoids 3332 1.1 christos adding more operand code to handle unusual encoding/decoding; on other 3333 1.1 christos hand, during the disassembling, the conversion is an effective approach to 3334 1.1 christos check the condition of an alias (as an alias may be adopted only if certain 3335 1.1 christos conditions are met). 3336 1.1 christos 3337 1.1 christos In order to speed up the alias opcode lookup, aarch64-gen has preprocessed 3338 1.1 christos aarch64_opcode_table and generated aarch64_find_alias_opcode and 3339 1.6 christos aarch64_find_next_alias_opcode (in opcodes/aarch64-dis-2.c) to help. */ 3340 1.6 christos 3341 1.1 christos static void 3342 1.1 christos determine_disassembling_preference (struct aarch64_inst *inst, 3343 1.1 christos aarch64_operand_error *errors) 3344 1.1 christos { 3345 1.1 christos const aarch64_opcode *opcode; 3346 1.1 christos const aarch64_opcode *alias; 3347 1.1 christos 3348 1.6 christos opcode = inst->opcode; 3349 1.1 christos 3350 1.1 christos /* This opcode does not have an alias, so use itself. */ 3351 1.1 christos if (!opcode_has_alias (opcode)) 3352 1.1 christos return; 3353 1.1 christos 3354 1.1 christos alias = aarch64_find_alias_opcode (opcode); 3355 1.1 christos assert (alias); 3356 1.1 christos 3357 1.1 christos #ifdef DEBUG_AARCH64 3358 1.1 christos if (debug_dump) 3359 1.1 christos { 3360 1.1 christos const aarch64_opcode *tmp = alias; 3361 1.1 christos printf ("#### LIST orderd: "); 3362 1.1 christos while (tmp) 3363 1.1 christos { 3364 1.1 christos printf ("%s, ", tmp->name); 3365 1.1 christos tmp = aarch64_find_next_alias_opcode (tmp); 3366 1.1 christos } 3367 1.1 christos printf ("\n"); 3368 1.1 christos } 3369 1.1 christos #endif /* DEBUG_AARCH64 */ 3370 1.1 christos 3371 1.3 christos for (; alias; alias = aarch64_find_next_alias_opcode (alias)) 3372 1.1 christos { 3373 1.1 christos DEBUG_TRACE ("try %s", alias->name); 3374 1.1 christos assert (alias_opcode_p (alias) || opcode_has_alias (opcode)); 3375 1.1 christos 3376 1.1 christos /* An alias can be a pseudo opcode which will never be used in the 3377 1.1 christos disassembly, e.g. BIC logical immediate is such a pseudo opcode 3378 1.1 christos aliasing AND. */ 3379 1.1 christos if (pseudo_opcode_p (alias)) 3380 1.1 christos { 3381 1.1 christos DEBUG_TRACE ("skip pseudo %s", alias->name); 3382 1.1 christos continue; 3383 1.1 christos } 3384 1.1 christos 3385 1.1 christos if ((inst->value & alias->mask) != alias->opcode) 3386 1.1 christos { 3387 1.8 christos DEBUG_TRACE ("skip %s as base opcode not match", alias->name); 3388 1.9 christos continue; 3389 1.8 christos } 3390 1.8 christos 3391 1.8 christos if (!AARCH64_CPU_HAS_ALL_FEATURES (arch_variant, *alias->avariant)) 3392 1.8 christos { 3393 1.8 christos DEBUG_TRACE ("skip %s: we're missing features", alias->name); 3394 1.1 christos continue; 3395 1.1 christos } 3396 1.1 christos 3397 1.1 christos /* No need to do any complicated transformation on operands, if the alias 3398 1.1 christos opcode does not have any operand. */ 3399 1.1 christos if (aarch64_num_of_operands (alias) == 0 && alias->opcode == inst->value) 3400 1.1 christos { 3401 1.1 christos DEBUG_TRACE ("succeed with 0-operand opcode %s", alias->name); 3402 1.1 christos aarch64_replace_opcode (inst, alias); 3403 1.1 christos return; 3404 1.1 christos } 3405 1.1 christos if (alias->flags & F_CONV) 3406 1.1 christos { 3407 1.1 christos aarch64_inst copy; 3408 1.1 christos memcpy (©, inst, sizeof (aarch64_inst)); 3409 1.1 christos /* ALIAS is the preference as long as the instruction can be 3410 1.1 christos successfully converted to the form of ALIAS. */ 3411 1.8 christos if (convert_to_alias (©, alias) == 1) 3412 1.8 christos { 3413 1.8 christos aarch64_replace_opcode (©, alias); 3414 1.8 christos if (aarch64_match_operands_constraint (©, NULL) != 1) 3415 1.8 christos { 3416 1.8 christos DEBUG_TRACE ("FAILED with alias %s ", alias->name); 3417 1.8 christos } 3418 1.8 christos else 3419 1.8 christos { 3420 1.1 christos DEBUG_TRACE ("succeed with %s via conversion", alias->name); 3421 1.1 christos memcpy (inst, ©, sizeof (aarch64_inst)); 3422 1.1 christos } 3423 1.1 christos return; 3424 1.1 christos } 3425 1.1 christos } 3426 1.1 christos else 3427 1.1 christos { 3428 1.6 christos /* Directly decode the alias opcode. */ 3429 1.1 christos aarch64_inst temp; 3430 1.1 christos memset (&temp, '\0', sizeof (aarch64_inst)); 3431 1.1 christos if (aarch64_opcode_decode (alias, inst->value, &temp, 1, errors) == 1) 3432 1.1 christos { 3433 1.1 christos DEBUG_TRACE ("succeed with %s via direct decoding", alias->name); 3434 1.1 christos memcpy (inst, &temp, sizeof (aarch64_inst)); 3435 1.1 christos return; 3436 1.1 christos } 3437 1.1 christos } 3438 1.6 christos } 3439 1.6 christos } 3440 1.6 christos 3441 1.6 christos /* Some instructions (including all SVE ones) use the instruction class 3442 1.6 christos to describe how a qualifiers_list index is represented in the instruction 3443 1.6 christos encoding. If INST is such an instruction, decode the appropriate fields 3444 1.8 christos and fill in the operand qualifiers accordingly. Return true if no 3445 1.6 christos problems are found. */ 3446 1.6 christos 3447 1.6 christos static bool 3448 1.6 christos aarch64_decode_variant_using_iclass (aarch64_inst *inst) 3449 1.6 christos { 3450 1.6 christos int i, variant; 3451 1.6 christos 3452 1.9 christos variant = 0; 3453 1.9 christos switch (inst->opcode->iclass) 3454 1.9 christos { 3455 1.9 christos case sme_mov: 3456 1.9 christos variant = extract_fields (inst->value, 0, 2, FLD_SME_Q, FLD_SME_size_22); 3457 1.9 christos if (variant >= 4 && variant < 7) 3458 1.9 christos return false; 3459 1.9 christos if (variant == 7) 3460 1.9 christos variant = 4; 3461 1.9 christos break; 3462 1.9 christos 3463 1.9 christos case sme_psel: 3464 1.9 christos i = extract_fields (inst->value, 0, 2, FLD_SME_tszh, FLD_SME_tszl); 3465 1.9 christos if (i == 0) 3466 1.9 christos return false; 3467 1.9 christos while ((i & 1) == 0) 3468 1.9 christos { 3469 1.9 christos i >>= 1; 3470 1.9 christos variant += 1; 3471 1.9 christos } 3472 1.9 christos break; 3473 1.9 christos 3474 1.9 christos case sme_shift: 3475 1.10 christos i = extract_field (FLD_SVE_tszh, inst->value, 0); 3476 1.10 christos goto sve_shift; 3477 1.10 christos 3478 1.10 christos case sme_size_12_bh: 3479 1.10 christos variant = extract_field (FLD_S, inst->value, 0); 3480 1.10 christos if (variant > 1) 3481 1.9 christos return false; 3482 1.9 christos break; 3483 1.9 christos 3484 1.9 christos case sme_size_12_bhs: 3485 1.9 christos variant = extract_field (FLD_SME_size_12, inst->value, 0); 3486 1.9 christos if (variant >= 3) 3487 1.9 christos return false; 3488 1.9 christos break; 3489 1.9 christos 3490 1.9 christos case sme_size_12_hs: 3491 1.9 christos variant = extract_field (FLD_SME_size_12, inst->value, 0); 3492 1.9 christos if (variant != 1 && variant != 2) 3493 1.9 christos return false; 3494 1.10 christos variant -= 1; 3495 1.10 christos break; 3496 1.10 christos 3497 1.10 christos case sme_size_12_b: 3498 1.10 christos variant = extract_field (FLD_SME_size_12, inst->value, 0); 3499 1.10 christos if (variant != 0) 3500 1.9 christos return false; 3501 1.9 christos break; 3502 1.9 christos 3503 1.9 christos case sme_size_22: 3504 1.9 christos variant = extract_field (FLD_SME_size_22, inst->value, 0); 3505 1.9 christos break; 3506 1.9 christos 3507 1.9 christos case sme_size_22_hsd: 3508 1.9 christos variant = extract_field (FLD_SME_size_22, inst->value, 0); 3509 1.9 christos if (variant < 1) 3510 1.9 christos return false; 3511 1.9 christos variant -= 1; 3512 1.9 christos break; 3513 1.9 christos 3514 1.9 christos case sme_sz_23: 3515 1.6 christos variant = extract_field (FLD_SME_sz_23, inst->value, 0); 3516 1.6 christos break; 3517 1.6 christos 3518 1.6 christos case sve_cpy: 3519 1.6 christos variant = extract_fields (inst->value, 0, 2, FLD_size, FLD_SVE_M_14); 3520 1.10 christos break; 3521 1.10 christos 3522 1.6 christos case sve_index: 3523 1.8 christos i = extract_field (FLD_imm5, inst->value, 0); 3524 1.6 christos 3525 1.6 christos if ((i & 31) == 0) 3526 1.6 christos return false; 3527 1.6 christos while ((i & 1) == 0) 3528 1.6 christos { 3529 1.6 christos i >>= 1; 3530 1.6 christos variant += 1; 3531 1.6 christos } 3532 1.6 christos break; 3533 1.6 christos 3534 1.6 christos case sve_limm: 3535 1.6 christos /* Pick the smallest applicable element size. */ 3536 1.6 christos if ((inst->value & 0x20600) == 0x600) 3537 1.6 christos variant = 0; 3538 1.6 christos else if ((inst->value & 0x20400) == 0x400) 3539 1.6 christos variant = 1; 3540 1.6 christos else if ((inst->value & 0x20000) == 0) 3541 1.6 christos variant = 2; 3542 1.6 christos else 3543 1.9 christos variant = 3; 3544 1.9 christos break; 3545 1.9 christos 3546 1.9 christos case sme2_mov: 3547 1.9 christos /* .D is preferred over the other sizes in disassembly. */ 3548 1.9 christos variant = 3; 3549 1.9 christos break; 3550 1.6 christos 3551 1.9 christos case sme2_movaz: 3552 1.6 christos case sme_misc: 3553 1.6 christos case sve_misc: 3554 1.6 christos /* These instructions have only a single variant. */ 3555 1.6 christos break; 3556 1.6 christos 3557 1.6 christos case sve_movprfx: 3558 1.6 christos variant = extract_fields (inst->value, 0, 2, FLD_size, FLD_SVE_M_16); 3559 1.6 christos break; 3560 1.6 christos 3561 1.6 christos case sve_pred_zm: 3562 1.6 christos variant = extract_field (FLD_SVE_M_4, inst->value, 0); 3563 1.6 christos break; 3564 1.6 christos 3565 1.6 christos case sve_shift_pred: 3566 1.8 christos i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_SVE_tszl_8); 3567 1.6 christos sve_shift: 3568 1.6 christos if (i == 0) 3569 1.6 christos return false; 3570 1.6 christos while (i != 1) 3571 1.6 christos { 3572 1.6 christos i >>= 1; 3573 1.6 christos variant += 1; 3574 1.6 christos } 3575 1.6 christos break; 3576 1.6 christos 3577 1.6 christos case sve_shift_unpred: 3578 1.6 christos i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_SVE_tszl_19); 3579 1.6 christos goto sve_shift; 3580 1.6 christos 3581 1.8 christos case sve_size_bhs: 3582 1.6 christos variant = extract_field (FLD_size, inst->value, 0); 3583 1.6 christos if (variant >= 3) 3584 1.6 christos return false; 3585 1.6 christos break; 3586 1.6 christos 3587 1.6 christos case sve_size_bhsd: 3588 1.6 christos variant = extract_field (FLD_size, inst->value, 0); 3589 1.6 christos break; 3590 1.6 christos 3591 1.8 christos case sve_size_hsd: 3592 1.6 christos i = extract_field (FLD_size, inst->value, 0); 3593 1.6 christos if (i < 1) 3594 1.6 christos return false; 3595 1.9 christos variant = i - 1; 3596 1.9 christos break; 3597 1.7 christos 3598 1.6 christos case sme_fp_sd: 3599 1.6 christos case sme_int_sd: 3600 1.6 christos case sve_size_bh: 3601 1.6 christos case sve_size_sd: 3602 1.7 christos variant = extract_field (FLD_SVE_sz, inst->value, 0); 3603 1.7 christos break; 3604 1.7 christos 3605 1.7 christos case sve_size_sd2: 3606 1.10 christos variant = extract_field (FLD_SVE_sz2, inst->value, 0); 3607 1.10 christos break; 3608 1.10 christos 3609 1.10 christos case sve_size_sd3: 3610 1.10 christos variant = extract_field (FLD_SVE_sz3, inst->value, 0); 3611 1.10 christos break; 3612 1.10 christos 3613 1.10 christos case sve_size_sd4: 3614 1.7 christos variant = extract_field (FLD_SVE_sz4, inst->value, 0); 3615 1.7 christos break; 3616 1.7 christos 3617 1.8 christos case sve_size_hsd2: 3618 1.7 christos i = extract_field (FLD_SVE_size, inst->value, 0); 3619 1.7 christos if (i < 1) 3620 1.7 christos return false; 3621 1.10 christos variant = i - 1; 3622 1.10 christos break; 3623 1.10 christos 3624 1.10 christos case sve_size_hsd3: 3625 1.10 christos i = extract_field (FLD_len, inst->value, 0); 3626 1.10 christos if (i < 1) 3627 1.10 christos return false; 3628 1.7 christos variant = i - 1; 3629 1.7 christos break; 3630 1.7 christos 3631 1.7 christos case sve_size_13: 3632 1.7 christos /* Ignore low bit of this field since that is set in the opcode for 3633 1.7 christos instructions of this iclass. */ 3634 1.7 christos i = (extract_field (FLD_size, inst->value, 0) & 2); 3635 1.7 christos variant = (i >> 1); 3636 1.7 christos break; 3637 1.7 christos 3638 1.8 christos case sve_shift_tsz_bhsd: 3639 1.7 christos i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_SVE_tszl_19); 3640 1.7 christos if (i == 0) 3641 1.7 christos return false; 3642 1.7 christos while (i != 1) 3643 1.7 christos { 3644 1.7 christos i >>= 1; 3645 1.7 christos variant += 1; 3646 1.7 christos } 3647 1.7 christos break; 3648 1.7 christos 3649 1.8 christos case sve_size_tsz_bhs: 3650 1.7 christos i = extract_fields (inst->value, 0, 2, FLD_SVE_sz, FLD_SVE_tszl_19); 3651 1.7 christos if (i == 0) 3652 1.7 christos return false; 3653 1.8 christos while (i != 1) 3654 1.7 christos { 3655 1.7 christos if (i & 1) 3656 1.7 christos return false; 3657 1.7 christos i >>= 1; 3658 1.7 christos variant += 1; 3659 1.7 christos } 3660 1.7 christos break; 3661 1.7 christos 3662 1.8 christos case sve_shift_tsz_hsd: 3663 1.7 christos i = extract_fields (inst->value, 0, 2, FLD_SVE_sz, FLD_SVE_tszl_19); 3664 1.7 christos if (i == 0) 3665 1.7 christos return false; 3666 1.7 christos while (i != 1) 3667 1.7 christos { 3668 1.7 christos i >>= 1; 3669 1.7 christos variant += 1; 3670 1.6 christos } 3671 1.6 christos break; 3672 1.8 christos 3673 1.6 christos default: 3674 1.6 christos /* No mapping between instruction class and qualifiers. */ 3675 1.6 christos return true; 3676 1.6 christos } 3677 1.8 christos 3678 1.6 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i) 3679 1.1 christos inst->operands[i].qualifier = inst->opcode->qualifiers_list[variant][i]; 3680 1.1 christos return true; 3681 1.1 christos } 3682 1.1 christos /* Decode the CODE according to OPCODE; fill INST. Return 0 if the decoding 3683 1.1 christos fails, which meanes that CODE is not an instruction of OPCODE; otherwise 3684 1.1 christos return 1. 3685 1.1 christos 3686 1.1 christos If OPCODE has alias(es) and NOALIASES_P is 0, an alias opcode may be 3687 1.8 christos determined and used to disassemble CODE; this is done just before the 3688 1.1 christos return. */ 3689 1.6 christos 3690 1.6 christos static bool 3691 1.1 christos aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code, 3692 1.1 christos aarch64_inst *inst, int noaliases_p, 3693 1.1 christos aarch64_operand_error *errors) 3694 1.1 christos { 3695 1.1 christos int i; 3696 1.1 christos 3697 1.1 christos DEBUG_TRACE ("enter with %s", opcode->name); 3698 1.6 christos 3699 1.6 christos assert (opcode && inst); 3700 1.6 christos 3701 1.1 christos /* Clear inst. */ 3702 1.1 christos memset (inst, '\0', sizeof (aarch64_inst)); 3703 1.1 christos 3704 1.1 christos /* Check the base opcode. */ 3705 1.1 christos if ((code & opcode->mask) != (opcode->opcode & opcode->mask)) 3706 1.1 christos { 3707 1.1 christos DEBUG_TRACE ("base opcode match FAIL"); 3708 1.1 christos goto decode_fail; 3709 1.1 christos } 3710 1.1 christos 3711 1.1 christos inst->opcode = opcode; 3712 1.1 christos inst->value = code; 3713 1.1 christos 3714 1.1 christos /* Assign operand codes and indexes. */ 3715 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i) 3716 1.1 christos { 3717 1.1 christos if (opcode->operands[i] == AARCH64_OPND_NIL) 3718 1.1 christos break; 3719 1.1 christos inst->operands[i].type = opcode->operands[i]; 3720 1.1 christos inst->operands[i].idx = i; 3721 1.1 christos } 3722 1.1 christos 3723 1.1 christos /* Call the opcode decoder indicated by flags. */ 3724 1.1 christos if (opcode_has_special_coder (opcode) && do_special_decoding (inst) == 0) 3725 1.1 christos { 3726 1.1 christos DEBUG_TRACE ("opcode flag-based decoder FAIL"); 3727 1.6 christos goto decode_fail; 3728 1.6 christos } 3729 1.6 christos 3730 1.6 christos /* Possibly use the instruction class to determine the correct 3731 1.6 christos qualifier. */ 3732 1.6 christos if (!aarch64_decode_variant_using_iclass (inst)) 3733 1.6 christos { 3734 1.6 christos DEBUG_TRACE ("iclass-based decoder FAIL"); 3735 1.1 christos goto decode_fail; 3736 1.1 christos } 3737 1.1 christos 3738 1.1 christos /* Call operand decoders. */ 3739 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i) 3740 1.5 christos { 3741 1.1 christos const aarch64_operand *opnd; 3742 1.1 christos enum aarch64_opnd type; 3743 1.1 christos 3744 1.1 christos type = opcode->operands[i]; 3745 1.1 christos if (type == AARCH64_OPND_NIL) 3746 1.6 christos break; 3747 1.6 christos opnd = &aarch64_operands[type]; 3748 1.1 christos if (operand_has_extractor (opnd) 3749 1.1 christos && (! aarch64_extract_operand (opnd, &inst->operands[i], code, inst, 3750 1.1 christos errors))) 3751 1.1 christos { 3752 1.1 christos DEBUG_TRACE ("operand decoder FAIL at operand %d", i); 3753 1.1 christos goto decode_fail; 3754 1.5 christos } 3755 1.7 christos } 3756 1.8 christos 3757 1.5 christos /* If the opcode has a verifier, then check it now. */ 3758 1.5 christos if (opcode->verifier 3759 1.5 christos && opcode->verifier (inst, code, 0, false, errors, NULL) != ERR_OK) 3760 1.5 christos { 3761 1.5 christos DEBUG_TRACE ("operand verifier FAIL"); 3762 1.1 christos goto decode_fail; 3763 1.1 christos } 3764 1.1 christos 3765 1.1 christos /* Match the qualifiers. */ 3766 1.1 christos if (aarch64_match_operands_constraint (inst, NULL) == 1) 3767 1.1 christos { 3768 1.1 christos /* Arriving here, the CODE has been determined as a valid instruction 3769 1.1 christos of OPCODE and *INST has been filled with information of this OPCODE 3770 1.1 christos instruction. Before the return, check if the instruction has any 3771 1.6 christos alias and should be disassembled in the form of its alias instead. 3772 1.1 christos If the answer is yes, *INST will be updated. */ 3773 1.8 christos if (!noaliases_p) 3774 1.1 christos determine_disassembling_preference (inst, errors); 3775 1.1 christos DEBUG_TRACE ("SUCCESS"); 3776 1.1 christos return true; 3777 1.1 christos } 3778 1.1 christos else 3779 1.1 christos { 3780 1.8 christos DEBUG_TRACE ("constraint matching FAIL"); 3781 1.8 christos } 3782 1.1 christos 3783 1.1 christos decode_fail: 3784 1.1 christos return false; 3785 1.1 christos } 3786 1.1 christos 3787 1.1 christos /* This does some user-friendly fix-up to *INST. It is currently focus on 3789 1.1 christos the adjustment of qualifiers to help the printed instruction 3790 1.1 christos recognized/understood more easily. */ 3791 1.1 christos 3792 1.1 christos static void 3793 1.1 christos user_friendly_fixup (aarch64_inst *inst) 3794 1.1 christos { 3795 1.1 christos switch (inst->opcode->iclass) 3796 1.1 christos { 3797 1.1 christos case testbranch: 3798 1.1 christos /* TBNZ Xn|Wn, #uimm6, label 3799 1.1 christos Test and Branch Not Zero: conditionally jumps to label if bit number 3800 1.1 christos uimm6 in register Xn is not zero. The bit number implies the width of 3801 1.1 christos the register, which may be written and should be disassembled as Wn if 3802 1.1 christos uimm is less than 32. Limited to a branch offset range of +/- 32KiB. 3803 1.1 christos */ 3804 1.1 christos if (inst->operands[1].imm.value < 32) 3805 1.1 christos inst->operands[0].qualifier = AARCH64_OPND_QLF_W; 3806 1.1 christos break; 3807 1.3 christos default: break; 3808 1.3 christos } 3809 1.3 christos } 3810 1.1 christos 3811 1.7 christos /* Decode INSN and fill in *INST the instruction information. An alias 3812 1.3 christos opcode may be filled in *INSN if NOALIASES_P is FALSE. Return zero on 3813 1.8 christos success. */ 3814 1.6 christos 3815 1.1 christos enum err_type 3816 1.1 christos aarch64_decode_insn (aarch64_insn insn, aarch64_inst *inst, 3817 1.1 christos bool noaliases_p, 3818 1.1 christos aarch64_operand_error *errors) 3819 1.1 christos { 3820 1.1 christos const aarch64_opcode *opcode = aarch64_opcode_lookup (insn); 3821 1.1 christos 3822 1.1 christos #ifdef DEBUG_AARCH64 3823 1.1 christos if (debug_dump) 3824 1.1 christos { 3825 1.1 christos const aarch64_opcode *tmp = opcode; 3826 1.1 christos printf ("\n"); 3827 1.1 christos DEBUG_TRACE ("opcode lookup:"); 3828 1.1 christos while (tmp != NULL) 3829 1.1 christos { 3830 1.1 christos aarch64_verbose (" %s", tmp->name); 3831 1.1 christos tmp = aarch64_find_next_opcode (tmp); 3832 1.1 christos } 3833 1.1 christos } 3834 1.1 christos #endif /* DEBUG_AARCH64 */ 3835 1.1 christos 3836 1.1 christos /* A list of opcodes may have been found, as aarch64_opcode_lookup cannot 3837 1.1 christos distinguish some opcodes, e.g. SSHR and MOVI, which almost share the same 3838 1.1 christos opcode field and value, apart from the difference that one of them has an 3839 1.1 christos extra field as part of the opcode, but such a field is used for operand 3840 1.1 christos encoding in other opcode(s) ('immh' in the case of the example). */ 3841 1.6 christos while (opcode != NULL) 3842 1.1 christos { 3843 1.1 christos /* But only one opcode can be decoded successfully for, as the 3844 1.1 christos decoding routine will check the constraint carefully. */ 3845 1.1 christos if (aarch64_opcode_decode (opcode, insn, inst, noaliases_p, errors) == 1) 3846 1.1 christos return ERR_OK; 3847 1.1 christos opcode = aarch64_find_next_opcode (opcode); 3848 1.1 christos } 3849 1.9 christos 3850 1.9 christos return ERR_UND; 3851 1.9 christos } 3852 1.9 christos 3853 1.9 christos /* Return a short string to indicate a switch to STYLE. These strings 3854 1.9 christos will be embedded into the disassembled operand text (as produced by 3855 1.9 christos aarch64_print_operand), and then spotted in the print_operands function 3856 1.9 christos so that the disassembler output can be split by style. */ 3857 1.9 christos 3858 1.9 christos static const char * 3859 1.9 christos get_style_text (enum disassembler_style style) 3860 1.9 christos { 3861 1.9 christos static bool init = false; 3862 1.9 christos static char formats[16][4]; 3863 1.9 christos unsigned num; 3864 1.9 christos 3865 1.9 christos /* First time through we build a string for every possible format. This 3866 1.9 christos code relies on there being no more than 16 different styles (there's 3867 1.9 christos an assert below for this). */ 3868 1.9 christos if (!init) 3869 1.9 christos { 3870 1.9 christos int i; 3871 1.9 christos 3872 1.9 christos for (i = 0; i <= 0xf; ++i) 3873 1.9 christos { 3874 1.9 christos int res ATTRIBUTE_UNUSED 3875 1.9 christos = snprintf (&formats[i][0], sizeof (formats[i]), "%c%x%c", 3876 1.9 christos STYLE_MARKER_CHAR, i, STYLE_MARKER_CHAR); 3877 1.9 christos assert (res == 3); 3878 1.9 christos } 3879 1.9 christos 3880 1.9 christos init = true; 3881 1.9 christos } 3882 1.9 christos 3883 1.9 christos /* Return the string that marks switching to STYLE. */ 3884 1.9 christos num = (unsigned) style; 3885 1.9 christos assert (style <= 0xf); 3886 1.9 christos return formats[num]; 3887 1.9 christos } 3888 1.9 christos 3889 1.9 christos /* Callback used by aarch64_print_operand to apply STYLE to the 3890 1.9 christos disassembler output created from FMT and ARGS. The STYLER object holds 3891 1.9 christos any required state. Must return a pointer to a string (created from FMT 3892 1.9 christos and ARGS) that will continue to be valid until the complete disassembled 3893 1.9 christos instruction has been printed. 3894 1.9 christos 3895 1.9 christos We return a string that includes two embedded style markers, the first, 3896 1.9 christos places at the start of the string, indicates a switch to STYLE, and the 3897 1.9 christos second, placed at the end of the string, indicates a switch back to the 3898 1.9 christos default text style. 3899 1.9 christos 3900 1.9 christos Later, when we print the operand text we take care to collapse any 3901 1.9 christos adjacent style markers, and to ignore any style markers that appear at 3902 1.9 christos the very end of a complete operand string. */ 3903 1.9 christos 3904 1.9 christos static const char *aarch64_apply_style (struct aarch64_styler *styler, 3905 1.9 christos enum disassembler_style style, 3906 1.9 christos const char *fmt, 3907 1.9 christos va_list args) 3908 1.9 christos { 3909 1.9 christos int res; 3910 1.9 christos char *ptr, *tmp; 3911 1.9 christos struct obstack *stack = (struct obstack *) styler->state; 3912 1.9 christos va_list ap; 3913 1.9 christos 3914 1.9 christos /* These are the two strings for switching styles. */ 3915 1.9 christos const char *style_on = get_style_text (style); 3916 1.9 christos const char *style_off = get_style_text (dis_style_text); 3917 1.9 christos 3918 1.9 christos /* Calculate space needed once FMT and ARGS are expanded. */ 3919 1.9 christos va_copy (ap, args); 3920 1.9 christos res = vsnprintf (NULL, 0, fmt, ap); 3921 1.9 christos va_end (ap); 3922 1.9 christos assert (res >= 0); 3923 1.9 christos 3924 1.9 christos /* Allocate space on the obstack for the expanded FMT and ARGS, as well 3925 1.9 christos as the two strings for switching styles, then write all of these 3926 1.9 christos strings onto the obstack. */ 3927 1.9 christos ptr = (char *) obstack_alloc (stack, res + strlen (style_on) 3928 1.9 christos + strlen (style_off) + 1); 3929 1.9 christos tmp = stpcpy (ptr, style_on); 3930 1.9 christos res = vsnprintf (tmp, (res + 1), fmt, args); 3931 1.9 christos assert (res >= 0); 3932 1.9 christos tmp += res; 3933 1.9 christos strcpy (tmp, style_off); 3934 1.1 christos 3935 1.1 christos return ptr; 3936 1.1 christos } 3937 1.1 christos 3938 1.7 christos /* Print operands. */ 3939 1.8 christos 3940 1.1 christos static void 3941 1.7 christos print_operands (bfd_vma pc, const aarch64_opcode *opcode, 3942 1.1 christos const aarch64_opnd_info *opnds, struct disassemble_info *info, 3943 1.9 christos bool *has_notes) 3944 1.9 christos { 3945 1.9 christos char *notes = NULL; 3946 1.9 christos int i, pcrel_p, num_printed; 3947 1.9 christos struct aarch64_styler styler; 3948 1.9 christos struct obstack content; 3949 1.9 christos obstack_init (&content); 3950 1.1 christos 3951 1.1 christos styler.apply_style = aarch64_apply_style; 3952 1.5 christos styler.state = (void *) &content; 3953 1.8 christos 3954 1.8 christos for (i = 0, num_printed = 0; i < AARCH64_MAX_OPND_NUM; ++i) 3955 1.1 christos { 3956 1.1 christos char str[128]; 3957 1.1 christos char cmt[128]; 3958 1.1 christos 3959 1.1 christos /* We regard the opcode operand info more, however we also look into 3960 1.1 christos the inst->operands to support the disassembling of the optional 3961 1.1 christos operand. 3962 1.1 christos The two operand code should be the same in all cases, apart from 3963 1.1 christos when the operand can be optional. */ 3964 1.1 christos if (opcode->operands[i] == AARCH64_OPND_NIL 3965 1.5 christos || opnds[i].type == AARCH64_OPND_NIL) 3966 1.8 christos break; 3967 1.9 christos 3968 1.1 christos /* Generate the operand string in STR. */ 3969 1.1 christos aarch64_print_operand (str, sizeof (str), pc, opcode, opnds, i, &pcrel_p, 3970 1.1 christos &info->target, ¬es, cmt, sizeof (cmt), 3971 1.9 christos arch_variant, &styler); 3972 1.9 christos 3973 1.1 christos /* Print the delimiter (taking account of omitted operand(s)). */ 3974 1.1 christos if (str[0] != '\0') 3975 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "%s", 3976 1.1 christos num_printed++ == 0 ? "\t" : ", "); 3977 1.1 christos 3978 1.8 christos /* Print the operand. */ 3979 1.9 christos if (pcrel_p) 3980 1.9 christos (*info->print_address_func) (info->target, info); 3981 1.9 christos else 3982 1.9 christos { 3983 1.9 christos /* This operand came from aarch64_print_operand, and will include 3984 1.9 christos embedded strings indicating which style each character should 3985 1.9 christos have. In the following code we split the text based on 3986 1.9 christos CURR_STYLE, and call the styled print callback to print each 3987 1.9 christos block of text in the appropriate style. */ 3988 1.9 christos char *start, *curr; 3989 1.9 christos enum disassembler_style curr_style = dis_style_text; 3990 1.9 christos 3991 1.9 christos start = curr = str; 3992 1.9 christos do 3993 1.9 christos { 3994 1.9 christos if (*curr == '\0' 3995 1.9 christos || (*curr == STYLE_MARKER_CHAR 3996 1.9 christos && ISXDIGIT (*(curr + 1)) 3997 1.9 christos && *(curr + 2) == STYLE_MARKER_CHAR)) 3998 1.9 christos { 3999 1.9 christos /* Output content between our START position and CURR. */ 4000 1.9 christos int len = curr - start; 4001 1.9 christos if (len > 0) 4002 1.9 christos { 4003 1.9 christos if ((*info->fprintf_styled_func) (info->stream, 4004 1.9 christos curr_style, 4005 1.9 christos "%.*s", 4006 1.9 christos len, start) < 0) 4007 1.9 christos break; 4008 1.9 christos } 4009 1.9 christos 4010 1.9 christos if (*curr == '\0') 4011 1.9 christos break; 4012 1.9 christos 4013 1.9 christos /* Skip over the initial STYLE_MARKER_CHAR. */ 4014 1.9 christos ++curr; 4015 1.9 christos 4016 1.9 christos /* Update the CURR_STYLE. As there are less than 16 4017 1.9 christos styles, it is possible, that if the input is corrupted 4018 1.9 christos in some way, that we might set CURR_STYLE to an 4019 1.9 christos invalid value. Don't worry though, we check for this 4020 1.9 christos situation. */ 4021 1.9 christos if (*curr >= '0' && *curr <= '9') 4022 1.9 christos curr_style = (enum disassembler_style) (*curr - '0'); 4023 1.9 christos else if (*curr >= 'a' && *curr <= 'f') 4024 1.9 christos curr_style = (enum disassembler_style) (*curr - 'a' + 10); 4025 1.9 christos else 4026 1.9 christos curr_style = dis_style_text; 4027 1.9 christos 4028 1.9 christos /* Check for an invalid style having been selected. This 4029 1.8 christos should never happen, but it doesn't hurt to be a 4030 1.9 christos little paranoid. */ 4031 1.9 christos if (curr_style > dis_style_comment_start) 4032 1.9 christos curr_style = dis_style_text; 4033 1.9 christos 4034 1.9 christos /* Skip the hex character, and the closing STYLE_MARKER_CHAR. */ 4035 1.9 christos curr += 2; 4036 1.9 christos 4037 1.9 christos /* Reset the START to after the style marker. */ 4038 1.9 christos start = curr; 4039 1.9 christos } 4040 1.8 christos else 4041 1.9 christos ++curr; 4042 1.9 christos } 4043 1.9 christos while (true); 4044 1.9 christos } 4045 1.9 christos 4046 1.9 christos /* Print the comment. This works because only the last operand ever 4047 1.9 christos adds a comment. If that ever changes then we'll need to be 4048 1.1 christos smarter here. */ 4049 1.6 christos if (cmt[0] != '\0') 4050 1.6 christos (*info->fprintf_styled_func) (info->stream, dis_style_comment_start, 4051 1.7 christos "\t// %s", cmt); 4052 1.8 christos } 4053 1.9 christos 4054 1.9 christos if (notes && !no_notes) 4055 1.7 christos { 4056 1.9 christos *has_notes = true; 4057 1.9 christos (*info->fprintf_styled_func) (info->stream, dis_style_comment_start, 4058 1.6 christos " // note: %s", notes); 4059 1.6 christos } 4060 1.6 christos 4061 1.6 christos obstack_free (&content, NULL); 4062 1.6 christos } 4063 1.6 christos 4064 1.6 christos /* Set NAME to a copy of INST's mnemonic with the "." suffix removed. */ 4065 1.6 christos 4066 1.6 christos static void 4067 1.6 christos remove_dot_suffix (char *name, const aarch64_inst *inst) 4068 1.6 christos { 4069 1.6 christos char *ptr; 4070 1.6 christos size_t len; 4071 1.6 christos 4072 1.6 christos ptr = strchr (inst->opcode->name, '.'); 4073 1.6 christos assert (ptr && inst->cond); 4074 1.1 christos len = ptr - inst->opcode->name; 4075 1.1 christos assert (len < 8); 4076 1.1 christos strncpy (name, inst->opcode->name, len); 4077 1.1 christos name[len] = '\0'; 4078 1.1 christos } 4079 1.1 christos 4080 1.1 christos /* Print the instruction mnemonic name. */ 4081 1.1 christos 4082 1.1 christos static void 4083 1.1 christos print_mnemonic_name (const aarch64_inst *inst, struct disassemble_info *info) 4084 1.1 christos { 4085 1.1 christos if (inst->opcode->flags & F_COND) 4086 1.6 christos { 4087 1.3 christos /* For instructions that are truly conditionally executed, e.g. b.cond, 4088 1.6 christos prepare the full mnemonic name with the corresponding condition 4089 1.9 christos suffix. */ 4090 1.9 christos char name[8]; 4091 1.1 christos 4092 1.1 christos remove_dot_suffix (name, inst); 4093 1.9 christos (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic, 4094 1.9 christos "%s.%s", name, inst->cond->names[0]); 4095 1.1 christos } 4096 1.1 christos else 4097 1.6 christos (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic, 4098 1.6 christos "%s", inst->opcode->name); 4099 1.6 christos } 4100 1.6 christos 4101 1.6 christos /* Decide whether we need to print a comment after the operands of 4102 1.6 christos instruction INST. */ 4103 1.6 christos 4104 1.6 christos static void 4105 1.6 christos print_comment (const aarch64_inst *inst, struct disassemble_info *info) 4106 1.6 christos { 4107 1.6 christos if (inst->opcode->flags & F_COND) 4108 1.6 christos { 4109 1.6 christos char name[8]; 4110 1.6 christos unsigned int i, num_conds; 4111 1.9 christos 4112 1.9 christos remove_dot_suffix (name, inst); 4113 1.9 christos num_conds = ARRAY_SIZE (inst->cond->names); 4114 1.9 christos for (i = 1; i < num_conds && inst->cond->names[i]; ++i) 4115 1.6 christos (*info->fprintf_styled_func) (info->stream, dis_style_comment_start, 4116 1.6 christos "%s %s.%s", 4117 1.6 christos i == 1 ? " //" : ",", 4118 1.7 christos name, inst->cond->names[i]); 4119 1.7 christos } 4120 1.7 christos } 4121 1.7 christos 4122 1.7 christos /* Build notes from verifiers into a string for printing. */ 4123 1.7 christos 4124 1.7 christos static void 4125 1.7 christos print_verifier_notes (aarch64_operand_error *detail, 4126 1.7 christos struct disassemble_info *info) 4127 1.7 christos { 4128 1.7 christos if (no_notes) 4129 1.7 christos return; 4130 1.7 christos 4131 1.9 christos /* The output of the verifier cannot be a fatal error, otherwise the assembly 4132 1.9 christos would not have succeeded. We can safely ignore these. */ 4133 1.8 christos assert (detail->non_fatal); 4134 1.8 christos 4135 1.8 christos (*info->fprintf_styled_func) (info->stream, dis_style_comment_start, 4136 1.9 christos " // note: "); 4137 1.9 christos switch (detail->kind) 4138 1.9 christos { 4139 1.9 christos case AARCH64_OPDE_A_SHOULD_FOLLOW_B: 4140 1.8 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, 4141 1.8 christos _("this `%s' should have an immediately" 4142 1.8 christos " preceding `%s'"), 4143 1.9 christos detail->data[0].s, detail->data[1].s); 4144 1.9 christos break; 4145 1.9 christos 4146 1.8 christos case AARCH64_OPDE_EXPECTED_A_AFTER_B: 4147 1.8 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, 4148 1.8 christos _("expected `%s' after previous `%s'"), 4149 1.8 christos detail->data[0].s, detail->data[1].s); 4150 1.9 christos break; 4151 1.9 christos 4152 1.8 christos default: 4153 1.9 christos assert (detail->error); 4154 1.9 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, 4155 1.8 christos "%s", detail->error); 4156 1.8 christos if (detail->index >= 0) 4157 1.7 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, 4158 1.7 christos " at operand %d", detail->index + 1); 4159 1.1 christos break; 4160 1.1 christos } 4161 1.1 christos } 4162 1.1 christos 4163 1.7 christos /* Print the instruction according to *INST. */ 4164 1.7 christos 4165 1.7 christos static void 4166 1.1 christos print_aarch64_insn (bfd_vma pc, const aarch64_inst *inst, 4167 1.8 christos const aarch64_insn code, 4168 1.7 christos struct disassemble_info *info, 4169 1.1 christos aarch64_operand_error *mismatch_details) 4170 1.7 christos { 4171 1.6 christos bool has_notes = false; 4172 1.7 christos 4173 1.7 christos print_mnemonic_name (inst, info); 4174 1.7 christos print_operands (pc, inst->opcode, inst->operands, info, &has_notes); 4175 1.7 christos print_comment (inst, info); 4176 1.7 christos 4177 1.7 christos /* We've already printed a note, not enough space to print more so exit. 4178 1.7 christos Usually notes shouldn't overlap so it shouldn't happen that we have a note 4179 1.7 christos from a register and instruction at the same time. */ 4180 1.7 christos if (has_notes) 4181 1.7 christos return; 4182 1.8 christos 4183 1.7 christos /* Always run constraint verifiers, this is needed because constraints need to 4184 1.7 christos maintain a global state regardless of whether the instruction has the flag 4185 1.7 christos set or not. */ 4186 1.8 christos enum err_type result = verify_constraints (inst, code, pc, false, 4187 1.8 christos mismatch_details, &insn_sequence); 4188 1.8 christos switch (result) 4189 1.7 christos { 4190 1.7 christos case ERR_VFI: 4191 1.7 christos print_verifier_notes (mismatch_details, info); 4192 1.7 christos break; 4193 1.7 christos case ERR_UND: 4194 1.7 christos case ERR_UNP: 4195 1.1 christos case ERR_NYI: 4196 1.1 christos default: 4197 1.1 christos break; 4198 1.1 christos } 4199 1.1 christos } 4200 1.1 christos 4201 1.1 christos /* Entry-point of the instruction disassembler and printer. */ 4202 1.6 christos 4203 1.6 christos static void 4204 1.1 christos print_insn_aarch64_word (bfd_vma pc, 4205 1.7 christos uint32_t word, 4206 1.1 christos struct disassemble_info *info, 4207 1.7 christos aarch64_operand_error *errors) 4208 1.7 christos { 4209 1.7 christos static const char *err_msg[ERR_NR_ENTRIES+1] = 4210 1.7 christos { 4211 1.1 christos [ERR_OK] = "_", 4212 1.1 christos [ERR_UND] = "undefined", 4213 1.7 christos [ERR_UNP] = "unpredictable", 4214 1.1 christos [ERR_NYI] = "NYI" 4215 1.1 christos }; 4216 1.1 christos 4217 1.1 christos enum err_type ret; 4218 1.1 christos aarch64_inst inst; 4219 1.1 christos 4220 1.1 christos info->insn_info_valid = 1; 4221 1.1 christos info->branch_delay_insns = 0; 4222 1.1 christos info->data_size = 0; 4223 1.1 christos info->target = 0; 4224 1.1 christos info->target2 = 0; 4225 1.1 christos 4226 1.1 christos if (info->flags & INSN_HAS_RELOC) 4227 1.1 christos /* If the instruction has a reloc associated with it, then 4228 1.1 christos the offset field in the instruction will actually be the 4229 1.1 christos addend for the reloc. (If we are using REL type relocs). 4230 1.6 christos In such cases, we can ignore the pc when computing 4231 1.1 christos addresses, since the addend is not currently pc-relative. */ 4232 1.1 christos pc = 0; 4233 1.1 christos 4234 1.3 christos ret = aarch64_decode_insn (word, &inst, no_aliases, errors); 4235 1.1 christos 4236 1.1 christos if (((word >> 21) & 0x3ff) == 1) 4237 1.1 christos { 4238 1.1 christos /* RESERVED for ALES. */ 4239 1.1 christos assert (ret != ERR_OK); 4240 1.1 christos ret = ERR_NYI; 4241 1.1 christos } 4242 1.1 christos 4243 1.1 christos switch (ret) 4244 1.1 christos { 4245 1.1 christos case ERR_UND: 4246 1.9 christos case ERR_UNP: 4247 1.9 christos case ERR_NYI: 4248 1.9 christos /* Handle undefined instructions. */ 4249 1.9 christos info->insn_type = dis_noninsn; 4250 1.9 christos (*info->fprintf_styled_func) (info->stream, 4251 1.9 christos dis_style_assembler_directive, 4252 1.9 christos ".inst\t"); 4253 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 4254 1.1 christos "0x%08x", word); 4255 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_comment_start, 4256 1.9 christos " ; %s", err_msg[ret]); 4257 1.9 christos break; 4258 1.9 christos case ERR_OK: 4259 1.9 christos user_friendly_fixup (&inst); 4260 1.9 christos if (inst.opcode->iclass == condbranch 4261 1.9 christos || inst.opcode->iclass == testbranch 4262 1.7 christos || inst.opcode->iclass == compbranch) 4263 1.1 christos info->insn_type = dis_condbranch; 4264 1.1 christos else if (inst.opcode->iclass == branch_imm) 4265 1.1 christos info->insn_type = dis_jsr; 4266 1.1 christos print_aarch64_insn (pc, &inst, word, info, errors); 4267 1.1 christos break; 4268 1.1 christos default: 4269 1.1 christos abort (); 4270 1.1 christos } 4271 1.1 christos } 4272 1.8 christos 4273 1.1 christos /* Disallow mapping symbols ($x, $d etc) from 4274 1.1 christos being displayed in symbol relative addresses. */ 4275 1.1 christos 4276 1.1 christos bool 4277 1.1 christos aarch64_symbol_is_valid (asymbol * sym, 4278 1.1 christos struct disassemble_info * info ATTRIBUTE_UNUSED) 4279 1.8 christos { 4280 1.1 christos const char * name; 4281 1.1 christos 4282 1.1 christos if (sym == NULL) 4283 1.1 christos return false; 4284 1.1 christos 4285 1.1 christos name = bfd_asymbol_name (sym); 4286 1.1 christos 4287 1.1 christos return name 4288 1.1 christos && (name[0] != '$' 4289 1.1 christos || (name[1] != 'x' && name[1] != 'd') 4290 1.1 christos || (name[2] != '\0' && name[2] != '.')); 4291 1.1 christos } 4292 1.1 christos 4293 1.1 christos /* Print data bytes on INFO->STREAM. */ 4294 1.6 christos 4295 1.6 christos static void 4296 1.1 christos print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED, 4297 1.1 christos uint32_t word, 4298 1.1 christos struct disassemble_info *info, 4299 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED) 4300 1.9 christos { 4301 1.9 christos switch (info->bytes_per_chunk) 4302 1.9 christos { 4303 1.9 christos case 1: 4304 1.1 christos info->fprintf_styled_func (info->stream, dis_style_assembler_directive, 4305 1.1 christos ".byte\t"); 4306 1.9 christos info->fprintf_styled_func (info->stream, dis_style_immediate, 4307 1.9 christos "0x%02x", word); 4308 1.9 christos break; 4309 1.9 christos case 2: 4310 1.1 christos info->fprintf_styled_func (info->stream, dis_style_assembler_directive, 4311 1.1 christos ".short\t"); 4312 1.9 christos info->fprintf_styled_func (info->stream, dis_style_immediate, 4313 1.9 christos "0x%04x", word); 4314 1.9 christos break; 4315 1.9 christos case 4: 4316 1.1 christos info->fprintf_styled_func (info->stream, dis_style_assembler_directive, 4317 1.1 christos ".word\t"); 4318 1.1 christos info->fprintf_styled_func (info->stream, dis_style_immediate, 4319 1.1 christos "0x%08x", word); 4320 1.1 christos break; 4321 1.1 christos default: 4322 1.1 christos abort (); 4323 1.1 christos } 4324 1.1 christos } 4325 1.1 christos 4326 1.1 christos /* Try to infer the code or data type from a symbol. 4327 1.1 christos Returns nonzero if *MAP_TYPE was set. */ 4328 1.1 christos 4329 1.8 christos static int 4330 1.1 christos get_sym_code_type (struct disassemble_info *info, int n, 4331 1.1 christos enum map_type *map_type) 4332 1.1 christos { 4333 1.1 christos asymbol * as; 4334 1.6 christos elf_symbol_type *es; 4335 1.6 christos unsigned int type; 4336 1.8 christos const char *name; 4337 1.8 christos 4338 1.8 christos /* If the symbol is in a different section, ignore it. */ 4339 1.8 christos if (info->section != NULL && info->section != info->symtab[n]->section) 4340 1.8 christos return false; 4341 1.8 christos 4342 1.8 christos if (n >= info->symtab_size) 4343 1.8 christos return false; 4344 1.8 christos 4345 1.6 christos as = info->symtab[n]; 4346 1.1 christos if (bfd_asymbol_flavour (as) != bfd_target_elf_flavour) 4347 1.1 christos return false; 4348 1.1 christos es = (elf_symbol_type *) as; 4349 1.1 christos 4350 1.1 christos type = ELF_ST_TYPE (es->internal_elf_sym.st_info); 4351 1.1 christos 4352 1.8 christos /* If the symbol has function type then use that. */ 4353 1.1 christos if (type == STT_FUNC) 4354 1.1 christos { 4355 1.1 christos *map_type = MAP_INSN; 4356 1.1 christos return true; 4357 1.1 christos } 4358 1.1 christos 4359 1.1 christos /* Check for mapping symbols. */ 4360 1.1 christos name = bfd_asymbol_name(info->symtab[n]); 4361 1.1 christos if (name[0] == '$' 4362 1.8 christos && (name[1] == 'x' || name[1] == 'd') 4363 1.1 christos && (name[2] == '\0' || name[2] == '.')) 4364 1.1 christos { 4365 1.8 christos *map_type = (name[1] == 'x' ? MAP_INSN : MAP_DATA); 4366 1.8 christos return true; 4367 1.8 christos } 4368 1.8 christos 4369 1.8 christos return false; 4370 1.8 christos } 4371 1.8 christos 4372 1.8 christos /* Set the feature bits in arch_variant in order to get the correct disassembly 4373 1.8 christos for the chosen architecture variant. 4374 1.8 christos 4375 1.8 christos Currently we only restrict disassembly for Armv8-R and otherwise enable all 4376 1.8 christos non-R-profile features. */ 4377 1.8 christos static void 4378 1.8 christos select_aarch64_variant (unsigned mach) 4379 1.9 christos { 4380 1.8 christos switch (mach) 4381 1.8 christos { 4382 1.9 christos case bfd_mach_aarch64_8R: 4383 1.9 christos AARCH64_SET_FEATURE (arch_variant, AARCH64_ARCH_V8R); 4384 1.8 christos break; 4385 1.1 christos default: 4386 1.1 christos arch_variant = (aarch64_feature_set) AARCH64_ALL_FEATURES; 4387 1.1 christos AARCH64_CLEAR_FEATURE (arch_variant, arch_variant, V8R); 4388 1.1 christos } 4389 1.1 christos } 4390 1.1 christos 4391 1.1 christos /* Entry-point of the AArch64 disassembler. */ 4392 1.1 christos 4393 1.1 christos int 4394 1.1 christos print_insn_aarch64 (bfd_vma pc, 4395 1.6 christos struct disassemble_info *info) 4396 1.6 christos { 4397 1.8 christos bfd_byte buffer[INSNLEN]; 4398 1.1 christos int status; 4399 1.1 christos void (*printer) (bfd_vma, uint32_t, struct disassemble_info *, 4400 1.6 christos aarch64_operand_error *); 4401 1.8 christos bool found = false; 4402 1.1 christos unsigned int size = 4; 4403 1.1 christos unsigned long data; 4404 1.1 christos aarch64_operand_error errors; 4405 1.1 christos static bool set_features; 4406 1.1 christos 4407 1.1 christos if (info->disassembler_options) 4408 1.1 christos { 4409 1.1 christos set_default_aarch64_dis_options (info); 4410 1.1 christos 4411 1.1 christos parse_aarch64_dis_options (info->disassembler_options); 4412 1.1 christos 4413 1.8 christos /* To avoid repeated parsing of these options, we remove them here. */ 4414 1.8 christos info->disassembler_options = NULL; 4415 1.8 christos } 4416 1.8 christos 4417 1.8 christos if (!set_features) 4418 1.8 christos { 4419 1.1 christos select_aarch64_variant (info->mach); 4420 1.1 christos set_features = true; 4421 1.1 christos } 4422 1.7 christos 4423 1.7 christos /* Aarch64 instructions are always little-endian */ 4424 1.7 christos info->endian_code = BFD_ENDIAN_LITTLE; 4425 1.7 christos 4426 1.7 christos /* Default to DATA. A text section is required by the ABI to contain an 4427 1.7 christos INSN mapping symbol at the start. A data section has no such 4428 1.7 christos requirement, hence if no mapping symbol is found the section must 4429 1.7 christos contain only data. This however isn't very useful if the user has 4430 1.7 christos fully stripped the binaries. If this is the case use the section 4431 1.7 christos attributes to determine the default. If we have no section default to 4432 1.7 christos INSN as well, as we may be disassembling some raw bytes on a baremetal 4433 1.7 christos HEX file or similar. */ 4434 1.1 christos enum map_type type = MAP_DATA; 4435 1.1 christos if ((info->section && info->section->flags & SEC_CODE) || !info->section) 4436 1.1 christos type = MAP_INSN; 4437 1.1 christos 4438 1.1 christos /* First check the full symtab for a mapping symbol, even if there 4439 1.1 christos are no usable non-mapping symbols for this address. */ 4440 1.7 christos if (info->symtab_size != 0 4441 1.8 christos && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour) 4442 1.1 christos { 4443 1.1 christos int last_sym = -1; 4444 1.1 christos bfd_vma addr, section_vma = 0; 4445 1.1 christos bool can_use_search_opt_p; 4446 1.1 christos int n; 4447 1.1 christos 4448 1.1 christos if (pc <= last_mapping_addr) 4449 1.1 christos last_mapping_sym = -1; 4450 1.7 christos 4451 1.7 christos /* Start scanning at the start of the function, or wherever 4452 1.7 christos we finished last time. */ 4453 1.7 christos n = info->symtab_pos + 1; 4454 1.7 christos 4455 1.7 christos /* If the last stop offset is different from the current one it means we 4456 1.7 christos are disassembling a different glob of bytes. As such the optimization 4457 1.7 christos would not be safe and we should start over. */ 4458 1.1 christos can_use_search_opt_p = last_mapping_sym >= 0 4459 1.1 christos && info->stop_offset == last_stop_offset; 4460 1.7 christos 4461 1.7 christos if (n >= last_mapping_sym && can_use_search_opt_p) 4462 1.7 christos n = last_mapping_sym; 4463 1.7 christos 4464 1.1 christos /* Look down while we haven't passed the location being disassembled. 4465 1.1 christos The reason for this is that there's no defined order between a symbol 4466 1.1 christos and an mapping symbol that may be at the same address. We may have to 4467 1.1 christos look at least one position ahead. */ 4468 1.1 christos for (; n < info->symtab_size; n++) 4469 1.6 christos { 4470 1.1 christos addr = bfd_asymbol_value (info->symtab[n]); 4471 1.1 christos if (addr > pc) 4472 1.8 christos break; 4473 1.1 christos if (get_sym_code_type (info, n, &type)) 4474 1.1 christos { 4475 1.1 christos last_sym = n; 4476 1.1 christos found = true; 4477 1.1 christos } 4478 1.1 christos } 4479 1.7 christos 4480 1.1 christos if (!found) 4481 1.1 christos { 4482 1.1 christos n = info->symtab_pos; 4483 1.7 christos if (n >= last_mapping_sym && can_use_search_opt_p) 4484 1.7 christos n = last_mapping_sym; 4485 1.7 christos 4486 1.7 christos /* No mapping symbol found at this address. Look backwards 4487 1.7 christos for a preceeding one, but don't go pass the section start 4488 1.7 christos otherwise a data section with no mapping symbol can pick up 4489 1.7 christos a text mapping symbol of a preceeding section. The documentation 4490 1.7 christos says section can be NULL, in which case we will seek up all the 4491 1.1 christos way to the top. */ 4492 1.1 christos if (info->section) 4493 1.7 christos section_vma = info->section->vma; 4494 1.7 christos 4495 1.7 christos for (; n >= 0; n--) 4496 1.7 christos { 4497 1.1 christos addr = bfd_asymbol_value (info->symtab[n]); 4498 1.1 christos if (addr < section_vma) 4499 1.1 christos break; 4500 1.8 christos 4501 1.1 christos if (get_sym_code_type (info, n, &type)) 4502 1.1 christos { 4503 1.1 christos last_sym = n; 4504 1.1 christos found = true; 4505 1.1 christos break; 4506 1.1 christos } 4507 1.1 christos } 4508 1.7 christos } 4509 1.1 christos 4510 1.1 christos last_mapping_sym = last_sym; 4511 1.1 christos last_type = type; 4512 1.1 christos last_stop_offset = info->stop_offset; 4513 1.1 christos 4514 1.1 christos /* Look a little bit ahead to see if we should print out 4515 1.1 christos less than four bytes of data. If there's a symbol, 4516 1.1 christos mapping or otherwise, after two bytes then don't 4517 1.1 christos print more. */ 4518 1.1 christos if (last_type == MAP_DATA) 4519 1.1 christos { 4520 1.1 christos size = 4 - (pc & 3); 4521 1.1 christos for (n = last_sym + 1; n < info->symtab_size; n++) 4522 1.1 christos { 4523 1.1 christos addr = bfd_asymbol_value (info->symtab[n]); 4524 1.1 christos if (addr > pc) 4525 1.1 christos { 4526 1.1 christos if (addr - pc < size) 4527 1.1 christos size = addr - pc; 4528 1.1 christos break; 4529 1.1 christos } 4530 1.1 christos } 4531 1.1 christos /* If the next symbol is after three bytes, we need to 4532 1.1 christos print only part of the data, so that we can use either 4533 1.1 christos .byte or .short. */ 4534 1.7 christos if (size == 3) 4535 1.7 christos size = (pc & 1) ? 1 : 2; 4536 1.1 christos } 4537 1.7 christos } 4538 1.7 christos else 4539 1.1 christos last_type = type; 4540 1.1 christos 4541 1.1 christos /* PR 10263: Disassemble data if requested to do so by the user. */ 4542 1.1 christos if (last_type == MAP_DATA && ((info->flags & DISASSEMBLE_DATA) == 0)) 4543 1.1 christos { 4544 1.1 christos /* size was set above. */ 4545 1.1 christos info->bytes_per_chunk = size; 4546 1.1 christos info->display_endian = info->endian; 4547 1.1 christos printer = print_insn_data; 4548 1.1 christos } 4549 1.1 christos else 4550 1.1 christos { 4551 1.1 christos info->bytes_per_chunk = size = INSNLEN; 4552 1.1 christos info->display_endian = info->endian_code; 4553 1.1 christos printer = print_insn_aarch64_word; 4554 1.1 christos } 4555 1.1 christos 4556 1.1 christos status = (*info->read_memory_func) (pc, buffer, size, info); 4557 1.1 christos if (status != 0) 4558 1.1 christos { 4559 1.1 christos (*info->memory_error_func) (status, pc, info); 4560 1.1 christos return -1; 4561 1.1 christos } 4562 1.6 christos 4563 1.1 christos data = bfd_get_bits (buffer, size * 8, 4564 1.1 christos info->display_endian == BFD_ENDIAN_BIG); 4565 1.1 christos 4566 1.1 christos (*printer) (pc, data, info, &errors); 4567 1.1 christos 4568 1.1 christos return size; 4569 1.1 christos } 4570 1.1 christos 4571 1.1 christos void 4573 1.1 christos print_aarch64_disassembler_options (FILE *stream) 4574 1.1 christos { 4575 1.1 christos fprintf (stream, _("\n\ 4576 1.1 christos The following AARCH64 specific disassembler options are supported for use\n\ 4577 1.1 christos with the -M switch (multiple options should be separated by commas):\n")); 4578 1.1 christos 4579 1.1 christos fprintf (stream, _("\n\ 4580 1.6 christos no-aliases Don't print instruction aliases.\n")); 4581 1.6 christos 4582 1.6 christos fprintf (stream, _("\n\ 4583 1.6 christos aliases Do print instruction aliases.\n")); 4584 1.6 christos 4585 1.6 christos fprintf (stream, _("\n\ 4586 1.1 christos no-notes Don't print instruction notes.\n")); 4587 1.1 christos 4588 1.1 christos fprintf (stream, _("\n\ 4589 1.1 christos notes Do print instruction notes.\n")); 4590 1.1 christos 4591 1.1 christos #ifdef DEBUG_AARCH64 4592 1.1 christos fprintf (stream, _("\n\ 4593 debug_dump Temp switch for debug trace.\n")); 4594 #endif /* DEBUG_AARCH64 */ 4595 4596 fprintf (stream, _("\n")); 4597 } 4598