/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.4M | #define AARCH64_FIELD(lsb, width) ((aarch64_field) {width, lsb, false}) |
59 | | #define AARCH64_FIELD_CONST(val, width) ((aarch64_field) {width, val, true}) |
60 | 80.6k | #define AARCH64_FIELD_NIL ((aarch64_field) {0, 0, false}) |
61 | | |
62 | | #define FLD_CONST_0 AARCH64_FIELD_CONST (0, 1) |
63 | | #define FLD_CONST_00 AARCH64_FIELD_CONST (0, 2) |
64 | | #define FLD_CONST_01 AARCH64_FIELD_CONST (1, 2) |
65 | | #define FLD_CONST_1 AARCH64_FIELD_CONST (1, 1) |
66 | | |
67 | | /* Instruction fields. These defines are included to reduce the initial diff |
68 | | size, but the indirection should eventually be eliminated. */ |
69 | 37.9k | #define FLD_CRm AARCH64_FIELD( 8, 4) |
70 | 420 | #define FLD_CRm_dsb_nxs AARCH64_FIELD(10, 2) |
71 | 36.9k | #define FLD_CRn AARCH64_FIELD(12, 4) |
72 | 89.3k | #define FLD_H AARCH64_FIELD(11, 1) |
73 | 87.6k | #define FLD_L AARCH64_FIELD(21, 1) |
74 | 41.8k | #define FLD_M AARCH64_FIELD(20, 1) |
75 | 172k | #define FLD_N AARCH64_FIELD(22, 1) |
76 | 1.00M | #define FLD_Q AARCH64_FIELD(30, 1) |
77 | 742k | #define FLD_Rm AARCH64_FIELD(16, 5) |
78 | 1.12M | #define FLD_Rn AARCH64_FIELD( 5, 5) |
79 | 825k | #define FLD_Rt AARCH64_FIELD( 0, 5) |
80 | 109k | #define FLD_S AARCH64_FIELD(12, 1) |
81 | 1.06k | #define FLD_SM3_imm2 AARCH64_FIELD(12, 2) |
82 | 80.0k | #define FLD_SME_Q AARCH64_FIELD(16, 1) |
83 | 2.36k | #define FLD_SME_size_12 AARCH64_FIELD(12, 2) |
84 | 94.7k | #define FLD_SME_size_22 AARCH64_FIELD(22, 2) |
85 | 166 | #define FLD_SME_sz_23 AARCH64_FIELD(23, 1) |
86 | 8.82k | #define FLD_SME_tszh AARCH64_FIELD(22, 1) |
87 | 8.82k | #define FLD_SME_tszl AARCH64_FIELD(18, 3) |
88 | 183 | #define FLD_SVE_M_4 AARCH64_FIELD( 4, 1) |
89 | 16.2k | #define FLD_SVE_M_14 AARCH64_FIELD(14, 1) |
90 | 3.66k | #define FLD_SVE_M_16 AARCH64_FIELD(16, 1) |
91 | 101k | #define FLD_SVE_imm4 AARCH64_FIELD(16, 4) |
92 | 23.6k | #define FLD_SVE_imm6 AARCH64_FIELD(16, 6) |
93 | 2.25k | #define FLD_SVE_msz AARCH64_FIELD(10, 2) |
94 | 299 | #define FLD_SVE_size AARCH64_FIELD(17, 2) |
95 | 21.2k | #define FLD_SVE_sz AARCH64_FIELD(22, 1) |
96 | 8.24k | #define FLD_SVE_sz2 AARCH64_FIELD(30, 1) |
97 | 686 | #define FLD_SVE_sz3 AARCH64_FIELD(17, 1) |
98 | 182 | #define FLD_SVE_sz4 AARCH64_FIELD(14, 1) |
99 | 9.82k | #define FLD_SVE_tszh AARCH64_FIELD(22, 2) |
100 | 5.18k | #define FLD_SVE_tszl_8 AARCH64_FIELD( 8, 2) |
101 | 12.0k | #define FLD_SVE_tszl_19 AARCH64_FIELD(19, 2) |
102 | 6.24k | #define FLD_abc AARCH64_FIELD(16, 3) |
103 | 34.9k | #define FLD_asisdlso_opcode AARCH64_FIELD(13, 3) |
104 | 3.38k | #define FLD_cmode AARCH64_FIELD(12, 4) |
105 | 28.3k | #define FLD_cond AARCH64_FIELD(12, 4) |
106 | 44.8k | #define FLD_cond2 AARCH64_FIELD( 0, 4) |
107 | 6.24k | #define FLD_defgh AARCH64_FIELD( 5, 5) |
108 | 115k | #define FLD_hw AARCH64_FIELD(21, 2) |
109 | 196 | #define FLD_imm1_22 AARCH64_FIELD(22, 1) |
110 | | #define FLD_imm3_5 AARCH64_FIELD( 5, 3) |
111 | 60.8k | #define FLD_imm3_10 AARCH64_FIELD(10, 3) |
112 | 3.64k | #define FLD_imm3_19 AARCH64_FIELD(19, 3) |
113 | 792 | #define FLD_imm4_5 AARCH64_FIELD( 5, 4) |
114 | 3.32k | #define FLD_imm4_11 AARCH64_FIELD(11, 4) |
115 | 45.1k | #define FLD_imm5 AARCH64_FIELD(16, 5) |
116 | 570k | #define FLD_imm6_10 AARCH64_FIELD(10, 6) |
117 | 448k | #define FLD_imm12 AARCH64_FIELD(10, 12) |
118 | 36.4k | #define FLD_immb AARCH64_FIELD(16, 3) |
119 | 78.2k | #define FLD_immh AARCH64_FIELD(19, 4) |
120 | 941k | #define FLD_ldst_size AARCH64_FIELD(30, 2) |
121 | 17.1k | #define FLD_len AARCH64_FIELD(13, 2) |
122 | 37.6k | #define FLD_lse_sz AARCH64_FIELD(30, 1) |
123 | 36.9k | #define FLD_op0 AARCH64_FIELD(19, 2) |
124 | 37.2k | #define FLD_op1 AARCH64_FIELD(16, 3) |
125 | 37.5k | #define FLD_op2 AARCH64_FIELD( 5, 3) |
126 | 38.6k | #define FLD_opc AARCH64_FIELD(22, 2) |
127 | 260k | #define FLD_opc1 AARCH64_FIELD(23, 1) |
128 | 61.8k | #define FLD_opcode AARCH64_FIELD(12, 4) |
129 | 124k | #define FLD_option AARCH64_FIELD(13, 3) |
130 | 2.97k | #define FLD_scale AARCH64_FIELD(10, 6) |
131 | 2.46M | #define FLD_sf AARCH64_FIELD(31, 1) |
132 | 1.20M | #define FLD_shift AARCH64_FIELD(22, 2) |
133 | 754k | #define FLD_size AARCH64_FIELD(22, 2) |
134 | 3.20k | #define FLD_sz AARCH64_FIELD(22, 1) |
135 | 72.2k | #define FLD_type AARCH64_FIELD(22, 2) |
136 | 98.9k | #define FLD_vldst_size AARCH64_FIELD(10, 2) |
137 | | #define FLD_off2 AARCH64_FIELD( 5, 2) |
138 | | #define FLD_ol AARCH64_FIELD( 5, 1) |
139 | 18.6k | #define FLD_opc2 AARCH64_FIELD(12, 4) |
140 | 30.5k | #define FLD_rcpc3_size AARCH64_FIELD(30, 2) |
141 | | #define FLD_ZA8_1 AARCH64_FIELD( 8, 1) |
142 | | #define FLD_ZA7_2 AARCH64_FIELD( 7, 2) |
143 | | #define FLD_ZA6_3 AARCH64_FIELD( 6, 3) |
144 | | #define FLD_ZA5_4 AARCH64_FIELD( 5, 4) |
145 | | |
146 | | |
147 | | /* Operand description. */ |
148 | | |
149 | | struct aarch64_operand |
150 | | { |
151 | | enum aarch64_operand_class op_class; |
152 | | |
153 | | /* Name of the operand code; used mainly for the purpose of internal |
154 | | debugging. */ |
155 | | const char *name; |
156 | | |
157 | | unsigned int flags; |
158 | | |
159 | | /* The associated instruction bit-fields; no operand has more than 5 |
160 | | bit-fields */ |
161 | | aarch64_field fields[6]; |
162 | | |
163 | | /* Brief description */ |
164 | | const char *desc; |
165 | | }; |
166 | | |
167 | | typedef struct aarch64_operand aarch64_operand; |
168 | | |
169 | | extern const aarch64_operand aarch64_operands[]; |
170 | | |
171 | | enum err_type |
172 | | verify_constraints (const struct aarch64_inst *, const aarch64_insn, bfd_vma, |
173 | | bool, aarch64_operand_error *, aarch64_instr_sequence*); |
174 | | |
175 | | /* Operand flags. */ |
176 | | |
177 | | #define OPD_F_HAS_INSERTER 0x00000001 |
178 | 20.3M | #define OPD_F_HAS_EXTRACTOR 0x00000002 |
179 | 4.12M | #define OPD_F_SEXT 0x00000004 /* Require sign-extension. */ |
180 | 5.52M | #define OPD_F_SHIFT_BY_2 0x00000008 /* Need to left shift the field |
181 | | value by 2 to get the value |
182 | | of an immediate operand. */ |
183 | 168k | #define OPD_F_MAYBE_SP 0x00000010 /* May potentially be SP. */ |
184 | 1.03M | #define OPD_F_OD_MASK 0x000001e0 /* Operand-dependent data. */ |
185 | 1.03M | #define OPD_F_OD_LSB 5 |
186 | 247k | #define OPD_F_NO_ZR 0x00000200 /* ZR index not allowed. */ |
187 | 3.09M | #define OPD_F_SHIFT_BY_3 0x00000400 /* Need to left shift the field |
188 | | value by 3 to get the value |
189 | | of an immediate operand. */ |
190 | 3.09M | #define OPD_F_SHIFT_BY_4 0x00000800 /* Need to left shift the field |
191 | | value by 4 to get the value |
192 | | of an immediate operand. */ |
193 | 1.39M | #define OPD_F_UNSIGNED 0x00001000 /* Expect an unsigned value. */ |
194 | | |
195 | | |
196 | | /* Register flags. */ |
197 | | |
198 | | #undef F_DEPRECATED |
199 | 1.75k | #define F_DEPRECATED (1 << 0) /* Deprecated system register. */ |
200 | | |
201 | | /* (1 << 1) Unused. */ |
202 | | |
203 | | #undef F_HASXT |
204 | 1.23k | #define F_HASXT (1 << 2) /* System instruction register <Xt> |
205 | | operand. */ |
206 | | |
207 | | #undef F_REG_READ |
208 | 9.70k | #define F_REG_READ (1 << 3) /* Register can only be used to read values |
209 | | out of. */ |
210 | | |
211 | | #undef F_REG_WRITE |
212 | 11.9k | #define F_REG_WRITE (1 << 4) /* Register can only be written to but not |
213 | | read from. */ |
214 | | |
215 | | #undef F_REG_IN_CRM |
216 | 804 | #define F_REG_IN_CRM (1 << 5) /* Register extra encoding in CRm. */ |
217 | | |
218 | | #undef F_REG_ALIAS |
219 | 1.75k | #define F_REG_ALIAS (1 << 6) /* Register name aliases another. */ |
220 | | |
221 | | #undef F_REG_128 |
222 | 0 | #define F_REG_128 (1 << 7) /* System register implementable as 128-bit wide. */ |
223 | | |
224 | | #undef F_TLBID_XT |
225 | 942 | #define F_TLBID_XT (1 << 8) /* System instruction register <Xt> as optional operand. */ |
226 | | |
227 | | |
228 | | /* PSTATE field name for the MSR instruction this is encoded in "op1:op2:CRm". |
229 | | Part of CRm can be used to encode <pstatefield>. E.g. CRm[3:1] for SME. |
230 | | In order to set/get full PSTATE field name use flag F_REG_IN_CRM and below |
231 | | macros to encode and decode CRm encoding. |
232 | | */ |
233 | | #define PSTATE_ENCODE_CRM(val) (val << 6) |
234 | 69 | #define PSTATE_DECODE_CRM(flags) ((flags >> 6) & 0x0f) |
235 | | |
236 | | #undef F_IMM_IN_CRM |
237 | 261 | #define F_IMM_IN_CRM (1 << 10) /* Immediate extra encoding in CRm. */ |
238 | | |
239 | | /* Also CRm may contain, in addition to <pstatefield> immediate. |
240 | | E.g. CRm[0] <imm1> at bit 0 for SME. Use below macros to encode and decode |
241 | | immediate mask. |
242 | | */ |
243 | | #define PSTATE_ENCODE_CRM_IMM(mask) (mask << 11) |
244 | 0 | #define PSTATE_DECODE_CRM_IMM(mask) ((mask >> 11) & 0x0f) |
245 | | |
246 | | /* Helper macro to ENCODE CRm and its immediate. */ |
247 | | #define PSTATE_ENCODE_CRM_AND_IMM(CVAL,IMASK) \ |
248 | | (F_REG_IN_CRM | PSTATE_ENCODE_CRM(CVAL) \ |
249 | | | F_IMM_IN_CRM | PSTATE_ENCODE_CRM_IMM(IMASK)) |
250 | | |
251 | | /* Bits [15, 18] contain the maximum value for an immediate MSR. */ |
252 | | #define F_REG_MAX_VALUE(X) ((X) << 15) |
253 | 261 | #define F_GET_REG_MAX_VALUE(X) (((X) >> 15) & 0x0f) |
254 | | |
255 | | static inline bool |
256 | | operand_has_inserter (const aarch64_operand *operand) |
257 | 0 | { |
258 | 0 | return (operand->flags & OPD_F_HAS_INSERTER) != 0; |
259 | 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 |
260 | | |
261 | | static inline bool |
262 | | operand_has_extractor (const aarch64_operand *operand) |
263 | 20.3M | { |
264 | 20.3M | return (operand->flags & OPD_F_HAS_EXTRACTOR) != 0; |
265 | 20.3M | } aarch64-dis.c:operand_has_extractor Line | Count | Source | 263 | 20.3M | { | 264 | 20.3M | return (operand->flags & OPD_F_HAS_EXTRACTOR) != 0; | 265 | 20.3M | } |
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 |
266 | | |
267 | | static inline bool |
268 | | operand_need_sign_extension (const aarch64_operand *operand) |
269 | 4.12M | { |
270 | 4.12M | return (operand->flags & OPD_F_SEXT) != 0; |
271 | 4.12M | } aarch64-dis.c:operand_need_sign_extension Line | Count | Source | 269 | 4.12M | { | 270 | 4.12M | return (operand->flags & OPD_F_SEXT) != 0; | 271 | 4.12M | } |
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 |
272 | | |
273 | | static inline bool |
274 | | operand_need_shift_by_two (const aarch64_operand *operand) |
275 | 5.52M | { |
276 | 5.52M | return (operand->flags & OPD_F_SHIFT_BY_2) != 0; |
277 | 5.52M | } aarch64-dis.c:operand_need_shift_by_two Line | Count | Source | 275 | 4.12M | { | 276 | 4.12M | return (operand->flags & OPD_F_SHIFT_BY_2) != 0; | 277 | 4.12M | } |
Unexecuted instantiation: aarch64-dis-2.c:operand_need_shift_by_two aarch64-opc.c:operand_need_shift_by_two Line | Count | Source | 275 | 1.39M | { | 276 | 1.39M | return (operand->flags & OPD_F_SHIFT_BY_2) != 0; | 277 | 1.39M | } |
Unexecuted instantiation: aarch64-opc-2.c:operand_need_shift_by_two |
278 | | |
279 | | static inline bool |
280 | | operand_need_shift_by_three (const aarch64_operand *operand) |
281 | 3.09M | { |
282 | 3.09M | return (operand->flags & OPD_F_SHIFT_BY_3) != 0; |
283 | 3.09M | } aarch64-dis.c:operand_need_shift_by_three Line | Count | Source | 281 | 3.09M | { | 282 | 3.09M | return (operand->flags & OPD_F_SHIFT_BY_3) != 0; | 283 | 3.09M | } |
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 |
284 | | |
285 | | static inline bool |
286 | | operand_need_shift_by_four (const aarch64_operand *operand) |
287 | 3.09M | { |
288 | 3.09M | return (operand->flags & OPD_F_SHIFT_BY_4) != 0; |
289 | 3.09M | } aarch64-dis.c:operand_need_shift_by_four Line | Count | Source | 287 | 3.09M | { | 288 | 3.09M | return (operand->flags & OPD_F_SHIFT_BY_4) != 0; | 289 | 3.09M | } |
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 |
290 | | |
291 | | static inline bool |
292 | | operand_need_unsigned_offset (const aarch64_operand *operand) |
293 | 1.39M | { |
294 | 1.39M | return (operand->flags & OPD_F_UNSIGNED) != 0; |
295 | 1.39M | } 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 | 293 | 1.39M | { | 294 | 1.39M | return (operand->flags & OPD_F_UNSIGNED) != 0; | 295 | 1.39M | } |
Unexecuted instantiation: aarch64-opc-2.c:operand_need_unsigned_offset |
296 | | |
297 | | static inline bool |
298 | | operand_maybe_stack_pointer (const aarch64_operand *operand) |
299 | 168k | { |
300 | 168k | return (operand->flags & OPD_F_MAYBE_SP) != 0; |
301 | 168k | } 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 | 299 | 168k | { | 300 | 168k | return (operand->flags & OPD_F_MAYBE_SP) != 0; | 301 | 168k | } |
Unexecuted instantiation: aarch64-opc-2.c:operand_maybe_stack_pointer |
302 | | |
303 | | /* Return the value of the operand-specific data field (OPD_F_OD_MASK). */ |
304 | | static inline unsigned int |
305 | | get_operand_specific_data (const aarch64_operand *operand) |
306 | 1.03M | { |
307 | 1.03M | return (operand->flags & OPD_F_OD_MASK) >> OPD_F_OD_LSB; |
308 | 1.03M | } aarch64-dis.c:get_operand_specific_data Line | Count | Source | 306 | 553k | { | 307 | 553k | return (operand->flags & OPD_F_OD_MASK) >> OPD_F_OD_LSB; | 308 | 553k | } |
Unexecuted instantiation: aarch64-dis-2.c:get_operand_specific_data aarch64-opc.c:get_operand_specific_data Line | Count | Source | 306 | 482k | { | 307 | 482k | return (operand->flags & OPD_F_OD_MASK) >> OPD_F_OD_LSB; | 308 | 482k | } |
Unexecuted instantiation: aarch64-opc-2.c:get_operand_specific_data |
309 | | |
310 | | /* Return the width of field number N of operand *OPERAND. */ |
311 | | static inline unsigned |
312 | | get_operand_field_width (const aarch64_operand *operand, unsigned n) |
313 | 547 | { |
314 | 547 | assert (operand->fields[n].width != 0); |
315 | 547 | return operand->fields[n].width; |
316 | 547 | } aarch64-dis.c:get_operand_field_width Line | Count | Source | 313 | 390 | { | 314 | 390 | assert (operand->fields[n].width != 0); | 315 | 390 | return operand->fields[n].width; | 316 | 390 | } |
Unexecuted instantiation: aarch64-dis-2.c:get_operand_field_width aarch64-opc.c:get_operand_field_width Line | Count | Source | 313 | 157 | { | 314 | 157 | assert (operand->fields[n].width != 0); | 315 | 157 | return operand->fields[n].width; | 316 | 157 | } |
Unexecuted instantiation: aarch64-opc-2.c:get_operand_field_width |
317 | | |
318 | | /* Return the total width of the operand *OPERAND. */ |
319 | | static inline unsigned |
320 | | get_operand_fields_width (const aarch64_operand *operand) |
321 | 5.09M | { |
322 | 5.09M | int i = 0; |
323 | 5.09M | unsigned width = 0; |
324 | 11.2M | while (operand->fields[i].width != 0) |
325 | 6.16M | width += operand->fields[i++].width; |
326 | 5.09M | assert (width > 0 && width < 32); |
327 | 5.09M | return width; |
328 | 5.09M | } aarch64-dis.c:get_operand_fields_width Line | Count | Source | 321 | 1.56M | { | 322 | 1.56M | int i = 0; | 323 | 1.56M | unsigned width = 0; | 324 | 3.64M | while (operand->fields[i].width != 0) | 325 | 2.07M | width += operand->fields[i++].width; | 326 | 1.56M | assert (width > 0 && width < 32); | 327 | 1.56M | return width; | 328 | 1.56M | } |
Unexecuted instantiation: aarch64-dis-2.c:get_operand_fields_width aarch64-opc.c:get_operand_fields_width Line | Count | Source | 321 | 3.53M | { | 322 | 3.53M | int i = 0; | 323 | 3.53M | unsigned width = 0; | 324 | 7.62M | while (operand->fields[i].width != 0) | 325 | 4.08M | width += operand->fields[i++].width; | 326 | 3.53M | assert (width > 0 && width < 32); | 327 | 3.53M | return width; | 328 | 3.53M | } |
Unexecuted instantiation: aarch64-opc-2.c:get_operand_fields_width |
329 | | |
330 | | static inline const aarch64_operand * |
331 | | get_operand_from_code (enum aarch64_opnd code) |
332 | 4.93M | { |
333 | 4.93M | return aarch64_operands + code; |
334 | 4.93M | } 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 | 332 | 4.93M | { | 333 | 4.93M | return aarch64_operands + code; | 334 | 4.93M | } |
Unexecuted instantiation: aarch64-opc-2.c:get_operand_from_code |
335 | | |
336 | | /* Operand qualifier and operand constraint checking. */ |
337 | | |
338 | | bool aarch64_match_operands_constraint (aarch64_inst *, |
339 | | aarch64_operand_error *); |
340 | | |
341 | | /* Operand qualifier related functions. */ |
342 | | const char* aarch64_get_qualifier_name (aarch64_opnd_qualifier_t); |
343 | | unsigned char aarch64_get_qualifier_nelem (aarch64_opnd_qualifier_t); |
344 | | aarch64_insn aarch64_get_qualifier_standard_value (aarch64_opnd_qualifier_t); |
345 | | int aarch64_find_best_match (const aarch64_inst *, |
346 | | const aarch64_opnd_qualifier_seq_t *, |
347 | | int, aarch64_opnd_qualifier_t *, int *); |
348 | | |
349 | | static inline void |
350 | | reset_operand_qualifier (aarch64_inst *inst, int idx) |
351 | 69.4k | { |
352 | 69.4k | assert (idx >=0 && idx < aarch64_num_of_operands (inst->opcode)); |
353 | 69.4k | inst->operands[idx].qualifier = AARCH64_OPND_QLF_UNKNOWN; |
354 | 69.4k | } aarch64-dis.c:reset_operand_qualifier Line | Count | Source | 351 | 69.4k | { | 352 | 69.4k | assert (idx >=0 && idx < aarch64_num_of_operands (inst->opcode)); | 353 | 69.4k | inst->operands[idx].qualifier = AARCH64_OPND_QLF_UNKNOWN; | 354 | 69.4k | } |
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 |
355 | | |
356 | | /* Inline functions operating on instruction bit-field(s). */ |
357 | | |
358 | | /* Generate a mask that has WIDTH number of consecutive 1s. */ |
359 | | |
360 | | static inline aarch64_insn |
361 | | gen_mask (int width) |
362 | 33.8M | { |
363 | 33.8M | return ((aarch64_insn) 1 << width) - 1; |
364 | 33.8M | } Line | Count | Source | 362 | 33.8M | { | 363 | 33.8M | return ((aarch64_insn) 1 << width) - 1; | 364 | 33.8M | } |
Unexecuted instantiation: aarch64-dis-2.c:gen_mask Unexecuted instantiation: aarch64-opc.c:gen_mask Unexecuted instantiation: aarch64-opc-2.c:gen_mask |
365 | | |
366 | | /* LSB_REL is the relative location of the lsb in the sub field, starting from 0. */ |
367 | | static inline int |
368 | | gen_sub_field (aarch64_field field, int lsb_rel, int width, aarch64_field *ret) |
369 | 77.8k | { |
370 | 77.8k | if (lsb_rel < 0 || width <= 0 || lsb_rel + width > field.width) |
371 | 116 | return 0; |
372 | 77.7k | ret->num = field.num + lsb_rel; |
373 | 77.7k | ret->width = width; |
374 | 77.7k | return 1; |
375 | 77.8k | } aarch64-dis.c:gen_sub_field Line | Count | Source | 369 | 77.8k | { | 370 | 77.8k | if (lsb_rel < 0 || width <= 0 || lsb_rel + width > field.width) | 371 | 116 | return 0; | 372 | 77.7k | ret->num = field.num + lsb_rel; | 373 | 77.7k | ret->width = width; | 374 | 77.7k | return 1; | 375 | 77.8k | } |
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 |
376 | | |
377 | | /* Insert VALUE into FIELD of CODE. MASK can be zero or the base mask |
378 | | of the opcode. */ |
379 | | |
380 | | static inline void |
381 | | insert_field (aarch64_field field, aarch64_insn *code, |
382 | | aarch64_insn value, aarch64_insn mask) |
383 | 0 | { |
384 | 0 | assert (field.width < 32 && field.width >= 1 |
385 | 0 | && (field.is_const ? (field.num < 1 << field.width) |
386 | 0 | : (field.num + field.width <= 32))); |
387 | 0 | value &= gen_mask (field.width); |
388 | 0 | if (field.is_const) |
389 | 0 | { |
390 | 0 | assert (value == field.num); |
391 | 0 | return; |
392 | 0 | } |
393 | 0 | value <<= field.num; |
394 | 0 | /* In some opcodes, field can be part of the base opcode, e.g. the size |
395 | 0 | field in FADD. The following helps avoid corrupt the base opcode. */ |
396 | 0 | value &= ~mask; |
397 | 0 | *code |= value; |
398 | 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 |
399 | | |
400 | | /* Extract FIELD of CODE and return the value. MASK can be zero or the base |
401 | | mask of the opcode. */ |
402 | | |
403 | | static inline aarch64_insn |
404 | | extract_field (aarch64_field field, aarch64_insn code, |
405 | | aarch64_insn mask) |
406 | 34.0M | { |
407 | 34.0M | aarch64_insn value; |
408 | | /* Check for constant field. */ |
409 | 34.0M | if (field.is_const) |
410 | 183k | return field.num; |
411 | | |
412 | | /* Clear any bit that is a part of the base opcode. */ |
413 | 33.8M | code &= ~mask; |
414 | 33.8M | value = (code >> field.num) & gen_mask (field.width); |
415 | 33.8M | return value; |
416 | 34.0M | } aarch64-dis.c:extract_field Line | Count | Source | 406 | 34.0M | { | 407 | 34.0M | aarch64_insn value; | 408 | | /* Check for constant field. */ | 409 | 34.0M | if (field.is_const) | 410 | 183k | return field.num; | 411 | | | 412 | | /* Clear any bit that is a part of the base opcode. */ | 413 | 33.8M | code &= ~mask; | 414 | 33.8M | value = (code >> field.num) & gen_mask (field.width); | 415 | 33.8M | return value; | 416 | 34.0M | } |
Unexecuted instantiation: aarch64-dis-2.c:extract_field Unexecuted instantiation: aarch64-opc.c:extract_field Unexecuted instantiation: aarch64-opc-2.c:extract_field |
417 | | |
418 | | extern aarch64_insn |
419 | | extract_fields (aarch64_insn code, aarch64_insn mask, ...); |
420 | | |
421 | | /* Inline functions selecting operand to do the encoding/decoding for a |
422 | | certain instruction bit-field. */ |
423 | | |
424 | | /* Select the operand to do the encoding/decoding of the 'sf' field. |
425 | | The heuristic-based rule is that the result operand is respected more. */ |
426 | | |
427 | | static inline int |
428 | | select_operand_for_sf_field_coding (const aarch64_opcode *opcode) |
429 | 2.50M | { |
430 | 2.50M | int idx = -1; |
431 | 2.50M | if (opcode->iclass == fprcvtfloat2int) |
432 | 1.98k | return 0; |
433 | 2.50M | else if (opcode->iclass == fprcvtint2float) |
434 | 218 | return 1; |
435 | | |
436 | 2.50M | if (aarch64_get_operand_class (opcode->operands[0]) |
437 | 2.50M | == AARCH64_OPND_CLASS_INT_REG) |
438 | | /* normal case. */ |
439 | 2.50M | idx = 0; |
440 | 1.68k | else if (aarch64_get_operand_class (opcode->operands[1]) |
441 | 1.68k | == AARCH64_OPND_CLASS_INT_REG) |
442 | | /* e.g. float2fix. */ |
443 | 1.68k | idx = 1; |
444 | 0 | else |
445 | 0 | { assert (0); abort (); } |
446 | 2.50M | return idx; |
447 | 2.50M | } aarch64-dis.c:select_operand_for_sf_field_coding Line | Count | Source | 429 | 2.50M | { | 430 | 2.50M | int idx = -1; | 431 | 2.50M | if (opcode->iclass == fprcvtfloat2int) | 432 | 1.98k | return 0; | 433 | 2.50M | else if (opcode->iclass == fprcvtint2float) | 434 | 218 | return 1; | 435 | | | 436 | 2.50M | if (aarch64_get_operand_class (opcode->operands[0]) | 437 | 2.50M | == AARCH64_OPND_CLASS_INT_REG) | 438 | | /* normal case. */ | 439 | 2.50M | idx = 0; | 440 | 1.68k | else if (aarch64_get_operand_class (opcode->operands[1]) | 441 | 1.68k | == AARCH64_OPND_CLASS_INT_REG) | 442 | | /* e.g. float2fix. */ | 443 | 1.68k | idx = 1; | 444 | 0 | else | 445 | 0 | { assert (0); abort (); } | 446 | 2.50M | return idx; | 447 | 2.50M | } |
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 |
448 | | |
449 | | /* Select the operand to do the encoding/decoding of the 'type' field in |
450 | | the floating-point instructions. |
451 | | The heuristic-based rule is that the source operand is respected more. */ |
452 | | |
453 | | static inline int |
454 | | select_operand_for_fptype_field_coding (const aarch64_opcode *opcode) |
455 | 72.2k | { |
456 | 72.2k | int idx; |
457 | 72.2k | if (opcode->iclass == fprcvtfloat2int) |
458 | 1.98k | return 1; |
459 | 70.2k | else if (opcode->iclass == fprcvtint2float) |
460 | 218 | return 0; |
461 | | |
462 | 70.0k | if (aarch64_get_operand_class (opcode->operands[1]) |
463 | 70.0k | == AARCH64_OPND_CLASS_FP_REG) |
464 | | /* normal case. */ |
465 | 67.9k | idx = 1; |
466 | 2.08k | else if (aarch64_get_operand_class (opcode->operands[0]) |
467 | 2.08k | == AARCH64_OPND_CLASS_FP_REG) |
468 | | /* e.g. float2fix. */ |
469 | 2.08k | idx = 0; |
470 | 0 | else |
471 | 0 | { assert (0); abort (); } |
472 | 70.0k | return idx; |
473 | 70.0k | } aarch64-dis.c:select_operand_for_fptype_field_coding Line | Count | Source | 455 | 72.2k | { | 456 | 72.2k | int idx; | 457 | 72.2k | if (opcode->iclass == fprcvtfloat2int) | 458 | 1.98k | return 1; | 459 | 70.2k | else if (opcode->iclass == fprcvtint2float) | 460 | 218 | return 0; | 461 | | | 462 | 70.0k | if (aarch64_get_operand_class (opcode->operands[1]) | 463 | 70.0k | == AARCH64_OPND_CLASS_FP_REG) | 464 | | /* normal case. */ | 465 | 67.9k | idx = 1; | 466 | 2.08k | else if (aarch64_get_operand_class (opcode->operands[0]) | 467 | 2.08k | == AARCH64_OPND_CLASS_FP_REG) | 468 | | /* e.g. float2fix. */ | 469 | 2.08k | idx = 0; | 470 | 0 | else | 471 | 0 | { assert (0); abort (); } | 472 | 70.0k | return idx; | 473 | 70.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 |
474 | | |
475 | | /* Select the operand to do the encoding/decoding of the 'size' field in |
476 | | the AdvSIMD scalar instructions. |
477 | | The heuristic-based rule is that the destination operand is respected |
478 | | more. */ |
479 | | |
480 | | static inline int |
481 | | select_operand_for_scalar_size_field_coding (const aarch64_opcode *opcode) |
482 | 19.4k | { |
483 | 19.4k | int src_size = 0, dst_size = 0; |
484 | 19.4k | if (aarch64_get_operand_class (opcode->operands[0]) |
485 | 19.4k | == AARCH64_OPND_CLASS_SISD_REG) |
486 | 19.4k | dst_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][0]); |
487 | 19.4k | if (aarch64_get_operand_class (opcode->operands[1]) |
488 | 19.4k | == AARCH64_OPND_CLASS_SISD_REG) |
489 | 19.4k | src_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][1]); |
490 | 19.4k | if (src_size == dst_size && src_size == 0) |
491 | 0 | { assert (0); abort (); } |
492 | | /* When the result is not a sisd register or it is a long operation. */ |
493 | 19.4k | if (dst_size == 0 || dst_size == src_size << 1) |
494 | 4.08k | return 1; |
495 | 15.3k | else |
496 | 15.3k | return 0; |
497 | 19.4k | } aarch64-dis.c:select_operand_for_scalar_size_field_coding Line | Count | Source | 482 | 19.4k | { | 483 | 19.4k | int src_size = 0, dst_size = 0; | 484 | 19.4k | if (aarch64_get_operand_class (opcode->operands[0]) | 485 | 19.4k | == AARCH64_OPND_CLASS_SISD_REG) | 486 | 19.4k | dst_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][0]); | 487 | 19.4k | if (aarch64_get_operand_class (opcode->operands[1]) | 488 | 19.4k | == AARCH64_OPND_CLASS_SISD_REG) | 489 | 19.4k | src_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][1]); | 490 | 19.4k | if (src_size == dst_size && src_size == 0) | 491 | 0 | { assert (0); abort (); } | 492 | | /* When the result is not a sisd register or it is a long operation. */ | 493 | 19.4k | if (dst_size == 0 || dst_size == src_size << 1) | 494 | 4.08k | return 1; | 495 | 15.3k | else | 496 | 15.3k | return 0; | 497 | 19.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 |
498 | | |
499 | | /* Select the operand to do the encoding/decoding of the 'size:Q' fields in |
500 | | the AdvSIMD instructions. */ |
501 | | |
502 | | int aarch64_select_operand_for_sizeq_field_coding (const aarch64_opcode *); |
503 | | |
504 | | /* Miscellaneous. */ |
505 | | |
506 | | aarch64_insn aarch64_get_operand_modifier_value (enum aarch64_modifier_kind); |
507 | | enum aarch64_modifier_kind |
508 | | aarch64_get_operand_modifier_from_value (aarch64_insn, bool); |
509 | | |
510 | | |
511 | | bool aarch64_wide_constant_p (uint64_t, int, unsigned int *); |
512 | | bool aarch64_logical_immediate_p (uint64_t, int, aarch64_insn *); |
513 | | int aarch64_shrink_expanded_imm8 (uint64_t); |
514 | | |
515 | | /* Copy the content of INST->OPERANDS[SRC] to INST->OPERANDS[DST]. */ |
516 | | static inline void |
517 | | copy_operand_info (aarch64_inst *inst, int dst, int src) |
518 | 2.63k | { |
519 | 2.63k | assert (dst >= 0 && src >= 0 && dst < AARCH64_MAX_OPND_NUM |
520 | 2.63k | && src < AARCH64_MAX_OPND_NUM); |
521 | 2.63k | memcpy (&inst->operands[dst], &inst->operands[src], |
522 | 2.63k | sizeof (aarch64_opnd_info)); |
523 | 2.63k | inst->operands[dst].idx = dst; |
524 | 2.63k | } aarch64-dis.c:copy_operand_info Line | Count | Source | 518 | 2.63k | { | 519 | 2.63k | assert (dst >= 0 && src >= 0 && dst < AARCH64_MAX_OPND_NUM | 520 | 2.63k | && src < AARCH64_MAX_OPND_NUM); | 521 | 2.63k | memcpy (&inst->operands[dst], &inst->operands[src], | 522 | 2.63k | sizeof (aarch64_opnd_info)); | 523 | 2.63k | inst->operands[dst].idx = dst; | 524 | 2.63k | } |
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 |
525 | | |
526 | | /* A primitive log caculator. */ |
527 | | |
528 | | static inline unsigned int |
529 | | get_logsz (unsigned int size) |
530 | 348k | { |
531 | 348k | const unsigned char ls[16] = |
532 | 348k | {0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4}; |
533 | 348k | if (size > 16) |
534 | 0 | { |
535 | 0 | assert (0); |
536 | 0 | return -1; |
537 | 0 | } |
538 | 348k | assert (ls[size - 1] != (unsigned char)-1); |
539 | 348k | return ls[size - 1]; |
540 | 348k | } Line | Count | Source | 530 | 307k | { | 531 | 307k | const unsigned char ls[16] = | 532 | 307k | {0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4}; | 533 | 307k | if (size > 16) | 534 | 0 | { | 535 | 0 | assert (0); | 536 | 0 | return -1; | 537 | 0 | } | 538 | 307k | assert (ls[size - 1] != (unsigned char)-1); | 539 | 307k | return ls[size - 1]; | 540 | 307k | } |
Unexecuted instantiation: aarch64-dis-2.c:get_logsz Line | Count | Source | 530 | 40.2k | { | 531 | 40.2k | const unsigned char ls[16] = | 532 | 40.2k | {0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4}; | 533 | 40.2k | if (size > 16) | 534 | 0 | { | 535 | 0 | assert (0); | 536 | 0 | return -1; | 537 | 0 | } | 538 | 40.2k | assert (ls[size - 1] != (unsigned char)-1); | 539 | 40.2k | return ls[size - 1]; | 540 | 40.2k | } |
Unexecuted instantiation: aarch64-opc-2.c:get_logsz |
541 | | |
542 | | #endif /* OPCODES_AARCH64_OPC_H */ |