Annotation of src/external/gpl3/binutils.old/dist/opcodes/aarch64-opc.h, Revision 1.1.1.3
1.1 christos 1: /* aarch64-opc.h -- Header file for aarch64-opc.c and aarch64-opc-2.c.
1.1.1.3 ! christos 2: Copyright (C) 2012-2016 Free Software Foundation, Inc.
1.1 christos 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,
1.1.1.2 christos 87: FLD_lse_sz,
1.1 christos 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. */
108:
109: struct 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:
127: typedef struct aarch64_operand aarch64_operand;
128:
129: extern 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:
141: static inline bfd_boolean
142: operand_has_inserter (const aarch64_operand *operand)
143: {
144: return (operand->flags & OPD_F_HAS_INSERTER) ? TRUE : FALSE;
145: }
146:
147: static inline bfd_boolean
148: operand_has_extractor (const aarch64_operand *operand)
149: {
150: return (operand->flags & OPD_F_HAS_EXTRACTOR) ? TRUE : FALSE;
151: }
152:
153: static inline bfd_boolean
154: operand_need_sign_extension (const aarch64_operand *operand)
155: {
156: return (operand->flags & OPD_F_SEXT) ? TRUE : FALSE;
157: }
158:
159: static inline bfd_boolean
160: operand_need_shift_by_two (const aarch64_operand *operand)
161: {
162: return (operand->flags & OPD_F_SHIFT_BY_2) ? TRUE : FALSE;
163: }
164:
165: static inline bfd_boolean
166: operand_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. */
172: static inline unsigned
173: get_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:
183: static inline const aarch64_operand *
184: get_operand_from_code (enum aarch64_opnd code)
185: {
186: return aarch64_operands + code;
187: }
188:
189: /* Operand qualifier and operand constraint checking. */
190:
191: int aarch64_match_operands_constraint (aarch64_inst *,
192: aarch64_operand_error *);
193:
194: /* Operand qualifier related functions. */
195: const char* aarch64_get_qualifier_name (aarch64_opnd_qualifier_t);
196: unsigned char aarch64_get_qualifier_nelem (aarch64_opnd_qualifier_t);
197: aarch64_insn aarch64_get_qualifier_standard_value (aarch64_opnd_qualifier_t);
198: int aarch64_find_best_match (const aarch64_inst *,
199: const aarch64_opnd_qualifier_seq_t *,
200: int, aarch64_opnd_qualifier_t *);
201:
202: static inline void
203: reset_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:
213: static inline aarch64_insn
214: gen_mask (int width)
215: {
1.1.1.2 christos 216: return ((aarch64_insn) 1 << width) - 1;
1.1 christos 217: }
218:
219: /* LSB_REL is the relative location of the lsb in the sub field, starting from 0. */
220: static inline int
221: gen_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:
234: static inline void
235: insert_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:
251: static inline aarch64_insn
252: extract_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:
265: static inline void
266: insert_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:
275: static inline aarch64_insn
276: extract_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:
288: static inline int
289: select_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:
309: static inline int
310: select_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:
331: static inline int
332: select_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:
353: int aarch64_select_operand_for_sizeq_field_coding (const aarch64_opcode *);
354:
355: /* Miscellaneous. */
356:
357: aarch64_insn aarch64_get_operand_modifier_value (enum aarch64_modifier_kind);
358: enum aarch64_modifier_kind
359: aarch64_get_operand_modifier_from_value (aarch64_insn, bfd_boolean);
360:
361:
362: bfd_boolean aarch64_wide_constant_p (int64_t, int, unsigned int *);
363: bfd_boolean aarch64_logical_immediate_p (uint64_t, int, aarch64_insn *);
364: int aarch64_shrink_expanded_imm8 (uint64_t);
365:
366: /* Copy the content of INST->OPERANDS[SRC] to INST->OPERANDS[DST]. */
367: static inline void
368: copy_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:
379: static inline unsigned int
380: get_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 */
CVSweb <webmaster@jp.NetBSD.org>