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