/src/binutils-gdb/opcodes/aarch64-opc.h
Line | Count | Source |
1 | | /* aarch64-opc.h -- Header file for aarch64-opc.c and aarch64-opc-2.c. |
2 | | Copyright (C) 2012-2026 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 | | /* Field description. |
28 | | |
29 | | If is_const is false, this identifies a bitfield in an instruction encoding |
30 | | that has size WIDTH and has its least significant bit at position NUM. |
31 | | |
32 | | If is_const is true, this represents the constant bit string of size WIDTH |
33 | | bits stored in the least significant bits of NUM. In this case, the |
34 | | leading 8-WIDTH bits of VALUE must be zero. |
35 | | |
36 | | A sequence of fields can be used to describe how instruction operands are |
37 | | represented in the 32-bit instruction encoding. |
38 | | |
39 | | For example, consider an instruction operand Zd that is an even numbered |
40 | | register in z16-z30, with the middle three bits of the register number |
41 | | stored in bits [19:17] of the encoding. The register number can then be |
42 | | constructed by concatenating: |
43 | | - a constant bit '1' (represented here as {1, 1, true}), |
44 | | - bits [19:17] of the encoding (represented here as {3, 17, false}), and |
45 | | - a constant bit '0' (represented here as {1, 0, true}). |
46 | | This sequence of fields fully describes both the constraints on which |
47 | | register numbers are valid, and how valid register numbers are represented |
48 | | in the instruction encoding. */ |
49 | | struct aarch64_field |
50 | | { |
51 | | unsigned int width:8; |
52 | | unsigned int num:7; |
53 | | bool is_const:1; |
54 | | }; |
55 | | |
56 | | typedef struct aarch64_field aarch64_field; |
57 | | |
58 | 12.1M | #define AARCH64_FIELD(lsb, width) ((aarch64_field) {width, lsb, false}) |
59 | | #define AARCH64_FIELD_CONST(val, width) ((aarch64_field) {width, val, true}) |
60 | 77.3k | #define AARCH64_FIELD_NIL ((aarch64_field) {0, 0, false}) |
61 | | |
62 | | /* Instruction fields. These defines are included to reduce the initial diff |
63 | | size, but the indirection should eventually be eliminated. */ |
64 | 38.3k | #define FLD_CRm AARCH64_FIELD( 8, 4) |
65 | 342 | #define FLD_CRm_dsb_nxs AARCH64_FIELD(10, 2) |
66 | 37.0k | #define FLD_CRn AARCH64_FIELD(12, 4) |
67 | 86.3k | #define FLD_H AARCH64_FIELD(11, 1) |
68 | 84.4k | #define FLD_L AARCH64_FIELD(21, 1) |
69 | 39.4k | #define FLD_M AARCH64_FIELD(20, 1) |
70 | 171k | #define FLD_N AARCH64_FIELD(22, 1) |
71 | 965k | #define FLD_Q AARCH64_FIELD(30, 1) |
72 | 714k | #define FLD_Rm AARCH64_FIELD(16, 5) |
73 | 1.09M | #define FLD_Rn AARCH64_FIELD( 5, 5) |
74 | 796k | #define FLD_Rt AARCH64_FIELD( 0, 5) |
75 | 98.4k | #define FLD_S AARCH64_FIELD(12, 1) |
76 | 868 | #define FLD_SM3_imm2 AARCH64_FIELD(12, 2) |
77 | 87.4k | #define FLD_SME_Q AARCH64_FIELD(16, 1) |
78 | 2.16k | #define FLD_SME_size_12 AARCH64_FIELD(12, 2) |
79 | 102k | #define FLD_SME_size_22 AARCH64_FIELD(22, 2) |
80 | 177 | #define FLD_SME_sz_23 AARCH64_FIELD(23, 1) |
81 | 10.3k | #define FLD_SME_tszh AARCH64_FIELD(22, 1) |
82 | 10.3k | #define FLD_SME_tszl AARCH64_FIELD(18, 3) |
83 | 182 | #define FLD_SVE_M_4 AARCH64_FIELD( 4, 1) |
84 | 17.0k | #define FLD_SVE_M_14 AARCH64_FIELD(14, 1) |
85 | 3.60k | #define FLD_SVE_M_16 AARCH64_FIELD(16, 1) |
86 | 95.6k | #define FLD_SVE_imm4 AARCH64_FIELD(16, 4) |
87 | 23.6k | #define FLD_SVE_imm6 AARCH64_FIELD(16, 6) |
88 | 2.23k | #define FLD_SVE_msz AARCH64_FIELD(10, 2) |
89 | 151 | #define FLD_SVE_size AARCH64_FIELD(17, 2) |
90 | 21.4k | #define FLD_SVE_sz AARCH64_FIELD(22, 1) |
91 | 7.74k | #define FLD_SVE_sz2 AARCH64_FIELD(30, 1) |
92 | 729 | #define FLD_SVE_sz3 AARCH64_FIELD(17, 1) |
93 | 161 | #define FLD_SVE_sz4 AARCH64_FIELD(14, 1) |
94 | 9.74k | #define FLD_SVE_tszh AARCH64_FIELD(22, 2) |
95 | 4.88k | #define FLD_SVE_tszl_8 AARCH64_FIELD( 8, 2) |
96 | 12.5k | #define FLD_SVE_tszl_19 AARCH64_FIELD(19, 2) |
97 | 6.47k | #define FLD_abc AARCH64_FIELD(16, 3) |
98 | 32.3k | #define FLD_asisdlso_opcode AARCH64_FIELD(13, 3) |
99 | 3.44k | #define FLD_cmode AARCH64_FIELD(12, 4) |
100 | 28.7k | #define FLD_cond AARCH64_FIELD(12, 4) |
101 | 41.6k | #define FLD_cond2 AARCH64_FIELD( 0, 4) |
102 | 6.47k | #define FLD_defgh AARCH64_FIELD( 5, 5) |
103 | 113k | #define FLD_hw AARCH64_FIELD(21, 2) |
104 | 318 | #define FLD_imm1_22 AARCH64_FIELD(22, 1) |
105 | | #define FLD_imm3_5 AARCH64_FIELD( 5, 3) |
106 | 67.0k | #define FLD_imm3_10 AARCH64_FIELD(10, 3) |
107 | 3.80k | #define FLD_imm3_19 AARCH64_FIELD(19, 3) |
108 | 734 | #define FLD_imm4_5 AARCH64_FIELD( 5, 4) |
109 | 3.81k | #define FLD_imm4_11 AARCH64_FIELD(11, 4) |
110 | 45.0k | #define FLD_imm5 AARCH64_FIELD(16, 5) |
111 | 544k | #define FLD_imm6_10 AARCH64_FIELD(10, 6) |
112 | 438k | #define FLD_imm12 AARCH64_FIELD(10, 12) |
113 | 34.3k | #define FLD_immb AARCH64_FIELD(16, 3) |
114 | 73.9k | #define FLD_immh AARCH64_FIELD(19, 4) |
115 | 917k | #define FLD_ldst_size AARCH64_FIELD(30, 2) |
116 | 16.9k | #define FLD_len AARCH64_FIELD(13, 2) |
117 | 39.1k | #define FLD_lse_sz AARCH64_FIELD(30, 1) |
118 | 37.0k | #define FLD_op0 AARCH64_FIELD(19, 2) |
119 | 37.3k | #define FLD_op1 AARCH64_FIELD(16, 3) |
120 | 37.7k | #define FLD_op2 AARCH64_FIELD( 5, 3) |
121 | 37.4k | #define FLD_opc AARCH64_FIELD(22, 2) |
122 | 258k | #define FLD_opc1 AARCH64_FIELD(23, 1) |
123 | 60.9k | #define FLD_opcode AARCH64_FIELD(12, 4) |
124 | 122k | #define FLD_option AARCH64_FIELD(13, 3) |
125 | 2.79k | #define FLD_scale AARCH64_FIELD(10, 6) |
126 | 2.41M | #define FLD_sf AARCH64_FIELD(31, 1) |
127 | 1.15M | #define FLD_shift AARCH64_FIELD(22, 2) |
128 | 750k | #define FLD_size AARCH64_FIELD(22, 2) |
129 | 3.25k | #define FLD_sz AARCH64_FIELD(22, 1) |
130 | 73.1k | #define FLD_type AARCH64_FIELD(22, 2) |
131 | 95.2k | #define FLD_vldst_size AARCH64_FIELD(10, 2) |
132 | | #define FLD_off2 AARCH64_FIELD( 5, 2) |
133 | | #define FLD_ol AARCH64_FIELD( 5, 1) |
134 | 16.9k | #define FLD_opc2 AARCH64_FIELD(12, 4) |
135 | 28.8k | #define FLD_rcpc3_size AARCH64_FIELD(30, 2) |
136 | | #define FLD_ZA8_1 AARCH64_FIELD( 8, 1) |
137 | | #define FLD_ZA7_2 AARCH64_FIELD( 7, 2) |
138 | | #define FLD_ZA6_3 AARCH64_FIELD( 6, 3) |
139 | | #define FLD_ZA5_4 AARCH64_FIELD( 5, 4) |
140 | | |
141 | | |
142 | | /* Operand description. */ |
143 | | |
144 | | struct aarch64_operand |
145 | | { |
146 | | enum aarch64_operand_class op_class; |
147 | | |
148 | | /* Name of the operand code; used mainly for the purpose of internal |
149 | | debugging. */ |
150 | | const char *name; |
151 | | |
152 | | unsigned int flags; |
153 | | |
154 | | /* The associated instruction bit-fields; no operand has more than 5 |
155 | | bit-fields */ |
156 | | aarch64_field fields[6]; |
157 | | |
158 | | /* Brief description */ |
159 | | const char *desc; |
160 | | }; |
161 | | |
162 | | typedef struct aarch64_operand aarch64_operand; |
163 | | |
164 | | extern const aarch64_operand aarch64_operands[]; |
165 | | |
166 | | enum err_type |
167 | | verify_constraints (const struct aarch64_inst *, const aarch64_insn, bfd_vma, |
168 | | bool, aarch64_operand_error *, aarch64_instr_sequence*); |
169 | | |
170 | | /* Operand flags. */ |
171 | | |
172 | | #define OPD_F_HAS_INSERTER 0x00000001 |
173 | 19.9M | #define OPD_F_HAS_EXTRACTOR 0x00000002 |
174 | 4.04M | #define OPD_F_SEXT 0x00000004 /* Require sign-extension. */ |
175 | 5.39M | #define OPD_F_SHIFT_BY_2 0x00000008 /* Need to left shift the field |
176 | | value by 2 to get the value |
177 | | of an immediate operand. */ |
178 | 188k | #define OPD_F_MAYBE_SP 0x00000010 /* May potentially be SP. */ |
179 | 1.00M | #define OPD_F_OD_MASK 0x000001e0 /* Operand-dependent data. */ |
180 | 1.00M | #define OPD_F_OD_LSB 5 |
181 | 237k | #define OPD_F_NO_ZR 0x00000200 /* ZR index not allowed. */ |
182 | 3.03M | #define OPD_F_SHIFT_BY_3 0x00000400 /* Need to left shift the field |
183 | | value by 3 to get the value |
184 | | of an immediate operand. */ |
185 | 3.03M | #define OPD_F_SHIFT_BY_4 0x00000800 /* Need to left shift the field |
186 | | value by 4 to get the value |
187 | | of an immediate operand. */ |
188 | 1.35M | #define OPD_F_UNSIGNED 0x00001000 /* Expect an unsigned value. */ |
189 | | |
190 | | |
191 | | /* Register flags. */ |
192 | | |
193 | | #undef F_DEPRECATED |
194 | 1.64k | #define F_DEPRECATED (1 << 0) /* Deprecated system register. */ |
195 | | |
196 | | /* (1 << 1) Unused. */ |
197 | | |
198 | | #undef F_HASXT |
199 | 1.32k | #define F_HASXT (1 << 2) /* System instruction register <Xt> |
200 | | operand. */ |
201 | | |
202 | | #undef F_REG_READ |
203 | 8.53k | #define F_REG_READ (1 << 3) /* Register can only be used to read values |
204 | | out of. */ |
205 | | |
206 | | #undef F_REG_WRITE |
207 | 11.1k | #define F_REG_WRITE (1 << 4) /* Register can only be written to but not |
208 | | read from. */ |
209 | | |
210 | | #undef F_REG_IN_CRM |
211 | 885 | #define F_REG_IN_CRM (1 << 5) /* Register extra encoding in CRm. */ |
212 | | |
213 | | #undef F_REG_ALIAS |
214 | 1.64k | #define F_REG_ALIAS (1 << 6) /* Register name aliases another. */ |
215 | | |
216 | | #undef F_REG_128 |
217 | 0 | #define F_REG_128 (1 << 7) /* System register implementable as 128-bit wide. */ |
218 | | |
219 | | #undef F_TLBID_XT |
220 | 1.03k | #define F_TLBID_XT (1 << 8) /* System instruction register <Xt> as optional operand. */ |
221 | | |
222 | | |
223 | | /* PSTATE field name for the MSR instruction this is encoded in "op1:op2:CRm". |
224 | | Part of CRm can be used to encode <pstatefield>. E.g. CRm[3:1] for SME. |
225 | | In order to set/get full PSTATE field name use flag F_REG_IN_CRM and below |
226 | | macros to encode and decode CRm encoding. |
227 | | */ |
228 | | #define PSTATE_ENCODE_CRM(val) (val << 6) |
229 | 264 | #define PSTATE_DECODE_CRM(flags) ((flags >> 6) & 0x0f) |
230 | | |
231 | | #undef F_IMM_IN_CRM |
232 | 261 | #define F_IMM_IN_CRM (1 << 10) /* Immediate extra encoding in CRm. */ |
233 | | |
234 | | /* Also CRm may contain, in addition to <pstatefield> immediate. |
235 | | E.g. CRm[0] <imm1> at bit 0 for SME. Use below macros to encode and decode |
236 | | immediate mask. |
237 | | */ |
238 | | #define PSTATE_ENCODE_CRM_IMM(mask) (mask << 11) |
239 | 0 | #define PSTATE_DECODE_CRM_IMM(mask) ((mask >> 11) & 0x0f) |
240 | | |
241 | | /* Helper macro to ENCODE CRm and its immediate. */ |
242 | | #define PSTATE_ENCODE_CRM_AND_IMM(CVAL,IMASK) \ |
243 | | (F_REG_IN_CRM | PSTATE_ENCODE_CRM(CVAL) \ |
244 | | | F_IMM_IN_CRM | PSTATE_ENCODE_CRM_IMM(IMASK)) |
245 | | |
246 | | /* Bits [15, 18] contain the maximum value for an immediate MSR. */ |
247 | | #define F_REG_MAX_VALUE(X) ((X) << 15) |
248 | 261 | #define F_GET_REG_MAX_VALUE(X) (((X) >> 15) & 0x0f) |
249 | | |
250 | | static inline bool |
251 | | operand_has_inserter (const aarch64_operand *operand) |
252 | 0 | { |
253 | 0 | return (operand->flags & OPD_F_HAS_INSERTER) != 0; |
254 | 0 | } Unexecuted instantiation: aarch64-dis.c:operand_has_inserter Unexecuted instantiation: aarch64-dis-2.c:operand_has_inserter Unexecuted instantiation: aarch64-opc.c:operand_has_inserter Unexecuted instantiation: aarch64-opc-2.c:operand_has_inserter |
255 | | |
256 | | static inline bool |
257 | | operand_has_extractor (const aarch64_operand *operand) |
258 | 19.9M | { |
259 | 19.9M | return (operand->flags & OPD_F_HAS_EXTRACTOR) != 0; |
260 | 19.9M | } aarch64-dis.c:operand_has_extractor Line | Count | Source | 258 | 19.9M | { | 259 | 19.9M | return (operand->flags & OPD_F_HAS_EXTRACTOR) != 0; | 260 | 19.9M | } |
Unexecuted instantiation: aarch64-dis-2.c:operand_has_extractor Unexecuted instantiation: aarch64-opc.c:operand_has_extractor Unexecuted instantiation: aarch64-opc-2.c:operand_has_extractor |
261 | | |
262 | | static inline bool |
263 | | operand_need_sign_extension (const aarch64_operand *operand) |
264 | 4.04M | { |
265 | 4.04M | return (operand->flags & OPD_F_SEXT) != 0; |
266 | 4.04M | } aarch64-dis.c:operand_need_sign_extension Line | Count | Source | 264 | 4.04M | { | 265 | 4.04M | return (operand->flags & OPD_F_SEXT) != 0; | 266 | 4.04M | } |
Unexecuted instantiation: aarch64-dis-2.c:operand_need_sign_extension Unexecuted instantiation: aarch64-opc.c:operand_need_sign_extension Unexecuted instantiation: aarch64-opc-2.c:operand_need_sign_extension |
267 | | |
268 | | static inline bool |
269 | | operand_need_shift_by_two (const aarch64_operand *operand) |
270 | 5.39M | { |
271 | 5.39M | return (operand->flags & OPD_F_SHIFT_BY_2) != 0; |
272 | 5.39M | } aarch64-dis.c:operand_need_shift_by_two Line | Count | Source | 270 | 4.04M | { | 271 | 4.04M | return (operand->flags & OPD_F_SHIFT_BY_2) != 0; | 272 | 4.04M | } |
Unexecuted instantiation: aarch64-dis-2.c:operand_need_shift_by_two aarch64-opc.c:operand_need_shift_by_two Line | Count | Source | 270 | 1.35M | { | 271 | 1.35M | return (operand->flags & OPD_F_SHIFT_BY_2) != 0; | 272 | 1.35M | } |
Unexecuted instantiation: aarch64-opc-2.c:operand_need_shift_by_two |
273 | | |
274 | | static inline bool |
275 | | operand_need_shift_by_three (const aarch64_operand *operand) |
276 | 3.03M | { |
277 | 3.03M | return (operand->flags & OPD_F_SHIFT_BY_3) != 0; |
278 | 3.03M | } aarch64-dis.c:operand_need_shift_by_three Line | Count | Source | 276 | 3.03M | { | 277 | 3.03M | return (operand->flags & OPD_F_SHIFT_BY_3) != 0; | 278 | 3.03M | } |
Unexecuted instantiation: aarch64-dis-2.c:operand_need_shift_by_three Unexecuted instantiation: aarch64-opc.c:operand_need_shift_by_three Unexecuted instantiation: aarch64-opc-2.c:operand_need_shift_by_three |
279 | | |
280 | | static inline bool |
281 | | operand_need_shift_by_four (const aarch64_operand *operand) |
282 | 3.03M | { |
283 | 3.03M | return (operand->flags & OPD_F_SHIFT_BY_4) != 0; |
284 | 3.03M | } aarch64-dis.c:operand_need_shift_by_four Line | Count | Source | 282 | 3.03M | { | 283 | 3.03M | return (operand->flags & OPD_F_SHIFT_BY_4) != 0; | 284 | 3.03M | } |
Unexecuted instantiation: aarch64-dis-2.c:operand_need_shift_by_four Unexecuted instantiation: aarch64-opc.c:operand_need_shift_by_four Unexecuted instantiation: aarch64-opc-2.c:operand_need_shift_by_four |
285 | | |
286 | | static inline bool |
287 | | operand_need_unsigned_offset (const aarch64_operand *operand) |
288 | 1.35M | { |
289 | 1.35M | return (operand->flags & OPD_F_UNSIGNED) != 0; |
290 | 1.35M | } Unexecuted instantiation: aarch64-dis.c:operand_need_unsigned_offset Unexecuted instantiation: aarch64-dis-2.c:operand_need_unsigned_offset aarch64-opc.c:operand_need_unsigned_offset Line | Count | Source | 288 | 1.35M | { | 289 | 1.35M | return (operand->flags & OPD_F_UNSIGNED) != 0; | 290 | 1.35M | } |
Unexecuted instantiation: aarch64-opc-2.c:operand_need_unsigned_offset |
291 | | |
292 | | static inline bool |
293 | | operand_maybe_stack_pointer (const aarch64_operand *operand) |
294 | 188k | { |
295 | 188k | return (operand->flags & OPD_F_MAYBE_SP) != 0; |
296 | 188k | } Unexecuted instantiation: aarch64-dis.c:operand_maybe_stack_pointer Unexecuted instantiation: aarch64-dis-2.c:operand_maybe_stack_pointer aarch64-opc.c:operand_maybe_stack_pointer Line | Count | Source | 294 | 188k | { | 295 | 188k | return (operand->flags & OPD_F_MAYBE_SP) != 0; | 296 | 188k | } |
Unexecuted instantiation: aarch64-opc-2.c:operand_maybe_stack_pointer |
297 | | |
298 | | /* Return the value of the operand-specific data field (OPD_F_OD_MASK). */ |
299 | | static inline unsigned int |
300 | | get_operand_specific_data (const aarch64_operand *operand) |
301 | 1.00M | { |
302 | 1.00M | return (operand->flags & OPD_F_OD_MASK) >> OPD_F_OD_LSB; |
303 | 1.00M | } aarch64-dis.c:get_operand_specific_data Line | Count | Source | 301 | 537k | { | 302 | 537k | return (operand->flags & OPD_F_OD_MASK) >> OPD_F_OD_LSB; | 303 | 537k | } |
Unexecuted instantiation: aarch64-dis-2.c:get_operand_specific_data aarch64-opc.c:get_operand_specific_data Line | Count | Source | 301 | 468k | { | 302 | 468k | return (operand->flags & OPD_F_OD_MASK) >> OPD_F_OD_LSB; | 303 | 468k | } |
Unexecuted instantiation: aarch64-opc-2.c:get_operand_specific_data |
304 | | |
305 | | /* Return the width of field number N of operand *OPERAND. */ |
306 | | static inline unsigned |
307 | | get_operand_field_width (const aarch64_operand *operand, unsigned n) |
308 | 665 | { |
309 | 665 | assert (operand->fields[n].width != 0); |
310 | 665 | return operand->fields[n].width; |
311 | 665 | } aarch64-dis.c:get_operand_field_width Line | Count | Source | 308 | 485 | { | 309 | 485 | assert (operand->fields[n].width != 0); | 310 | 485 | return operand->fields[n].width; | 311 | 485 | } |
Unexecuted instantiation: aarch64-dis-2.c:get_operand_field_width aarch64-opc.c:get_operand_field_width Line | Count | Source | 308 | 180 | { | 309 | 180 | assert (operand->fields[n].width != 0); | 310 | 180 | return operand->fields[n].width; | 311 | 180 | } |
Unexecuted instantiation: aarch64-opc-2.c:get_operand_field_width |
312 | | |
313 | | /* Return the total width of the operand *OPERAND. */ |
314 | | static inline unsigned |
315 | | get_operand_fields_width (const aarch64_operand *operand) |
316 | 4.97M | { |
317 | 4.97M | int i = 0; |
318 | 4.97M | unsigned width = 0; |
319 | 10.9M | while (operand->fields[i].width != 0) |
320 | 6.01M | width += operand->fields[i++].width; |
321 | 4.97M | assert (width > 0 && width < 32); |
322 | 4.97M | return width; |
323 | 4.97M | } aarch64-dis.c:get_operand_fields_width Line | Count | Source | 316 | 1.52M | { | 317 | 1.52M | int i = 0; | 318 | 1.52M | unsigned width = 0; | 319 | 3.56M | while (operand->fields[i].width != 0) | 320 | 2.03M | width += operand->fields[i++].width; | 321 | 1.52M | assert (width > 0 && width < 32); | 322 | 1.52M | return width; | 323 | 1.52M | } |
Unexecuted instantiation: aarch64-dis-2.c:get_operand_fields_width aarch64-opc.c:get_operand_fields_width Line | Count | Source | 316 | 3.44M | { | 317 | 3.44M | int i = 0; | 318 | 3.44M | unsigned width = 0; | 319 | 7.42M | while (operand->fields[i].width != 0) | 320 | 3.97M | width += operand->fields[i++].width; | 321 | 3.44M | assert (width > 0 && width < 32); | 322 | 3.44M | return width; | 323 | 3.44M | } |
Unexecuted instantiation: aarch64-opc-2.c:get_operand_fields_width |
324 | | |
325 | | static inline const aarch64_operand * |
326 | | get_operand_from_code (enum aarch64_opnd code) |
327 | 4.79M | { |
328 | 4.79M | return aarch64_operands + code; |
329 | 4.79M | } Unexecuted instantiation: aarch64-dis.c:get_operand_from_code Unexecuted instantiation: aarch64-dis-2.c:get_operand_from_code aarch64-opc.c:get_operand_from_code Line | Count | Source | 327 | 4.79M | { | 328 | 4.79M | return aarch64_operands + code; | 329 | 4.79M | } |
Unexecuted instantiation: aarch64-opc-2.c:get_operand_from_code |
330 | | |
331 | | /* Operand qualifier and operand constraint checking. */ |
332 | | |
333 | | bool aarch64_match_operands_constraint (aarch64_inst *, |
334 | | aarch64_operand_error *); |
335 | | |
336 | | /* Operand qualifier related functions. */ |
337 | | const char* aarch64_get_qualifier_name (aarch64_opnd_qualifier_t); |
338 | | unsigned char aarch64_get_qualifier_nelem (aarch64_opnd_qualifier_t); |
339 | | aarch64_insn aarch64_get_qualifier_standard_value (aarch64_opnd_qualifier_t); |
340 | | int aarch64_find_best_match (const aarch64_inst *, |
341 | | const aarch64_opnd_qualifier_seq_t *, |
342 | | int, aarch64_opnd_qualifier_t *, int *); |
343 | | |
344 | | static inline void |
345 | | reset_operand_qualifier (aarch64_inst *inst, int idx) |
346 | 68.9k | { |
347 | 68.9k | assert (idx >=0 && idx < aarch64_num_of_operands (inst->opcode)); |
348 | 68.9k | inst->operands[idx].qualifier = AARCH64_OPND_QLF_UNKNOWN; |
349 | 68.9k | } aarch64-dis.c:reset_operand_qualifier Line | Count | Source | 346 | 68.9k | { | 347 | 68.9k | assert (idx >=0 && idx < aarch64_num_of_operands (inst->opcode)); | 348 | 68.9k | inst->operands[idx].qualifier = AARCH64_OPND_QLF_UNKNOWN; | 349 | 68.9k | } |
Unexecuted instantiation: aarch64-dis-2.c:reset_operand_qualifier Unexecuted instantiation: aarch64-opc.c:reset_operand_qualifier Unexecuted instantiation: aarch64-opc-2.c:reset_operand_qualifier |
350 | | |
351 | | /* Inline functions operating on instruction bit-field(s). */ |
352 | | |
353 | | /* Generate a mask that has WIDTH number of consecutive 1s. */ |
354 | | |
355 | | static inline aarch64_insn |
356 | | gen_mask (int width) |
357 | 33.2M | { |
358 | 33.2M | return ((aarch64_insn) 1 << width) - 1; |
359 | 33.2M | } Line | Count | Source | 357 | 33.2M | { | 358 | 33.2M | return ((aarch64_insn) 1 << width) - 1; | 359 | 33.2M | } |
Unexecuted instantiation: aarch64-dis-2.c:gen_mask Unexecuted instantiation: aarch64-opc.c:gen_mask Unexecuted instantiation: aarch64-opc-2.c:gen_mask |
360 | | |
361 | | /* LSB_REL is the relative location of the lsb in the sub field, starting from 0. */ |
362 | | static inline int |
363 | | gen_sub_field (aarch64_field field, int lsb_rel, int width, aarch64_field *ret) |
364 | 74.3k | { |
365 | 74.3k | if (lsb_rel < 0 || width <= 0 || lsb_rel + width > field.width) |
366 | 133 | return 0; |
367 | 74.2k | ret->num = field.num + lsb_rel; |
368 | 74.2k | ret->width = width; |
369 | 74.2k | return 1; |
370 | 74.3k | } aarch64-dis.c:gen_sub_field Line | Count | Source | 364 | 74.3k | { | 365 | 74.3k | if (lsb_rel < 0 || width <= 0 || lsb_rel + width > field.width) | 366 | 133 | return 0; | 367 | 74.2k | ret->num = field.num + lsb_rel; | 368 | 74.2k | ret->width = width; | 369 | 74.2k | return 1; | 370 | 74.3k | } |
Unexecuted instantiation: aarch64-dis-2.c:gen_sub_field Unexecuted instantiation: aarch64-opc.c:gen_sub_field Unexecuted instantiation: aarch64-opc-2.c:gen_sub_field |
371 | | |
372 | | /* Insert VALUE into FIELD of CODE. MASK can be zero or the base mask |
373 | | of the opcode. */ |
374 | | |
375 | | static inline void |
376 | | insert_field (aarch64_field field, aarch64_insn *code, |
377 | | aarch64_insn value, aarch64_insn mask) |
378 | 0 | { |
379 | 0 | assert (field.width < 32 && field.width >= 1 |
380 | 0 | && (field.is_const ? (field.num < 1 << field.width) |
381 | 0 | : (field.num + field.width <= 32))); |
382 | 0 | value &= gen_mask (field.width); |
383 | 0 | if (field.is_const) |
384 | 0 | { |
385 | 0 | assert (value == field.num); |
386 | 0 | return; |
387 | 0 | } |
388 | 0 | value <<= field.num; |
389 | 0 | /* In some opcodes, field can be part of the base opcode, e.g. the size |
390 | 0 | field in FADD. The following helps avoid corrupt the base opcode. */ |
391 | 0 | value &= ~mask; |
392 | 0 | *code |= value; |
393 | 0 | } Unexecuted instantiation: aarch64-dis.c:insert_field Unexecuted instantiation: aarch64-dis-2.c:insert_field Unexecuted instantiation: aarch64-opc.c:insert_field Unexecuted instantiation: aarch64-opc-2.c:insert_field |
394 | | |
395 | | /* Extract FIELD of CODE and return the value. MASK can be zero or the base |
396 | | mask of the opcode. */ |
397 | | |
398 | | static inline aarch64_insn |
399 | | extract_field (aarch64_field field, aarch64_insn code, |
400 | | aarch64_insn mask) |
401 | 33.4M | { |
402 | 33.4M | aarch64_insn value; |
403 | | /* Check for constant field. */ |
404 | 33.4M | if (field.is_const) |
405 | 184k | return field.num; |
406 | | |
407 | | /* Clear any bit that is a part of the base opcode. */ |
408 | 33.2M | code &= ~mask; |
409 | 33.2M | value = (code >> field.num) & gen_mask (field.width); |
410 | 33.2M | return value; |
411 | 33.4M | } aarch64-dis.c:extract_field Line | Count | Source | 401 | 33.4M | { | 402 | 33.4M | aarch64_insn value; | 403 | | /* Check for constant field. */ | 404 | 33.4M | if (field.is_const) | 405 | 184k | return field.num; | 406 | | | 407 | | /* Clear any bit that is a part of the base opcode. */ | 408 | 33.2M | code &= ~mask; | 409 | 33.2M | value = (code >> field.num) & gen_mask (field.width); | 410 | 33.2M | return value; | 411 | 33.4M | } |
Unexecuted instantiation: aarch64-dis-2.c:extract_field Unexecuted instantiation: aarch64-opc.c:extract_field Unexecuted instantiation: aarch64-opc-2.c:extract_field |
412 | | |
413 | | extern aarch64_insn |
414 | | extract_fields (aarch64_insn code, aarch64_insn mask, ...); |
415 | | |
416 | | /* Inline functions selecting operand to do the encoding/decoding for a |
417 | | certain instruction bit-field. */ |
418 | | |
419 | | /* Select the operand to do the encoding/decoding of the 'sf' field. |
420 | | The heuristic-based rule is that the result operand is respected more. */ |
421 | | |
422 | | static inline int |
423 | | select_operand_for_sf_field_coding (const aarch64_opcode *opcode) |
424 | 2.45M | { |
425 | 2.45M | int idx = -1; |
426 | 2.45M | if (opcode->iclass == fprcvtfloat2int) |
427 | 1.80k | return 0; |
428 | 2.44M | else if (opcode->iclass == fprcvtint2float) |
429 | 268 | return 1; |
430 | | |
431 | 2.44M | if (aarch64_get_operand_class (opcode->operands[0]) |
432 | 2.44M | == AARCH64_OPND_CLASS_INT_REG) |
433 | | /* normal case. */ |
434 | 2.44M | idx = 0; |
435 | 1.52k | else if (aarch64_get_operand_class (opcode->operands[1]) |
436 | 1.52k | == AARCH64_OPND_CLASS_INT_REG) |
437 | | /* e.g. float2fix. */ |
438 | 1.52k | idx = 1; |
439 | 0 | else |
440 | 0 | { assert (0); abort (); } |
441 | 2.44M | return idx; |
442 | 2.44M | } aarch64-dis.c:select_operand_for_sf_field_coding Line | Count | Source | 424 | 2.45M | { | 425 | 2.45M | int idx = -1; | 426 | 2.45M | if (opcode->iclass == fprcvtfloat2int) | 427 | 1.80k | return 0; | 428 | 2.44M | else if (opcode->iclass == fprcvtint2float) | 429 | 268 | return 1; | 430 | | | 431 | 2.44M | if (aarch64_get_operand_class (opcode->operands[0]) | 432 | 2.44M | == AARCH64_OPND_CLASS_INT_REG) | 433 | | /* normal case. */ | 434 | 2.44M | idx = 0; | 435 | 1.52k | else if (aarch64_get_operand_class (opcode->operands[1]) | 436 | 1.52k | == AARCH64_OPND_CLASS_INT_REG) | 437 | | /* e.g. float2fix. */ | 438 | 1.52k | idx = 1; | 439 | 0 | else | 440 | 0 | { assert (0); abort (); } | 441 | 2.44M | return idx; | 442 | 2.44M | } |
Unexecuted instantiation: aarch64-dis-2.c:select_operand_for_sf_field_coding Unexecuted instantiation: aarch64-opc.c:select_operand_for_sf_field_coding Unexecuted instantiation: aarch64-opc-2.c:select_operand_for_sf_field_coding |
443 | | |
444 | | /* Select the operand to do the encoding/decoding of the 'type' field in |
445 | | the floating-point instructions. |
446 | | The heuristic-based rule is that the source operand is respected more. */ |
447 | | |
448 | | static inline int |
449 | | select_operand_for_fptype_field_coding (const aarch64_opcode *opcode) |
450 | 73.1k | { |
451 | 73.1k | int idx; |
452 | 73.1k | if (opcode->iclass == fprcvtfloat2int) |
453 | 1.80k | return 1; |
454 | 71.3k | else if (opcode->iclass == fprcvtint2float) |
455 | 268 | return 0; |
456 | | |
457 | 71.0k | if (aarch64_get_operand_class (opcode->operands[1]) |
458 | 71.0k | == AARCH64_OPND_CLASS_FP_REG) |
459 | | /* normal case. */ |
460 | 69.2k | idx = 1; |
461 | 1.80k | else if (aarch64_get_operand_class (opcode->operands[0]) |
462 | 1.80k | == AARCH64_OPND_CLASS_FP_REG) |
463 | | /* e.g. float2fix. */ |
464 | 1.80k | idx = 0; |
465 | 0 | else |
466 | 0 | { assert (0); abort (); } |
467 | 71.0k | return idx; |
468 | 71.0k | } aarch64-dis.c:select_operand_for_fptype_field_coding Line | Count | Source | 450 | 73.1k | { | 451 | 73.1k | int idx; | 452 | 73.1k | if (opcode->iclass == fprcvtfloat2int) | 453 | 1.80k | return 1; | 454 | 71.3k | else if (opcode->iclass == fprcvtint2float) | 455 | 268 | return 0; | 456 | | | 457 | 71.0k | if (aarch64_get_operand_class (opcode->operands[1]) | 458 | 71.0k | == AARCH64_OPND_CLASS_FP_REG) | 459 | | /* normal case. */ | 460 | 69.2k | idx = 1; | 461 | 1.80k | else if (aarch64_get_operand_class (opcode->operands[0]) | 462 | 1.80k | == AARCH64_OPND_CLASS_FP_REG) | 463 | | /* e.g. float2fix. */ | 464 | 1.80k | idx = 0; | 465 | 0 | else | 466 | 0 | { assert (0); abort (); } | 467 | 71.0k | return idx; | 468 | 71.0k | } |
Unexecuted instantiation: aarch64-dis-2.c:select_operand_for_fptype_field_coding Unexecuted instantiation: aarch64-opc.c:select_operand_for_fptype_field_coding Unexecuted instantiation: aarch64-opc-2.c:select_operand_for_fptype_field_coding |
469 | | |
470 | | /* Select the operand to do the encoding/decoding of the 'size' field in |
471 | | the AdvSIMD scalar instructions. |
472 | | The heuristic-based rule is that the destination operand is respected |
473 | | more. */ |
474 | | |
475 | | static inline int |
476 | | select_operand_for_scalar_size_field_coding (const aarch64_opcode *opcode) |
477 | 18.4k | { |
478 | 18.4k | int src_size = 0, dst_size = 0; |
479 | 18.4k | if (aarch64_get_operand_class (opcode->operands[0]) |
480 | 18.4k | == AARCH64_OPND_CLASS_SISD_REG) |
481 | 18.4k | dst_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][0]); |
482 | 18.4k | if (aarch64_get_operand_class (opcode->operands[1]) |
483 | 18.4k | == AARCH64_OPND_CLASS_SISD_REG) |
484 | 18.4k | src_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][1]); |
485 | 18.4k | if (src_size == dst_size && src_size == 0) |
486 | 0 | { assert (0); abort (); } |
487 | | /* When the result is not a sisd register or it is a long operation. */ |
488 | 18.4k | if (dst_size == 0 || dst_size == src_size << 1) |
489 | 3.67k | return 1; |
490 | 14.8k | else |
491 | 14.8k | return 0; |
492 | 18.4k | } aarch64-dis.c:select_operand_for_scalar_size_field_coding Line | Count | Source | 477 | 18.4k | { | 478 | 18.4k | int src_size = 0, dst_size = 0; | 479 | 18.4k | if (aarch64_get_operand_class (opcode->operands[0]) | 480 | 18.4k | == AARCH64_OPND_CLASS_SISD_REG) | 481 | 18.4k | dst_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][0]); | 482 | 18.4k | if (aarch64_get_operand_class (opcode->operands[1]) | 483 | 18.4k | == AARCH64_OPND_CLASS_SISD_REG) | 484 | 18.4k | src_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][1]); | 485 | 18.4k | if (src_size == dst_size && src_size == 0) | 486 | 0 | { assert (0); abort (); } | 487 | | /* When the result is not a sisd register or it is a long operation. */ | 488 | 18.4k | if (dst_size == 0 || dst_size == src_size << 1) | 489 | 3.67k | return 1; | 490 | 14.8k | else | 491 | 14.8k | return 0; | 492 | 18.4k | } |
Unexecuted instantiation: aarch64-dis-2.c:select_operand_for_scalar_size_field_coding Unexecuted instantiation: aarch64-opc.c:select_operand_for_scalar_size_field_coding Unexecuted instantiation: aarch64-opc-2.c:select_operand_for_scalar_size_field_coding |
493 | | |
494 | | /* Select the operand to do the encoding/decoding of the 'size:Q' fields in |
495 | | the AdvSIMD instructions. */ |
496 | | |
497 | | int aarch64_select_operand_for_sizeq_field_coding (const aarch64_opcode *); |
498 | | |
499 | | /* Miscellaneous. */ |
500 | | |
501 | | aarch64_insn aarch64_get_operand_modifier_value (enum aarch64_modifier_kind); |
502 | | enum aarch64_modifier_kind |
503 | | aarch64_get_operand_modifier_from_value (aarch64_insn, bool); |
504 | | |
505 | | |
506 | | bool aarch64_wide_constant_p (uint64_t, int, unsigned int *); |
507 | | bool aarch64_logical_immediate_p (uint64_t, int, aarch64_insn *); |
508 | | int aarch64_shrink_expanded_imm8 (uint64_t); |
509 | | |
510 | | /* Copy the content of INST->OPERANDS[SRC] to INST->OPERANDS[DST]. */ |
511 | | static inline void |
512 | | copy_operand_info (aarch64_inst *inst, int dst, int src) |
513 | 2.82k | { |
514 | 2.82k | assert (dst >= 0 && src >= 0 && dst < AARCH64_MAX_OPND_NUM |
515 | 2.82k | && src < AARCH64_MAX_OPND_NUM); |
516 | 2.82k | memcpy (&inst->operands[dst], &inst->operands[src], |
517 | 2.82k | sizeof (aarch64_opnd_info)); |
518 | 2.82k | inst->operands[dst].idx = dst; |
519 | 2.82k | } aarch64-dis.c:copy_operand_info Line | Count | Source | 513 | 2.82k | { | 514 | 2.82k | assert (dst >= 0 && src >= 0 && dst < AARCH64_MAX_OPND_NUM | 515 | 2.82k | && src < AARCH64_MAX_OPND_NUM); | 516 | 2.82k | memcpy (&inst->operands[dst], &inst->operands[src], | 517 | 2.82k | sizeof (aarch64_opnd_info)); | 518 | 2.82k | inst->operands[dst].idx = dst; | 519 | 2.82k | } |
Unexecuted instantiation: aarch64-dis-2.c:copy_operand_info Unexecuted instantiation: aarch64-opc.c:copy_operand_info Unexecuted instantiation: aarch64-opc-2.c:copy_operand_info |
520 | | |
521 | | /* A primitive log caculator. */ |
522 | | |
523 | | static inline unsigned int |
524 | | get_logsz (unsigned int size) |
525 | 332k | { |
526 | 332k | const unsigned char ls[16] = |
527 | 332k | {0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4}; |
528 | 332k | if (size > 16) |
529 | 0 | { |
530 | 0 | assert (0); |
531 | 0 | return -1; |
532 | 0 | } |
533 | 332k | assert (ls[size - 1] != (unsigned char)-1); |
534 | 332k | return ls[size - 1]; |
535 | 332k | } Line | Count | Source | 525 | 298k | { | 526 | 298k | const unsigned char ls[16] = | 527 | 298k | {0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4}; | 528 | 298k | if (size > 16) | 529 | 0 | { | 530 | 0 | assert (0); | 531 | 0 | return -1; | 532 | 0 | } | 533 | 298k | assert (ls[size - 1] != (unsigned char)-1); | 534 | 298k | return ls[size - 1]; | 535 | 298k | } |
Unexecuted instantiation: aarch64-dis-2.c:get_logsz Line | Count | Source | 525 | 34.3k | { | 526 | 34.3k | const unsigned char ls[16] = | 527 | 34.3k | {0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4}; | 528 | 34.3k | if (size > 16) | 529 | 0 | { | 530 | 0 | assert (0); | 531 | 0 | return -1; | 532 | 0 | } | 533 | 34.3k | assert (ls[size - 1] != (unsigned char)-1); | 534 | 34.3k | return ls[size - 1]; | 535 | 34.3k | } |
Unexecuted instantiation: aarch64-opc-2.c:get_logsz |
536 | | |
537 | | #endif /* OPCODES_AARCH64_OPC_H */ |