1 /* aarch64-opc.h -- Header file for aarch64-opc.c and aarch64-opc-2.c. 2 Copyright (C) 2012-2022 Free Software Foundation, Inc. 3 Contributed by ARM Ltd. 4 5 This file is part of the GNU opcodes library. 6 7 This library is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 It is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; see the file COPYING3. If not, 19 see <http://www.gnu.org/licenses/>. */ 20 21 #ifndef OPCODES_AARCH64_OPC_H 22 #define OPCODES_AARCH64_OPC_H 23 24 #include <string.h> 25 #include "opcode/aarch64.h" 26 27 /* Instruction fields. 28 Keep synced with fields. */ 29 enum aarch64_field_kind 30 { 31 FLD_NIL, 32 FLD_cond2, 33 FLD_nzcv, 34 FLD_defgh, 35 FLD_abc, 36 FLD_imm19, 37 FLD_immhi, 38 FLD_immlo, 39 FLD_size, 40 FLD_vldst_size, 41 FLD_op, 42 FLD_Q, 43 FLD_Rt, 44 FLD_Rd, 45 FLD_Rn, 46 FLD_Rt2, 47 FLD_Ra, 48 FLD_op2, 49 FLD_CRm, 50 FLD_CRn, 51 FLD_op1, 52 FLD_op0, 53 FLD_imm3, 54 FLD_cond, 55 FLD_opcode, 56 FLD_cmode, 57 FLD_asisdlso_opcode, 58 FLD_len, 59 FLD_Rm, 60 FLD_Rs, 61 FLD_option, 62 FLD_S, 63 FLD_hw, 64 FLD_opc, 65 FLD_opc1, 66 FLD_shift, 67 FLD_type, 68 FLD_ldst_size, 69 FLD_imm6, 70 FLD_imm6_2, 71 FLD_imm4, 72 FLD_imm4_2, 73 FLD_imm4_3, 74 FLD_imm4_5, 75 FLD_imm5, 76 FLD_imm7, 77 FLD_imm8, 78 FLD_imm9, 79 FLD_imm12, 80 FLD_imm14, 81 FLD_imm16, 82 FLD_imm16_2, 83 FLD_imm26, 84 FLD_imms, 85 FLD_immr, 86 FLD_immb, 87 FLD_immh, 88 FLD_S_imm10, 89 FLD_N, 90 FLD_index, 91 FLD_index2, 92 FLD_sf, 93 FLD_lse_sz, 94 FLD_H, 95 FLD_L, 96 FLD_M, 97 FLD_b5, 98 FLD_b40, 99 FLD_scale, 100 FLD_SVE_M_4, 101 FLD_SVE_M_14, 102 FLD_SVE_M_16, 103 FLD_SVE_N, 104 FLD_SVE_Pd, 105 FLD_SVE_Pg3, 106 FLD_SVE_Pg4_5, 107 FLD_SVE_Pg4_10, 108 FLD_SVE_Pg4_16, 109 FLD_SVE_Pm, 110 FLD_SVE_Pn, 111 FLD_SVE_Pt, 112 FLD_SVE_Rm, 113 FLD_SVE_Rn, 114 FLD_SVE_Vd, 115 FLD_SVE_Vm, 116 FLD_SVE_Vn, 117 FLD_SVE_Za_5, 118 FLD_SVE_Za_16, 119 FLD_SVE_Zd, 120 FLD_SVE_Zm_5, 121 FLD_SVE_Zm_16, 122 FLD_SVE_Zn, 123 FLD_SVE_Zt, 124 FLD_SVE_i1, 125 FLD_SVE_i3h, 126 FLD_SVE_i3l, 127 FLD_SVE_i3h2, 128 FLD_SVE_i2h, 129 FLD_SVE_imm3, 130 FLD_SVE_imm4, 131 FLD_SVE_imm5, 132 FLD_SVE_imm5b, 133 FLD_SVE_imm6, 134 FLD_SVE_imm7, 135 FLD_SVE_imm8, 136 FLD_SVE_imm9, 137 FLD_SVE_immr, 138 FLD_SVE_imms, 139 FLD_SVE_msz, 140 FLD_SVE_pattern, 141 FLD_SVE_prfop, 142 FLD_SVE_rot1, 143 FLD_SVE_rot2, 144 FLD_SVE_rot3, 145 FLD_SVE_sz, 146 FLD_SVE_size, 147 FLD_SVE_sz2, 148 FLD_SVE_tsz, 149 FLD_SVE_tszh, 150 FLD_SVE_tszl_8, 151 FLD_SVE_tszl_19, 152 FLD_SVE_xs_14, 153 FLD_SVE_xs_22, 154 FLD_SME_ZAda_2b, 155 FLD_SME_ZAda_3b, 156 FLD_SME_size_10, 157 FLD_SME_Q, 158 FLD_SME_V, 159 FLD_SME_Rv, 160 FLD_SME_Pm, 161 FLD_SME_zero_mask, 162 FLD_SME_Rm, 163 FLD_SME_i1, 164 FLD_SME_tszh, 165 FLD_SME_tszl, 166 FLD_rotate1, 167 FLD_rotate2, 168 FLD_rotate3, 169 FLD_SM3_imm2, 170 FLD_sz, 171 FLD_CRm_dsb_nxs 172 }; 173 174 /* Field description. */ 175 struct aarch64_field 176 { 177 int lsb; 178 int width; 179 }; 180 181 typedef struct aarch64_field aarch64_field; 182 183 extern const aarch64_field fields[]; 184 185 /* Operand description. */ 186 187 struct aarch64_operand 188 { 189 enum aarch64_operand_class op_class; 190 191 /* Name of the operand code; used mainly for the purpose of internal 192 debugging. */ 193 const char *name; 194 195 unsigned int flags; 196 197 /* The associated instruction bit-fields; no operand has more than 4 198 bit-fields */ 199 enum aarch64_field_kind fields[5]; 200 201 /* Brief description */ 202 const char *desc; 203 }; 204 205 typedef struct aarch64_operand aarch64_operand; 206 207 extern const aarch64_operand aarch64_operands[]; 208 209 enum err_type 210 verify_constraints (const struct aarch64_inst *, const aarch64_insn, bfd_vma, 211 bool, aarch64_operand_error *, aarch64_instr_sequence*); 212 213 /* Operand flags. */ 214 215 #define OPD_F_HAS_INSERTER 0x00000001 216 #define OPD_F_HAS_EXTRACTOR 0x00000002 217 #define OPD_F_SEXT 0x00000004 /* Require sign-extension. */ 218 #define OPD_F_SHIFT_BY_2 0x00000008 /* Need to left shift the field 219 value by 2 to get the value 220 of an immediate operand. */ 221 #define OPD_F_MAYBE_SP 0x00000010 /* May potentially be SP. */ 222 #define OPD_F_OD_MASK 0x000000e0 /* Operand-dependent data. */ 223 #define OPD_F_OD_LSB 5 224 #define OPD_F_NO_ZR 0x00000100 /* ZR index not allowed. */ 225 #define OPD_F_SHIFT_BY_4 0x00000200 /* Need to left shift the field 226 value by 4 to get the value 227 of an immediate operand. */ 228 229 230 /* Register flags. */ 231 232 #undef F_DEPRECATED 233 #define F_DEPRECATED (1 << 0) /* Deprecated system register. */ 234 235 #undef F_ARCHEXT 236 #define F_ARCHEXT (1 << 1) /* Architecture dependent system register. */ 237 238 #undef F_HASXT 239 #define F_HASXT (1 << 2) /* System instruction register <Xt> 240 operand. */ 241 242 #undef F_REG_READ 243 #define F_REG_READ (1 << 3) /* Register can only be used to read values 244 out of. */ 245 246 #undef F_REG_WRITE 247 #define F_REG_WRITE (1 << 4) /* Register can only be written to but not 248 read from. */ 249 250 #undef F_REG_IN_CRM 251 #define F_REG_IN_CRM (1 << 5) /* Register extra encoding in CRm. */ 252 253 /* PSTATE field name for the MSR instruction this is encoded in "op1:op2:CRm". 254 Part of CRm can be used to encode <pstatefield>. E.g. CRm[3:1] for SME. 255 In order to set/get full PSTATE field name use flag F_REG_IN_CRM and below 256 macros to encode and decode CRm encoding. 257 */ 258 #define PSTATE_ENCODE_CRM(val) (val << 6) 259 #define PSTATE_DECODE_CRM(flags) ((flags >> 6) & 0x0f) 260 261 #undef F_IMM_IN_CRM 262 #define F_IMM_IN_CRM (1 << 10) /* Immediate extra encoding in CRm. */ 263 264 /* Also CRm may contain, in addition to <pstatefield> immediate. 265 E.g. CRm[0] <imm1> at bit 0 for SME. Use below macros to encode and decode 266 immediate mask. 267 */ 268 #define PSTATE_ENCODE_CRM_IMM(mask) (mask << 11) 269 #define PSTATE_DECODE_CRM_IMM(mask) ((mask >> 11) & 0x0f) 270 271 /* Helper macro to ENCODE CRm and its immediate. */ 272 #define PSTATE_ENCODE_CRM_AND_IMM(CVAL,IMASK) \ 273 (F_REG_IN_CRM | PSTATE_ENCODE_CRM(CVAL) \ 274 | F_IMM_IN_CRM | PSTATE_ENCODE_CRM_IMM(IMASK)) 275 276 /* Bits [15, 18] contain the maximum value for an immediate MSR. */ 277 #define F_REG_MAX_VALUE(X) ((X) << 15) 278 #define F_GET_REG_MAX_VALUE(X) (((X) >> 15) & 0x0f) 279 280 /* HINT operand flags. */ 281 #define HINT_OPD_F_NOPRINT (1 << 0) /* Should not be printed. */ 282 283 /* Encode 7-bit HINT #imm in the lower 8 bits. Use higher bits for flags. */ 284 #define HINT_ENCODE(flag, val) ((flag << 8) | val) 285 #define HINT_FLAG(val) (val >> 8) 286 #define HINT_VAL(val) (val & 0xff) 287 288 static inline bool 289 operand_has_inserter (const aarch64_operand *operand) 290 { 291 return (operand->flags & OPD_F_HAS_INSERTER) != 0; 292 } 293 294 static inline bool 295 operand_has_extractor (const aarch64_operand *operand) 296 { 297 return (operand->flags & OPD_F_HAS_EXTRACTOR) != 0; 298 } 299 300 static inline bool 301 operand_need_sign_extension (const aarch64_operand *operand) 302 { 303 return (operand->flags & OPD_F_SEXT) != 0; 304 } 305 306 static inline bool 307 operand_need_shift_by_two (const aarch64_operand *operand) 308 { 309 return (operand->flags & OPD_F_SHIFT_BY_2) != 0; 310 } 311 312 static inline bool 313 operand_need_shift_by_four (const aarch64_operand *operand) 314 { 315 return (operand->flags & OPD_F_SHIFT_BY_4) != 0; 316 } 317 318 static inline bool 319 operand_maybe_stack_pointer (const aarch64_operand *operand) 320 { 321 return (operand->flags & OPD_F_MAYBE_SP) != 0; 322 } 323 324 /* Return the value of the operand-specific data field (OPD_F_OD_MASK). */ 325 static inline unsigned int 326 get_operand_specific_data (const aarch64_operand *operand) 327 { 328 return (operand->flags & OPD_F_OD_MASK) >> OPD_F_OD_LSB; 329 } 330 331 /* Return the width of field number N of operand *OPERAND. */ 332 static inline unsigned 333 get_operand_field_width (const aarch64_operand *operand, unsigned n) 334 { 335 assert (operand->fields[n] != FLD_NIL); 336 return fields[operand->fields[n]].width; 337 } 338 339 /* Return the total width of the operand *OPERAND. */ 340 static inline unsigned 341 get_operand_fields_width (const aarch64_operand *operand) 342 { 343 int i = 0; 344 unsigned width = 0; 345 while (operand->fields[i] != FLD_NIL) 346 width += fields[operand->fields[i++]].width; 347 assert (width > 0 && width < 32); 348 return width; 349 } 350 351 static inline const aarch64_operand * 352 get_operand_from_code (enum aarch64_opnd code) 353 { 354 return aarch64_operands + code; 355 } 356 357 /* Operand qualifier and operand constraint checking. */ 358 359 int aarch64_match_operands_constraint (aarch64_inst *, 360 aarch64_operand_error *); 361 362 /* Operand qualifier related functions. */ 363 const char* aarch64_get_qualifier_name (aarch64_opnd_qualifier_t); 364 unsigned char aarch64_get_qualifier_nelem (aarch64_opnd_qualifier_t); 365 aarch64_insn aarch64_get_qualifier_standard_value (aarch64_opnd_qualifier_t); 366 int aarch64_find_best_match (const aarch64_inst *, 367 const aarch64_opnd_qualifier_seq_t *, 368 int, aarch64_opnd_qualifier_t *); 369 370 static inline void 371 reset_operand_qualifier (aarch64_inst *inst, int idx) 372 { 373 assert (idx >=0 && idx < aarch64_num_of_operands (inst->opcode)); 374 inst->operands[idx].qualifier = AARCH64_OPND_QLF_NIL; 375 } 376 377 /* Inline functions operating on instruction bit-field(s). */ 378 379 /* Generate a mask that has WIDTH number of consecutive 1s. */ 380 381 static inline aarch64_insn 382 gen_mask (int width) 383 { 384 return ((aarch64_insn) 1 << width) - 1; 385 } 386 387 /* LSB_REL is the relative location of the lsb in the sub field, starting from 0. */ 388 static inline int 389 gen_sub_field (enum aarch64_field_kind kind, int lsb_rel, int width, aarch64_field *ret) 390 { 391 const aarch64_field *field = &fields[kind]; 392 if (lsb_rel < 0 || width <= 0 || lsb_rel + width > field->width) 393 return 0; 394 ret->lsb = field->lsb + lsb_rel; 395 ret->width = width; 396 return 1; 397 } 398 399 /* Insert VALUE into FIELD of CODE. MASK can be zero or the base mask 400 of the opcode. */ 401 402 static inline void 403 insert_field_2 (const aarch64_field *field, aarch64_insn *code, 404 aarch64_insn value, aarch64_insn mask) 405 { 406 assert (field->width < 32 && field->width >= 1 && field->lsb >= 0 407 && field->lsb + field->width <= 32); 408 value &= gen_mask (field->width); 409 value <<= field->lsb; 410 /* In some opcodes, field can be part of the base opcode, e.g. the size 411 field in FADD. The following helps avoid corrupt the base opcode. */ 412 value &= ~mask; 413 *code |= value; 414 } 415 416 /* Extract FIELD of CODE and return the value. MASK can be zero or the base 417 mask of the opcode. */ 418 419 static inline aarch64_insn 420 extract_field_2 (const aarch64_field *field, aarch64_insn code, 421 aarch64_insn mask) 422 { 423 aarch64_insn value; 424 /* Clear any bit that is a part of the base opcode. */ 425 code &= ~mask; 426 value = (code >> field->lsb) & gen_mask (field->width); 427 return value; 428 } 429 430 /* Insert VALUE into field KIND of CODE. MASK can be zero or the base mask 431 of the opcode. */ 432 433 static inline void 434 insert_field (enum aarch64_field_kind kind, aarch64_insn *code, 435 aarch64_insn value, aarch64_insn mask) 436 { 437 insert_field_2 (&fields[kind], code, value, mask); 438 } 439 440 /* Extract field KIND of CODE and return the value. MASK can be zero or the 441 base mask of the opcode. */ 442 443 static inline aarch64_insn 444 extract_field (enum aarch64_field_kind kind, aarch64_insn code, 445 aarch64_insn mask) 446 { 447 return extract_field_2 (&fields[kind], code, mask); 448 } 449 450 extern aarch64_insn 451 extract_fields (aarch64_insn code, aarch64_insn mask, ...); 452 453 /* Inline functions selecting operand to do the encoding/decoding for a 454 certain instruction bit-field. */ 455 456 /* Select the operand to do the encoding/decoding of the 'sf' field. 457 The heuristic-based rule is that the result operand is respected more. */ 458 459 static inline int 460 select_operand_for_sf_field_coding (const aarch64_opcode *opcode) 461 { 462 int idx = -1; 463 if (aarch64_get_operand_class (opcode->operands[0]) 464 == AARCH64_OPND_CLASS_INT_REG) 465 /* normal case. */ 466 idx = 0; 467 else if (aarch64_get_operand_class (opcode->operands[1]) 468 == AARCH64_OPND_CLASS_INT_REG) 469 /* e.g. float2fix. */ 470 idx = 1; 471 else 472 { assert (0); abort (); } 473 return idx; 474 } 475 476 /* Select the operand to do the encoding/decoding of the 'type' field in 477 the floating-point instructions. 478 The heuristic-based rule is that the source operand is respected more. */ 479 480 static inline int 481 select_operand_for_fptype_field_coding (const aarch64_opcode *opcode) 482 { 483 int idx; 484 if (aarch64_get_operand_class (opcode->operands[1]) 485 == AARCH64_OPND_CLASS_FP_REG) 486 /* normal case. */ 487 idx = 1; 488 else if (aarch64_get_operand_class (opcode->operands[0]) 489 == AARCH64_OPND_CLASS_FP_REG) 490 /* e.g. float2fix. */ 491 idx = 0; 492 else 493 { assert (0); abort (); } 494 return idx; 495 } 496 497 /* Select the operand to do the encoding/decoding of the 'size' field in 498 the AdvSIMD scalar instructions. 499 The heuristic-based rule is that the destination operand is respected 500 more. */ 501 502 static inline int 503 select_operand_for_scalar_size_field_coding (const aarch64_opcode *opcode) 504 { 505 int src_size = 0, dst_size = 0; 506 if (aarch64_get_operand_class (opcode->operands[0]) 507 == AARCH64_OPND_CLASS_SISD_REG) 508 dst_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][0]); 509 if (aarch64_get_operand_class (opcode->operands[1]) 510 == AARCH64_OPND_CLASS_SISD_REG) 511 src_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][1]); 512 if (src_size == dst_size && src_size == 0) 513 { assert (0); abort (); } 514 /* When the result is not a sisd register or it is a long operantion. */ 515 if (dst_size == 0 || dst_size == src_size << 1) 516 return 1; 517 else 518 return 0; 519 } 520 521 /* Select the operand to do the encoding/decoding of the 'size:Q' fields in 522 the AdvSIMD instructions. */ 523 524 int aarch64_select_operand_for_sizeq_field_coding (const aarch64_opcode *); 525 526 /* Miscellaneous. */ 527 528 aarch64_insn aarch64_get_operand_modifier_value (enum aarch64_modifier_kind); 529 enum aarch64_modifier_kind 530 aarch64_get_operand_modifier_from_value (aarch64_insn, bool); 531 532 533 bool aarch64_wide_constant_p (uint64_t, int, unsigned int *); 534 bool aarch64_logical_immediate_p (uint64_t, int, aarch64_insn *); 535 int aarch64_shrink_expanded_imm8 (uint64_t); 536 537 /* Copy the content of INST->OPERANDS[SRC] to INST->OPERANDS[DST]. */ 538 static inline void 539 copy_operand_info (aarch64_inst *inst, int dst, int src) 540 { 541 assert (dst >= 0 && src >= 0 && dst < AARCH64_MAX_OPND_NUM 542 && src < AARCH64_MAX_OPND_NUM); 543 memcpy (&inst->operands[dst], &inst->operands[src], 544 sizeof (aarch64_opnd_info)); 545 inst->operands[dst].idx = dst; 546 } 547 548 /* A primitive log caculator. */ 549 550 static inline unsigned int 551 get_logsz (unsigned int size) 552 { 553 const unsigned char ls[16] = 554 {0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4}; 555 if (size > 16) 556 { 557 assert (0); 558 return -1; 559 } 560 assert (ls[size - 1] != (unsigned char)-1); 561 return ls[size - 1]; 562 } 563 564 #endif /* OPCODES_AARCH64_OPC_H */ 565