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