1 /* aarch64-opc.h -- Header file for aarch64-opc.c and aarch64-opc-2.c. 2 Copyright 2012 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_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_N, 84 FLD_index, 85 FLD_index2, 86 FLD_sf, 87 FLD_H, 88 FLD_L, 89 FLD_M, 90 FLD_b5, 91 FLD_b40, 92 FLD_scale, 93 }; 94 95 /* Field description. */ 96 struct aarch64_field 97 { 98 int lsb; 99 int width; 100 }; 101 102 typedef struct aarch64_field aarch64_field; 103 104 extern const aarch64_field fields[]; 105 106 /* Operand description. */ 107 108 struct aarch64_operand 109 { 110 enum aarch64_operand_class op_class; 111 112 /* Name of the operand code; used mainly for the purpose of internal 113 debugging. */ 114 const char *name; 115 116 unsigned int flags; 117 118 /* The associated instruction bit-fields; no operand has more than 4 119 bit-fields */ 120 enum aarch64_field_kind fields[4]; 121 122 /* Brief description */ 123 const char *desc; 124 }; 125 126 typedef struct aarch64_operand aarch64_operand; 127 128 extern const aarch64_operand aarch64_operands[]; 129 130 /* Operand flags. */ 131 132 #define OPD_F_HAS_INSERTER 0x00000001 133 #define OPD_F_HAS_EXTRACTOR 0x00000002 134 #define OPD_F_SEXT 0x00000004 /* Require sign-extension. */ 135 #define OPD_F_SHIFT_BY_2 0x00000008 /* Need to left shift the field 136 value by 2 to get the value 137 of an immediate operand. */ 138 #define OPD_F_MAYBE_SP 0x00000010 /* May potentially be SP. */ 139 140 static inline bfd_boolean 141 operand_has_inserter (const aarch64_operand *operand) 142 { 143 return (operand->flags & OPD_F_HAS_INSERTER) ? TRUE : FALSE; 144 } 145 146 static inline bfd_boolean 147 operand_has_extractor (const aarch64_operand *operand) 148 { 149 return (operand->flags & OPD_F_HAS_EXTRACTOR) ? TRUE : FALSE; 150 } 151 152 static inline bfd_boolean 153 operand_need_sign_extension (const aarch64_operand *operand) 154 { 155 return (operand->flags & OPD_F_SEXT) ? TRUE : FALSE; 156 } 157 158 static inline bfd_boolean 159 operand_need_shift_by_two (const aarch64_operand *operand) 160 { 161 return (operand->flags & OPD_F_SHIFT_BY_2) ? TRUE : FALSE; 162 } 163 164 static inline bfd_boolean 165 operand_maybe_stack_pointer (const aarch64_operand *operand) 166 { 167 return (operand->flags & OPD_F_MAYBE_SP) ? TRUE : FALSE; 168 } 169 170 /* Return the total width of the operand *OPERAND. */ 171 static inline unsigned 172 get_operand_fields_width (const aarch64_operand *operand) 173 { 174 int i = 0; 175 unsigned width = 0; 176 while (operand->fields[i] != FLD_NIL) 177 width += fields[operand->fields[i++]].width; 178 assert (width > 0 && width < 32); 179 return width; 180 } 181 182 static inline const aarch64_operand * 183 get_operand_from_code (enum aarch64_opnd code) 184 { 185 return aarch64_operands + code; 186 } 187 188 /* Operand qualifier and operand constraint checking. */ 189 190 int aarch64_match_operands_constraint (aarch64_inst *, 191 aarch64_operand_error *); 192 193 /* Operand qualifier related functions. */ 194 const char* aarch64_get_qualifier_name (aarch64_opnd_qualifier_t); 195 unsigned char aarch64_get_qualifier_nelem (aarch64_opnd_qualifier_t); 196 aarch64_insn aarch64_get_qualifier_standard_value (aarch64_opnd_qualifier_t); 197 int aarch64_find_best_match (const aarch64_inst *, 198 const aarch64_opnd_qualifier_seq_t *, 199 int, aarch64_opnd_qualifier_t *); 200 201 static inline void 202 reset_operand_qualifier (aarch64_inst *inst, int idx) 203 { 204 assert (idx >=0 && idx < aarch64_num_of_operands (inst->opcode)); 205 inst->operands[idx].qualifier = AARCH64_OPND_QLF_NIL; 206 } 207 208 /* Inline functions operating on instruction bit-field(s). */ 209 210 /* Generate a mask that has WIDTH number of consecutive 1s. */ 211 212 static inline aarch64_insn 213 gen_mask (int width) 214 { 215 return ((aarch64_insn) 1 << width) - 1;; 216 } 217 218 /* LSB_REL is the relative location of the lsb in the sub field, starting from 0. */ 219 static inline int 220 gen_sub_field (enum aarch64_field_kind kind, int lsb_rel, int width, aarch64_field *ret) 221 { 222 const aarch64_field *field = &fields[kind]; 223 if (lsb_rel < 0 || width <= 0 || lsb_rel + width > field->width) 224 return 0; 225 ret->lsb = field->lsb + lsb_rel; 226 ret->width = width; 227 return 1; 228 } 229 230 /* Insert VALUE into FIELD of CODE. MASK can be zero or the base mask 231 of the opcode. */ 232 233 static inline void 234 insert_field_2 (const aarch64_field *field, aarch64_insn *code, 235 aarch64_insn value, aarch64_insn mask) 236 { 237 assert (field->width < 32 && field->width >= 1 && field->lsb >= 0 238 && field->lsb + field->width <= 32); 239 value &= gen_mask (field->width); 240 value <<= field->lsb; 241 /* In some opcodes, field can be part of the base opcode, e.g. the size 242 field in FADD. The following helps avoid corrupt the base opcode. */ 243 value &= ~mask; 244 *code |= value; 245 } 246 247 /* Extract FIELD of CODE and return the value. MASK can be zero or the base 248 mask of the opcode. */ 249 250 static inline aarch64_insn 251 extract_field_2 (const aarch64_field *field, aarch64_insn code, 252 aarch64_insn mask) 253 { 254 aarch64_insn value; 255 /* Clear any bit that is a part of the base opcode. */ 256 code &= ~mask; 257 value = (code >> field->lsb) & gen_mask (field->width); 258 return value; 259 } 260 261 /* Insert VALUE into field KIND of CODE. MASK can be zero or the base mask 262 of the opcode. */ 263 264 static inline void 265 insert_field (enum aarch64_field_kind kind, aarch64_insn *code, 266 aarch64_insn value, aarch64_insn mask) 267 { 268 insert_field_2 (&fields[kind], code, value, mask); 269 } 270 271 /* Extract field KIND of CODE and return the value. MASK can be zero or the 272 base mask of the opcode. */ 273 274 static inline aarch64_insn 275 extract_field (enum aarch64_field_kind kind, aarch64_insn code, 276 aarch64_insn mask) 277 { 278 return extract_field_2 (&fields[kind], code, mask); 279 } 280 281 /* Inline functions selecting operand to do the encoding/decoding for a 282 certain instruction bit-field. */ 283 284 /* Select the operand to do the encoding/decoding of the 'sf' field. 285 The heuristic-based rule is that the result operand is respected more. */ 286 287 static inline int 288 select_operand_for_sf_field_coding (const aarch64_opcode *opcode) 289 { 290 int idx = -1; 291 if (aarch64_get_operand_class (opcode->operands[0]) 292 == AARCH64_OPND_CLASS_INT_REG) 293 /* normal case. */ 294 idx = 0; 295 else if (aarch64_get_operand_class (opcode->operands[1]) 296 == AARCH64_OPND_CLASS_INT_REG) 297 /* e.g. float2fix. */ 298 idx = 1; 299 else 300 { assert (0); abort (); } 301 return idx; 302 } 303 304 /* Select the operand to do the encoding/decoding of the 'type' field in 305 the floating-point instructions. 306 The heuristic-based rule is that the source operand is respected more. */ 307 308 static inline int 309 select_operand_for_fptype_field_coding (const aarch64_opcode *opcode) 310 { 311 int idx; 312 if (aarch64_get_operand_class (opcode->operands[1]) 313 == AARCH64_OPND_CLASS_FP_REG) 314 /* normal case. */ 315 idx = 1; 316 else if (aarch64_get_operand_class (opcode->operands[0]) 317 == AARCH64_OPND_CLASS_FP_REG) 318 /* e.g. float2fix. */ 319 idx = 0; 320 else 321 { assert (0); abort (); } 322 return idx; 323 } 324 325 /* Select the operand to do the encoding/decoding of the 'size' field in 326 the AdvSIMD scalar instructions. 327 The heuristic-based rule is that the destination operand is respected 328 more. */ 329 330 static inline int 331 select_operand_for_scalar_size_field_coding (const aarch64_opcode *opcode) 332 { 333 int src_size = 0, dst_size = 0; 334 if (aarch64_get_operand_class (opcode->operands[0]) 335 == AARCH64_OPND_CLASS_SISD_REG) 336 dst_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][0]); 337 if (aarch64_get_operand_class (opcode->operands[1]) 338 == AARCH64_OPND_CLASS_SISD_REG) 339 src_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][1]); 340 if (src_size == dst_size && src_size == 0) 341 { assert (0); abort (); } 342 /* When the result is not a sisd register or it is a long operantion. */ 343 if (dst_size == 0 || dst_size == src_size << 1) 344 return 1; 345 else 346 return 0; 347 } 348 349 /* Select the operand to do the encoding/decoding of the 'size:Q' fields in 350 the AdvSIMD instructions. */ 351 352 int aarch64_select_operand_for_sizeq_field_coding (const aarch64_opcode *); 353 354 /* Miscellaneous. */ 355 356 aarch64_insn aarch64_get_operand_modifier_value (enum aarch64_modifier_kind); 357 enum aarch64_modifier_kind 358 aarch64_get_operand_modifier_from_value (aarch64_insn, bfd_boolean); 359 360 361 bfd_boolean aarch64_wide_constant_p (int64_t, int, unsigned int *); 362 bfd_boolean aarch64_logical_immediate_p (uint64_t, int, aarch64_insn *); 363 int aarch64_shrink_expanded_imm8 (uint64_t); 364 365 /* Copy the content of INST->OPERANDS[SRC] to INST->OPERANDS[DST]. */ 366 static inline void 367 copy_operand_info (aarch64_inst *inst, int dst, int src) 368 { 369 assert (dst >= 0 && src >= 0 && dst < AARCH64_MAX_OPND_NUM 370 && src < AARCH64_MAX_OPND_NUM); 371 memcpy (&inst->operands[dst], &inst->operands[src], 372 sizeof (aarch64_opnd_info)); 373 inst->operands[dst].idx = dst; 374 } 375 376 /* A primitive log caculator. */ 377 378 static inline unsigned int 379 get_logsz (unsigned int size) 380 { 381 const unsigned char ls[16] = 382 {0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4}; 383 if (size > 16) 384 { 385 assert (0); 386 return -1; 387 } 388 assert (ls[size - 1] != (unsigned char)-1); 389 return ls[size - 1]; 390 } 391 392 #endif /* OPCODES_AARCH64_OPC_H */ 393