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