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