1/* aarch64-opc.h -- Header file for aarch64-opc.c and aarch64-opc-2.c. 2 Copyright (C) 2012-2017 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. */ 29enum 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_imm4, 71 FLD_imm5, 72 FLD_imm7, 73 FLD_imm8, 74 FLD_imm9, 75 FLD_imm12, 76 FLD_imm14, 77 FLD_imm16, 78 FLD_imm26, 79 FLD_imms, 80 FLD_immr, 81 FLD_immb, 82 FLD_immh, 83 FLD_S_imm10, 84 FLD_N, 85 FLD_index, 86 FLD_index2, 87 FLD_sf, 88 FLD_lse_sz, 89 FLD_H, 90 FLD_L, 91 FLD_M, 92 FLD_b5, 93 FLD_b40, 94 FLD_scale, 95 FLD_SVE_M_4, 96 FLD_SVE_M_14, 97 FLD_SVE_M_16, 98 FLD_SVE_N, 99 FLD_SVE_Pd, 100 FLD_SVE_Pg3, 101 FLD_SVE_Pg4_5, 102 FLD_SVE_Pg4_10, 103 FLD_SVE_Pg4_16, 104 FLD_SVE_Pm, 105 FLD_SVE_Pn, 106 FLD_SVE_Pt, 107 FLD_SVE_Rm, 108 FLD_SVE_Rn, 109 FLD_SVE_Vd, 110 FLD_SVE_Vm, 111 FLD_SVE_Vn, 112 FLD_SVE_Za_5, 113 FLD_SVE_Za_16, 114 FLD_SVE_Zd, 115 FLD_SVE_Zm_5, 116 FLD_SVE_Zm_16, 117 FLD_SVE_Zn, 118 FLD_SVE_Zt, 119 FLD_SVE_i1, 120 FLD_SVE_i3h, 121 FLD_SVE_imm3, 122 FLD_SVE_imm4, 123 FLD_SVE_imm5, 124 FLD_SVE_imm5b, 125 FLD_SVE_imm6, 126 FLD_SVE_imm7, 127 FLD_SVE_imm8, 128 FLD_SVE_imm9, 129 FLD_SVE_immr, 130 FLD_SVE_imms, 131 FLD_SVE_msz, 132 FLD_SVE_pattern, 133 FLD_SVE_prfop, 134 FLD_SVE_rot1, 135 FLD_SVE_rot2, 136 FLD_SVE_sz, 137 FLD_SVE_tsz, 138 FLD_SVE_tszh, 139 FLD_SVE_tszl_8, 140 FLD_SVE_tszl_19, 141 FLD_SVE_xs_14, 142 FLD_SVE_xs_22, 143 FLD_rotate1, 144 FLD_rotate2, 145 FLD_rotate3, 146}; 147 148/* Field description. */ 149struct aarch64_field 150{ 151 int lsb; 152 int width; 153}; 154 155typedef struct aarch64_field aarch64_field; 156 157extern const aarch64_field fields[]; 158 159/* Operand description. */ 160 161struct aarch64_operand 162{ 163 enum aarch64_operand_class op_class; 164 165 /* Name of the operand code; used mainly for the purpose of internal 166 debugging. */ 167 const char *name; 168 169 unsigned int flags; 170 171 /* The associated instruction bit-fields; no operand has more than 4 172 bit-fields */ 173 enum aarch64_field_kind fields[4]; 174 175 /* Brief description */ 176 const char *desc; 177}; 178 179typedef struct aarch64_operand aarch64_operand; 180 181extern const aarch64_operand aarch64_operands[]; 182 183/* Operand flags. */ 184 185#define OPD_F_HAS_INSERTER 0x00000001 186#define OPD_F_HAS_EXTRACTOR 0x00000002 187#define OPD_F_SEXT 0x00000004 /* Require sign-extension. */ 188#define OPD_F_SHIFT_BY_2 0x00000008 /* Need to left shift the field 189 value by 2 to get the value 190 of an immediate operand. */ 191#define OPD_F_MAYBE_SP 0x00000010 /* May potentially be SP. */ 192#define OPD_F_OD_MASK 0x000000e0 /* Operand-dependent data. */ 193#define OPD_F_OD_LSB 5 194#define OPD_F_NO_ZR 0x00000100 /* ZR index not allowed. */ 195 196static inline bfd_boolean 197operand_has_inserter (const aarch64_operand *operand) 198{ 199 return (operand->flags & OPD_F_HAS_INSERTER) ? TRUE : FALSE; 200} 201 202static inline bfd_boolean 203operand_has_extractor (const aarch64_operand *operand) 204{ 205 return (operand->flags & OPD_F_HAS_EXTRACTOR) ? TRUE : FALSE; 206} 207 208static inline bfd_boolean 209operand_need_sign_extension (const aarch64_operand *operand) 210{ 211 return (operand->flags & OPD_F_SEXT) ? TRUE : FALSE; 212} 213 214static inline bfd_boolean 215operand_need_shift_by_two (const aarch64_operand *operand) 216{ 217 return (operand->flags & OPD_F_SHIFT_BY_2) ? TRUE : FALSE; 218} 219 220static inline bfd_boolean 221operand_maybe_stack_pointer (const aarch64_operand *operand) 222{ 223 return (operand->flags & OPD_F_MAYBE_SP) ? TRUE : FALSE; 224} 225 226/* Return the value of the operand-specific data field (OPD_F_OD_MASK). */ 227static inline unsigned int 228get_operand_specific_data (const aarch64_operand *operand) 229{ 230 return (operand->flags & OPD_F_OD_MASK) >> OPD_F_OD_LSB; 231} 232 233/* Return the width of field number N of operand *OPERAND. */ 234static inline unsigned 235get_operand_field_width (const aarch64_operand *operand, unsigned n) 236{ 237 assert (operand->fields[n] != FLD_NIL); 238 return fields[operand->fields[n]].width; 239} 240 241/* Return the total width of the operand *OPERAND. */ 242static inline unsigned 243get_operand_fields_width (const aarch64_operand *operand) 244{ 245 int i = 0; 246 unsigned width = 0; 247 while (operand->fields[i] != FLD_NIL) 248 width += fields[operand->fields[i++]].width; 249 assert (width > 0 && width < 32); 250 return width; 251} 252 253static inline const aarch64_operand * 254get_operand_from_code (enum aarch64_opnd code) 255{ 256 return aarch64_operands + code; 257} 258 259/* Operand qualifier and operand constraint checking. */ 260 261int aarch64_match_operands_constraint (aarch64_inst *, 262 aarch64_operand_error *); 263 264/* Operand qualifier related functions. */ 265const char* aarch64_get_qualifier_name (aarch64_opnd_qualifier_t); 266unsigned char aarch64_get_qualifier_nelem (aarch64_opnd_qualifier_t); 267aarch64_insn aarch64_get_qualifier_standard_value (aarch64_opnd_qualifier_t); 268int aarch64_find_best_match (const aarch64_inst *, 269 const aarch64_opnd_qualifier_seq_t *, 270 int, aarch64_opnd_qualifier_t *); 271 272static inline void 273reset_operand_qualifier (aarch64_inst *inst, int idx) 274{ 275 assert (idx >=0 && idx < aarch64_num_of_operands (inst->opcode)); 276 inst->operands[idx].qualifier = AARCH64_OPND_QLF_NIL; 277} 278 279/* Inline functions operating on instruction bit-field(s). */ 280 281/* Generate a mask that has WIDTH number of consecutive 1s. */ 282 283static inline aarch64_insn 284gen_mask (int width) 285{ 286 return ((aarch64_insn) 1 << width) - 1; 287} 288 289/* LSB_REL is the relative location of the lsb in the sub field, starting from 0. */ 290static inline int 291gen_sub_field (enum aarch64_field_kind kind, int lsb_rel, int width, aarch64_field *ret) 292{ 293 const aarch64_field *field = &fields[kind]; 294 if (lsb_rel < 0 || width <= 0 || lsb_rel + width > field->width) 295 return 0; 296 ret->lsb = field->lsb + lsb_rel; 297 ret->width = width; 298 return 1; 299} 300 301/* Insert VALUE into FIELD of CODE. MASK can be zero or the base mask 302 of the opcode. */ 303 304static inline void 305insert_field_2 (const aarch64_field *field, aarch64_insn *code, 306 aarch64_insn value, aarch64_insn mask) 307{ 308 assert (field->width < 32 && field->width >= 1 && field->lsb >= 0 309 && field->lsb + field->width <= 32); 310 value &= gen_mask (field->width); 311 value <<= field->lsb; 312 /* In some opcodes, field can be part of the base opcode, e.g. the size 313 field in FADD. The following helps avoid corrupt the base opcode. */ 314 value &= ~mask; 315 *code |= value; 316} 317 318/* Extract FIELD of CODE and return the value. MASK can be zero or the base 319 mask of the opcode. */ 320 321static inline aarch64_insn 322extract_field_2 (const aarch64_field *field, aarch64_insn code, 323 aarch64_insn mask) 324{ 325 aarch64_insn value; 326 /* Clear any bit that is a part of the base opcode. */ 327 code &= ~mask; 328 value = (code >> field->lsb) & gen_mask (field->width); 329 return value; 330} 331 332/* Insert VALUE into field KIND of CODE. MASK can be zero or the base mask 333 of the opcode. */ 334 335static inline void 336insert_field (enum aarch64_field_kind kind, aarch64_insn *code, 337 aarch64_insn value, aarch64_insn mask) 338{ 339 insert_field_2 (&fields[kind], code, value, mask); 340} 341 342/* Extract field KIND of CODE and return the value. MASK can be zero or the 343 base mask of the opcode. */ 344 345static inline aarch64_insn 346extract_field (enum aarch64_field_kind kind, aarch64_insn code, 347 aarch64_insn mask) 348{ 349 return extract_field_2 (&fields[kind], code, mask); 350} 351 352extern aarch64_insn 353extract_fields (aarch64_insn code, aarch64_insn mask, ...); 354 355/* Inline functions selecting operand to do the encoding/decoding for a 356 certain instruction bit-field. */ 357 358/* Select the operand to do the encoding/decoding of the 'sf' field. 359 The heuristic-based rule is that the result operand is respected more. */ 360 361static inline int 362select_operand_for_sf_field_coding (const aarch64_opcode *opcode) 363{ 364 int idx = -1; 365 if (aarch64_get_operand_class (opcode->operands[0]) 366 == AARCH64_OPND_CLASS_INT_REG) 367 /* normal case. */ 368 idx = 0; 369 else if (aarch64_get_operand_class (opcode->operands[1]) 370 == AARCH64_OPND_CLASS_INT_REG) 371 /* e.g. float2fix. */ 372 idx = 1; 373 else 374 { assert (0); abort (); } 375 return idx; 376} 377 378/* Select the operand to do the encoding/decoding of the 'type' field in 379 the floating-point instructions. 380 The heuristic-based rule is that the source operand is respected more. */ 381 382static inline int 383select_operand_for_fptype_field_coding (const aarch64_opcode *opcode) 384{ 385 int idx; 386 if (aarch64_get_operand_class (opcode->operands[1]) 387 == AARCH64_OPND_CLASS_FP_REG) 388 /* normal case. */ 389 idx = 1; 390 else if (aarch64_get_operand_class (opcode->operands[0]) 391 == AARCH64_OPND_CLASS_FP_REG) 392 /* e.g. float2fix. */ 393 idx = 0; 394 else 395 { assert (0); abort (); } 396 return idx; 397} 398 399/* Select the operand to do the encoding/decoding of the 'size' field in 400 the AdvSIMD scalar instructions. 401 The heuristic-based rule is that the destination operand is respected 402 more. */ 403 404static inline int 405select_operand_for_scalar_size_field_coding (const aarch64_opcode *opcode) 406{ 407 int src_size = 0, dst_size = 0; 408 if (aarch64_get_operand_class (opcode->operands[0]) 409 == AARCH64_OPND_CLASS_SISD_REG) 410 dst_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][0]); 411 if (aarch64_get_operand_class (opcode->operands[1]) 412 == AARCH64_OPND_CLASS_SISD_REG) 413 src_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][1]); 414 if (src_size == dst_size && src_size == 0) 415 { assert (0); abort (); } 416 /* When the result is not a sisd register or it is a long operantion. */ 417 if (dst_size == 0 || dst_size == src_size << 1) 418 return 1; 419 else 420 return 0; 421} 422 423/* Select the operand to do the encoding/decoding of the 'size:Q' fields in 424 the AdvSIMD instructions. */ 425 426int aarch64_select_operand_for_sizeq_field_coding (const aarch64_opcode *); 427 428/* Miscellaneous. */ 429 430aarch64_insn aarch64_get_operand_modifier_value (enum aarch64_modifier_kind); 431enum aarch64_modifier_kind 432aarch64_get_operand_modifier_from_value (aarch64_insn, bfd_boolean); 433 434 435bfd_boolean aarch64_wide_constant_p (int64_t, int, unsigned int *); 436bfd_boolean aarch64_logical_immediate_p (uint64_t, int, aarch64_insn *); 437int aarch64_shrink_expanded_imm8 (uint64_t); 438 439/* Copy the content of INST->OPERANDS[SRC] to INST->OPERANDS[DST]. */ 440static inline void 441copy_operand_info (aarch64_inst *inst, int dst, int src) 442{ 443 assert (dst >= 0 && src >= 0 && dst < AARCH64_MAX_OPND_NUM 444 && src < AARCH64_MAX_OPND_NUM); 445 memcpy (&inst->operands[dst], &inst->operands[src], 446 sizeof (aarch64_opnd_info)); 447 inst->operands[dst].idx = dst; 448} 449 450/* A primitive log caculator. */ 451 452static inline unsigned int 453get_logsz (unsigned int size) 454{ 455 const unsigned char ls[16] = 456 {0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4}; 457 if (size > 16) 458 { 459 assert (0); 460 return -1; 461 } 462 assert (ls[size - 1] != (unsigned char)-1); 463 return ls[size - 1]; 464} 465 466#endif /* OPCODES_AARCH64_OPC_H */ 467