xref: /netbsd-src/external/gpl3/binutils.old/dist/opcodes/aarch64-opc.h (revision e992f068c547fd6e84b3f104dc2340adcc955732)
1 /* aarch64-opc.h -- Header file for aarch64-opc.c and aarch64-opc-2.c.
2    Copyright (C) 2012-2022 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_imm6_2,
71   FLD_imm4,
72   FLD_imm4_2,
73   FLD_imm4_3,
74   FLD_imm4_5,
75   FLD_imm5,
76   FLD_imm7,
77   FLD_imm8,
78   FLD_imm9,
79   FLD_imm12,
80   FLD_imm14,
81   FLD_imm16,
82   FLD_imm16_2,
83   FLD_imm26,
84   FLD_imms,
85   FLD_immr,
86   FLD_immb,
87   FLD_immh,
88   FLD_S_imm10,
89   FLD_N,
90   FLD_index,
91   FLD_index2,
92   FLD_sf,
93   FLD_lse_sz,
94   FLD_H,
95   FLD_L,
96   FLD_M,
97   FLD_b5,
98   FLD_b40,
99   FLD_scale,
100   FLD_SVE_M_4,
101   FLD_SVE_M_14,
102   FLD_SVE_M_16,
103   FLD_SVE_N,
104   FLD_SVE_Pd,
105   FLD_SVE_Pg3,
106   FLD_SVE_Pg4_5,
107   FLD_SVE_Pg4_10,
108   FLD_SVE_Pg4_16,
109   FLD_SVE_Pm,
110   FLD_SVE_Pn,
111   FLD_SVE_Pt,
112   FLD_SVE_Rm,
113   FLD_SVE_Rn,
114   FLD_SVE_Vd,
115   FLD_SVE_Vm,
116   FLD_SVE_Vn,
117   FLD_SVE_Za_5,
118   FLD_SVE_Za_16,
119   FLD_SVE_Zd,
120   FLD_SVE_Zm_5,
121   FLD_SVE_Zm_16,
122   FLD_SVE_Zn,
123   FLD_SVE_Zt,
124   FLD_SVE_i1,
125   FLD_SVE_i3h,
126   FLD_SVE_i3l,
127   FLD_SVE_i3h2,
128   FLD_SVE_i2h,
129   FLD_SVE_imm3,
130   FLD_SVE_imm4,
131   FLD_SVE_imm5,
132   FLD_SVE_imm5b,
133   FLD_SVE_imm6,
134   FLD_SVE_imm7,
135   FLD_SVE_imm8,
136   FLD_SVE_imm9,
137   FLD_SVE_immr,
138   FLD_SVE_imms,
139   FLD_SVE_msz,
140   FLD_SVE_pattern,
141   FLD_SVE_prfop,
142   FLD_SVE_rot1,
143   FLD_SVE_rot2,
144   FLD_SVE_rot3,
145   FLD_SVE_sz,
146   FLD_SVE_size,
147   FLD_SVE_sz2,
148   FLD_SVE_tsz,
149   FLD_SVE_tszh,
150   FLD_SVE_tszl_8,
151   FLD_SVE_tszl_19,
152   FLD_SVE_xs_14,
153   FLD_SVE_xs_22,
154   FLD_SME_ZAda_2b,
155   FLD_SME_ZAda_3b,
156   FLD_SME_size_10,
157   FLD_SME_Q,
158   FLD_SME_V,
159   FLD_SME_Rv,
160   FLD_SME_Pm,
161   FLD_SME_zero_mask,
162   FLD_SME_Rm,
163   FLD_SME_i1,
164   FLD_SME_tszh,
165   FLD_SME_tszl,
166   FLD_rotate1,
167   FLD_rotate2,
168   FLD_rotate3,
169   FLD_SM3_imm2,
170   FLD_sz,
171   FLD_CRm_dsb_nxs
172 };
173 
174 /* Field description.  */
175 struct aarch64_field
176 {
177   int lsb;
178   int width;
179 };
180 
181 typedef struct aarch64_field aarch64_field;
182 
183 extern const aarch64_field fields[];
184 
185 /* Operand description.  */
186 
187 struct aarch64_operand
188 {
189   enum aarch64_operand_class op_class;
190 
191   /* Name of the operand code; used mainly for the purpose of internal
192      debugging.  */
193   const char *name;
194 
195   unsigned int flags;
196 
197   /* The associated instruction bit-fields; no operand has more than 4
198      bit-fields */
199   enum aarch64_field_kind fields[5];
200 
201   /* Brief description */
202   const char *desc;
203 };
204 
205 typedef struct aarch64_operand aarch64_operand;
206 
207 extern const aarch64_operand aarch64_operands[];
208 
209 enum err_type
210 verify_constraints (const struct aarch64_inst *, const aarch64_insn, bfd_vma,
211 		    bool, aarch64_operand_error *, aarch64_instr_sequence*);
212 
213 /* Operand flags.  */
214 
215 #define OPD_F_HAS_INSERTER	0x00000001
216 #define OPD_F_HAS_EXTRACTOR	0x00000002
217 #define OPD_F_SEXT		0x00000004	/* Require sign-extension.  */
218 #define OPD_F_SHIFT_BY_2	0x00000008	/* Need to left shift the field
219 						   value by 2 to get the value
220 						   of an immediate operand.  */
221 #define OPD_F_MAYBE_SP		0x00000010	/* May potentially be SP.  */
222 #define OPD_F_OD_MASK		0x000000e0	/* Operand-dependent data.  */
223 #define OPD_F_OD_LSB		5
224 #define OPD_F_NO_ZR		0x00000100	/* ZR index not allowed.  */
225 #define OPD_F_SHIFT_BY_4	0x00000200	/* Need to left shift the field
226 						   value by 4 to get the value
227 						   of an immediate operand.  */
228 
229 
230 /* Register flags.  */
231 
232 #undef F_DEPRECATED
233 #define F_DEPRECATED	(1 << 0)  /* Deprecated system register.  */
234 
235 #undef F_ARCHEXT
236 #define F_ARCHEXT	(1 << 1)  /* Architecture dependent system register.  */
237 
238 #undef F_HASXT
239 #define F_HASXT		(1 << 2)  /* System instruction register <Xt>
240 				     operand.  */
241 
242 #undef F_REG_READ
243 #define F_REG_READ	(1 << 3)  /* Register can only be used to read values
244 				     out of.  */
245 
246 #undef F_REG_WRITE
247 #define F_REG_WRITE	(1 << 4)  /* Register can only be written to but not
248 				     read from.  */
249 
250 #undef F_REG_IN_CRM
251 #define F_REG_IN_CRM	(1 << 5)  /* Register extra encoding in CRm.  */
252 
253 /* PSTATE field name for the MSR instruction this is encoded in "op1:op2:CRm".
254    Part of CRm can be used to encode <pstatefield>. E.g. CRm[3:1] for SME.
255    In order to set/get full PSTATE field name use flag F_REG_IN_CRM and below
256    macros to encode and decode CRm encoding.
257 */
258 #define PSTATE_ENCODE_CRM(val) (val << 6)
259 #define PSTATE_DECODE_CRM(flags) ((flags >> 6) & 0x0f)
260 
261 #undef F_IMM_IN_CRM
262 #define F_IMM_IN_CRM	(1 << 10)  /* Immediate extra encoding in CRm.  */
263 
264 /* Also CRm may contain, in addition to <pstatefield> immediate.
265    E.g. CRm[0] <imm1> at bit 0 for SME. Use below macros to encode and decode
266    immediate mask.
267 */
268 #define PSTATE_ENCODE_CRM_IMM(mask) (mask << 11)
269 #define PSTATE_DECODE_CRM_IMM(mask) ((mask >> 11) & 0x0f)
270 
271 /* Helper macro to ENCODE CRm and its immediate.  */
272 #define PSTATE_ENCODE_CRM_AND_IMM(CVAL,IMASK) \
273         (F_REG_IN_CRM | PSTATE_ENCODE_CRM(CVAL) \
274          | F_IMM_IN_CRM | PSTATE_ENCODE_CRM_IMM(IMASK))
275 
276 /* Bits [15, 18] contain the maximum value for an immediate MSR.  */
277 #define F_REG_MAX_VALUE(X) ((X) << 15)
278 #define F_GET_REG_MAX_VALUE(X) (((X) >> 15) & 0x0f)
279 
280 /* HINT operand flags.  */
281 #define HINT_OPD_F_NOPRINT	(1 << 0)  /* Should not be printed.  */
282 
283 /* Encode 7-bit HINT #imm in the lower 8 bits.  Use higher bits for flags.  */
284 #define HINT_ENCODE(flag, val) ((flag << 8) | val)
285 #define HINT_FLAG(val) (val >> 8)
286 #define HINT_VAL(val) (val & 0xff)
287 
288 static inline bool
operand_has_inserter(const aarch64_operand * operand)289 operand_has_inserter (const aarch64_operand *operand)
290 {
291   return (operand->flags & OPD_F_HAS_INSERTER) != 0;
292 }
293 
294 static inline bool
operand_has_extractor(const aarch64_operand * operand)295 operand_has_extractor (const aarch64_operand *operand)
296 {
297   return (operand->flags & OPD_F_HAS_EXTRACTOR) != 0;
298 }
299 
300 static inline bool
operand_need_sign_extension(const aarch64_operand * operand)301 operand_need_sign_extension (const aarch64_operand *operand)
302 {
303   return (operand->flags & OPD_F_SEXT) != 0;
304 }
305 
306 static inline bool
operand_need_shift_by_two(const aarch64_operand * operand)307 operand_need_shift_by_two (const aarch64_operand *operand)
308 {
309   return (operand->flags & OPD_F_SHIFT_BY_2) != 0;
310 }
311 
312 static inline bool
operand_need_shift_by_four(const aarch64_operand * operand)313 operand_need_shift_by_four (const aarch64_operand *operand)
314 {
315   return (operand->flags & OPD_F_SHIFT_BY_4) != 0;
316 }
317 
318 static inline bool
operand_maybe_stack_pointer(const aarch64_operand * operand)319 operand_maybe_stack_pointer (const aarch64_operand *operand)
320 {
321   return (operand->flags & OPD_F_MAYBE_SP) != 0;
322 }
323 
324 /* Return the value of the operand-specific data field (OPD_F_OD_MASK).  */
325 static inline unsigned int
get_operand_specific_data(const aarch64_operand * operand)326 get_operand_specific_data (const aarch64_operand *operand)
327 {
328   return (operand->flags & OPD_F_OD_MASK) >> OPD_F_OD_LSB;
329 }
330 
331 /* Return the width of field number N of operand *OPERAND.  */
332 static inline unsigned
get_operand_field_width(const aarch64_operand * operand,unsigned n)333 get_operand_field_width (const aarch64_operand *operand, unsigned n)
334 {
335   assert (operand->fields[n] != FLD_NIL);
336   return fields[operand->fields[n]].width;
337 }
338 
339 /* Return the total width of the operand *OPERAND.  */
340 static inline unsigned
get_operand_fields_width(const aarch64_operand * operand)341 get_operand_fields_width (const aarch64_operand *operand)
342 {
343   int i = 0;
344   unsigned width = 0;
345   while (operand->fields[i] != FLD_NIL)
346     width += fields[operand->fields[i++]].width;
347   assert (width > 0 && width < 32);
348   return width;
349 }
350 
351 static inline const aarch64_operand *
get_operand_from_code(enum aarch64_opnd code)352 get_operand_from_code (enum aarch64_opnd code)
353 {
354   return aarch64_operands + code;
355 }
356 
357 /* Operand qualifier and operand constraint checking.  */
358 
359 int aarch64_match_operands_constraint (aarch64_inst *,
360 				       aarch64_operand_error *);
361 
362 /* Operand qualifier related functions.  */
363 const char* aarch64_get_qualifier_name (aarch64_opnd_qualifier_t);
364 unsigned char aarch64_get_qualifier_nelem (aarch64_opnd_qualifier_t);
365 aarch64_insn aarch64_get_qualifier_standard_value (aarch64_opnd_qualifier_t);
366 int aarch64_find_best_match (const aarch64_inst *,
367 			     const aarch64_opnd_qualifier_seq_t *,
368 			     int, aarch64_opnd_qualifier_t *);
369 
370 static inline void
reset_operand_qualifier(aarch64_inst * inst,int idx)371 reset_operand_qualifier (aarch64_inst *inst, int idx)
372 {
373   assert (idx >=0 && idx < aarch64_num_of_operands (inst->opcode));
374   inst->operands[idx].qualifier = AARCH64_OPND_QLF_NIL;
375 }
376 
377 /* Inline functions operating on instruction bit-field(s).  */
378 
379 /* Generate a mask that has WIDTH number of consecutive 1s.  */
380 
381 static inline aarch64_insn
gen_mask(int width)382 gen_mask (int width)
383 {
384   return ((aarch64_insn) 1 << width) - 1;
385 }
386 
387 /* LSB_REL is the relative location of the lsb in the sub field, starting from 0.  */
388 static inline int
gen_sub_field(enum aarch64_field_kind kind,int lsb_rel,int width,aarch64_field * ret)389 gen_sub_field (enum aarch64_field_kind kind, int lsb_rel, int width, aarch64_field *ret)
390 {
391   const aarch64_field *field = &fields[kind];
392   if (lsb_rel < 0 || width <= 0 || lsb_rel + width > field->width)
393     return 0;
394   ret->lsb = field->lsb + lsb_rel;
395   ret->width = width;
396   return 1;
397 }
398 
399 /* Insert VALUE into FIELD of CODE.  MASK can be zero or the base mask
400    of the opcode.  */
401 
402 static inline void
insert_field_2(const aarch64_field * field,aarch64_insn * code,aarch64_insn value,aarch64_insn mask)403 insert_field_2 (const aarch64_field *field, aarch64_insn *code,
404 		aarch64_insn value, aarch64_insn mask)
405 {
406   assert (field->width < 32 && field->width >= 1 && field->lsb >= 0
407 	  && field->lsb + field->width <= 32);
408   value &= gen_mask (field->width);
409   value <<= field->lsb;
410   /* In some opcodes, field can be part of the base opcode, e.g. the size
411      field in FADD.  The following helps avoid corrupt the base opcode.  */
412   value &= ~mask;
413   *code |= value;
414 }
415 
416 /* Extract FIELD of CODE and return the value.  MASK can be zero or the base
417    mask of the opcode.  */
418 
419 static inline aarch64_insn
extract_field_2(const aarch64_field * field,aarch64_insn code,aarch64_insn mask)420 extract_field_2 (const aarch64_field *field, aarch64_insn code,
421 		 aarch64_insn mask)
422 {
423   aarch64_insn value;
424   /* Clear any bit that is a part of the base opcode.  */
425   code &= ~mask;
426   value = (code >> field->lsb) & gen_mask (field->width);
427   return value;
428 }
429 
430 /* Insert VALUE into field KIND of CODE.  MASK can be zero or the base mask
431    of the opcode.  */
432 
433 static inline void
insert_field(enum aarch64_field_kind kind,aarch64_insn * code,aarch64_insn value,aarch64_insn mask)434 insert_field (enum aarch64_field_kind kind, aarch64_insn *code,
435 	      aarch64_insn value, aarch64_insn mask)
436 {
437   insert_field_2 (&fields[kind], code, value, mask);
438 }
439 
440 /* Extract field KIND of CODE and return the value.  MASK can be zero or the
441    base mask of the opcode.  */
442 
443 static inline aarch64_insn
extract_field(enum aarch64_field_kind kind,aarch64_insn code,aarch64_insn mask)444 extract_field (enum aarch64_field_kind kind, aarch64_insn code,
445 	       aarch64_insn mask)
446 {
447   return extract_field_2 (&fields[kind], code, mask);
448 }
449 
450 extern aarch64_insn
451 extract_fields (aarch64_insn code, aarch64_insn mask, ...);
452 
453 /* Inline functions selecting operand to do the encoding/decoding for a
454    certain instruction bit-field.  */
455 
456 /* Select the operand to do the encoding/decoding of the 'sf' field.
457    The heuristic-based rule is that the result operand is respected more.  */
458 
459 static inline int
select_operand_for_sf_field_coding(const aarch64_opcode * opcode)460 select_operand_for_sf_field_coding (const aarch64_opcode *opcode)
461 {
462   int idx = -1;
463   if (aarch64_get_operand_class (opcode->operands[0])
464       == AARCH64_OPND_CLASS_INT_REG)
465     /* normal case.  */
466     idx = 0;
467   else if (aarch64_get_operand_class (opcode->operands[1])
468 	   == AARCH64_OPND_CLASS_INT_REG)
469     /* e.g. float2fix.  */
470     idx = 1;
471   else
472     { assert (0); abort (); }
473   return idx;
474 }
475 
476 /* Select the operand to do the encoding/decoding of the 'type' field in
477    the floating-point instructions.
478    The heuristic-based rule is that the source operand is respected more.  */
479 
480 static inline int
select_operand_for_fptype_field_coding(const aarch64_opcode * opcode)481 select_operand_for_fptype_field_coding (const aarch64_opcode *opcode)
482 {
483   int idx;
484   if (aarch64_get_operand_class (opcode->operands[1])
485       == AARCH64_OPND_CLASS_FP_REG)
486     /* normal case.  */
487     idx = 1;
488   else if (aarch64_get_operand_class (opcode->operands[0])
489 	   == AARCH64_OPND_CLASS_FP_REG)
490     /* e.g. float2fix.  */
491     idx = 0;
492   else
493     { assert (0); abort (); }
494   return idx;
495 }
496 
497 /* Select the operand to do the encoding/decoding of the 'size' field in
498    the AdvSIMD scalar instructions.
499    The heuristic-based rule is that the destination operand is respected
500    more.  */
501 
502 static inline int
select_operand_for_scalar_size_field_coding(const aarch64_opcode * opcode)503 select_operand_for_scalar_size_field_coding (const aarch64_opcode *opcode)
504 {
505   int src_size = 0, dst_size = 0;
506   if (aarch64_get_operand_class (opcode->operands[0])
507       == AARCH64_OPND_CLASS_SISD_REG)
508     dst_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][0]);
509   if (aarch64_get_operand_class (opcode->operands[1])
510       == AARCH64_OPND_CLASS_SISD_REG)
511     src_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][1]);
512   if (src_size == dst_size && src_size == 0)
513     { assert (0); abort (); }
514   /* When the result is not a sisd register or it is a long operantion.  */
515   if (dst_size == 0 || dst_size == src_size << 1)
516     return 1;
517   else
518     return 0;
519 }
520 
521 /* Select the operand to do the encoding/decoding of the 'size:Q' fields in
522    the AdvSIMD instructions.  */
523 
524 int aarch64_select_operand_for_sizeq_field_coding (const aarch64_opcode *);
525 
526 /* Miscellaneous.  */
527 
528 aarch64_insn aarch64_get_operand_modifier_value (enum aarch64_modifier_kind);
529 enum aarch64_modifier_kind
530 aarch64_get_operand_modifier_from_value (aarch64_insn, bool);
531 
532 
533 bool aarch64_wide_constant_p (uint64_t, int, unsigned int *);
534 bool aarch64_logical_immediate_p (uint64_t, int, aarch64_insn *);
535 int aarch64_shrink_expanded_imm8 (uint64_t);
536 
537 /* Copy the content of INST->OPERANDS[SRC] to INST->OPERANDS[DST].  */
538 static inline void
copy_operand_info(aarch64_inst * inst,int dst,int src)539 copy_operand_info (aarch64_inst *inst, int dst, int src)
540 {
541   assert (dst >= 0 && src >= 0 && dst < AARCH64_MAX_OPND_NUM
542 	  && src < AARCH64_MAX_OPND_NUM);
543   memcpy (&inst->operands[dst], &inst->operands[src],
544 	  sizeof (aarch64_opnd_info));
545   inst->operands[dst].idx = dst;
546 }
547 
548 /* A primitive log caculator.  */
549 
550 static inline unsigned int
get_logsz(unsigned int size)551 get_logsz (unsigned int size)
552 {
553   const unsigned char ls[16] =
554     {0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4};
555   if (size > 16)
556     {
557       assert (0);
558       return -1;
559     }
560   assert (ls[size - 1] != (unsigned char)-1);
561   return ls[size - 1];
562 }
563 
564 #endif /* OPCODES_AARCH64_OPC_H */
565