Line data Source code
1 : #ifdef __PLUMED_HAS_ASMJIT
2 : // This file is part of AsmJit project <https://asmjit.com>
3 : //
4 : // See asmjit.h or LICENSE.md for license and copyright information
5 : // SPDX-License-Identifier: Zlib
6 :
7 : #include "api-build_p.h"
8 : #if !defined(ASMJIT_NO_AARCH64)
9 :
10 : #include "codewriter_p.h"
11 : #include "cpuinfo.h"
12 : #include "emitterutils_p.h"
13 : #include "formatter.h"
14 : #include "logger.h"
15 : #include "misc_p.h"
16 : #include "support.h"
17 : #include "armformatter_p.h"
18 : #include "a64assembler.h"
19 : #include "a64emithelper_p.h"
20 : #include "a64instdb_p.h"
21 : #include "a64utils.h"
22 :
23 : ASMJIT_BEGIN_SUB_NAMESPACE(a64)
24 :
25 : // a64::Assembler - Cond
26 : // =====================
27 :
28 : static inline uint32_t condCodeToOpcodeCond(uint32_t cond) noexcept {
29 0 : return (uint32_t(cond) - 2u) & 0xFu;
30 : }
31 :
32 : // a64::Assembler - Bits
33 : // =====================
34 :
35 : template<typename T>
36 : static inline constexpr uint32_t B(const T& index) noexcept { return uint32_t(1u) << uint32_t(index); }
37 :
38 : static constexpr uint32_t kSP = Gp::kIdSp;
39 : static constexpr uint32_t kZR = Gp::kIdZr;
40 : static constexpr uint32_t kWX = InstDB::kWX;
41 :
42 : // a64::Assembler - ShiftOpToLdStOptMap
43 : // ====================================
44 :
45 : // Table that maps ShiftOp to OPT part in LD/ST (register) opcode.
46 : #define VALUE(index) index == uint32_t(ShiftOp::kUXTW) ? 2u : \
47 : index == uint32_t(ShiftOp::kLSL) ? 3u : \
48 : index == uint32_t(ShiftOp::kSXTW) ? 6u : \
49 : index == uint32_t(ShiftOp::kSXTX) ? 7u : 0xFF
50 : static const uint8_t armShiftOpToLdStOptMap[] = { ASMJIT_LOOKUP_TABLE_16(VALUE, 0) };
51 : #undef VALUE
52 :
53 : static inline constexpr uint32_t diff(RegType a, RegType b) noexcept {
54 0 : return uint32_t(a) - uint32_t(b);
55 : }
56 :
57 : // asmjit::a64::Assembler - SizeOp
58 : // ===============================
59 :
60 : //! Struct that contains Size (2 bits), Q flag, and S (scalar) flag. These values
61 : //! are used to encode Q, Size, and Scalar fields in an opcode.
62 : struct SizeOp {
63 : enum : uint8_t {
64 : k128BitShift = 0,
65 : kScalarShift = 1,
66 : kSizeShift = 2,
67 :
68 : kQ = uint8_t(1u << k128BitShift),
69 : kS = uint8_t(1u << kScalarShift),
70 :
71 : k00 = uint8_t(0 << kSizeShift),
72 : k01 = uint8_t(1 << kSizeShift),
73 : k10 = uint8_t(2 << kSizeShift),
74 : k11 = uint8_t(3 << kSizeShift),
75 :
76 : k00Q = k00 | kQ,
77 : k01Q = k01 | kQ,
78 : k10Q = k10 | kQ,
79 : k11Q = k11 | kQ,
80 :
81 : k00S = k00 | kS,
82 : k01S = k01 | kS,
83 : k10S = k10 | kS,
84 : k11S = k11 | kS,
85 :
86 : kInvalid = 0xFFu,
87 :
88 : // Masks used by SizeOpMap.
89 : kSzQ = (0x3u << kSizeShift) | kQ,
90 : kSzS = (0x3u << kSizeShift) | kS,
91 : kSzQS = (0x3u << kSizeShift) | kQ | kS
92 : };
93 :
94 : uint8_t value;
95 :
96 : inline bool isValid() const noexcept { return value != kInvalid; }
97 0 : inline void makeInvalid() noexcept { value = kInvalid; }
98 :
99 0 : inline uint32_t q() const noexcept { return (value >> k128BitShift) & 0x1u; }
100 0 : inline uint32_t qs() const noexcept { return ((value >> k128BitShift) | (value >> kScalarShift)) & 0x1u; }
101 0 : inline uint32_t scalar() const noexcept { return (value >> kScalarShift) & 0x1u; }
102 0 : inline uint32_t size() const noexcept { return (value >> kSizeShift) & 0x3u; }
103 :
104 : inline void decrementSize() noexcept {
105 : ASMJIT_ASSERT(size() > 0);
106 0 : value = uint8_t(value - (1u << kSizeShift));
107 0 : }
108 : };
109 :
110 : struct SizeOpTable {
111 : enum TableId : uint8_t {
112 : kTableBin = 0,
113 : kTableAny,
114 : kCount
115 : };
116 :
117 : // 40 elements for each combination.
118 : SizeOp array[(uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB) + 1) * 8];
119 : };
120 :
121 : #define VALUE_BIN(x) { \
122 : x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00 : \
123 : x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00Q : \
124 : x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00 : \
125 : x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00Q : SizeOp::kInvalid \
126 : }
127 :
128 : #define VALUE_ANY(x) { \
129 : x == (((uint32_t(RegType::kARM_VecB) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00S : \
130 : x == (((uint32_t(RegType::kARM_VecH) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k01S : \
131 : x == (((uint32_t(RegType::kARM_VecS) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k10S : \
132 : x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k11S : \
133 : x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00 : \
134 : x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00Q : \
135 : x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeH )) ? SizeOp::k01 : \
136 : x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeH )) ? SizeOp::k01Q : \
137 : x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeS )) ? SizeOp::k10 : \
138 : x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeS )) ? SizeOp::k10Q : \
139 : x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeD )) ? SizeOp::k11S : \
140 : x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeD )) ? SizeOp::k11Q : SizeOp::kInvalid \
141 : }
142 :
143 : static const SizeOpTable sizeOpTable[SizeOpTable::kCount] = {
144 : {{ ASMJIT_LOOKUP_TABLE_40(VALUE_BIN, 0) }},
145 : {{ ASMJIT_LOOKUP_TABLE_40(VALUE_ANY, 0) }}
146 : };
147 :
148 : #undef VALUE_ANY
149 : #undef VALUE_BIN
150 :
151 : struct SizeOpMap {
152 : uint8_t tableId;
153 : uint8_t sizeOpMask;
154 : uint16_t acceptMask;
155 : };
156 :
157 : static const constexpr SizeOpMap sizeOpMap[InstDB::kVO_Count] = {
158 : { // kVO_V_B:
159 : SizeOpTable::kTableBin, SizeOp::kQ , uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q))
160 : },
161 :
162 : { // kVO_V_BH:
163 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q))
164 : },
165 :
166 : { // kVO_V_BH_4S:
167 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10Q))
168 : },
169 :
170 : { // kVO_V_BHS:
171 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10) | B(SizeOp::k10Q))
172 : },
173 :
174 : { // kVO_V_BHS_D2:
175 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10) | B(SizeOp::k10Q) | B(SizeOp::k11Q))
176 : },
177 :
178 : { // kVO_V_HS:
179 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10) | B(SizeOp::k10Q))
180 : },
181 :
182 : { // kVO_V_S:
183 : SizeOpTable::kTableAny, SizeOp::kQ , uint16_t(B(SizeOp::k10) | B(SizeOp::k10Q))
184 : },
185 :
186 : { // kVO_V_B8H4:
187 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k01))
188 : },
189 :
190 : { // kVO_V_B8H4S2:
191 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k01) | B(SizeOp::k10))
192 : },
193 :
194 : { // kVO_V_B8D1:
195 : SizeOpTable::kTableAny, SizeOp::kSzQ , uint16_t(B(SizeOp::k00) | B(SizeOp::k11S))
196 : },
197 :
198 : { // kVO_V_H4S2:
199 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k01) | B(SizeOp::k10))
200 : },
201 :
202 : { // kVO_V_B16:
203 : SizeOpTable::kTableBin, SizeOp::kQ , uint16_t(B(SizeOp::k00Q))
204 : },
205 :
206 : { // kVO_V_B16H8:
207 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00Q) | B(SizeOp::k01Q))
208 : },
209 :
210 : { // kVO_V_B16H8S4:
211 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00Q) | B(SizeOp::k01Q) | B(SizeOp::k10Q))
212 : },
213 :
214 : { // kVO_V_B16D2:
215 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00Q) | B(SizeOp::k11Q))
216 : },
217 :
218 : { // kVO_V_H8S4:
219 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k01Q) | B(SizeOp::k10Q))
220 : },
221 :
222 : { // kVO_V_S4:
223 : SizeOpTable::kTableAny, 0 , uint16_t(B(SizeOp::k10Q))
224 : },
225 :
226 : { // kVO_V_D2:
227 : SizeOpTable::kTableAny, 0 , uint16_t(B(SizeOp::k11Q))
228 : },
229 :
230 : { // kVO_SV_BHS:
231 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k00S) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k01S) | B(SizeOp::k10) | B(SizeOp::k10Q) | B(SizeOp::k10S))
232 : },
233 :
234 : { // kVO_SV_B8H4S2:
235 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00S) | B(SizeOp::k01) | B(SizeOp::k01S) | B(SizeOp::k10) | B(SizeOp::k10S))
236 : },
237 :
238 : { // kVO_SV_HS:
239 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k01S) | B(SizeOp::k10) | B(SizeOp::k10Q) | B(SizeOp::k10S))
240 : },
241 :
242 : { // kVO_V_Any:
243 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10) | B(SizeOp::k10Q) | B(SizeOp::k11S) | B(SizeOp::k11Q))
244 : },
245 :
246 : { // kVO_SV_Any:
247 : SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k00S) |
248 : B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k01S) |
249 : B(SizeOp::k10) | B(SizeOp::k10Q) | B(SizeOp::k10S) |
250 : B(SizeOp::k11) | B(SizeOp::k11Q) | B(SizeOp::k11S))
251 : }
252 : };
253 :
254 0 : static const Operand_& significantSimdOp(const Operand_& o0, const Operand_& o1, uint32_t instFlags) noexcept {
255 0 : return !(instFlags & InstDB::kInstFlagLong) ? o0 : o1;
256 : }
257 :
258 0 : static inline SizeOp armElementTypeToSizeOp(uint32_t vecOpType, RegType regType, uint32_t elementType) noexcept {
259 : // Instruction data or Assembler is wrong if this triggers an assertion failure.
260 : ASMJIT_ASSERT(vecOpType < InstDB::kVO_Count);
261 : // ElementType uses 3 bits in the operand signature, it should never overflow.
262 : ASMJIT_ASSERT(elementType <= 0x7u);
263 :
264 : const SizeOpMap& map = sizeOpMap[vecOpType];
265 0 : const SizeOpTable& table = sizeOpTable[map.tableId];
266 :
267 0 : size_t index = (Support::min<uint32_t>(diff(regType, RegType::kARM_VecB), diff(RegType::kARM_VecV, RegType::kARM_VecB) + 1) << 3) | elementType;
268 0 : SizeOp op = table.array[index];
269 0 : SizeOp modifiedOp { uint8_t(op.value & map.sizeOpMask) };
270 :
271 0 : if (!Support::bitTest(map.acceptMask, op.value))
272 : modifiedOp.makeInvalid();
273 :
274 0 : return modifiedOp;
275 : }
276 :
277 : // a64::Assembler - Immediate Encoding Utilities (Integral)
278 : // ========================================================
279 :
280 : using Utils::LogicalImm;
281 :
282 : struct HalfWordImm {
283 : uint32_t hw;
284 : uint32_t inv;
285 : uint32_t imm;
286 : };
287 :
288 : struct LMHImm {
289 : uint32_t lm;
290 : uint32_t h;
291 : uint32_t maxRmId;
292 : };
293 :
294 0 : static inline uint32_t countZeroHalfWords64(uint64_t imm) noexcept {
295 0 : return uint32_t((imm & 0x000000000000FFFFu) == 0) +
296 0 : uint32_t((imm & 0x00000000FFFF0000u) == 0) +
297 0 : uint32_t((imm & 0x0000FFFF00000000u) == 0) +
298 0 : uint32_t((imm & 0xFFFF000000000000u) == 0) ;
299 : }
300 :
301 0 : static uint32_t encodeMovSequence32(uint32_t out[2], uint32_t imm, uint32_t rd, uint32_t x) noexcept {
302 : ASMJIT_ASSERT(rd <= 31);
303 :
304 0 : uint32_t kMovZ = 0b01010010100000000000000000000000 | (x << 31);
305 : uint32_t kMovN = 0b00010010100000000000000000000000;
306 : uint32_t kMovK = 0b01110010100000000000000000000000;
307 :
308 0 : if ((imm & 0xFFFF0000u) == 0x00000000u) {
309 0 : out[0] = kMovZ | (0 << 21) | ((imm & 0xFFFFu) << 5) | rd;
310 0 : return 1;
311 : }
312 :
313 0 : if ((imm & 0xFFFF0000u) == 0xFFFF0000u) {
314 0 : out[0] = kMovN | (0 << 21) | ((~imm & 0xFFFFu) << 5) | rd;
315 0 : return 1;
316 : }
317 :
318 0 : if ((imm & 0x0000FFFFu) == 0x00000000u) {
319 0 : out[0] = kMovZ | (1 << 21) | ((imm >> 16) << 5) | rd;
320 0 : return 1;
321 : }
322 :
323 0 : if ((imm & 0x0000FFFFu) == 0x0000FFFFu) {
324 0 : out[0] = kMovN | (1 << 21) | ((~imm >> 16) << 5) | rd;
325 0 : return 1;
326 : }
327 :
328 0 : out[0] = kMovZ | (0 << 21) | ((imm & 0xFFFFu) << 5) | rd;
329 0 : out[1] = kMovK | (1 << 21) | ((imm >> 16) << 5) | rd;
330 0 : return 2;
331 : }
332 :
333 0 : static uint32_t encodeMovSequence64(uint32_t out[4], uint64_t imm, uint32_t rd, uint32_t x) noexcept {
334 : ASMJIT_ASSERT(rd <= 31);
335 :
336 : uint32_t kMovZ = 0b11010010100000000000000000000000;
337 : uint32_t kMovN = 0b10010010100000000000000000000000;
338 : uint32_t kMovK = 0b11110010100000000000000000000000;
339 :
340 0 : if (imm <= 0xFFFFFFFFu)
341 0 : return encodeMovSequence32(out, uint32_t(imm), rd, x);
342 :
343 0 : uint32_t zhw = countZeroHalfWords64( imm);
344 0 : uint32_t ohw = countZeroHalfWords64(~imm);
345 :
346 0 : if (zhw >= ohw) {
347 : uint32_t op = kMovZ;
348 : uint32_t count = 0;
349 :
350 0 : for (uint32_t hwIndex = 0; hwIndex < 4; hwIndex++, imm >>= 16) {
351 0 : uint32_t hwImm = uint32_t(imm & 0xFFFFu);
352 0 : if (hwImm == 0)
353 0 : continue;
354 :
355 0 : out[count++] = op | (hwIndex << 21) | (hwImm << 5) | rd;
356 : op = kMovK;
357 : }
358 :
359 : // This should not happen - zero should be handled by encodeMovSequence32().
360 : ASMJIT_ASSERT(count > 0);
361 :
362 : return count;
363 : }
364 : else {
365 : uint32_t op = kMovN;
366 : uint32_t count = 0;
367 : uint32_t negMask = 0xFFFFu;
368 :
369 0 : for (uint32_t hwIndex = 0; hwIndex < 4; hwIndex++, imm >>= 16) {
370 0 : uint32_t hwImm = uint32_t(imm & 0xFFFFu);
371 0 : if (hwImm == 0xFFFFu)
372 0 : continue;
373 :
374 0 : out[count++] = op | (hwIndex << 21) | ((hwImm ^ negMask) << 5) | rd;
375 : op = kMovK;
376 : negMask = 0;
377 : }
378 :
379 0 : if (count == 0) {
380 0 : out[count++] = kMovN | ((0xFFFF ^ negMask) << 5) | rd;
381 : }
382 :
383 0 : return count;
384 : }
385 : }
386 :
387 0 : static inline bool encodeLMH(uint32_t sizeField, uint32_t elementIndex, LMHImm* out) noexcept {
388 0 : if (sizeField != 1 && sizeField != 2)
389 : return false;
390 :
391 0 : uint32_t hShift = 3u - sizeField;
392 : uint32_t lmShift = sizeField - 1u;
393 0 : uint32_t maxElementIndex = 15u >> sizeField;
394 :
395 0 : out->h = elementIndex >> hShift;
396 0 : out->lm = (elementIndex << lmShift) & 0x3u;
397 0 : out->maxRmId = (8u << sizeField) - 1;
398 :
399 0 : return elementIndex <= maxElementIndex;
400 : }
401 :
402 : // [.......A|B.......|.......C|D.......|.......E|F.......|.......G|H.......]
403 0 : static inline uint32_t encodeImm64ByteMaskToImm8(uint64_t imm) noexcept {
404 0 : return uint32_t(((imm >> (7 - 0)) & 0b00000011) | // [.......G|H.......]
405 0 : ((imm >> (23 - 2)) & 0b00001100) | // [.......E|F.......]
406 0 : ((imm >> (39 - 4)) & 0b00110000) | // [.......C|D.......]
407 0 : ((imm >> (55 - 6)) & 0b11000000)); // [.......A|B.......]
408 : }
409 :
410 : // a64::Assembler - Opcode
411 : // =======================
412 :
413 : //! Helper class to store and manipulate ARM opcode.
414 : struct Opcode {
415 : uint32_t v;
416 :
417 : enum Bits : uint32_t {
418 : kN = (1u << 22),
419 : kQ = (1u << 30),
420 : kX = (1u << 31)
421 : };
422 :
423 : // --------------------------------------------------------------------------
424 : // [Opcode Builder]
425 : // --------------------------------------------------------------------------
426 :
427 0 : inline uint32_t get() const noexcept { return v; }
428 0 : inline void reset(uint32_t value) noexcept { v = value; }
429 :
430 0 : inline bool hasQ() const noexcept { return (v & kQ) != 0; }
431 : inline bool hasX() const noexcept { return (v & kX) != 0; }
432 :
433 : template<typename T>
434 0 : inline Opcode& addImm(T value, uint32_t bitIndex) noexcept { return operator|=(uint32_t(value) << bitIndex); }
435 :
436 : template<typename T>
437 0 : inline Opcode& xorImm(T value, uint32_t bitIndex) noexcept { return operator^=(uint32_t(value) << bitIndex); }
438 :
439 : template<typename T, typename Condition>
440 : inline Opcode& addIf(T value, const Condition& condition) noexcept { return operator|=(condition ? uint32_t(value) : uint32_t(0)); }
441 :
442 0 : inline Opcode& addLogicalImm(const LogicalImm& logicalImm) noexcept {
443 0 : addImm(logicalImm.n, 22);
444 0 : addImm(logicalImm.r, 16);
445 0 : addImm(logicalImm.s, 10);
446 0 : return *this;
447 : }
448 :
449 0 : inline Opcode& addReg(uint32_t id, uint32_t bitIndex) noexcept { return operator|=((id & 31u) << bitIndex); }
450 : inline Opcode& addReg(const Operand_& op, uint32_t bitIndex) noexcept { return addReg(op.id(), bitIndex); }
451 :
452 : inline Opcode& operator=(uint32_t x) noexcept { v = x; return *this; }
453 : inline Opcode& operator&=(uint32_t x) noexcept { v &= x; return *this; }
454 0 : inline Opcode& operator|=(uint32_t x) noexcept { v |= x; return *this; }
455 0 : inline Opcode& operator^=(uint32_t x) noexcept { v ^= x; return *this; }
456 :
457 : inline uint32_t operator&(uint32_t x) const noexcept { return v & x; }
458 : inline uint32_t operator|(uint32_t x) const noexcept { return v | x; }
459 : inline uint32_t operator^(uint32_t x) const noexcept { return v ^ x; }
460 : };
461 :
462 : // a64::Assembler - Signature Utilities
463 : // ====================================
464 :
465 : // TODO: [ARM] Deprecate matchSignature.
466 : static inline bool matchSignature(const Operand_& o0, const Operand_& o1, uint32_t instFlags) noexcept {
467 0 : if (!(instFlags & (InstDB::kInstFlagLong | InstDB::kInstFlagNarrow)))
468 : return o0.signature() == o1.signature();
469 :
470 : // TODO: [ARM] Something smart to validate this.
471 : return true;
472 : }
473 :
474 : static inline bool matchSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2, uint32_t instFlags) noexcept {
475 0 : return matchSignature(o0, o1, instFlags) && o1.signature() == o2.signature();
476 : }
477 :
478 : static inline bool matchSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, uint32_t instFlags) noexcept {
479 0 : return matchSignature(o0, o1, instFlags) && o1.signature() == o2.signature() && o2.signature() == o3.signature();;
480 : }
481 :
482 : // Memory must be either:
483 : // 1. Absolute address, which will be converted to relative.
484 : // 2. Relative displacement (Label).
485 : // 3. Base register + either offset or index.
486 0 : static inline bool armCheckMemBaseIndexRel(const Mem& mem) noexcept {
487 : // Allowed base types (Nothing, Label, and GpX).
488 : constexpr uint32_t kBaseMask = B(0) |
489 : B(RegType::kLabelTag) |
490 : B(RegType::kARM_GpX);
491 :
492 : // Allowed index types (Nothing, GpW, and GpX).
493 : constexpr uint32_t kIndexMask = B(0) |
494 : B(RegType::kARM_GpW) |
495 : B(RegType::kARM_GpX) ;
496 :
497 : RegType baseType = mem.baseType();
498 : RegType indexType = mem.indexType();
499 :
500 0 : if (!Support::bitTest(kBaseMask, baseType))
501 : return false;
502 :
503 0 : if (baseType > RegType::kLabelTag) {
504 : // Index allows either GpW or GpX.
505 0 : if (!Support::bitTest(kIndexMask, indexType))
506 : return false;
507 :
508 0 : if (indexType == RegType::kNone)
509 : return true;
510 : else
511 0 : return !mem.hasOffset();
512 : }
513 : else {
514 : // No index register allowed if this is a PC relative address (literal).
515 0 : return indexType == RegType::kNone;
516 : }
517 : }
518 :
519 : struct EncodeFpOpcodeBits {
520 : uint32_t sizeMask;
521 : uint32_t mask[3];
522 : };
523 :
524 0 : static inline bool pickFpOpcode(const Vec& reg, uint32_t sOp, uint32_t sHf, uint32_t vOp, uint32_t vHf, Opcode* opcode, uint32_t* szOut) noexcept {
525 : static constexpr uint32_t kQBitIndex = 30;
526 :
527 : static const EncodeFpOpcodeBits szBits[InstDB::kHF_Count] = {
528 : { B(2) | B(1) , { 0u , 0u, B(22) } },
529 : { B(2) | B(1) | B(0), { 0u , 0u, 0u } },
530 : { B(2) | B(1) | B(0), { B(23) | B(22) , 0u, B(22) } },
531 : { B(2) | B(1) | B(0), { B(22) | B(20) | B(19) , 0u, B(22) } },
532 : { B(2) | B(1) | B(0), { B(22) | B(21) | B(15) | B(14), 0u, B(22) } },
533 : { B(2) | B(1) | B(0), { B(23) , 0u, B(22) } }
534 : };
535 :
536 0 : if (!reg.hasElementType()) {
537 : // Scalar operation [HSD].
538 : uint32_t sz = diff(reg.type(), RegType::kARM_VecH);
539 0 : if (sz > 2u || !Support::bitTest(szBits[sHf].sizeMask, sz))
540 : return false;
541 :
542 0 : opcode->reset(szBits[sHf].mask[sz] ^ sOp);
543 0 : *szOut = sz;
544 0 : return sOp != 0;
545 : }
546 : else {
547 : // Vector operation [HSD].
548 : uint32_t q = diff(reg.type(), RegType::kARM_VecD);
549 0 : uint32_t sz = reg.elementType() - Vec::kElementTypeH;
550 :
551 0 : if (q > 1u || sz > 2u || !Support::bitTest(szBits[vHf].sizeMask, sz))
552 : return false;
553 :
554 0 : opcode->reset(szBits[vHf].mask[sz] ^ (vOp | (q << kQBitIndex)));
555 0 : *szOut = sz;
556 0 : return vOp != 0;
557 : }
558 : }
559 :
560 : static inline bool pickFpOpcode(const Vec& reg, uint32_t sOp, uint32_t sHf, uint32_t vOp, uint32_t vHf, Opcode* opcode) noexcept {
561 : uint32_t sz;
562 0 : return pickFpOpcode(reg, sOp, sHf, vOp, vHf, opcode, &sz);
563 : }
564 :
565 : // a64::Assembler - Operand Checks
566 : // ===============================
567 :
568 : // Checks whether all operands have the same signature.
569 : static inline bool checkSignature(const Operand_& o0, const Operand_& o1) noexcept {
570 : return o0.signature() == o1.signature();
571 : }
572 :
573 : static inline bool checkSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept {
574 0 : return o0.signature() == o1.signature() &&
575 : o1.signature() == o2.signature();
576 : }
577 :
578 : static inline bool checkSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept {
579 0 : return o0.signature() == o1.signature() &&
580 0 : o1.signature() == o2.signature() &&
581 : o2.signature() == o3.signature();
582 : }
583 :
584 : // Checks whether the register is GP register of the allowed types.
585 : //
586 : // Allowed is a 2-bit mask, where the first bits allows GpW and the second bit
587 : // allows GpX. These bits are usually stored within the instruction, but could
588 : // be also hardcoded in the assembler for instructions where GP types are not
589 : // selectable.
590 : static inline bool checkGpType(const Operand_& op, uint32_t allowed) noexcept {
591 : RegType type = op.as<Reg>().type();
592 0 : return Support::bitTest(allowed << uint32_t(RegType::kARM_GpW), type);
593 : }
594 :
595 : static inline bool checkGpType(const Operand_& op, uint32_t allowed, uint32_t* x) noexcept {
596 : // NOTE: We set 'x' to one only when GpW is allowed, otherwise the X is part
597 : // of the opcode and we cannot set it. This is why this works without requiring
598 : // additional logic.
599 : RegType type = op.as<Reg>().type();
600 0 : *x = diff(type, RegType::kARM_GpW) & allowed;
601 0 : return Support::bitTest(allowed << uint32_t(RegType::kARM_GpW), type);
602 : }
603 :
604 0 : static inline bool checkGpType(const Operand_& o0, const Operand_& o1, uint32_t allowed, uint32_t* x) noexcept {
605 0 : return checkGpType(o0, allowed, x) && checkSignature(o0, o1);
606 : }
607 :
608 0 : static inline bool checkGpType(const Operand_& o0, const Operand_& o1, const Operand_& o2, uint32_t allowed, uint32_t* x) noexcept {
609 0 : return checkGpType(o0, allowed, x) && checkSignature(o0, o1, o2);
610 : }
611 :
612 : static inline bool checkGpId(const Operand_& op, uint32_t hiId = kZR) noexcept {
613 : uint32_t id = op.as<Reg>().id();
614 0 : return id < 31u || id == hiId;
615 : }
616 :
617 : static inline bool checkGpId(const Operand_& o0, const Operand_& o1, uint32_t hiId = kZR) noexcept {
618 : uint32_t id0 = o0.as<Reg>().id();
619 : uint32_t id1 = o1.as<Reg>().id();
620 :
621 0 : return (id0 < 31u || id0 == hiId) && (id1 < 31u || id1 == hiId);
622 : }
623 :
624 0 : static inline bool checkGpId(const Operand_& o0, const Operand_& o1, const Operand_& o2, uint32_t hiId = kZR) noexcept {
625 : uint32_t id0 = o0.as<Reg>().id();
626 : uint32_t id1 = o1.as<Reg>().id();
627 : uint32_t id2 = o2.as<Reg>().id();
628 :
629 0 : return (id0 < 31u || id0 == hiId) && (id1 < 31u || id1 == hiId) && (id2 < 31u || id2 == hiId);
630 : }
631 :
632 : static inline bool checkVecId(const Operand_& op) noexcept {
633 : uint32_t id = op.as<Reg>().id();
634 : return id <= 31u;
635 : }
636 :
637 : static inline bool checkVecId(const Operand_& o0, const Operand_& o1) noexcept {
638 : uint32_t id0 = o0.as<Reg>().id();
639 : uint32_t id1 = o1.as<Reg>().id();
640 :
641 0 : return (id0 | id1) <= 31u;
642 : }
643 :
644 : /* Unused at the moment.
645 : static inline bool checkVecId(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept {
646 : uint32_t id0 = o0.as<Reg>().id();
647 : uint32_t id1 = o1.as<Reg>().id();
648 : uint32_t id2 = o2.as<Reg>().id();
649 :
650 : return (id0 | id1 | id2) <= 31u;
651 : }
652 :
653 : static inline bool checkVecId(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept {
654 : uint32_t id0 = o0.as<Reg>().id();
655 : uint32_t id1 = o1.as<Reg>().id();
656 : uint32_t id2 = o2.as<Reg>().id();
657 : uint32_t id3 = o3.as<Reg>().id();
658 :
659 : return (id0 | id1 | id2 | id3) <= 31u;
660 : }
661 : */
662 :
663 : static inline bool checkMemBase(const Mem& mem) noexcept {
664 0 : return mem.baseType() == RegType::kARM_GpX && mem.baseId() <= 31;
665 : }
666 :
667 : static inline bool checkEven(const Operand_& o0, const Operand_& o1) noexcept {
668 0 : return ((o0.id() | o1.id()) & 1) == 0;
669 : }
670 :
671 : static inline bool checkConsecutive(const Operand_& o0, const Operand_& o1) noexcept {
672 0 : return ((o0.id() + 1u) & 0x1Fu) == o1.id();
673 : }
674 :
675 : static inline bool checkConsecutive(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept {
676 0 : return ((o0.id() + 1u) & 0x1Fu) == o1.id() &&
677 0 : ((o0.id() + 2u) & 0x1Fu) == o2.id();
678 : }
679 :
680 0 : static inline bool checkConsecutive(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept {
681 0 : return ((o0.id() + 1u) & 0x1Fu) == o1.id() &&
682 0 : ((o0.id() + 2u) & 0x1Fu) == o2.id() &&
683 0 : ((o0.id() + 3u) & 0x1Fu) == o3.id();
684 : }
685 :
686 : // a64::Assembler - CheckReg
687 : // =========================
688 :
689 : #define V(index) (index == uint32_t(RegType::kARM_GpW) ? Gp::kIdZr : \
690 : index == uint32_t(RegType::kARM_GpX) ? Gp::kIdZr : \
691 : index == uint32_t(RegType::kARM_VecB) ? 31u : \
692 : index == uint32_t(RegType::kARM_VecH) ? 31u : \
693 : index == uint32_t(RegType::kARM_VecS) ? 31u : \
694 : index == uint32_t(RegType::kARM_VecD) ? 31u : \
695 : index == uint32_t(RegType::kARM_VecV) ? 31u : 0)
696 : static const Support::Array<uint8_t, 32> commonHiRegIdOfType = {{
697 : ASMJIT_LOOKUP_TABLE_32(V, 0)
698 : }};
699 : #undef V
700 :
701 : static inline bool checkValidRegs(const Operand_& o0) noexcept {
702 0 : return ((o0.id() < 31) | (o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()]));
703 : }
704 :
705 0 : static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1) noexcept {
706 0 : return ((o0.id() < 31) | (o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])) &
707 0 : ((o1.id() < 31) | (o1.id() == commonHiRegIdOfType[o1.as<Reg>().type()])) ;
708 : }
709 :
710 0 : static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept {
711 0 : return ((o0.id() < 31) | (o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])) &
712 0 : ((o1.id() < 31) | (o1.id() == commonHiRegIdOfType[o1.as<Reg>().type()])) &
713 0 : ((o2.id() < 31) | (o2.id() == commonHiRegIdOfType[o2.as<Reg>().type()])) ;
714 : }
715 :
716 0 : static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept {
717 0 : return ((o0.id() < 31) | (o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])) &
718 0 : ((o1.id() < 31) | (o1.id() == commonHiRegIdOfType[o1.as<Reg>().type()])) &
719 0 : ((o2.id() < 31) | (o2.id() == commonHiRegIdOfType[o2.as<Reg>().type()])) &
720 0 : ((o3.id() < 31) | (o3.id() == commonHiRegIdOfType[o3.as<Reg>().type()])) ;
721 : }
722 :
723 : // a64::Assembler - Construction & Destruction
724 : // ===========================================
725 :
726 0 : Assembler::Assembler(CodeHolder* code) noexcept : BaseAssembler() {
727 0 : _archMask = uint64_t(1) << uint32_t(Arch::kAArch64);
728 0 : assignEmitterFuncs(this);
729 :
730 0 : if (code)
731 0 : code->attach(this);
732 0 : }
733 :
734 0 : Assembler::~Assembler() noexcept {}
735 :
736 : // a64::Assembler - Emit
737 : // =====================
738 :
739 : #define ENC_OPS1(OP0) \
740 : (uint32_t(OperandType::k##OP0))
741 :
742 : #define ENC_OPS2(OP0, OP1) \
743 : (uint32_t(OperandType::k##OP0) + \
744 : (uint32_t(OperandType::k##OP1) << 3))
745 :
746 : #define ENC_OPS3(OP0, OP1, OP2) \
747 : (uint32_t(OperandType::k##OP0) + \
748 : (uint32_t(OperandType::k##OP1) << 3) + \
749 : (uint32_t(OperandType::k##OP2) << 6))
750 :
751 : #define ENC_OPS4(OP0, OP1, OP2, OP3) \
752 : (uint32_t(OperandType::k##OP0) + \
753 : (uint32_t(OperandType::k##OP1) << 3) + \
754 : (uint32_t(OperandType::k##OP2) << 6) + \
755 : (uint32_t(OperandType::k##OP3) << 9))
756 :
757 0 : Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) {
758 : // Logging/Validation/Error.
759 : constexpr InstOptions kRequiresSpecialHandling = InstOptions::kReserved;
760 :
761 : Error err;
762 : CodeWriter writer(this);
763 :
764 : // Combine all instruction options and also check whether the instruction
765 : // is valid. All options that require special handling (including invalid
766 : // instruction) are handled by the next branch.
767 0 : InstOptions options = InstOptions(instId - 1 >= Inst::_kIdCount - 1) | InstOptions((size_t)(_bufferEnd - writer.cursor()) < 4) | instOptions() | forcedInstOptions();
768 :
769 : CondCode instCC = BaseInst::extractARMCondCode(instId);
770 0 : instId = instId & uint32_t(InstIdParts::kRealId);
771 :
772 0 : if (instId >= Inst::_kIdCount)
773 : instId = 0;
774 :
775 : const InstDB::InstInfo* instInfo = &InstDB::_instInfoTable[instId];
776 0 : uint32_t encodingIndex = instInfo->_encodingDataIndex;
777 :
778 : Opcode opcode;
779 : uint32_t isign4;
780 : uint32_t instFlags;
781 :
782 : const Operand_& o3 = opExt[EmitterUtils::kOp3];
783 : const Operand_* rmRel = nullptr;
784 :
785 : uint32_t multipleOpData[4];
786 : uint32_t multipleOpCount;
787 :
788 : // These are only used when instruction uses a relative displacement.
789 : OffsetFormat offsetFormat; // Offset format.
790 : uint64_t offsetValue; // Offset value (if known).
791 :
792 0 : if (ASMJIT_UNLIKELY(Support::test(options, kRequiresSpecialHandling))) {
793 0 : if (ASMJIT_UNLIKELY(!_code))
794 0 : return reportError(DebugUtils::errored(kErrorNotInitialized));
795 :
796 : // Unknown instruction.
797 0 : if (ASMJIT_UNLIKELY(instId == 0))
798 0 : goto InvalidInstruction;
799 :
800 : // Condition code can only be used with 'B' instruction.
801 0 : if (ASMJIT_UNLIKELY(instCC != CondCode::kAL && instId != Inst::kIdB))
802 0 : goto InvalidInstruction;
803 :
804 : // Grow request, happens rarely.
805 : err = writer.ensureSpace(this, 4);
806 0 : if (ASMJIT_UNLIKELY(err))
807 0 : goto Failed;
808 :
809 : #ifndef ASMJIT_NO_VALIDATION
810 : // Strict validation.
811 0 : if (hasDiagnosticOption(DiagnosticOptions::kValidateAssembler)) {
812 : Operand_ opArray[Globals::kMaxOpCount];
813 : EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt);
814 :
815 0 : err = _funcs.validate(arch(), BaseInst(instId, options, _extraReg), opArray, Globals::kMaxOpCount, ValidationFlags::kNone);
816 0 : if (ASMJIT_UNLIKELY(err))
817 0 : goto Failed;
818 : }
819 : #endif
820 : }
821 :
822 : // Signature of the first 4 operands.
823 0 : isign4 = (uint32_t(o0.opType()) ) +
824 0 : (uint32_t(o1.opType()) << 3) +
825 0 : (uint32_t(o2.opType()) << 6) +
826 0 : (uint32_t(o3.opType()) << 9);
827 : instFlags = instInfo->flags();
828 :
829 0 : switch (instInfo->_encoding) {
830 : // ------------------------------------------------------------------------
831 : // [Base - Universal]
832 : // ------------------------------------------------------------------------
833 :
834 0 : case InstDB::kEncodingBaseOp: {
835 : const InstDB::EncodingData::BaseOp& opData = InstDB::EncodingData::baseOp[encodingIndex];
836 :
837 0 : if (isign4 == 0) {
838 0 : opcode.reset(opData.opcode);
839 0 : goto EmitOp;
840 : }
841 :
842 : break;
843 : }
844 :
845 0 : case InstDB::kEncodingBaseOpImm: {
846 : const InstDB::EncodingData::BaseOpImm& opData = InstDB::EncodingData::baseOpImm[encodingIndex];
847 :
848 0 : if (isign4 == ENC_OPS1(Imm)) {
849 : uint64_t imm = o0.as<Imm>().valueAs<uint64_t>();
850 0 : uint32_t immMax = 1u << opData.immBits;
851 :
852 0 : if (imm >= immMax)
853 0 : goto InvalidImmediate;
854 :
855 0 : opcode.reset(opData.opcode);
856 0 : opcode.addImm(imm, opData.immOffset);
857 0 : goto EmitOp;
858 : }
859 :
860 : break;
861 : }
862 :
863 0 : case InstDB::kEncodingBaseR: {
864 : const InstDB::EncodingData::BaseR& opData = InstDB::EncodingData::baseR[encodingIndex];
865 :
866 0 : if (isign4 == ENC_OPS1(Reg)) {
867 0 : if (!checkGpType(o0, opData.rType))
868 0 : goto InvalidInstruction;
869 :
870 0 : if (!checkGpId(o0, opData.rHiId))
871 0 : goto InvalidPhysId;
872 :
873 0 : opcode.reset(opData.opcode);
874 0 : opcode.addReg(o0, opData.rShift);
875 0 : goto EmitOp;
876 : }
877 :
878 : break;
879 : }
880 :
881 0 : case InstDB::kEncodingBaseRR: {
882 : const InstDB::EncodingData::BaseRR& opData = InstDB::EncodingData::baseRR[encodingIndex];
883 :
884 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
885 : uint32_t x;
886 0 : if (!checkGpType(o0, opData.aType, &x))
887 0 : goto InvalidInstruction;
888 :
889 0 : if (!checkGpType(o1, opData.bType))
890 0 : goto InvalidInstruction;
891 :
892 0 : if (opData.uniform && !checkSignature(o0, o1))
893 0 : goto InvalidInstruction;
894 :
895 0 : if (!checkGpId(o0, opData.aHiId))
896 0 : goto InvalidPhysId;
897 :
898 0 : if (!checkGpId(o1, opData.bHiId))
899 0 : goto InvalidPhysId;
900 :
901 0 : opcode.reset(opData.opcode);
902 : opcode.addImm(x, 31);
903 0 : opcode.addReg(o1, opData.bShift);
904 0 : opcode.addReg(o0, opData.aShift);
905 0 : goto EmitOp;
906 : }
907 :
908 : break;
909 : }
910 :
911 0 : case InstDB::kEncodingBaseRRR: {
912 : const InstDB::EncodingData::BaseRRR& opData = InstDB::EncodingData::baseRRR[encodingIndex];
913 :
914 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
915 : uint32_t x;
916 0 : if (!checkGpType(o0, opData.aType, &x))
917 0 : goto InvalidInstruction;
918 :
919 0 : if (!checkGpType(o1, opData.bType))
920 0 : goto InvalidInstruction;
921 :
922 0 : if (!checkGpType(o2, opData.cType))
923 0 : goto InvalidInstruction;
924 :
925 0 : if (opData.uniform && !checkSignature(o0, o1, o2))
926 0 : goto InvalidInstruction;
927 :
928 0 : if (!checkGpId(o0, opData.aHiId))
929 0 : goto InvalidPhysId;
930 :
931 0 : if (!checkGpId(o1, opData.bHiId))
932 0 : goto InvalidPhysId;
933 :
934 0 : if (!checkGpId(o2, opData.cHiId))
935 0 : goto InvalidPhysId;
936 :
937 : opcode.reset(opData.opcode());
938 : opcode.addImm(x, 31);
939 : opcode.addReg(o2, 16);
940 : opcode.addReg(o1, 5);
941 : opcode.addReg(o0, 0);
942 0 : goto EmitOp;
943 : }
944 :
945 : break;
946 : }
947 :
948 0 : case InstDB::kEncodingBaseRRRR: {
949 : const InstDB::EncodingData::BaseRRRR& opData = InstDB::EncodingData::baseRRRR[encodingIndex];
950 :
951 0 : if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
952 : uint32_t x;
953 0 : if (!checkGpType(o0, opData.aType, &x))
954 0 : goto InvalidInstruction;
955 :
956 0 : if (!checkGpType(o1, opData.bType))
957 0 : goto InvalidInstruction;
958 :
959 0 : if (!checkGpType(o2, opData.cType))
960 0 : goto InvalidInstruction;
961 :
962 0 : if (!checkGpType(o3, opData.dType))
963 0 : goto InvalidInstruction;
964 :
965 0 : if (opData.uniform && !checkSignature(o0, o1, o2, o3))
966 0 : goto InvalidInstruction;
967 :
968 0 : if (!checkGpId(o0, opData.aHiId))
969 0 : goto InvalidPhysId;
970 :
971 0 : if (!checkGpId(o1, opData.bHiId))
972 0 : goto InvalidPhysId;
973 :
974 0 : if (!checkGpId(o2, opData.cHiId))
975 0 : goto InvalidPhysId;
976 :
977 0 : if (!checkGpId(o3, opData.dHiId))
978 0 : goto InvalidPhysId;
979 :
980 : opcode.reset(opData.opcode());
981 : opcode.addImm(x, 31);
982 : opcode.addReg(o2, 16);
983 : opcode.addReg(o3, 10);
984 : opcode.addReg(o1, 5);
985 : opcode.addReg(o0, 0);
986 0 : goto EmitOp;
987 : }
988 :
989 : break;
990 : }
991 :
992 0 : case InstDB::kEncodingBaseRRII: {
993 : const InstDB::EncodingData::BaseRRII& opData = InstDB::EncodingData::baseRRII[encodingIndex];
994 :
995 0 : if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
996 0 : if (!checkGpType(o0, opData.aType))
997 0 : goto InvalidInstruction;
998 :
999 0 : if (!checkGpType(o1, opData.bType))
1000 0 : goto InvalidInstruction;
1001 :
1002 0 : if (!checkGpId(o0, opData.aHiId))
1003 0 : goto InvalidPhysId;
1004 :
1005 0 : if (!checkGpId(o1, opData.bHiId))
1006 0 : goto InvalidPhysId;
1007 :
1008 0 : if (o2.as<Imm>().valueAs<uint64_t>() >= Support::bitMask(opData.aImmSize + opData.aImmDiscardLsb) ||
1009 0 : o3.as<Imm>().valueAs<uint64_t>() >= Support::bitMask(opData.bImmSize + opData.bImmDiscardLsb))
1010 0 : goto InvalidImmediate;
1011 :
1012 0 : uint32_t aImm = o2.as<Imm>().valueAs<uint32_t>() >> opData.aImmDiscardLsb;
1013 0 : uint32_t bImm = o3.as<Imm>().valueAs<uint32_t>() >> opData.bImmDiscardLsb;
1014 :
1015 0 : if ((aImm << opData.aImmDiscardLsb) != o2.as<Imm>().valueAs<uint32_t>() ||
1016 0 : (bImm << opData.bImmDiscardLsb) != o3.as<Imm>().valueAs<uint32_t>())
1017 0 : goto InvalidImmediate;
1018 :
1019 : opcode.reset(opData.opcode());
1020 0 : opcode.addImm(aImm, opData.aImmOffset);
1021 0 : opcode.addImm(bImm, opData.bImmOffset);
1022 : opcode.addReg(o1, 5);
1023 : opcode.addReg(o0, 0);
1024 0 : goto EmitOp;
1025 : }
1026 :
1027 : break;
1028 : }
1029 :
1030 : // ------------------------------------------------------------------------
1031 : // [Base - Mov]
1032 : // ------------------------------------------------------------------------
1033 :
1034 : case InstDB::kEncodingBaseMov: {
1035 : // MOV is a pseudo instruction that uses various instructions depending on its signature.
1036 : uint32_t x = diff(o0.as<Reg>().type(), RegType::kARM_GpW);
1037 0 : if (x > 1)
1038 0 : goto InvalidInstruction;
1039 :
1040 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
1041 0 : if (!o0.as<Reg>().isGp())
1042 0 : goto InvalidInstruction;
1043 :
1044 0 : if (!checkSignature(o0, o1))
1045 0 : goto InvalidInstruction;
1046 :
1047 0 : bool hasSP = o0.as<Gp>().isSP() || o1.as<Gp>().isSP();
1048 : if (hasSP) {
1049 : // Cannot be combined with ZR.
1050 0 : if (!checkGpId(o0, o1, kSP))
1051 0 : goto InvalidPhysId;
1052 :
1053 : // MOV Rd, Rm -> ADD Rd, Rn, #0.
1054 : opcode.reset(0b00010001000000000000000000000000);
1055 : opcode.addImm(x, 31);
1056 : opcode.addReg(o1, 5);
1057 : opcode.addReg(o0, 0);
1058 0 : goto EmitOp;
1059 : }
1060 : else {
1061 0 : if (!checkGpId(o0, o1, kZR))
1062 0 : goto InvalidPhysId;
1063 :
1064 : // MOV Rd, Rm -> ORR Rd, <ZR>, Rm.
1065 : opcode.reset(0b00101010000000000000001111100000);
1066 : opcode.addImm(x, 31);
1067 : opcode.addReg(o1, 16);
1068 : opcode.addReg(o0, 0);
1069 0 : goto EmitOp;
1070 : }
1071 : }
1072 :
1073 0 : if (isign4 == ENC_OPS2(Reg, Imm)) {
1074 0 : if (!o0.as<Reg>().isGp())
1075 0 : goto InvalidInstruction;
1076 :
1077 : uint64_t immValue = o1.as<Imm>().valueAs<uint64_t>();
1078 0 : if (!x)
1079 0 : immValue &= 0xFFFFFFFFu;
1080 :
1081 : // Prefer a single MOVN/MOVZ instruction over a logical instruction.
1082 0 : multipleOpCount = encodeMovSequence64(multipleOpData, immValue, o0.id() & 31, x);
1083 0 : if (multipleOpCount == 1 && !o0.as<Gp>().isSP()) {
1084 0 : opcode.reset(multipleOpData[0]);
1085 0 : goto EmitOp;
1086 : }
1087 :
1088 : // Logical instructions use 13-bit immediate pattern encoded as N:ImmR:ImmS.
1089 : LogicalImm logicalImm;
1090 0 : if (!o0.as<Gp>().isZR()) {
1091 0 : if (Utils::encodeLogicalImm(immValue, x ? 64 : 32, &logicalImm)) {
1092 0 : if (!checkGpId(o0, kSP))
1093 0 : goto InvalidPhysId;
1094 :
1095 : opcode.reset(0b00110010000000000000001111100000);
1096 : opcode.addImm(x, 31);
1097 0 : opcode.addLogicalImm(logicalImm);
1098 : opcode.addReg(o0, 0);
1099 0 : goto EmitOp;
1100 : }
1101 : }
1102 :
1103 0 : if (!checkGpId(o0, kZR))
1104 0 : goto InvalidPhysId;
1105 :
1106 0 : goto EmitOp_Multiple;
1107 : }
1108 :
1109 : break;
1110 : }
1111 :
1112 0 : case InstDB::kEncodingBaseMovKNZ: {
1113 : const InstDB::EncodingData::BaseMovKNZ& opData = InstDB::EncodingData::baseMovKNZ[encodingIndex];
1114 :
1115 : uint32_t x = diff(o0.as<Reg>().type(), RegType::kARM_GpW);
1116 0 : if (x > 1)
1117 0 : goto InvalidInstruction;
1118 :
1119 0 : if (!checkGpId(o0, kZR))
1120 0 : goto InvalidPhysId;
1121 :
1122 0 : opcode.reset(opData.opcode);
1123 : opcode.addImm(x, 31);
1124 :
1125 0 : if (isign4 == ENC_OPS2(Reg, Imm)) {
1126 : uint64_t imm16 = o1.as<Imm>().valueAs<uint64_t>();
1127 0 : if (imm16 > 0xFFFFu)
1128 0 : goto InvalidImmediate;
1129 :
1130 : opcode.addImm(imm16, 5);
1131 : opcode.addReg(o0, 0);
1132 0 : goto EmitOp;
1133 : }
1134 :
1135 0 : if (isign4 == ENC_OPS3(Reg, Imm, Imm)) {
1136 : uint64_t imm16 = o1.as<Imm>().valueAs<uint64_t>();
1137 : uint32_t shiftType = o2.as<Imm>().predicate();
1138 : uint64_t shiftValue = o2.as<Imm>().valueAs<uint64_t>();
1139 :
1140 0 : if (imm16 > 0xFFFFu || shiftValue > 48 || shiftType != uint32_t(ShiftOp::kLSL))
1141 0 : goto InvalidImmediate;
1142 :
1143 : // Convert shift value to 'hw' field.
1144 0 : uint32_t hw = uint32_t(shiftValue) >> 4;
1145 0 : if ((hw << 4) != uint32_t(shiftValue))
1146 0 : goto InvalidImmediate;
1147 :
1148 : opcode.addImm(hw, 21);
1149 : opcode.addImm(imm16, 5);
1150 : opcode.addReg(o0, 0);
1151 :
1152 0 : if (!x && hw > 1u)
1153 0 : goto InvalidImmediate;
1154 :
1155 0 : goto EmitOp;
1156 : }
1157 :
1158 : break;
1159 : }
1160 :
1161 : // ------------------------------------------------------------------------
1162 : // [Base - Adr]
1163 : // ------------------------------------------------------------------------
1164 :
1165 0 : case InstDB::kEncodingBaseAdr: {
1166 : const InstDB::EncodingData::BaseAdr& opData = InstDB::EncodingData::baseAdr[encodingIndex];
1167 :
1168 0 : if (isign4 == ENC_OPS2(Reg, Label) || isign4 == ENC_OPS2(Reg, Imm)) {
1169 0 : if (!o0.as<Reg>().isGpX())
1170 0 : goto InvalidInstruction;
1171 :
1172 0 : if (!checkGpId(o0, kZR))
1173 0 : goto InvalidPhysId;
1174 :
1175 : opcode.reset(opData.opcode());
1176 : opcode.addReg(o0, 0);
1177 0 : offsetFormat.resetToImmValue(opData.offsetType, 4, 5, 21, 0);
1178 :
1179 0 : if (instId == Inst::kIdAdrp)
1180 0 : offsetFormat._immDiscardLsb = 12;
1181 :
1182 : rmRel = &o1;
1183 0 : goto EmitOp_Rel;
1184 : }
1185 :
1186 : break;
1187 : }
1188 :
1189 : // ------------------------------------------------------------------------
1190 : // [Base - Arithmetic and Logical]
1191 : // ------------------------------------------------------------------------
1192 :
1193 0 : case InstDB::kEncodingBaseAddSub: {
1194 : const InstDB::EncodingData::BaseAddSub& opData = InstDB::EncodingData::baseAddSub[encodingIndex];
1195 :
1196 : uint32_t x;
1197 : if (!checkGpType(o0, o1, kWX, &x))
1198 0 : goto InvalidInstruction;
1199 :
1200 0 : if (isign4 == ENC_OPS3(Reg, Reg, Imm) || isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
1201 0 : opcode.reset(uint32_t(opData.immediateOp) << 24);
1202 :
1203 : // ADD | SUB (immediate) - ZR is not allowed.
1204 : // ADDS|SUBS (immediate) - ZR allowed in Rd, SP allowed in Rn.
1205 0 : uint32_t aHiId = opcode.get() & B(29) ? kZR : kSP;
1206 : uint32_t bHiId = kSP;
1207 :
1208 0 : if (!checkGpId(o0, aHiId) || !checkGpId(o1, bHiId))
1209 0 : goto InvalidPhysId;
1210 :
1211 : // ADD|SUB (immediate) use 12-bit immediate optionally shifted by 'LSL #12'.
1212 : uint64_t imm = o2.as<Imm>().valueAs<uint64_t>();
1213 : uint32_t shift = 0;
1214 :
1215 0 : if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
1216 0 : if (o3.as<Imm>().predicate() != uint32_t(ShiftOp::kLSL))
1217 0 : goto InvalidImmediate;
1218 :
1219 0 : if (o3.as<Imm>().value() != 0 && o3.as<Imm>().value() != 12)
1220 0 : goto InvalidImmediate;
1221 :
1222 0 : shift = uint32_t(o3.as<Imm>().value() != 0);
1223 : }
1224 :
1225 : // Accept immediate value of '0x00XXX000' by setting 'shift' to 12.
1226 0 : if (imm > 0xFFFu) {
1227 0 : if (shift || (imm & ~uint64_t(0xFFFu << 12)) != 0)
1228 0 : goto InvalidImmediate;
1229 : shift = 1;
1230 0 : imm >>= 12;
1231 : }
1232 :
1233 : opcode.addImm(x, 31);
1234 : opcode.addImm(shift, 22);
1235 : opcode.addImm(imm, 10);
1236 : opcode.addReg(o1, 5);
1237 : opcode.addReg(o0, 0);
1238 0 : goto EmitOp;
1239 : }
1240 :
1241 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg) || isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
1242 0 : if (!checkSignature(o1, o2))
1243 0 : goto InvalidInstruction;
1244 :
1245 0 : uint32_t opSize = x ? 64 : 32;
1246 : uint64_t shift = 0;
1247 : uint32_t sType = uint32_t(ShiftOp::kLSL);
1248 :
1249 0 : if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
1250 : sType = o3.as<Imm>().predicate();
1251 : shift = o3.as<Imm>().valueAs<uint64_t>();
1252 : }
1253 :
1254 0 : if (!checkGpId(o2, kZR))
1255 0 : goto InvalidPhysId;
1256 :
1257 : // Shift operation - LSL, LSR, ASR.
1258 0 : if (sType <= uint32_t(ShiftOp::kASR)) {
1259 0 : bool hasSP = o0.as<Gp>().isSP() || o1.as<Gp>().isSP();
1260 : if (!hasSP) {
1261 0 : if (!checkGpId(o0, o1, kZR))
1262 0 : goto InvalidPhysId;
1263 :
1264 0 : if (shift >= opSize)
1265 0 : goto InvalidImmediate;
1266 :
1267 0 : opcode.reset(uint32_t(opData.shiftedOp) << 21);
1268 : opcode.addImm(x, 31);
1269 : opcode.addImm(sType, 22);
1270 : opcode.addReg(o2, 16);
1271 : opcode.addImm(shift, 10);
1272 : opcode.addReg(o1, 5);
1273 : opcode.addReg(o0, 0);
1274 0 : goto EmitOp;
1275 : }
1276 :
1277 : // SP register can only be used with LSL or Extend.
1278 0 : if (sType != uint32_t(ShiftOp::kLSL))
1279 0 : goto InvalidImmediate;
1280 0 : sType = x ? uint32_t(ShiftOp::kUXTX) : uint32_t(ShiftOp::kUXTW);
1281 : }
1282 :
1283 : // Extend operation - UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX.
1284 0 : opcode.reset(uint32_t(opData.extendedOp) << 21);
1285 0 : sType -= uint32_t(ShiftOp::kUXTB);
1286 :
1287 0 : if (sType > 7 || shift > 4)
1288 0 : goto InvalidImmediate;
1289 :
1290 0 : if (!(opcode.get() & B(29))) {
1291 : // ADD|SUB (extend) - ZR is not allowed.
1292 0 : if (!checkGpId(o0, o1, kSP))
1293 0 : goto InvalidPhysId;
1294 : }
1295 : else {
1296 : // ADDS|SUBS (extend) - ZR allowed in Rd, SP allowed in Rn.
1297 0 : if (!checkGpId(o0, kZR) || !checkGpId(o1, kSP))
1298 0 : goto InvalidPhysId;
1299 : }
1300 :
1301 : opcode.addImm(x, 31);
1302 : opcode.addReg(o2, 16);
1303 : opcode.addImm(sType, 13);
1304 : opcode.addImm(shift, 10);
1305 : opcode.addReg(o1, 5);
1306 : opcode.addReg(o0, 0);
1307 0 : goto EmitOp;
1308 : }
1309 :
1310 : break;
1311 : }
1312 :
1313 0 : case InstDB::kEncodingBaseLogical: {
1314 : const InstDB::EncodingData::BaseLogical& opData = InstDB::EncodingData::baseLogical[encodingIndex];
1315 :
1316 : uint32_t x;
1317 : if (!checkGpType(o0, o1, kWX, &x))
1318 0 : goto InvalidInstruction;
1319 :
1320 0 : if (!checkSignature(o0, o1))
1321 0 : goto InvalidInstruction;
1322 :
1323 0 : uint32_t opSize = x ? 64 : 32;
1324 :
1325 0 : if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.immediateOp != 0) {
1326 0 : opcode.reset(uint32_t(opData.immediateOp) << 23);
1327 :
1328 : // AND|ANDS|BIC|BICS|ORR|EOR (immediate) uses a LogicalImm format described by N:R:S values.
1329 : uint64_t immMask = Support::lsbMask<uint64_t>(opSize);
1330 : uint64_t immValue = o2.as<Imm>().valueAs<uint64_t>();
1331 :
1332 0 : if (opData.negateImm)
1333 0 : immValue ^= immMask;
1334 :
1335 : // Logical instructions use 13-bit immediate pattern encoded as N:ImmS:ImmR.
1336 : LogicalImm logicalImm;
1337 0 : if (!Utils::encodeLogicalImm(immValue & immMask, opSize, &logicalImm))
1338 0 : goto InvalidImmediate;
1339 :
1340 : // AND|BIC|ORR|EOR (immediate) can have SP on destination, but ANDS|BICS (immediate) cannot.
1341 : uint32_t kOpANDS = 0x3 << 29;
1342 0 : bool isANDS = (opcode.get() & kOpANDS) == kOpANDS;
1343 :
1344 0 : if (!checkGpId(o0, isANDS ? kZR : kSP) || !checkGpId(o1, kZR))
1345 0 : goto InvalidPhysId;
1346 :
1347 : opcode.addImm(x, 31);
1348 0 : opcode.addLogicalImm(logicalImm);
1349 : opcode.addReg(o1, 5);
1350 : opcode.addReg(o0, 0);
1351 0 : goto EmitOp;
1352 : }
1353 :
1354 0 : if (!checkSignature(o1, o2))
1355 0 : goto InvalidInstruction;
1356 :
1357 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
1358 0 : if (!checkGpId(o0, o1, o2, kZR))
1359 0 : goto InvalidPhysId;
1360 :
1361 0 : opcode.reset(uint32_t(opData.shiftedOp) << 21);
1362 : opcode.addImm(x, 31);
1363 : opcode.addReg(o2, 16);
1364 : opcode.addReg(o1, 5);
1365 : opcode.addReg(o0, 0);
1366 0 : goto EmitOp;
1367 : }
1368 :
1369 0 : if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
1370 0 : if (!checkGpId(o0, o1, o2, kZR))
1371 0 : goto InvalidPhysId;
1372 :
1373 : uint32_t shiftType = o3.as<Imm>().predicate();
1374 : uint64_t opShift = o3.as<Imm>().valueAs<uint64_t>();
1375 :
1376 0 : if (shiftType > 0x3 || opShift >= opSize)
1377 0 : goto InvalidImmediate;
1378 :
1379 0 : opcode.reset(uint32_t(opData.shiftedOp) << 21);
1380 : opcode.addImm(x, 31);
1381 : opcode.addImm(shiftType, 22);
1382 : opcode.addReg(o2, 16);
1383 : opcode.addImm(opShift, 10);
1384 : opcode.addReg(o1, 5);
1385 : opcode.addReg(o0, 0);
1386 0 : goto EmitOp;
1387 : }
1388 :
1389 : break;
1390 : }
1391 :
1392 0 : case InstDB::kEncodingBaseCmpCmn: {
1393 : const InstDB::EncodingData::BaseCmpCmn& opData = InstDB::EncodingData::baseCmpCmn[encodingIndex];
1394 :
1395 : uint32_t x;
1396 0 : if (!checkGpType(o0, kWX, &x))
1397 0 : goto InvalidInstruction;
1398 :
1399 0 : if (isign4 == ENC_OPS2(Reg, Imm)) {
1400 : // CMN|CMP (immediate) - ZR is not allowed.
1401 0 : if (!checkGpId(o0, kSP))
1402 0 : goto InvalidPhysId;
1403 :
1404 : // CMN|CMP (immediate) use 12-bit immediate optionally shifted by 'LSL #12'.
1405 : const Imm& imm12 = o1.as<Imm>();
1406 : uint32_t immShift = 0;
1407 : uint64_t immValue = imm12.valueAs<uint64_t>();
1408 :
1409 0 : if (immValue > 0xFFFu) {
1410 0 : if ((immValue & ~uint64_t(0xFFFu << 12)) != 0)
1411 0 : goto InvalidImmediate;
1412 : immShift = 1;
1413 0 : immValue >>= 12;
1414 : }
1415 :
1416 0 : opcode.reset(uint32_t(opData.immediateOp) << 24);
1417 : opcode.addImm(x, 31);
1418 : opcode.addImm(immShift, 22);
1419 : opcode.addImm(immValue, 10);
1420 : opcode.addReg(o0, 5);
1421 : opcode.addReg(Gp::kIdZr, 0);
1422 0 : goto EmitOp;
1423 : }
1424 :
1425 0 : if (isign4 == ENC_OPS2(Reg, Reg) || isign4 == ENC_OPS3(Reg, Reg, Imm)) {
1426 0 : if (!checkSignature(o0, o1))
1427 0 : goto InvalidInstruction;
1428 :
1429 0 : uint32_t opSize = x ? 64 : 32;
1430 : uint32_t sType = 0;
1431 : uint64_t shift = 0;
1432 :
1433 0 : if (isign4 == ENC_OPS3(Reg, Reg, Imm)) {
1434 : sType = o2.as<Imm>().predicate();
1435 : shift = o2.as<Imm>().valueAs<uint64_t>();
1436 : }
1437 :
1438 0 : bool hasSP = o0.as<Gp>().isSP() || o1.as<Gp>().isSP();
1439 :
1440 : // Shift operation - LSL, LSR, ASR.
1441 0 : if (sType <= uint32_t(ShiftOp::kASR)) {
1442 0 : if (!hasSP) {
1443 0 : if (shift >= opSize)
1444 0 : goto InvalidImmediate;
1445 :
1446 0 : opcode.reset(uint32_t(opData.shiftedOp) << 21);
1447 : opcode.addImm(x, 31);
1448 : opcode.addImm(sType, 22);
1449 : opcode.addReg(o1, 16);
1450 : opcode.addImm(shift, 10);
1451 : opcode.addReg(o0, 5);
1452 : opcode.addReg(Gp::kIdZr, 0);
1453 0 : goto EmitOp;
1454 : }
1455 :
1456 : // SP register can only be used with LSL or Extend.
1457 0 : if (sType != uint32_t(ShiftOp::kLSL))
1458 0 : goto InvalidImmediate;
1459 :
1460 0 : sType = x ? uint32_t(ShiftOp::kUXTX) : uint32_t(ShiftOp::kUXTW);
1461 : }
1462 :
1463 : // Extend operation - UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX.
1464 0 : sType -= uint32_t(ShiftOp::kUXTB);
1465 0 : if (sType > 7 || shift > 4)
1466 0 : goto InvalidImmediate;
1467 :
1468 0 : opcode.reset(uint32_t(opData.extendedOp) << 21);
1469 : opcode.addImm(x, 31);
1470 : opcode.addReg(o1, 16);
1471 : opcode.addImm(sType, 13);
1472 : opcode.addImm(shift, 10);
1473 : opcode.addReg(o0, 5);
1474 : opcode.addReg(Gp::kIdZr, 0);
1475 0 : goto EmitOp;
1476 : }
1477 :
1478 : break;
1479 : }
1480 :
1481 0 : case InstDB::kEncodingBaseMvnNeg: {
1482 : const InstDB::EncodingData::BaseMvnNeg& opData = InstDB::EncodingData::baseMvnNeg[encodingIndex];
1483 :
1484 : uint32_t x;
1485 : if (!checkGpType(o0, o1, kWX, &x))
1486 0 : goto InvalidInstruction;
1487 :
1488 0 : opcode.reset(opData.opcode);
1489 : opcode.addImm(x, 31);
1490 : opcode.addReg(o1, 16);
1491 : opcode.addReg(o0, 0);
1492 :
1493 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
1494 0 : if (!checkGpId(o0, o1, kZR))
1495 0 : goto InvalidPhysId;
1496 :
1497 0 : goto EmitOp;
1498 : }
1499 :
1500 0 : if (isign4 == ENC_OPS3(Reg, Reg, Imm)) {
1501 0 : if (!checkGpId(o0, o1, kZR))
1502 0 : goto InvalidPhysId;
1503 :
1504 0 : uint32_t opSize = x ? 64 : 32;
1505 : uint32_t shiftType = o2.as<Imm>().predicate();
1506 : uint64_t opShift = o2.as<Imm>().valueAs<uint64_t>();
1507 :
1508 0 : if (shiftType > uint32_t(ShiftOp::kROR) || opShift >= opSize)
1509 0 : goto InvalidImmediate;
1510 :
1511 : opcode.addImm(shiftType, 22);
1512 : opcode.addImm(opShift, 10);
1513 0 : goto EmitOp;
1514 : }
1515 :
1516 : break;
1517 : }
1518 :
1519 0 : case InstDB::kEncodingBaseTst: {
1520 : const InstDB::EncodingData::BaseTst& opData = InstDB::EncodingData::baseTst[encodingIndex];
1521 :
1522 : uint32_t x;
1523 0 : if (!checkGpType(o0, kWX, &x))
1524 0 : goto InvalidInstruction;
1525 :
1526 0 : uint32_t opSize = x ? 64 : 32;
1527 :
1528 0 : if (isign4 == ENC_OPS2(Reg, Imm) && opData.immediateOp != 0) {
1529 0 : if (!checkGpId(o0, kZR))
1530 0 : goto InvalidPhysId;
1531 :
1532 : // TST (immediate) uses a LogicalImm format described by N:R:S values.
1533 : uint64_t immMask = Support::lsbMask<uint64_t>(opSize);
1534 : uint64_t immValue = o1.as<Imm>().valueAs<uint64_t>();
1535 :
1536 : // Logical instructions use 13-bit immediate pattern encoded as N:ImmS:ImmR.
1537 : LogicalImm logicalImm;
1538 0 : if (!Utils::encodeLogicalImm(immValue & immMask, opSize, &logicalImm))
1539 0 : goto InvalidImmediate;
1540 :
1541 0 : opcode.reset(uint32_t(opData.immediateOp) << 22);
1542 0 : opcode.addLogicalImm(logicalImm);
1543 : opcode.addImm(x, 31);
1544 : opcode.addReg(o0, 5);
1545 : opcode.addReg(Gp::kIdZr, 0);
1546 0 : goto EmitOp;
1547 : }
1548 :
1549 0 : opcode.reset(uint32_t(opData.shiftedOp) << 21);
1550 : opcode.addImm(x, 31);
1551 : opcode.addReg(o1, 16);
1552 : opcode.addReg(o0, 5);
1553 : opcode.addReg(Gp::kIdZr, 0);
1554 :
1555 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
1556 0 : if (!checkGpId(o0, o1, kZR))
1557 0 : goto InvalidPhysId;
1558 :
1559 0 : goto EmitOp;
1560 : }
1561 :
1562 0 : if (isign4 == ENC_OPS3(Reg, Reg, Imm)) {
1563 0 : if (!checkGpId(o0, o1, kZR))
1564 0 : goto InvalidPhysId;
1565 :
1566 : uint32_t shiftType = o2.as<Imm>().predicate();
1567 : uint64_t opShift = o2.as<Imm>().valueAs<uint64_t>();
1568 :
1569 0 : if (shiftType > 0x3 || opShift >= opSize)
1570 0 : goto InvalidImmediate;
1571 :
1572 : opcode.addImm(shiftType, 22);
1573 : opcode.addImm(opShift, 10);
1574 0 : goto EmitOp;
1575 : }
1576 :
1577 : break;
1578 : }
1579 :
1580 : // ------------------------------------------------------------------------
1581 : // [Base - Bit Manipulation]
1582 : // ------------------------------------------------------------------------
1583 :
1584 0 : case InstDB::kEncodingBaseBfc: {
1585 : const InstDB::EncodingData::BaseBfc& opData = InstDB::EncodingData::baseBfc[encodingIndex];
1586 :
1587 0 : if (isign4 == ENC_OPS3(Reg, Imm, Imm)) {
1588 : uint32_t x;
1589 0 : if (!checkGpType(o0, InstDB::kWX, &x))
1590 0 : goto InvalidInstruction;
1591 :
1592 0 : if (!checkGpId(o0))
1593 0 : goto InvalidPhysId;
1594 :
1595 : uint64_t lsb = o1.as<Imm>().valueAs<uint64_t>();
1596 : uint64_t width = o2.as<Imm>().valueAs<uint64_t>();
1597 0 : uint32_t opSize = x ? 64 : 32;
1598 :
1599 0 : if (lsb >= opSize || width == 0 || width > opSize)
1600 0 : goto InvalidImmediate;
1601 :
1602 0 : uint32_t lsb32 = Support::neg(uint32_t(lsb)) & (opSize - 1);
1603 0 : uint32_t width32 = uint32_t(width) - 1;
1604 :
1605 0 : opcode.reset(opData.opcode);
1606 : opcode.addImm(x, 31);
1607 : opcode.addImm(x, 22);
1608 : opcode.addImm(lsb32, 16);
1609 : opcode.addImm(width32, 10);
1610 : opcode.addReg(o0, 0);
1611 0 : goto EmitOp;
1612 : }
1613 :
1614 : break;
1615 : }
1616 :
1617 0 : case InstDB::kEncodingBaseBfi: {
1618 : const InstDB::EncodingData::BaseBfi& opData = InstDB::EncodingData::baseBfi[encodingIndex];
1619 :
1620 0 : if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
1621 : uint32_t x;
1622 0 : if (!checkGpType(o0, InstDB::kWX, &x))
1623 0 : goto InvalidInstruction;
1624 :
1625 0 : if (!checkSignature(o0, o1))
1626 0 : goto InvalidInstruction;
1627 :
1628 0 : if (!checkGpId(o0, o1))
1629 0 : goto InvalidPhysId;
1630 :
1631 : uint64_t lsb = o2.as<Imm>().valueAs<uint64_t>();
1632 : uint64_t width = o3.as<Imm>().valueAs<uint64_t>();
1633 0 : uint32_t opSize = x ? 64 : 32;
1634 :
1635 0 : if (lsb >= opSize || width == 0 || width > opSize)
1636 0 : goto InvalidImmediate;
1637 :
1638 0 : uint32_t lImm = Support::neg(uint32_t(lsb)) & (opSize - 1);
1639 0 : uint32_t wImm = uint32_t(width) - 1;
1640 :
1641 0 : opcode.reset(opData.opcode);
1642 : opcode.addImm(x, 31);
1643 : opcode.addImm(x, 22);
1644 : opcode.addImm(lImm, 16);
1645 : opcode.addImm(wImm, 10);
1646 : opcode.addReg(o1, 5);
1647 : opcode.addReg(o0, 0);
1648 0 : goto EmitOp;
1649 : }
1650 :
1651 : break;
1652 : }
1653 :
1654 0 : case InstDB::kEncodingBaseBfm: {
1655 : const InstDB::EncodingData::BaseBfm& opData = InstDB::EncodingData::baseBfm[encodingIndex];
1656 :
1657 0 : if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
1658 : uint32_t x;
1659 0 : if (!checkGpType(o0, InstDB::kWX, &x))
1660 0 : goto InvalidInstruction;
1661 :
1662 0 : if (!checkSignature(o0, o1))
1663 0 : goto InvalidInstruction;
1664 :
1665 0 : if (!checkGpId(o0, o1))
1666 0 : goto InvalidPhysId;
1667 :
1668 : uint64_t immR = o2.as<Imm>().valueAs<uint64_t>();
1669 : uint64_t immS = o3.as<Imm>().valueAs<uint64_t>();
1670 0 : uint32_t opSize = x ? 64 : 32;
1671 :
1672 0 : if ((immR | immS) >= opSize)
1673 0 : goto InvalidImmediate;
1674 :
1675 0 : opcode.reset(opData.opcode);
1676 : opcode.addImm(x, 31);
1677 : opcode.addImm(x, 22);
1678 : opcode.addImm(immR, 16);
1679 : opcode.addImm(immS, 10);
1680 : opcode.addReg(o1, 5);
1681 : opcode.addReg(o0, 0);
1682 0 : goto EmitOp;
1683 : }
1684 :
1685 : break;
1686 : }
1687 :
1688 0 : case InstDB::kEncodingBaseBfx: {
1689 : const InstDB::EncodingData::BaseBfx& opData = InstDB::EncodingData::baseBfx[encodingIndex];
1690 :
1691 0 : if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
1692 : uint32_t x;
1693 0 : if (!checkGpType(o0, InstDB::kWX, &x))
1694 0 : goto InvalidInstruction;
1695 :
1696 0 : if (!checkSignature(o0, o1))
1697 0 : goto InvalidInstruction;
1698 :
1699 0 : if (!checkGpId(o0, o1))
1700 0 : goto InvalidPhysId;
1701 :
1702 : uint64_t lsb = o2.as<Imm>().valueAs<uint64_t>();
1703 : uint64_t width = o3.as<Imm>().valueAs<uint64_t>();
1704 0 : uint32_t opSize = x ? 64 : 32;
1705 :
1706 0 : if (lsb >= opSize || width == 0 || width > opSize)
1707 0 : goto InvalidImmediate;
1708 :
1709 0 : uint32_t lsb32 = uint32_t(lsb);
1710 0 : uint32_t width32 = lsb32 + uint32_t(width) - 1u;
1711 :
1712 0 : if (width32 >= opSize)
1713 0 : goto InvalidImmediate;
1714 :
1715 0 : opcode.reset(opData.opcode);
1716 : opcode.addImm(x, 31);
1717 : opcode.addImm(x, 22);
1718 : opcode.addImm(lsb32, 16);
1719 : opcode.addImm(width32, 10);
1720 : opcode.addReg(o1, 5);
1721 : opcode.addReg(o0, 0);
1722 0 : goto EmitOp;
1723 : }
1724 :
1725 : break;
1726 : }
1727 :
1728 0 : case InstDB::kEncodingBaseExtend: {
1729 : const InstDB::EncodingData::BaseExtend& opData = InstDB::EncodingData::baseExtend[encodingIndex];
1730 :
1731 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
1732 : uint32_t x;
1733 0 : if (!checkGpType(o0, opData.rType, &x))
1734 0 : goto InvalidInstruction;
1735 :
1736 0 : if (!o1.as<Reg>().isGpW())
1737 0 : goto InvalidInstruction;
1738 :
1739 0 : if (!checkGpId(o0, o1))
1740 0 : goto InvalidPhysId;
1741 :
1742 : opcode.reset(opData.opcode());
1743 : opcode.addImm(x, 31);
1744 : opcode.addImm(x, 22);
1745 : opcode.addReg(o1, 5);
1746 : opcode.addReg(o0, 0);
1747 0 : goto EmitOp;
1748 : }
1749 :
1750 : break;
1751 : }
1752 :
1753 0 : case InstDB::kEncodingBaseExtract: {
1754 : const InstDB::EncodingData::BaseExtract& opData = InstDB::EncodingData::baseExtract[encodingIndex];
1755 :
1756 0 : if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
1757 : uint32_t x;
1758 0 : if (!checkGpType(o0, kWX, &x))
1759 0 : goto InvalidInstruction;
1760 :
1761 : if (!checkSignature(o0, o1, o2))
1762 0 : goto InvalidInstruction;
1763 :
1764 0 : if (!checkGpId(o0, o1, o2))
1765 0 : goto InvalidPhysId;
1766 :
1767 : uint64_t lsb = o3.as<Imm>().valueAs<uint64_t>();
1768 0 : uint32_t opSize = x ? 64 : 32;
1769 :
1770 0 : if (lsb >= opSize)
1771 0 : goto InvalidImmediate;
1772 :
1773 0 : opcode.reset(opData.opcode);
1774 : opcode.addImm(x, 31);
1775 : opcode.addImm(x, 22);
1776 : opcode.addReg(o2, 16);
1777 : opcode.addImm(lsb, 10);
1778 : opcode.addReg(o1, 5);
1779 : opcode.addReg(o0, 0);
1780 0 : goto EmitOp;
1781 : }
1782 :
1783 : break;
1784 : }
1785 :
1786 0 : case InstDB::kEncodingBaseRev: {
1787 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
1788 : uint32_t x;
1789 0 : if (!checkGpType(o0, InstDB::kWX, &x))
1790 0 : goto InvalidInstruction;
1791 :
1792 0 : if (!checkSignature(o0, o1))
1793 0 : goto InvalidInstruction;
1794 :
1795 0 : if (!checkGpId(o0, o1))
1796 0 : goto InvalidPhysId;
1797 :
1798 : opcode.reset(0b01011010110000000000100000000000);
1799 : opcode.addImm(x, 31);
1800 : opcode.addImm(x, 10);
1801 : opcode.addReg(o1, 5);
1802 : opcode.addReg(o0, 0);
1803 0 : goto EmitOp;
1804 : }
1805 :
1806 : break;
1807 : }
1808 :
1809 0 : case InstDB::kEncodingBaseShift: {
1810 : const InstDB::EncodingData::BaseShift& opData = InstDB::EncodingData::baseShift[encodingIndex];
1811 :
1812 : uint32_t x;
1813 0 : if (!checkGpType(o0, kWX, &x))
1814 0 : goto InvalidInstruction;
1815 :
1816 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
1817 : if (!checkSignature(o0, o1, o2))
1818 0 : goto InvalidInstruction;
1819 :
1820 0 : if (!checkGpId(o0, o1, o2, kZR))
1821 0 : goto InvalidPhysId;
1822 :
1823 : opcode.reset(opData.registerOp());
1824 : opcode.addImm(x, 31);
1825 : opcode.addReg(o2, 16);
1826 : opcode.addReg(o1, 5);
1827 : opcode.addReg(o0, 0);
1828 0 : goto EmitOp;
1829 : }
1830 :
1831 0 : if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.immediateOp()) {
1832 0 : if (!checkSignature(o0, o1))
1833 0 : goto InvalidInstruction;
1834 :
1835 0 : if (!checkGpId(o0, o1, kZR))
1836 0 : goto InvalidPhysId;
1837 :
1838 : uint64_t immR = o2.as<Imm>().valueAs<uint64_t>();
1839 0 : uint32_t opSize = x ? 64 : 32;
1840 :
1841 0 : if (immR >= opSize)
1842 0 : goto InvalidImmediate;
1843 :
1844 : opcode.reset(opData.immediateOp());
1845 : opcode.addImm(x, 31);
1846 : opcode.addImm(x, 22);
1847 : opcode.addReg(o1, 5);
1848 : opcode.addReg(o0, 0);
1849 :
1850 0 : if (opcode.get() & B(10)) {
1851 : // ASR and LSR (immediate) has the same logic.
1852 : opcode.addImm(x, 15);
1853 : opcode.addImm(immR, 16);
1854 0 : goto EmitOp;
1855 : }
1856 :
1857 0 : if (opData.ror == 0) {
1858 : // LSL (immediate) is an alias to UBFM
1859 0 : uint32_t ubfmImmR = Support::neg(uint32_t(immR)) & (opSize - 1);
1860 0 : uint32_t ubfmImmS = opSize - 1 - uint32_t(immR);
1861 :
1862 : opcode.addImm(ubfmImmR, 16);
1863 : opcode.addImm(ubfmImmS, 10);
1864 0 : goto EmitOp;
1865 : }
1866 : else {
1867 : // ROR (immediate) is an alias to EXTR.
1868 : opcode.addImm(immR, 10);
1869 : opcode.addReg(o1, 16);
1870 0 : goto EmitOp;
1871 : }
1872 : }
1873 :
1874 : break;
1875 : }
1876 :
1877 : // ------------------------------------------------------------------------
1878 : // [Base - Conditionals]
1879 : // ------------------------------------------------------------------------
1880 :
1881 0 : case InstDB::kEncodingBaseCCmp: {
1882 : const InstDB::EncodingData::BaseCCmp& opData = InstDB::EncodingData::baseCCmp[encodingIndex];
1883 :
1884 0 : if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm) || isign4 == ENC_OPS4(Reg, Imm, Imm, Imm)) {
1885 : uint32_t x;
1886 0 : if (!checkGpType(o0, InstDB::kWX, &x))
1887 0 : goto InvalidInstruction;
1888 :
1889 0 : if (!checkGpId(o0, kZR))
1890 0 : goto InvalidPhysId;
1891 :
1892 : uint64_t nzcv = o2.as<Imm>().valueAs<uint64_t>();
1893 : uint64_t cond = o3.as<Imm>().valueAs<uint64_t>();
1894 :
1895 0 : if ((nzcv | cond) > 0xFu)
1896 0 : goto InvalidImmediate;
1897 :
1898 0 : opcode.reset(opData.opcode);
1899 : opcode.addImm(x, 31);
1900 0 : opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)), 12);
1901 : opcode.addImm(nzcv, 0);
1902 :
1903 0 : if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
1904 : // CCMN|CCMP (register) form.
1905 0 : if (!checkSignature(o0, o1))
1906 0 : goto InvalidInstruction;
1907 :
1908 0 : if (!checkGpId(o1, kZR))
1909 0 : goto InvalidPhysId;
1910 :
1911 : opcode.addReg(o1, 16);
1912 : opcode.addReg(o0, 5);
1913 0 : goto EmitOp;
1914 : }
1915 : else {
1916 : // CCMN|CCMP (immediate) form.
1917 : uint64_t imm5 = o1.as<Imm>().valueAs<uint64_t>();
1918 0 : if (imm5 > 0x1F)
1919 0 : goto InvalidImmediate;
1920 :
1921 : opcode.addImm(1, 11);
1922 : opcode.addImm(imm5, 16);
1923 : opcode.addReg(o0, 5);
1924 0 : goto EmitOp;
1925 : }
1926 : }
1927 :
1928 : break;
1929 : }
1930 :
1931 0 : case InstDB::kEncodingBaseCInc: {
1932 : const InstDB::EncodingData::BaseCInc& opData = InstDB::EncodingData::baseCInc[encodingIndex];
1933 :
1934 0 : if (isign4 == ENC_OPS3(Reg, Reg, Imm)) {
1935 : uint32_t x;
1936 : if (!checkGpType(o0, o1, InstDB::kWX, &x))
1937 0 : goto InvalidInstruction;
1938 :
1939 0 : if (!checkGpId(o0, o1, kZR))
1940 0 : goto InvalidPhysId;
1941 :
1942 : uint64_t cond = o2.as<Imm>().valueAs<uint64_t>();
1943 0 : if (cond - 2u > 0xEu)
1944 0 : goto InvalidImmediate;
1945 :
1946 0 : opcode.reset(opData.opcode);
1947 : opcode.addImm(x, 31);
1948 : opcode.addReg(o1, 16);
1949 0 : opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)) ^ 1u, 12);
1950 : opcode.addReg(o1, 5);
1951 : opcode.addReg(o0, 0);
1952 0 : goto EmitOp;
1953 : }
1954 :
1955 : break;
1956 : }
1957 :
1958 0 : case InstDB::kEncodingBaseCSel: {
1959 : const InstDB::EncodingData::BaseCSel& opData = InstDB::EncodingData::baseCSel[encodingIndex];
1960 :
1961 0 : if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
1962 : uint32_t x;
1963 0 : if (!checkGpType(o0, o1, o2, InstDB::kWX, &x))
1964 0 : goto InvalidInstruction;
1965 :
1966 0 : if (!checkGpId(o0, o1, o2, kZR))
1967 0 : goto InvalidPhysId;
1968 :
1969 : uint64_t cond = o3.as<Imm>().valueAs<uint64_t>();
1970 0 : if (cond > 0xFu)
1971 0 : goto InvalidImmediate;
1972 :
1973 0 : opcode.reset(opData.opcode);
1974 0 : opcode.addImm(x, 31);
1975 : opcode.addReg(o2, 16);
1976 0 : opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)), 12);
1977 : opcode.addReg(o1, 5);
1978 : opcode.addReg(o0, 0);
1979 0 : goto EmitOp;
1980 : }
1981 :
1982 : break;
1983 : }
1984 :
1985 0 : case InstDB::kEncodingBaseCSet: {
1986 : const InstDB::EncodingData::BaseCSet& opData = InstDB::EncodingData::baseCSet[encodingIndex];
1987 :
1988 0 : if (isign4 == ENC_OPS2(Reg, Imm)) {
1989 : uint32_t x;
1990 0 : if (!checkGpType(o0, InstDB::kWX, &x))
1991 0 : goto InvalidInstruction;
1992 :
1993 0 : if (!checkGpId(o0, kZR))
1994 0 : goto InvalidPhysId;
1995 :
1996 : uint64_t cond = o1.as<Imm>().valueAs<uint64_t>();
1997 0 : if (cond - 2u >= 0xEu)
1998 0 : goto InvalidImmediate;
1999 :
2000 0 : opcode.reset(opData.opcode);
2001 : opcode.addImm(x, 31);
2002 0 : opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)) ^ 1u, 12);
2003 : opcode.addReg(o0, 0);
2004 0 : goto EmitOp;
2005 : }
2006 :
2007 : break;
2008 : }
2009 :
2010 : // ------------------------------------------------------------------------
2011 : // [Base - Special]
2012 : // ------------------------------------------------------------------------
2013 :
2014 0 : case InstDB::kEncodingBaseAtDcIcTlbi: {
2015 : const InstDB::EncodingData::BaseAtDcIcTlbi& opData = InstDB::EncodingData::baseAtDcIcTlbi[encodingIndex];
2016 :
2017 0 : if (isign4 == ENC_OPS1(Imm) || isign4 == ENC_OPS2(Imm, Reg)) {
2018 0 : if (opData.mandatoryReg && isign4 != ENC_OPS2(Imm, Reg))
2019 0 : goto InvalidInstruction;
2020 :
2021 0 : if (o0.as<Imm>().valueAs<uint64_t>() > 0x7FFFu)
2022 0 : goto InvalidImmediate;
2023 :
2024 : uint32_t imm = o0.as<Imm>().valueAs<uint32_t>();
2025 0 : if ((imm & opData.immVerifyMask) != opData.immVerifyData)
2026 0 : goto InvalidImmediate;
2027 :
2028 : uint32_t rt = 31;
2029 0 : if (o1.isReg()) {
2030 0 : if (!o1.as<Reg>().isGpX())
2031 0 : goto InvalidInstruction;
2032 :
2033 0 : if (!checkGpId(o1, kZR))
2034 0 : goto InvalidPhysId;
2035 :
2036 0 : rt = o1.id() & 31;
2037 : }
2038 :
2039 : opcode.reset(0b11010101000010000000000000000000);
2040 : opcode.addImm(imm, 5);
2041 : opcode.addReg(rt, 0);
2042 0 : goto EmitOp;
2043 : }
2044 : break;
2045 : }
2046 :
2047 0 : case InstDB::kEncodingBaseMrs: {
2048 0 : if (isign4 == ENC_OPS2(Reg, Imm)) {
2049 0 : if (!o0.as<Reg>().isGpX())
2050 0 : goto InvalidInstruction;
2051 :
2052 0 : if (!checkGpId(o0, kZR))
2053 0 : goto InvalidPhysId;
2054 :
2055 0 : if (o1.as<Imm>().valueAs<uint64_t>() > 0xFFFFu)
2056 0 : goto InvalidImmediate;
2057 :
2058 : uint32_t imm = o1.as<Imm>().valueAs<uint32_t>();
2059 0 : if (!(imm & B(15)))
2060 0 : goto InvalidImmediate;
2061 :
2062 : opcode.reset(0b11010101001100000000000000000000);
2063 : opcode.addImm(imm, 5);
2064 : opcode.addReg(o0, 0);
2065 0 : goto EmitOp;
2066 : }
2067 :
2068 : break;
2069 : }
2070 :
2071 0 : case InstDB::kEncodingBaseMsr: {
2072 0 : if (isign4 == ENC_OPS2(Imm, Reg)) {
2073 0 : if (!o1.as<Reg>().isGpX())
2074 0 : goto InvalidInstruction;
2075 :
2076 0 : if (o0.as<Imm>().valueAs<uint64_t>() > 0xFFFFu)
2077 0 : goto InvalidImmediate;
2078 :
2079 : uint32_t imm = o0.as<Imm>().valueAs<uint32_t>();
2080 0 : if (!(imm & B(15)))
2081 0 : goto InvalidImmediate;
2082 :
2083 0 : if (!checkGpId(o1, kZR))
2084 0 : goto InvalidPhysId;
2085 :
2086 : opcode.reset(0b11010101000100000000000000000000);
2087 : opcode.addImm(imm, 5);
2088 : opcode.addReg(o1, 0);
2089 0 : goto EmitOp;
2090 : }
2091 :
2092 0 : if (isign4 == ENC_OPS2(Imm, Imm)) {
2093 0 : if (o0.as<Imm>().valueAs<uint64_t>() > 0x1Fu)
2094 0 : goto InvalidImmediate;
2095 :
2096 0 : if (o1.as<Imm>().valueAs<uint64_t>() > 0xFu)
2097 0 : goto InvalidImmediate;
2098 :
2099 : uint32_t op = o0.as<Imm>().valueAs<uint32_t>();
2100 : uint32_t cRm = o1.as<Imm>().valueAs<uint32_t>();
2101 :
2102 0 : uint32_t op1 = uint32_t(op) >> 3;
2103 : uint32_t op2 = uint32_t(op) & 0x7u;
2104 :
2105 : opcode.reset(0b11010101000000000100000000011111);
2106 : opcode.addImm(op1, 16);
2107 : opcode.addImm(cRm, 8);
2108 : opcode.addImm(op2, 5);
2109 0 : goto EmitOp;
2110 : }
2111 :
2112 : break;
2113 : }
2114 :
2115 0 : case InstDB::kEncodingBaseSys: {
2116 0 : if (isign4 == ENC_OPS4(Imm, Imm, Imm, Imm)) {
2117 0 : if (o0.as<Imm>().valueAs<uint64_t>() > 0x7u ||
2118 0 : o1.as<Imm>().valueAs<uint64_t>() > 0xFu ||
2119 0 : o2.as<Imm>().valueAs<uint64_t>() > 0xFu ||
2120 : o3.as<Imm>().valueAs<uint64_t>() > 0x7u)
2121 0 : goto InvalidImmediate;
2122 :
2123 : uint32_t op1 = o0.as<Imm>().valueAs<uint32_t>();
2124 : uint32_t cRn = o1.as<Imm>().valueAs<uint32_t>();
2125 : uint32_t cRm = o2.as<Imm>().valueAs<uint32_t>();
2126 : uint32_t op2 = o3.as<Imm>().valueAs<uint32_t>();
2127 : uint32_t rt = 31;
2128 :
2129 : const Operand_& o4 = opExt[EmitterUtils::kOp4];
2130 0 : if (o4.isReg()) {
2131 0 : if (!o4.as<Reg>().isGpX())
2132 0 : goto InvalidInstruction;
2133 :
2134 0 : if (!checkGpId(o4, kZR))
2135 0 : goto InvalidPhysId;
2136 :
2137 0 : rt = o4.id() & 31;
2138 : }
2139 0 : else if (!o4.isNone()) {
2140 0 : goto InvalidInstruction;
2141 : }
2142 :
2143 : opcode.reset(0b11010101000010000000000000000000);
2144 : opcode.addImm(op1, 16);
2145 : opcode.addImm(cRn, 12);
2146 : opcode.addImm(cRm, 8);
2147 : opcode.addImm(op2, 5);
2148 : opcode.addImm(rt, 0);
2149 0 : goto EmitOp;
2150 : }
2151 :
2152 : break;
2153 : }
2154 :
2155 : // ------------------------------------------------------------------------
2156 : // [Base - Branch]
2157 : // ------------------------------------------------------------------------
2158 :
2159 0 : case InstDB::kEncodingBaseBranchReg: {
2160 : const InstDB::EncodingData::BaseBranchReg& opData = InstDB::EncodingData::baseBranchReg[encodingIndex];
2161 :
2162 0 : if (isign4 == ENC_OPS1(Reg)) {
2163 0 : if (!o0.as<Reg>().isGpX())
2164 0 : goto InvalidInstruction;
2165 :
2166 0 : if (!checkGpId(o0, kZR))
2167 0 : goto InvalidPhysId;
2168 :
2169 0 : opcode.reset(opData.opcode);
2170 : opcode.addReg(o0, 5);
2171 0 : goto EmitOp;
2172 : }
2173 :
2174 : break;
2175 : }
2176 :
2177 0 : case InstDB::kEncodingBaseBranchRel: {
2178 : const InstDB::EncodingData::BaseBranchRel& opData = InstDB::EncodingData::baseBranchRel[encodingIndex];
2179 :
2180 0 : if (isign4 == ENC_OPS1(Label) || isign4 == ENC_OPS1(Imm)) {
2181 0 : opcode.reset(opData.opcode);
2182 : rmRel = &o0;
2183 :
2184 0 : if (instCC != CondCode::kAL) {
2185 : opcode |= B(30);
2186 0 : opcode.addImm(condCodeToOpcodeCond(uint32_t(instCC)), 0);
2187 : offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2);
2188 0 : goto EmitOp_Rel;
2189 : }
2190 :
2191 : offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 0, 26, 2);
2192 0 : goto EmitOp_Rel;
2193 : }
2194 :
2195 : break;
2196 : }
2197 :
2198 0 : case InstDB::kEncodingBaseBranchCmp: {
2199 : const InstDB::EncodingData::BaseBranchCmp& opData = InstDB::EncodingData::baseBranchCmp[encodingIndex];
2200 :
2201 0 : if (isign4 == ENC_OPS2(Reg, Label) || isign4 == ENC_OPS2(Reg, Imm)) {
2202 : uint32_t x;
2203 0 : if (!checkGpType(o0, kWX, &x))
2204 0 : goto InvalidInstruction;
2205 :
2206 0 : if (!checkGpId(o0, kZR))
2207 0 : goto InvalidPhysId;
2208 :
2209 0 : opcode.reset(opData.opcode);
2210 : opcode.addImm(x, 31);
2211 : opcode.addReg(o0, 0);
2212 : offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2);
2213 :
2214 : rmRel = &o1;
2215 0 : goto EmitOp_Rel;
2216 : }
2217 :
2218 : break;
2219 : }
2220 :
2221 0 : case InstDB::kEncodingBaseBranchTst: {
2222 : const InstDB::EncodingData::BaseBranchTst& opData = InstDB::EncodingData::baseBranchTst[encodingIndex];
2223 :
2224 0 : if (isign4 == ENC_OPS3(Reg, Imm, Label) || isign4 == ENC_OPS3(Reg, Imm, Imm)) {
2225 : uint32_t x;
2226 0 : if (!checkGpType(o0, kWX, &x))
2227 0 : goto InvalidInstruction;
2228 :
2229 0 : if (!checkGpId(o0, kZR))
2230 0 : goto InvalidPhysId;
2231 :
2232 : uint64_t imm = o1.as<Imm>().valueAs<uint64_t>();
2233 :
2234 0 : opcode.reset(opData.opcode);
2235 0 : if (imm >= 32) {
2236 0 : if (!x)
2237 0 : goto InvalidImmediate;
2238 : opcode.addImm(x, 31);
2239 0 : imm &= 0x1F;
2240 : }
2241 :
2242 : opcode.addReg(o0, 0);
2243 : opcode.addImm(imm, 19);
2244 : offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 14, 2);
2245 :
2246 : rmRel = &o2;
2247 0 : goto EmitOp_Rel;
2248 : }
2249 :
2250 : break;
2251 : }
2252 :
2253 : // ------------------------------------------------------------------------
2254 : // [Base - Load / Store]
2255 : // ------------------------------------------------------------------------
2256 :
2257 0 : case InstDB::kEncodingBaseLdSt: {
2258 : const InstDB::EncodingData::BaseLdSt& opData = InstDB::EncodingData::baseLdSt[encodingIndex];
2259 :
2260 0 : if (isign4 == ENC_OPS2(Reg, Mem)) {
2261 : const Mem& m = o1.as<Mem>();
2262 0 : rmRel = &m;
2263 :
2264 : uint32_t x;
2265 0 : if (!checkGpType(o0, opData.rType, &x))
2266 0 : goto InvalidInstruction;
2267 :
2268 0 : if (!checkGpId(o0, kZR))
2269 0 : goto InvalidPhysId;
2270 :
2271 : // Instructions that work with either word or dword have the unsigned
2272 : // offset shift set to 2 (word), so we set it to 3 (dword) if this is
2273 : // X version of the instruction.
2274 0 : uint32_t xShiftMask = uint32_t(opData.uOffsetShift == 2);
2275 0 : uint32_t immShift = uint32_t(opData.uOffsetShift) + (x & xShiftMask);
2276 :
2277 0 : if (!armCheckMemBaseIndexRel(m))
2278 0 : goto InvalidAddress;
2279 :
2280 : int64_t offset = m.offset();
2281 0 : if (m.hasBaseReg()) {
2282 : // [Base {Offset | Index}]
2283 0 : if (m.hasIndex()) {
2284 0 : uint32_t opt = armShiftOpToLdStOptMap[m.predicate()];
2285 0 : if (opt == 0xFF)
2286 0 : goto InvalidAddress;
2287 :
2288 : uint32_t shift = m.shift();
2289 0 : uint32_t s = shift != 0;
2290 :
2291 0 : if (s && shift != immShift)
2292 0 : goto InvalidAddressScale;
2293 :
2294 0 : opcode.reset(uint32_t(opData.registerOp) << 21);
2295 0 : opcode.xorImm(x, opData.xOffset);
2296 : opcode.addImm(opt, 13);
2297 : opcode.addImm(s, 12);
2298 : opcode |= B(11);
2299 : opcode.addReg(o0, 0);
2300 0 : goto EmitOp_MemBaseIndex_Rn5_Rm16;
2301 : }
2302 :
2303 : // Makes it easier to work with the offset especially on 32-bit arch.
2304 : if (!Support::isInt32(offset))
2305 0 : goto InvalidDisplacement;
2306 0 : int32_t offset32 = int32_t(offset);
2307 :
2308 0 : if (m.isPreOrPost()) {
2309 : if (!Support::isInt9(offset32))
2310 0 : goto InvalidDisplacement;
2311 :
2312 0 : opcode.reset(uint32_t(opData.prePostOp) << 21);
2313 0 : opcode.xorImm(x, opData.xOffset);
2314 : opcode.addImm(offset32 & 0x1FF, 12);
2315 : opcode.addImm(m.isPreIndex(), 11);
2316 : opcode |= B(10);
2317 : opcode.addReg(o0, 0);
2318 0 : goto EmitOp_MemBase_Rn5;
2319 : }
2320 : else {
2321 0 : uint32_t imm12 = uint32_t(offset32) >> immShift;
2322 :
2323 : // Alternative form of LDUR/STUR and related instructions as described by AArch64 reference manual:
2324 : //
2325 : // If this instruction is not encodable with scaled unsigned offset, try unscaled signed offset.
2326 0 : if (!Support::isUInt12(imm12) || (imm12 << immShift) != uint32_t(offset32)) {
2327 0 : instId = opData.uAltInstId;
2328 : instInfo = &InstDB::_instInfoTable[instId];
2329 0 : encodingIndex = instInfo->_encodingDataIndex;
2330 0 : goto Case_BaseLdurStur;
2331 : }
2332 :
2333 0 : opcode.reset(uint32_t(opData.uOffsetOp) << 22);
2334 0 : opcode.xorImm(x, opData.xOffset);
2335 : opcode.addImm(imm12, 10);
2336 : opcode.addReg(o0, 0);
2337 0 : goto EmitOp_MemBase_Rn5;
2338 : }
2339 : }
2340 : else {
2341 0 : if (!opData.literalOp)
2342 0 : goto InvalidAddress;
2343 :
2344 0 : opcode.reset(uint32_t(opData.literalOp) << 24);
2345 0 : opcode.xorImm(x, opData.xOffset);
2346 : opcode.addReg(o0, 0);
2347 : offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2);
2348 0 : goto EmitOp_Rel;
2349 : }
2350 : }
2351 :
2352 : break;
2353 : }
2354 :
2355 0 : case InstDB::kEncodingBaseLdpStp: {
2356 : const InstDB::EncodingData::BaseLdpStp& opData = InstDB::EncodingData::baseLdpStp[encodingIndex];
2357 :
2358 0 : if (isign4 == ENC_OPS3(Reg, Reg, Mem)) {
2359 : const Mem& m = o2.as<Mem>();
2360 0 : rmRel = &m;
2361 :
2362 : uint32_t x;
2363 0 : if (!checkGpType(o0, o1, opData.rType, &x))
2364 0 : goto InvalidInstruction;
2365 :
2366 0 : if (!checkGpId(o0, o1, kZR))
2367 0 : goto InvalidPhysId;
2368 :
2369 0 : if (m.baseType() != RegType::kARM_GpX || m.hasIndex())
2370 0 : goto InvalidAddress;
2371 :
2372 0 : if (m.isOffset64Bit())
2373 0 : goto InvalidDisplacement;
2374 :
2375 0 : uint32_t offsetShift = opData.offsetShift + x;
2376 0 : int32_t offset32 = m.offsetLo32() >> offsetShift;
2377 :
2378 : // Make sure we didn't lose bits by applying the mandatory offset shift.
2379 0 : if (uint32_t(offset32) << offsetShift != uint32_t(m.offsetLo32()))
2380 0 : goto InvalidDisplacement;
2381 :
2382 : // Offset is encoded as 7-bit immediate.
2383 : if (!Support::isInt7(offset32))
2384 0 : goto InvalidDisplacement;
2385 :
2386 0 : if (m.isPreOrPost() && offset32 != 0) {
2387 0 : if (!opData.prePostOp)
2388 0 : goto InvalidAddress;
2389 :
2390 0 : opcode.reset(uint32_t(opData.prePostOp) << 22);
2391 : opcode.addImm(m.isPreIndex(), 24);
2392 : }
2393 : else {
2394 0 : opcode.reset(uint32_t(opData.offsetOp) << 22);
2395 : }
2396 :
2397 0 : opcode.addImm(x, opData.xOffset);
2398 : opcode.addImm(offset32 & 0x7F, 15);
2399 : opcode.addReg(o1, 10);
2400 : opcode.addReg(o0, 0);
2401 0 : goto EmitOp_MemBase_Rn5;
2402 : }
2403 :
2404 : break;
2405 : }
2406 :
2407 0 : case InstDB::kEncodingBaseStx: {
2408 : const InstDB::EncodingData::BaseStx& opData = InstDB::EncodingData::baseStx[encodingIndex];
2409 :
2410 0 : if (isign4 == ENC_OPS3(Reg, Reg, Mem)) {
2411 : const Mem& m = o2.as<Mem>();
2412 : uint32_t x;
2413 :
2414 0 : if (!o0.as<Reg>().isGpW() || !checkGpType(o1, opData.rType, &x))
2415 0 : goto InvalidInstruction;
2416 :
2417 0 : if (!checkGpId(o0, o1, kZR))
2418 0 : goto InvalidPhysId;
2419 :
2420 : opcode.reset(opData.opcode());
2421 0 : opcode.addImm(x, opData.xOffset);
2422 : opcode.addReg(o0, 16);
2423 : opcode.addReg(o1, 0);
2424 :
2425 0 : rmRel = &m;
2426 0 : goto EmitOp_MemBaseNoImm_Rn5;
2427 : }
2428 :
2429 : break;
2430 : }
2431 :
2432 0 : case InstDB::kEncodingBaseLdxp: {
2433 : const InstDB::EncodingData::BaseLdxp& opData = InstDB::EncodingData::baseLdxp[encodingIndex];
2434 :
2435 0 : if (isign4 == ENC_OPS3(Reg, Reg, Mem)) {
2436 : const Mem& m = o2.as<Mem>();
2437 : uint32_t x;
2438 :
2439 0 : if (!checkGpType(o0, opData.rType, &x) || !checkSignature(o0, o1))
2440 0 : goto InvalidInstruction;
2441 :
2442 0 : if (!checkGpId(o0, o1, kZR))
2443 0 : goto InvalidPhysId;
2444 :
2445 : opcode.reset(opData.opcode());
2446 0 : opcode.addImm(x, opData.xOffset);
2447 : opcode.addReg(o1, 10);
2448 : opcode.addReg(o0, 0);
2449 :
2450 0 : rmRel = &m;
2451 0 : goto EmitOp_MemBaseNoImm_Rn5;
2452 : }
2453 :
2454 : break;
2455 : }
2456 :
2457 0 : case InstDB::kEncodingBaseStxp: {
2458 : const InstDB::EncodingData::BaseStxp& opData = InstDB::EncodingData::baseStxp[encodingIndex];
2459 :
2460 0 : if (isign4 == ENC_OPS4(Reg, Reg, Reg, Mem)) {
2461 : const Mem& m = o3.as<Mem>();
2462 : uint32_t x;
2463 :
2464 0 : if (!o0.as<Reg>().isGpW() || !checkGpType(o1, opData.rType, &x) || !checkSignature(o1, o2))
2465 0 : goto InvalidInstruction;
2466 :
2467 0 : if (!checkGpId(o0, o1, o2, kZR))
2468 0 : goto InvalidPhysId;
2469 :
2470 : opcode.reset(opData.opcode());
2471 0 : opcode.addImm(x, opData.xOffset);
2472 : opcode.addReg(o0, 16);
2473 : opcode.addReg(o2, 10);
2474 : opcode.addReg(o1, 0);
2475 :
2476 0 : rmRel = &m;
2477 0 : goto EmitOp_MemBaseNoImm_Rn5;
2478 : }
2479 :
2480 : break;
2481 : }
2482 :
2483 0 : case InstDB::kEncodingBaseRM_NoImm: {
2484 : const InstDB::EncodingData::BaseRM_NoImm& opData = InstDB::EncodingData::baseRM_NoImm[encodingIndex];
2485 :
2486 0 : if (isign4 == ENC_OPS2(Reg, Mem)) {
2487 : const Mem& m = o1.as<Mem>();
2488 0 : rmRel = &m;
2489 :
2490 : uint32_t x;
2491 0 : if (!checkGpType(o0, opData.rType, &x))
2492 0 : goto InvalidInstruction;
2493 :
2494 0 : if (!checkGpId(o0, opData.rHiId))
2495 0 : goto InvalidPhysId;
2496 :
2497 : opcode.reset(opData.opcode());
2498 0 : opcode.addImm(x, opData.xOffset);
2499 : opcode.addReg(o0, 0);
2500 0 : goto EmitOp_MemBaseNoImm_Rn5;
2501 : }
2502 :
2503 : break;
2504 : }
2505 :
2506 : case InstDB::kEncodingBaseRM_SImm9: {
2507 0 : Case_BaseLdurStur:
2508 : const InstDB::EncodingData::BaseRM_SImm9& opData = InstDB::EncodingData::baseRM_SImm9[encodingIndex];
2509 :
2510 0 : if (isign4 == ENC_OPS2(Reg, Mem)) {
2511 : const Mem& m = o1.as<Mem>();
2512 0 : rmRel = &m;
2513 :
2514 : uint32_t x;
2515 0 : if (!checkGpType(o0, opData.rType, &x))
2516 0 : goto InvalidInstruction;
2517 :
2518 0 : if (!checkGpId(o0, opData.rHiId))
2519 0 : goto InvalidPhysId;
2520 :
2521 0 : if (m.hasBaseReg() && !m.hasIndex()) {
2522 0 : if (m.isOffset64Bit())
2523 0 : goto InvalidDisplacement;
2524 :
2525 0 : int32_t offset32 = m.offsetLo32() >> opData.immShift;
2526 0 : if (Support::shl(offset32, opData.immShift) != m.offsetLo32())
2527 0 : goto InvalidDisplacement;
2528 :
2529 : if (!Support::isInt9(offset32))
2530 0 : goto InvalidDisplacement;
2531 :
2532 0 : if (m.isFixedOffset()) {
2533 : opcode.reset(opData.offsetOp());
2534 : }
2535 : else {
2536 0 : if (!opData.prePostOp())
2537 0 : goto InvalidInstruction;
2538 :
2539 : opcode.reset(opData.prePostOp());
2540 : opcode.xorImm(m.isPreIndex(), 11);
2541 : }
2542 :
2543 0 : opcode.xorImm(x, opData.xOffset);
2544 : opcode.addImm(offset32 & 0x1FF, 12);
2545 : opcode.addReg(o0, 0);
2546 0 : goto EmitOp_MemBase_Rn5;
2547 : }
2548 :
2549 0 : goto InvalidAddress;
2550 : }
2551 :
2552 : break;
2553 : }
2554 :
2555 0 : case InstDB::kEncodingBaseRM_SImm10: {
2556 : const InstDB::EncodingData::BaseRM_SImm10& opData = InstDB::EncodingData::baseRM_SImm10[encodingIndex];
2557 :
2558 0 : if (isign4 == ENC_OPS2(Reg, Mem)) {
2559 : const Mem& m = o1.as<Mem>();
2560 0 : rmRel = &m;
2561 :
2562 : uint32_t x;
2563 0 : if (!checkGpType(o0, opData.rType, &x))
2564 0 : goto InvalidInstruction;
2565 :
2566 0 : if (!checkGpId(o0, opData.rHiId))
2567 0 : goto InvalidPhysId;
2568 :
2569 0 : if (m.hasBaseReg() && !m.hasIndex()) {
2570 0 : if (m.isOffset64Bit())
2571 0 : goto InvalidDisplacement;
2572 :
2573 0 : int32_t offset32 = m.offsetLo32() >> opData.immShift;
2574 0 : if (Support::shl(offset32, opData.immShift) != m.offsetLo32())
2575 0 : goto InvalidDisplacement;
2576 :
2577 : if (!Support::isInt10(offset32))
2578 0 : goto InvalidDisplacement;
2579 :
2580 0 : if (m.isPostIndex())
2581 0 : goto InvalidAddress;
2582 :
2583 : // Offset has 10 bits, sign is stored in the 10th bit.
2584 0 : offset32 &= 0x3FF;
2585 :
2586 : opcode.reset(opData.opcode());
2587 : opcode.xorImm(m.isPreIndex(), 11);
2588 0 : opcode.xorImm(x, opData.xOffset);
2589 0 : opcode.addImm(offset32 >> 9, 22);
2590 : opcode.addImm(offset32, 12);
2591 : opcode.addReg(o0, 0);
2592 0 : goto EmitOp_MemBase_Rn5;
2593 : }
2594 :
2595 0 : goto InvalidAddress;
2596 : }
2597 :
2598 : break;
2599 : }
2600 :
2601 0 : case InstDB::kEncodingBaseAtomicOp: {
2602 : const InstDB::EncodingData::BaseAtomicOp& opData = InstDB::EncodingData::baseAtomicOp[encodingIndex];
2603 :
2604 0 : if (isign4 == ENC_OPS3(Reg, Reg, Mem)) {
2605 : const Mem& m = o2.as<Mem>();
2606 : uint32_t x;
2607 :
2608 0 : if (!checkGpType(o0, opData.rType, &x) || !checkSignature(o0, o1))
2609 0 : goto InvalidInstruction;
2610 :
2611 0 : if (!checkGpId(o0, o1, kZR))
2612 0 : goto InvalidInstruction;
2613 :
2614 : opcode.reset(opData.opcode());
2615 0 : opcode.addImm(x, opData.xOffset);
2616 : opcode.addReg(o0, 16);
2617 : opcode.addReg(o1, 0);
2618 :
2619 0 : rmRel = &m;
2620 0 : goto EmitOp_MemBaseNoImm_Rn5;
2621 : }
2622 :
2623 : break;
2624 : }
2625 :
2626 0 : case InstDB::kEncodingBaseAtomicSt: {
2627 : const InstDB::EncodingData::BaseAtomicSt& opData = InstDB::EncodingData::baseAtomicSt[encodingIndex];
2628 :
2629 0 : if (isign4 == ENC_OPS2(Reg, Mem)) {
2630 : const Mem& m = o1.as<Mem>();
2631 : uint32_t x;
2632 :
2633 0 : if (!checkGpType(o0, opData.rType, &x))
2634 0 : goto InvalidInstruction;
2635 :
2636 0 : if (!checkGpId(o0, kZR))
2637 0 : goto InvalidPhysId;
2638 :
2639 : opcode.reset(opData.opcode());
2640 0 : opcode.addImm(x, opData.xOffset);
2641 : opcode.addReg(o0, 16);
2642 : opcode.addReg(Gp::kIdZr, 0);
2643 :
2644 0 : rmRel = &m;
2645 0 : goto EmitOp_MemBaseNoImm_Rn5;
2646 : }
2647 :
2648 : break;
2649 : }
2650 :
2651 0 : case InstDB::kEncodingBaseAtomicCasp: {
2652 : const InstDB::EncodingData::BaseAtomicCasp& opData = InstDB::EncodingData::baseAtomicCasp[encodingIndex];
2653 : const Operand_& o4 = opExt[EmitterUtils::kOp4];
2654 :
2655 0 : if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg) && o4.isMem()) {
2656 : const Mem& m = o4.as<Mem>();
2657 : uint32_t x;
2658 :
2659 0 : if (!checkGpType(o0, opData.rType, &x))
2660 0 : goto InvalidInstruction;
2661 :
2662 : if (!checkSignature(o0, o1, o2, o3))
2663 0 : goto InvalidInstruction;
2664 :
2665 0 : if (!checkEven(o0, o2) || !checkGpId(o0, o2, kZR))
2666 0 : goto InvalidPhysId;
2667 :
2668 0 : if (!checkConsecutive(o0, o1) || !checkConsecutive(o2, o3))
2669 0 : goto InvalidPhysId;
2670 :
2671 : opcode.reset(opData.opcode());
2672 0 : opcode.addImm(x, opData.xOffset);
2673 : opcode.addReg(o0, 16);
2674 : opcode.addReg(o2, 0);
2675 :
2676 0 : rmRel = &m;
2677 0 : goto EmitOp_MemBaseNoImm_Rn5;
2678 : }
2679 :
2680 : break;
2681 : }
2682 :
2683 : // ------------------------------------------------------------------------
2684 : // [FSimd - Instructions]
2685 : // ------------------------------------------------------------------------
2686 :
2687 0 : case InstDB::kEncodingFSimdSV: {
2688 : const InstDB::EncodingData::FSimdSV& opData = InstDB::EncodingData::fSimdSV[encodingIndex];
2689 :
2690 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
2691 : uint32_t q = diff(o1.as<Reg>().type(), RegType::kARM_VecD);
2692 0 : if (q > 1)
2693 0 : goto InvalidInstruction;
2694 :
2695 0 : if (o0.as<Vec>().hasElementType())
2696 0 : goto InvalidInstruction;
2697 :
2698 : // This operation is only defined for:
2699 : // hD, vS.{4|8}h (16-bit)
2700 : // sD, vS.4s (32-bit)
2701 : uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
2702 0 : uint32_t elementSz = o1.as<Vec>().elementType() - Vec::kElementTypeH;
2703 :
2704 : // Size greater than 1 means 64-bit elements, not supported.
2705 0 : if ((sz | elementSz) > 1 || sz != elementSz)
2706 0 : goto InvalidInstruction;
2707 :
2708 : // Size 1 (32-bit float) requires at least 4 elements.
2709 0 : if (sz && !q)
2710 0 : goto InvalidInstruction;
2711 :
2712 : // Bit flipping according to sz.
2713 : static const uint32_t szBits[] = { B(29), 0 };
2714 :
2715 0 : opcode.reset(opData.opcode << 10);
2716 0 : opcode ^= szBits[sz];
2717 : opcode.addImm(q, 30);
2718 0 : goto EmitOp_Rd0_Rn5;
2719 : }
2720 :
2721 : break;
2722 : }
2723 :
2724 0 : case InstDB::kEncodingFSimdVV: {
2725 : const InstDB::EncodingData::FSimdVV& opData = InstDB::EncodingData::fSimdVV[encodingIndex];
2726 :
2727 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
2728 0 : if (!matchSignature(o0, o1, instFlags))
2729 0 : goto InvalidInstruction;
2730 :
2731 0 : if (!pickFpOpcode(o0.as<Vec>(), opData.scalarOp(), opData.scalarHf(), opData.vectorOp(), opData.vectorHf(), &opcode))
2732 0 : goto InvalidInstruction;
2733 :
2734 0 : goto EmitOp_Rd0_Rn5;
2735 : }
2736 :
2737 : break;
2738 : }
2739 :
2740 0 : case InstDB::kEncodingFSimdVVV: {
2741 : const InstDB::EncodingData::FSimdVVV& opData = InstDB::EncodingData::fSimdVVV[encodingIndex];
2742 :
2743 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
2744 : if (!matchSignature(o0, o1, o2, instFlags))
2745 0 : goto InvalidInstruction;
2746 :
2747 0 : if (!pickFpOpcode(o0.as<Vec>(), opData.scalarOp(), opData.scalarHf(), opData.vectorOp(), opData.vectorHf(), &opcode))
2748 0 : goto InvalidInstruction;
2749 :
2750 0 : goto EmitOp_Rd0_Rn5_Rm16;
2751 : }
2752 :
2753 : break;
2754 : }
2755 :
2756 0 : case InstDB::kEncodingFSimdVVVe: {
2757 : const InstDB::EncodingData::FSimdVVVe& opData = InstDB::EncodingData::fSimdVVVe[encodingIndex];
2758 :
2759 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
2760 0 : if (!o2.as<Vec>().hasElementIndex()) {
2761 : if (!matchSignature(o0, o1, o2, instFlags))
2762 0 : goto InvalidInstruction;
2763 :
2764 0 : if (!pickFpOpcode(o0.as<Vec>(), opData.scalarOp(), opData.scalarHf(), opData.vectorOp(), opData.vectorHf(), &opcode))
2765 0 : goto InvalidInstruction;
2766 :
2767 0 : goto EmitOp_Rd0_Rn5_Rm16;
2768 : }
2769 : else {
2770 0 : if (!matchSignature(o0, o1, instFlags))
2771 0 : goto InvalidInstruction;
2772 :
2773 0 : uint32_t q = o1.as<Reg>().isVecQ();
2774 : uint32_t sz;
2775 :
2776 0 : if (!pickFpOpcode(o0.as<Vec>(), opData.elementScalarOp(), InstDB::kHF_D, opData.elementVectorOp(), InstDB::kHF_D, &opcode, &sz))
2777 0 : goto InvalidInstruction;
2778 :
2779 0 : if (sz == 0 && o2.as<Reg>().id() > 15)
2780 0 : goto InvalidPhysId;
2781 :
2782 : uint32_t elementIndex = o2.as<Vec>().elementIndex();
2783 0 : if (elementIndex > (7u >> sz))
2784 0 : goto InvalidElementIndex;
2785 :
2786 0 : uint32_t hlm = elementIndex << sz;
2787 : opcode.addImm(q, 30);
2788 : opcode.addImm(hlm & 3u, 20);
2789 0 : opcode.addImm(hlm >> 2, 11);
2790 0 : goto EmitOp_Rd0_Rn5_Rm16;
2791 : }
2792 : }
2793 :
2794 : break;
2795 : }
2796 :
2797 0 : case InstDB::kEncodingFSimdVVVV: {
2798 : const InstDB::EncodingData::FSimdVVVV& opData = InstDB::EncodingData::fSimdVVVV[encodingIndex];
2799 :
2800 0 : if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
2801 : if (!matchSignature(o0, o1, o2, o3, instFlags))
2802 0 : goto InvalidInstruction;
2803 :
2804 0 : if (!pickFpOpcode(o0.as<Vec>(), opData.scalarOp(), opData.scalarHf(), opData.vectorOp(), opData.vectorHf(), &opcode))
2805 0 : goto InvalidInstruction;
2806 :
2807 0 : goto EmitOp_Rd0_Rn5_Rm16_Ra10;
2808 : }
2809 :
2810 : break;
2811 : }
2812 :
2813 0 : case InstDB::kEncodingSimdFcadd: {
2814 : const InstDB::EncodingData::SimdFcadd& opData = InstDB::EncodingData::simdFcadd[encodingIndex];
2815 :
2816 0 : if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
2817 0 : if (!checkSignature(o0, o1, o2) || o0.as<Vec>().hasElementIndex())
2818 0 : goto InvalidInstruction;
2819 :
2820 : uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
2821 0 : if (q > 1)
2822 0 : goto InvalidInstruction;
2823 :
2824 0 : uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeB;
2825 0 : if (sz == 0 || sz > 3)
2826 0 : goto InvalidInstruction;
2827 :
2828 : // 0 <- 90deg.
2829 : // 1 <- 270deg.
2830 : uint32_t rot = 0;
2831 0 : if (o3.as<Imm>().value() == 270)
2832 : rot = 1;
2833 0 : else if (o3.as<Imm>().value() != 90)
2834 0 : goto InvalidImmediate;
2835 :
2836 : opcode.reset(opData.opcode());
2837 : opcode.addImm(q, 30);
2838 : opcode.addImm(sz, 22);
2839 : opcode.addImm(rot, 12);
2840 0 : goto EmitOp_Rd0_Rn5_Rm16;
2841 : }
2842 :
2843 : break;
2844 : }
2845 :
2846 0 : case InstDB::kEncodingSimdFccmpFccmpe: {
2847 : const InstDB::EncodingData::SimdFccmpFccmpe& opData = InstDB::EncodingData::simdFccmpFccmpe[encodingIndex];
2848 :
2849 0 : if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
2850 : uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
2851 0 : if (sz > 2)
2852 0 : goto InvalidInstruction;
2853 :
2854 0 : if (!checkSignature(o0, o1) || o0.as<Vec>().hasElementType())
2855 0 : goto InvalidInstruction;
2856 :
2857 : uint64_t nzcv = o2.as<Imm>().valueAs<uint64_t>();
2858 : uint64_t cond = o3.as<Imm>().valueAs<uint64_t>();
2859 :
2860 0 : if ((nzcv | cond) > 0xFu)
2861 0 : goto InvalidImmediate;
2862 :
2863 0 : uint32_t type = (sz - 1) & 0x3u;
2864 :
2865 : opcode.reset(opData.opcode());
2866 : opcode.addImm(type, 22);
2867 0 : opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)), 12);
2868 : opcode.addImm(nzcv, 0);
2869 :
2870 0 : goto EmitOp_Rn5_Rm16;
2871 : }
2872 :
2873 : break;
2874 : }
2875 :
2876 0 : case InstDB::kEncodingSimdFcm: {
2877 : const InstDB::EncodingData::SimdFcm& opData = InstDB::EncodingData::simdFcm[encodingIndex];
2878 :
2879 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg) && opData.hasRegisterOp()) {
2880 : if (!matchSignature(o0, o1, o2, instFlags))
2881 0 : goto InvalidInstruction;
2882 :
2883 0 : if (!pickFpOpcode(o0.as<Vec>(), opData.registerScalarOp(), opData.registerScalarHf(), opData.registerVectorOp(), opData.registerVectorHf(), &opcode))
2884 0 : goto InvalidInstruction;
2885 :
2886 0 : goto EmitOp_Rd0_Rn5_Rm16;
2887 : }
2888 :
2889 0 : if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.hasZeroOp()) {
2890 0 : if (!checkSignature(o0, o1))
2891 0 : goto InvalidInstruction;
2892 :
2893 0 : if (o2.as<Imm>().value() != 0 || o2.as<Imm>().predicate() != 0)
2894 0 : goto InvalidImmediate;
2895 :
2896 0 : if (!pickFpOpcode(o0.as<Vec>(), opData.zeroScalarOp(), InstDB::kHF_B, opData.zeroVectorOp(), InstDB::kHF_B, &opcode))
2897 0 : goto InvalidInstruction;
2898 :
2899 0 : goto EmitOp_Rd0_Rn5;
2900 : }
2901 :
2902 : break;
2903 : }
2904 :
2905 0 : case InstDB::kEncodingSimdFcmla: {
2906 : const InstDB::EncodingData::SimdFcmla& opData = InstDB::EncodingData::simdFcmla[encodingIndex];
2907 :
2908 0 : if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
2909 0 : if (!checkSignature(o0, o1))
2910 0 : goto InvalidInstruction;
2911 :
2912 : uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
2913 0 : if (q > 1)
2914 0 : goto InvalidInstruction;
2915 :
2916 0 : uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeB;
2917 0 : if (sz == 0 || sz > 3)
2918 0 : goto InvalidInstruction;
2919 :
2920 : uint32_t rot = 0;
2921 0 : switch (o3.as<Imm>().value()) {
2922 : case 0 : rot = 0; break;
2923 0 : case 90 : rot = 1; break;
2924 0 : case 180: rot = 2; break;
2925 0 : case 270: rot = 3; break;
2926 0 : default:
2927 0 : goto InvalidImmediate;
2928 : }
2929 :
2930 0 : if (!o2.as<Vec>().hasElementIndex()) {
2931 0 : if (!checkSignature(o1, o2))
2932 0 : goto InvalidInstruction;
2933 :
2934 : opcode.reset(opData.regularOp());
2935 : opcode.addImm(q, 30);
2936 : opcode.addImm(sz, 22);
2937 : opcode.addImm(rot, 11);
2938 0 : goto EmitOp_Rd0_Rn5_Rm16;
2939 : }
2940 : else {
2941 0 : if (o0.as<Vec>().elementType() != o2.as<Vec>().elementType())
2942 0 : goto InvalidInstruction;
2943 :
2944 : // Only allowed vectors are: 4H, 8H, and 4S.
2945 0 : if (!(sz == 1 || (q == 1 && sz == 2)))
2946 0 : goto InvalidInstruction;
2947 :
2948 : // Element index ranges:
2949 : // 4H - ElementIndex[0..1] (index 2..3 is UNDEFINED).
2950 : // 8H - ElementIndex[0..3].
2951 : // 4S - ElementIndex[0..1].
2952 : uint32_t elementIndex = o2.as<Vec>().elementIndex();
2953 0 : uint32_t hlFieldShift = sz == 1 ? 0u : 1u;
2954 0 : uint32_t maxElementIndex = q == 1 && sz == 1 ? 3u : 1u;
2955 :
2956 0 : if (elementIndex > maxElementIndex)
2957 0 : goto InvalidElementIndex;
2958 :
2959 0 : uint32_t hl = elementIndex << hlFieldShift;
2960 :
2961 : opcode.reset(opData.elementOp());
2962 : opcode.addImm(q, 30);
2963 : opcode.addImm(sz, 22);
2964 : opcode.addImm(hl & 1u, 21); // L field.
2965 0 : opcode.addImm(hl >> 1, 11); // H field.
2966 : opcode.addImm(rot, 13);
2967 0 : goto EmitOp_Rd0_Rn5_Rm16;
2968 : }
2969 : }
2970 :
2971 : break;
2972 : }
2973 :
2974 0 : case InstDB::kEncodingSimdFcmpFcmpe: {
2975 : const InstDB::EncodingData::SimdFcmpFcmpe& opData = InstDB::EncodingData::simdFcmpFcmpe[encodingIndex];
2976 :
2977 : uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
2978 0 : uint32_t type = (sz - 1) & 0x3u;
2979 :
2980 0 : if (sz > 2)
2981 0 : goto InvalidInstruction;
2982 :
2983 0 : if (o0.as<Vec>().hasElementType())
2984 0 : goto InvalidInstruction;
2985 :
2986 : opcode.reset(opData.opcode());
2987 : opcode.addImm(type, 22);
2988 :
2989 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
2990 0 : if (!checkSignature(o0, o1))
2991 0 : goto InvalidInstruction;
2992 :
2993 0 : goto EmitOp_Rn5_Rm16;
2994 : }
2995 :
2996 0 : if (isign4 == ENC_OPS2(Reg, Imm)) {
2997 0 : if (o1.as<Imm>().value() != 0 || o1.as<Imm>().predicate() != 0)
2998 0 : goto InvalidInstruction;
2999 :
3000 : opcode |= B(3);
3001 0 : goto EmitOp_Rn5;
3002 : }
3003 :
3004 : break;
3005 : }
3006 :
3007 0 : case InstDB::kEncodingSimdFcsel: {
3008 0 : if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
3009 : if (!checkSignature(o0, o1, o2))
3010 0 : goto InvalidInstruction;
3011 :
3012 : uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
3013 0 : uint32_t type = (sz - 1) & 0x3u;
3014 :
3015 0 : if (sz > 2 || o0.as<Vec>().hasElementType())
3016 0 : goto InvalidInstruction;
3017 :
3018 : uint64_t cond = o3.as<Imm>().valueAs<uint64_t>();
3019 0 : if (cond > 0xFu)
3020 0 : goto InvalidImmediate;
3021 :
3022 : opcode.reset(0b00011110001000000000110000000000);
3023 : opcode.addImm(type, 22);
3024 0 : opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)), 12);
3025 0 : goto EmitOp_Rd0_Rn5_Rm16;
3026 : }
3027 :
3028 : break;
3029 : }
3030 :
3031 0 : case InstDB::kEncodingSimdFcvt: {
3032 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
3033 : uint32_t dstSz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
3034 : uint32_t srcSz = diff(o1.as<Reg>().type(), RegType::kARM_VecH);
3035 :
3036 0 : if ((dstSz | srcSz) > 3)
3037 0 : goto InvalidInstruction;
3038 :
3039 0 : if (o0.as<Vec>().hasElementType() || o1.as<Vec>().hasElementType())
3040 0 : goto InvalidInstruction;
3041 :
3042 : // Table that provides 'type' and 'opc' according to the dst/src combination.
3043 : static const uint8_t table[] = {
3044 : 0xFFu, // H <- H (Invalid).
3045 : 0x03u, // H <- S (type=00 opc=11).
3046 : 0x13u, // H <- D (type=01 opc=11).
3047 : 0xFFu, // H <- Q (Invalid).
3048 : 0x30u, // S <- H (type=11 opc=00).
3049 : 0xFFu, // S <- S (Invalid).
3050 : 0x10u, // S <- D (type=01 opc=00).
3051 : 0xFFu, // S <- Q (Invalid).
3052 : 0x31u, // D <- H (type=11 opc=01).
3053 : 0x01u, // D <- S (type=00 opc=01).
3054 : 0xFFu, // D <- D (Invalid).
3055 : 0xFFu, // D <- Q (Invalid).
3056 : 0xFFu, // Q <- H (Invalid).
3057 : 0xFFu, // Q <- S (Invalid).
3058 : 0xFFu, // Q <- D (Invalid).
3059 : 0xFFu // Q <- Q (Invalid).
3060 : };
3061 :
3062 0 : uint32_t typeOpc = table[(dstSz << 2) | srcSz];
3063 : opcode.reset(0b0001111000100010010000 << 10);
3064 0 : opcode.addImm(typeOpc >> 4, 22);
3065 0 : opcode.addImm(typeOpc & 15, 15);
3066 0 : goto EmitOp_Rd0_Rn5;
3067 : }
3068 :
3069 : break;
3070 : }
3071 :
3072 0 : case InstDB::kEncodingSimdFcvtLN: {
3073 : const InstDB::EncodingData::SimdFcvtLN& opData = InstDB::EncodingData::simdFcvtLN[encodingIndex];
3074 :
3075 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
3076 : // Scalar form - only FCVTXN.
3077 0 : if (o0.as<Vec>().isVecS() && o1.as<Vec>().isVecD()) {
3078 0 : if (!opData.hasScalar())
3079 0 : goto InvalidInstruction;
3080 :
3081 0 : if (o0.as<Vec>().hasElementType() || o1.as<Vec>().hasElementType())
3082 0 : goto InvalidInstruction;
3083 :
3084 : opcode.reset(opData.scalarOp());
3085 : opcode |= B(22); // sz bit must be 1, the only supported combination of FCVTXN.
3086 0 : goto EmitOp_Rd0_Rn5;
3087 : }
3088 :
3089 : opcode.reset(opData.vectorOp());
3090 :
3091 0 : const Vec& rL = (instFlags & InstDB::kInstFlagLong) ? o0.as<Vec>() : o1.as<Vec>();
3092 0 : const Vec& rN = (instFlags & InstDB::kInstFlagLong) ? o1.as<Vec>() : o0.as<Vec>();
3093 :
3094 : uint32_t q = diff(rN.type(), RegType::kARM_VecD);
3095 0 : if (uint32_t(opcode.hasQ()) != q)
3096 0 : goto InvalidInstruction;
3097 :
3098 0 : if (rL.isVecS4() && rN.elementType() == Vec::kElementTypeH && !opData.isCvtxn()) {
3099 0 : goto EmitOp_Rd0_Rn5;
3100 : }
3101 :
3102 0 : if (rL.isVecD2() && rN.elementType() == Vec::kElementTypeS) {
3103 : opcode |= B(22);
3104 0 : goto EmitOp_Rd0_Rn5;
3105 : }
3106 : }
3107 :
3108 : break;
3109 : }
3110 :
3111 0 : case InstDB::kEncodingSimdFcvtSV: {
3112 : const InstDB::EncodingData::SimdFcvtSV& opData = InstDB::EncodingData::simdFcvtSV[encodingIndex];
3113 :
3114 : // So we can support both IntToFloat and FloatToInt conversions.
3115 0 : const Operand_& oGp = opData.isFloatToInt() ? o0 : o1;
3116 0 : const Operand_& oVec = opData.isFloatToInt() ? o1 : o0;
3117 :
3118 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
3119 0 : if (oGp.as<Reg>().isGp() && oVec.as<Reg>().isVec()) {
3120 0 : uint32_t x = oGp.as<Reg>().isGpX();
3121 : uint32_t type = diff(oVec.as<Reg>().type(), RegType::kARM_VecH);
3122 :
3123 0 : if (type > 2u)
3124 0 : goto InvalidInstruction;
3125 :
3126 0 : type = (type - 1u) & 0x3;
3127 : opcode.reset(opData.generalOp());
3128 : opcode.addImm(type, 22);
3129 : opcode.addImm(x, 31);
3130 0 : goto EmitOp_Rd0_Rn5;
3131 : }
3132 :
3133 0 : if (o0.as<Reg>().isVec() && o1.as<Reg>().isVec()) {
3134 0 : if (!checkSignature(o0, o1))
3135 0 : goto InvalidInstruction;
3136 :
3137 0 : if (!pickFpOpcode(o0.as<Vec>(), opData.scalarIntOp(), InstDB::kHF_B, opData.vectorIntOp(), InstDB::kHF_B, &opcode))
3138 0 : goto InvalidInstruction;
3139 :
3140 0 : goto EmitOp_Rd0_Rn5;
3141 : }
3142 : }
3143 :
3144 0 : if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.isFixedPoint()) {
3145 0 : if (o2.as<Imm>().valueAs<uint64_t>() >= 64)
3146 0 : goto InvalidInstruction;
3147 :
3148 : uint32_t scale = o2.as<Imm>().valueAs<uint32_t>();
3149 0 : if (scale == 0)
3150 0 : goto InvalidInstruction;
3151 :
3152 0 : if (oGp.as<Reg>().isGp() && oVec.as<Reg>().isVec()) {
3153 0 : uint32_t x = oGp.as<Reg>().isGpX();
3154 : uint32_t type = diff(oVec.as<Reg>().type(), RegType::kARM_VecH);
3155 :
3156 0 : uint32_t scaleLimit = 32u << x;
3157 0 : if (scale > scaleLimit)
3158 0 : goto InvalidInstruction;
3159 :
3160 0 : type = (type - 1u) & 0x3;
3161 0 : opcode.reset(opData.generalOp() ^ B(21));
3162 : opcode.addImm(type, 22);
3163 : opcode.addImm(x, 31);
3164 0 : opcode.addImm(64u - scale, 10);
3165 0 : goto EmitOp_Rd0_Rn5;
3166 : }
3167 :
3168 0 : if (o0.as<Reg>().isVec() && o1.as<Reg>().isVec()) {
3169 0 : if (!checkSignature(o0, o1))
3170 0 : goto InvalidInstruction;
3171 :
3172 : uint32_t sz;
3173 0 : if (!pickFpOpcode(o0.as<Vec>(), opData.scalarFpOp(), InstDB::kHF_0, opData.vectorFpOp(), InstDB::kHF_0, &opcode, &sz))
3174 0 : goto InvalidInstruction;
3175 :
3176 0 : uint32_t scaleLimit = 16u << sz;
3177 0 : if (scale > scaleLimit)
3178 0 : goto InvalidInstruction;
3179 :
3180 0 : uint32_t imm = Support::neg(scale) & Support::lsbMask<uint32_t>(sz + 4 + 1);
3181 : opcode.addImm(imm, 16);
3182 0 : goto EmitOp_Rd0_Rn5;
3183 : }
3184 : }
3185 :
3186 : break;
3187 : }
3188 :
3189 0 : case InstDB::kEncodingSimdFmlal: {
3190 : const InstDB::EncodingData::SimdFmlal& opData = InstDB::EncodingData::simdFmlal[encodingIndex];
3191 :
3192 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
3193 : uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
3194 : uint32_t qIsOptional = opData.optionalQ();
3195 :
3196 0 : if (qIsOptional) {
3197 : // This instruction works with either 64-bit or 128-bit registers,
3198 : // encoded by Q bit.
3199 0 : if (q > 1)
3200 0 : goto InvalidInstruction;
3201 : }
3202 : else {
3203 : // This instruction requires 128-bit vector registers.
3204 0 : if (q != 1)
3205 0 : goto InvalidInstruction;
3206 :
3207 : // The instruction is ehtier B (bottom) or T (top), which is part of
3208 : // the opcode, which uses Q bit, so we have to clear it explicitly.
3209 : q = 0;
3210 : }
3211 :
3212 0 : if (uint32_t(o0.as<Reg>().type()) != uint32_t(o1.as<Reg>().type()) + qIsOptional ||
3213 0 : o0.as<Vec>().elementType() != opData.tA ||
3214 0 : o1.as<Vec>().elementType() != opData.tB)
3215 0 : goto InvalidInstruction;
3216 :
3217 0 : if (!o2.as<Vec>().hasElementIndex()) {
3218 0 : if (!checkSignature(o1, o2))
3219 0 : goto InvalidInstruction;
3220 :
3221 : opcode.reset(opData.vectorOp());
3222 : opcode.addImm(q, 30);
3223 0 : goto EmitOp_Rd0_Rn5_Rm16;
3224 : }
3225 : else {
3226 0 : if (o2.as<Vec>().elementType() != opData.tElement)
3227 0 : goto InvalidInstruction;
3228 :
3229 0 : if (o2.as<Reg>().id() > 15)
3230 0 : goto InvalidPhysId;
3231 :
3232 : uint32_t elementIndex = o2.as<Vec>().elementIndex();
3233 0 : if (elementIndex > 7u)
3234 0 : goto InvalidElementIndex;
3235 :
3236 : opcode.reset(opData.elementOp());
3237 : opcode.addImm(q, 30);
3238 : opcode.addImm(elementIndex & 3u, 20);
3239 0 : opcode.addImm(elementIndex >> 2, 11);
3240 0 : goto EmitOp_Rd0_Rn5_Rm16;
3241 : }
3242 : }
3243 :
3244 : break;
3245 : }
3246 :
3247 0 : case InstDB::kEncodingSimdFmov: {
3248 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
3249 : // FMOV Gp <-> Vec opcode:
3250 : opcode.reset(0b00011110001001100000000000000000);
3251 :
3252 0 : if (o0.as<Reg>().isGp() && o1.as<Reg>().isVec()) {
3253 : // FMOV Wd, Hn (sf=0 type=11 rmode=00 op=110)
3254 : // FMOV Xd, Hn (sf=1 type=11 rmode=00 op=110)
3255 : // FMOV Wd, Sn (sf=0 type=00 rmode=00 op=110)
3256 : // FMOV Xd, Dn (sf=1 type=11 rmode=00 op=110)
3257 : // FMOV Xd, Vn.d[1] (sf=1 type=10 rmode=01 op=110)
3258 0 : uint32_t x = o0.as<Reg>().isGpX();
3259 : uint32_t sz = diff(o1.as<Reg>().type(), RegType::kARM_VecH);
3260 :
3261 0 : uint32_t type = (sz - 1) & 0x3u;
3262 : uint32_t rModeOp = 0b00110;
3263 :
3264 0 : if (o1.as<Vec>().hasElementIndex()) {
3265 : // Special case.
3266 0 : if (!x || !o1.as<Vec>().isVecD2() || o1.as<Vec>().elementIndex() != 1)
3267 0 : goto InvalidInstruction;
3268 : type = 0b10;
3269 : rModeOp = 0b01110;
3270 : }
3271 : else {
3272 : // Must be scalar.
3273 0 : if (sz > 2)
3274 0 : goto InvalidInstruction;
3275 :
3276 0 : if (o1.as<Vec>().hasElementType())
3277 0 : goto InvalidInstruction;
3278 :
3279 0 : if (o1.as<Vec>().isVecS() && x)
3280 0 : goto InvalidInstruction;
3281 :
3282 0 : if (o1.as<Vec>().isVecD() && !x)
3283 0 : goto InvalidInstruction;
3284 : }
3285 :
3286 : opcode.addImm(x, 31);
3287 : opcode.addImm(type, 22);
3288 : opcode.addImm(rModeOp, 16);
3289 0 : goto EmitOp_Rd0_Rn5;
3290 : }
3291 :
3292 0 : if (o0.as<Reg>().isVec() && o1.as<Reg>().isGp()) {
3293 : // FMOV Hd, Wn (sf=0 type=11 rmode=00 op=111)
3294 : // FMOV Hd, Xn (sf=1 type=11 rmode=00 op=111)
3295 : // FMOV Sd, Wn (sf=0 type=00 rmode=00 op=111)
3296 : // FMOV Dd, Xn (sf=1 type=11 rmode=00 op=111)
3297 : // FMOV Vd.d[1], Xn (sf=1 type=10 rmode=01 op=111)
3298 0 : uint32_t x = o1.as<Reg>().isGpX();
3299 : uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
3300 :
3301 0 : uint32_t type = (sz - 1) & 0x3u;
3302 : uint32_t rModeOp = 0b00111;
3303 :
3304 0 : if (o0.as<Vec>().hasElementIndex()) {
3305 : // Special case.
3306 0 : if (!x || !o0.as<Vec>().isVecD2() || o0.as<Vec>().elementIndex() != 1)
3307 0 : goto InvalidInstruction;
3308 : type = 0b10;
3309 : rModeOp = 0b01111;
3310 : }
3311 : else {
3312 : // Must be scalar.
3313 0 : if (sz > 2)
3314 0 : goto InvalidInstruction;
3315 :
3316 0 : if (o0.as<Vec>().hasElementType())
3317 0 : goto InvalidInstruction;
3318 :
3319 0 : if (o0.as<Vec>().isVecS() && x)
3320 0 : goto InvalidInstruction;
3321 :
3322 0 : if (o0.as<Vec>().isVecD() && !x)
3323 0 : goto InvalidInstruction;
3324 : }
3325 :
3326 : opcode.addImm(x, 31);
3327 : opcode.addImm(type, 22);
3328 : opcode.addImm(rModeOp, 16);
3329 0 : goto EmitOp_Rd0_Rn5;
3330 : }
3331 :
3332 0 : if (checkSignature(o0, o1)) {
3333 : uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
3334 0 : if (sz > 2)
3335 0 : goto InvalidInstruction;
3336 :
3337 0 : if (o0.as<Vec>().hasElementType())
3338 0 : goto InvalidInstruction;
3339 :
3340 0 : uint32_t type = (sz - 1) & 0x3;
3341 : opcode.reset(0b00011110001000000100000000000000);
3342 : opcode.addImm(type, 22);
3343 0 : goto EmitOp_Rd0_Rn5;
3344 : }
3345 : }
3346 :
3347 0 : if (isign4 == ENC_OPS2(Reg, Imm)) {
3348 0 : if (o0.as<Reg>().isVec()) {
3349 : double fpValue;
3350 0 : if (o1.as<Imm>().isDouble())
3351 : fpValue = o1.as<Imm>().valueAs<double>();
3352 0 : else if (o1.as<Imm>().isInt32())
3353 0 : fpValue = o1.as<Imm>().valueAs<int32_t>();
3354 : else
3355 0 : goto InvalidImmediate;
3356 :
3357 : if (!Utils::isFP64Imm8(fpValue))
3358 0 : goto InvalidImmediate;
3359 :
3360 : uint32_t imm8 = Utils::encodeFP64ToImm8(fpValue);
3361 0 : if (!o0.as<Vec>().hasElementType()) {
3362 : // FMOV (scalar, immediate).
3363 : uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
3364 0 : uint32_t type = (sz - 1u) & 0x3u;
3365 :
3366 0 : if (sz > 2)
3367 0 : goto InvalidInstruction;
3368 :
3369 : opcode.reset(0b00011110001000000001000000000000);
3370 : opcode.addImm(type, 22);
3371 : opcode.addImm(imm8, 13);
3372 0 : goto EmitOp_Rd0;
3373 : }
3374 : else {
3375 : uint32_t q = diff(o0.as<Vec>().type(), RegType::kARM_VecD);
3376 0 : uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeH;
3377 :
3378 0 : if (q > 1 || sz > 2)
3379 0 : goto InvalidInstruction;
3380 :
3381 : static const uint32_t szBits[3] = { B(11), B(0), B(29) };
3382 : opcode.reset(0b00001111000000001111010000000000);
3383 0 : opcode ^= szBits[sz];
3384 : opcode.addImm(q, 30);
3385 0 : opcode.addImm(imm8 >> 5, 16);
3386 : opcode.addImm(imm8 & 31, 5);
3387 0 : goto EmitOp_Rd0;
3388 : }
3389 : }
3390 : }
3391 :
3392 : break;
3393 : }
3394 :
3395 0 : case InstDB::kEncodingFSimdPair: {
3396 : const InstDB::EncodingData::FSimdPair& opData = InstDB::EncodingData::fSimdPair[encodingIndex];
3397 :
3398 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
3399 : // This operation is only defined for:
3400 : // hD, vS.2h (16-bit)
3401 : // sD, vS.2s (32-bit)
3402 : // dD, vS.2d (64-bit)
3403 : uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
3404 0 : if (sz > 2)
3405 0 : goto InvalidInstruction;
3406 :
3407 : static const uint32_t szSignatures[3] = {
3408 : VecS::kSignature | (Vec::kSignatureElementH),
3409 : VecD::kSignature | (Vec::kSignatureElementS),
3410 : VecV::kSignature | (Vec::kSignatureElementD)
3411 : };
3412 :
3413 0 : if (o1.signature() != szSignatures[sz])
3414 0 : goto InvalidInstruction;
3415 :
3416 : static const uint32_t szBits[] = { B(29), 0, B(22) };
3417 : opcode.reset(opData.scalarOp());
3418 0 : opcode ^= szBits[sz];
3419 0 : goto EmitOp_Rd0_Rn5;
3420 : }
3421 :
3422 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
3423 : if (!checkSignature(o0, o1, o2))
3424 0 : goto InvalidInstruction;
3425 :
3426 : uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
3427 0 : if (q > 1)
3428 0 : goto InvalidInstruction;
3429 :
3430 0 : uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeH;
3431 0 : if (sz > 2)
3432 0 : goto InvalidInstruction;
3433 :
3434 : static const uint32_t szBits[3] = { B(22) | B(21) | B(15) | B(14), 0, B(22) };
3435 : opcode.reset(opData.vectorOp());
3436 0 : opcode ^= szBits[sz];
3437 : opcode.addImm(q, 30);
3438 0 : goto EmitOp_Rd0_Rn5_Rm16;
3439 : }
3440 :
3441 : break;
3442 : }
3443 :
3444 : // ------------------------------------------------------------------------
3445 : // [ISimd - Instructions]
3446 : // ------------------------------------------------------------------------
3447 :
3448 0 : case InstDB::kEncodingISimdSV: {
3449 : const InstDB::EncodingData::ISimdSV& opData = InstDB::EncodingData::iSimdSV[encodingIndex];
3450 :
3451 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
3452 : // The first destination operand is scalar, which matches element-type of source vectors.
3453 0 : uint32_t L = (instFlags & InstDB::kInstFlagLong) != 0;
3454 0 : if (diff(o0.as<Vec>().type(), RegType::kARM_VecB) != o1.as<Vec>().elementType() - Vec::kElementTypeB + L)
3455 0 : goto InvalidInstruction;
3456 :
3457 0 : SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as<Reg>().type(), o1.as<Vec>().elementType());
3458 0 : if (!sizeOp.isValid())
3459 0 : goto InvalidInstruction;
3460 :
3461 : opcode.reset(opData.opcode());
3462 : opcode.addImm(sizeOp.q(), 30);
3463 : opcode.addImm(sizeOp.size(), 22);
3464 0 : goto EmitOp_Rd0_Rn5;
3465 : }
3466 :
3467 : break;
3468 : }
3469 :
3470 0 : case InstDB::kEncodingISimdVV: {
3471 : const InstDB::EncodingData::ISimdVV& opData = InstDB::EncodingData::iSimdVV[encodingIndex];
3472 :
3473 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
3474 0 : const Operand_& sop = significantSimdOp(o0, o1, instFlags);
3475 0 : if (!matchSignature(o0, o1, instFlags))
3476 0 : goto InvalidInstruction;
3477 :
3478 0 : SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as<Reg>().type(), sop.as<Vec>().elementType());
3479 0 : if (!sizeOp.isValid())
3480 0 : goto InvalidInstruction;
3481 :
3482 : opcode.reset(opData.opcode());
3483 : opcode.addImm(sizeOp.qs(), 30);
3484 : opcode.addImm(sizeOp.scalar(), 28);
3485 : opcode.addImm(sizeOp.size(), 22);
3486 0 : goto EmitOp_Rd0_Rn5;
3487 : }
3488 :
3489 : break;
3490 : }
3491 :
3492 0 : case InstDB::kEncodingISimdVVx: {
3493 : const InstDB::EncodingData::ISimdVVx& opData = InstDB::EncodingData::iSimdVVx[encodingIndex];
3494 :
3495 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
3496 0 : if (o0.signature() != opData.op0Signature ||
3497 0 : o1.signature() != opData.op1Signature)
3498 0 : goto InvalidInstruction;
3499 :
3500 : opcode.reset(opData.opcode());
3501 0 : goto EmitOp_Rd0_Rn5;
3502 : }
3503 :
3504 : break;
3505 : }
3506 :
3507 0 : case InstDB::kEncodingISimdVVV: {
3508 : const InstDB::EncodingData::ISimdVVV& opData = InstDB::EncodingData::iSimdVVV[encodingIndex];
3509 :
3510 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
3511 0 : const Operand_& sop = significantSimdOp(o0, o1, instFlags);
3512 : if (!matchSignature(o0, o1, o2, instFlags))
3513 0 : goto InvalidInstruction;
3514 :
3515 0 : SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as<Reg>().type(), sop.as<Vec>().elementType());
3516 0 : if (!sizeOp.isValid())
3517 0 : goto InvalidInstruction;
3518 :
3519 : opcode.reset(opData.opcode());
3520 : opcode.addImm(sizeOp.qs(), 30);
3521 : opcode.addImm(sizeOp.scalar(), 28);
3522 : opcode.addImm(sizeOp.size(), 22);
3523 0 : goto EmitOp_Rd0_Rn5_Rm16;
3524 : }
3525 :
3526 : break;
3527 : }
3528 :
3529 0 : case InstDB::kEncodingISimdVVVx: {
3530 : const InstDB::EncodingData::ISimdVVVx& opData = InstDB::EncodingData::iSimdVVVx[encodingIndex];
3531 :
3532 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
3533 0 : if (o0.signature() != opData.op0Signature ||
3534 0 : o1.signature() != opData.op1Signature ||
3535 0 : o2.signature() != opData.op2Signature)
3536 0 : goto InvalidInstruction;
3537 :
3538 : opcode.reset(opData.opcode());
3539 0 : goto EmitOp_Rd0_Rn5_Rm16;
3540 : }
3541 :
3542 : break;
3543 : }
3544 :
3545 0 : case InstDB::kEncodingISimdWWV: {
3546 : // Special case for wide add/sub [s|b][add|sub][w]{2}.
3547 : const InstDB::EncodingData::ISimdWWV& opData = InstDB::EncodingData::iSimdWWV[encodingIndex];
3548 :
3549 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
3550 0 : SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o2.as<Reg>().type(), o2.as<Vec>().elementType());
3551 0 : if (!sizeOp.isValid())
3552 0 : goto InvalidInstruction;
3553 :
3554 0 : if (!checkSignature(o0, o1) || !o0.as<Reg>().isVecV() || o0.as<Vec>().elementType() != o2.as<Vec>().elementType() + 1)
3555 0 : goto InvalidInstruction;
3556 :
3557 : opcode.reset(opData.opcode());
3558 : opcode.addImm(sizeOp.qs(), 30);
3559 : opcode.addImm(sizeOp.scalar(), 28);
3560 : opcode.addImm(sizeOp.size(), 22);
3561 0 : goto EmitOp_Rd0_Rn5_Rm16;
3562 : }
3563 :
3564 : break;
3565 : }
3566 :
3567 0 : case InstDB::kEncodingISimdVVVe: {
3568 : const InstDB::EncodingData::ISimdVVVe& opData = InstDB::EncodingData::iSimdVVVe[encodingIndex];
3569 :
3570 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
3571 0 : const Operand_& sop = significantSimdOp(o0, o1, instFlags);
3572 0 : if (!matchSignature(o0, o1, instFlags))
3573 0 : goto InvalidInstruction;
3574 :
3575 0 : if (!o2.as<Vec>().hasElementIndex()) {
3576 0 : SizeOp sizeOp = armElementTypeToSizeOp(opData.regularVecType, sop.as<Reg>().type(), sop.as<Vec>().elementType());
3577 0 : if (!sizeOp.isValid())
3578 0 : goto InvalidInstruction;
3579 :
3580 0 : if (!checkSignature(o1, o2))
3581 0 : goto InvalidInstruction;
3582 :
3583 0 : opcode.reset(uint32_t(opData.regularOp) << 10);
3584 : opcode.addImm(sizeOp.qs(), 30);
3585 : opcode.addImm(sizeOp.scalar(), 28);
3586 : opcode.addImm(sizeOp.size(), 22);
3587 0 : goto EmitOp_Rd0_Rn5_Rm16;
3588 : }
3589 : else {
3590 0 : SizeOp sizeOp = armElementTypeToSizeOp(opData.elementVecType, sop.as<Reg>().type(), sop.as<Vec>().elementType());
3591 0 : if (!sizeOp.isValid())
3592 0 : goto InvalidInstruction;
3593 :
3594 : uint32_t elementIndex = o2.as<Vec>().elementIndex();
3595 : LMHImm lmh;
3596 :
3597 0 : if (!encodeLMH(sizeOp.size(), elementIndex, &lmh))
3598 0 : goto InvalidElementIndex;
3599 :
3600 0 : if (o2.as<Reg>().id() > lmh.maxRmId)
3601 0 : goto InvalidPhysId;
3602 :
3603 0 : opcode.reset(uint32_t(opData.elementOp) << 10);
3604 : opcode.addImm(sizeOp.q(), 30);
3605 : opcode.addImm(sizeOp.size(), 22);
3606 0 : opcode.addImm(lmh.lm, 20);
3607 0 : opcode.addImm(lmh.h, 11);
3608 0 : goto EmitOp_Rd0_Rn5_Rm16;
3609 : }
3610 : }
3611 :
3612 : break;
3613 : }
3614 :
3615 0 : case InstDB::kEncodingISimdVVVI: {
3616 : const InstDB::EncodingData::ISimdVVVI& opData = InstDB::EncodingData::iSimdVVVI[encodingIndex];
3617 :
3618 0 : if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
3619 0 : const Operand_& sop = significantSimdOp(o0, o1, instFlags);
3620 : if (!matchSignature(o0, o1, o2, instFlags))
3621 0 : goto InvalidInstruction;
3622 :
3623 0 : SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as<Reg>().type(), sop.as<Vec>().elementType());
3624 0 : if (!sizeOp.isValid())
3625 0 : goto InvalidInstruction;
3626 :
3627 : uint64_t immValue = o3.as<Imm>().valueAs<uint64_t>();
3628 0 : uint32_t immSize = opData.immSize;
3629 :
3630 0 : if (opData.imm64HasOneBitLess && !sizeOp.q())
3631 0 : immSize--;
3632 :
3633 0 : uint32_t immMax = 1u << immSize;
3634 0 : if (immValue >= immMax)
3635 0 : goto InvalidImmediate;
3636 :
3637 : opcode.reset(opData.opcode());
3638 : opcode.addImm(sizeOp.qs(), 30);
3639 : opcode.addImm(sizeOp.scalar(), 28);
3640 : opcode.addImm(sizeOp.size(), 22);
3641 0 : opcode.addImm(immValue, opData.immShift);
3642 0 : goto EmitOp_Rd0_Rn5_Rm16;
3643 : }
3644 :
3645 : break;
3646 : }
3647 :
3648 0 : case InstDB::kEncodingISimdVVVV: {
3649 : const InstDB::EncodingData::ISimdVVVV& opData = InstDB::EncodingData::iSimdVVVV[encodingIndex];
3650 :
3651 0 : if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
3652 0 : const Operand_& sop = significantSimdOp(o0, o1, instFlags);
3653 : if (!matchSignature(o0, o1, o2, o3, instFlags))
3654 0 : goto InvalidInstruction;
3655 :
3656 0 : SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as<Reg>().type(), sop.as<Vec>().elementType());
3657 0 : if (!sizeOp.isValid())
3658 0 : goto InvalidInstruction;
3659 :
3660 0 : opcode.reset(uint32_t(opData.opcode) << 10);
3661 : opcode.addImm(sizeOp.qs(), 30);
3662 : opcode.addImm(sizeOp.scalar(), 28);
3663 : opcode.addImm(sizeOp.size(), 22);
3664 0 : goto EmitOp_Rd0_Rn5_Rm16_Ra10;
3665 : }
3666 :
3667 : break;
3668 : }
3669 :
3670 0 : case InstDB::kEncodingISimdVVVVx: {
3671 : const InstDB::EncodingData::ISimdVVVVx& opData = InstDB::EncodingData::iSimdVVVVx[encodingIndex];
3672 :
3673 0 : if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
3674 0 : if (o0.signature() != opData.op0Signature ||
3675 0 : o1.signature() != opData.op1Signature ||
3676 0 : o2.signature() != opData.op2Signature ||
3677 0 : o3.signature() != opData.op3Signature)
3678 0 : goto InvalidInstruction;
3679 :
3680 0 : opcode.reset(uint32_t(opData.opcode) << 10);
3681 0 : goto EmitOp_Rd0_Rn5_Rm16_Ra10;
3682 : }
3683 :
3684 : break;
3685 : }
3686 :
3687 :
3688 0 : case InstDB::kEncodingISimdPair: {
3689 : const InstDB::EncodingData::ISimdPair& opData = InstDB::EncodingData::iSimdPair[encodingIndex];
3690 :
3691 0 : if (isign4 == ENC_OPS2(Reg, Reg) && opData.opcode2) {
3692 0 : if (o0.as<Vec>().isVecD1() && o1.as<Vec>().isVecD2()) {
3693 0 : opcode.reset(uint32_t(opData.opcode2) << 10);
3694 : opcode.addImm(0x3, 22); // size.
3695 0 : goto EmitOp_Rd0_Rn5;
3696 : }
3697 : }
3698 :
3699 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
3700 : if (!matchSignature(o0, o1, o2, instFlags))
3701 0 : goto InvalidInstruction;
3702 :
3703 0 : SizeOp sizeOp = armElementTypeToSizeOp(opData.opType3, o0.as<Reg>().type(), o0.as<Vec>().elementType());
3704 0 : if (!sizeOp.isValid())
3705 0 : goto InvalidInstruction;
3706 :
3707 0 : opcode.reset(uint32_t(opData.opcode3) << 10);
3708 : opcode.addImm(sizeOp.qs(), 30);
3709 : opcode.addImm(sizeOp.scalar(), 28);
3710 : opcode.addImm(sizeOp.size(), 22);
3711 0 : goto EmitOp_Rd0_Rn5_Rm16;
3712 : }
3713 :
3714 : break;
3715 : }
3716 :
3717 0 : case InstDB::kEncodingSimdBicOrr: {
3718 : const InstDB::EncodingData::SimdBicOrr& opData = InstDB::EncodingData::simdBicOrr[encodingIndex];
3719 :
3720 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
3721 : if (!matchSignature(o0, o1, o2, instFlags))
3722 0 : goto InvalidInstruction;
3723 :
3724 0 : SizeOp sizeOp = armElementTypeToSizeOp(InstDB::kVO_V_B, o0.as<Reg>().type(), o0.as<Vec>().elementType());
3725 0 : if (!sizeOp.isValid())
3726 0 : goto InvalidInstruction;
3727 :
3728 0 : opcode.reset(uint32_t(opData.registerOp) << 10);
3729 : opcode.addImm(sizeOp.q(), 30);
3730 0 : goto EmitOp_Rd0_Rn5_Rm16;
3731 : }
3732 :
3733 0 : if (isign4 == ENC_OPS2(Reg, Imm) || isign4 == ENC_OPS3(Reg, Imm, Imm)) {
3734 0 : SizeOp sizeOp = armElementTypeToSizeOp(InstDB::kVO_V_HS, o0.as<Reg>().type(), o0.as<Vec>().elementType());
3735 0 : if (!sizeOp.isValid())
3736 0 : goto InvalidInstruction;
3737 :
3738 0 : if (o1.as<Imm>().valueAs<uint64_t>() > 0xFFFFFFFFu)
3739 0 : goto InvalidImmediate;
3740 :
3741 : uint32_t imm = o1.as<Imm>().valueAs<uint32_t>();
3742 : uint32_t shift = 0;
3743 0 : uint32_t maxShift = (8u << sizeOp.size()) - 8u;
3744 :
3745 0 : if (o2.isImm()) {
3746 0 : if (o2.as<Imm>().predicate() != uint32_t(ShiftOp::kLSL))
3747 0 : goto InvalidImmediate;
3748 :
3749 0 : if (imm > 0xFFu || o2.as<Imm>().valueAs<uint64_t>() > maxShift)
3750 0 : goto InvalidImmediate;
3751 :
3752 : shift = o2.as<Imm>().valueAs<uint32_t>();
3753 0 : if ((shift & 0x7u) != 0u)
3754 0 : goto InvalidImmediate;
3755 : }
3756 0 : else if (imm) {
3757 0 : shift = Support::ctz(imm) & 0x7u;
3758 0 : imm >>= shift;
3759 :
3760 0 : if (imm > 0xFFu || shift > maxShift)
3761 0 : goto InvalidImmediate;
3762 : }
3763 :
3764 0 : uint32_t cmode = 0x1u | ((shift / 8u) << 1);
3765 0 : if (sizeOp.size() == 1)
3766 0 : cmode |= B(3);
3767 :
3768 : // The immediate value is split into ABC and DEFGH parts.
3769 0 : uint32_t abc = (imm >> 5) & 0x7u;
3770 : uint32_t defgh = imm & 0x1Fu;
3771 :
3772 0 : opcode.reset(uint32_t(opData.immediateOp) << 10);
3773 : opcode.addImm(sizeOp.q(), 30);
3774 : opcode.addImm(abc, 16);
3775 : opcode.addImm(cmode, 12);
3776 : opcode.addImm(defgh, 5);
3777 0 : goto EmitOp_Rd0;
3778 : }
3779 :
3780 : break;
3781 : }
3782 :
3783 0 : case InstDB::kEncodingSimdCmp: {
3784 : const InstDB::EncodingData::SimdCmp& opData = InstDB::EncodingData::simdCmp[encodingIndex];
3785 :
3786 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg) && opData.regOp) {
3787 : if (!matchSignature(o0, o1, o2, instFlags))
3788 0 : goto InvalidInstruction;
3789 :
3790 0 : SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o0.as<Reg>().type(), o0.as<Vec>().elementType());
3791 0 : if (!sizeOp.isValid())
3792 0 : goto InvalidInstruction;
3793 :
3794 0 : opcode.reset(uint32_t(opData.regOp) << 10);
3795 : opcode.addImm(sizeOp.qs(), 30);
3796 : opcode.addImm(sizeOp.scalar(), 28);
3797 : opcode.addImm(sizeOp.size(), 22);
3798 0 : goto EmitOp_Rd0_Rn5_Rm16;
3799 : }
3800 :
3801 0 : if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.zeroOp) {
3802 0 : if (!matchSignature(o0, o1, instFlags))
3803 0 : goto InvalidInstruction;
3804 :
3805 0 : if (o2.as<Imm>().value() != 0)
3806 0 : goto InvalidImmediate;
3807 :
3808 0 : SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o0.as<Reg>().type(), o0.as<Vec>().elementType());
3809 0 : if (!sizeOp.isValid())
3810 0 : goto InvalidInstruction;
3811 :
3812 0 : opcode.reset(uint32_t(opData.zeroOp) << 10);
3813 : opcode.addImm(sizeOp.qs(), 30);
3814 : opcode.addImm(sizeOp.scalar(), 28);
3815 : opcode.addImm(sizeOp.size(), 22);
3816 0 : goto EmitOp_Rd0_Rn5;
3817 : }
3818 :
3819 : break;
3820 : }
3821 :
3822 0 : case InstDB::kEncodingSimdDot: {
3823 : const InstDB::EncodingData::SimdDot& opData = InstDB::EncodingData::simdDot[encodingIndex];
3824 :
3825 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
3826 : uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
3827 : uint32_t size = 2;
3828 :
3829 0 : if (q > 1u)
3830 0 : goto InvalidInstruction;
3831 :
3832 0 : if (!o2.as<Vec>().hasElementIndex()) {
3833 0 : if (!opData.vectorOp)
3834 0 : goto InvalidInstruction;
3835 :
3836 0 : if (o0.as<Reg>().type() != o1.as<Reg>().type() || o1.as<Reg>().type() != o2.as<Reg>().type())
3837 0 : goto InvalidInstruction;
3838 :
3839 0 : if (o0.as<Vec>().elementType() != opData.tA ||
3840 0 : o1.as<Vec>().elementType() != opData.tB ||
3841 : o2.as<Vec>().elementType() != opData.tB)
3842 0 : goto InvalidInstruction;
3843 :
3844 0 : opcode.reset(uint32_t(opData.vectorOp) << 10);
3845 : opcode.addImm(q, 30);
3846 0 : goto EmitOp_Rd0_Rn5_Rm16;
3847 : }
3848 : else {
3849 0 : if (!opData.elementOp)
3850 0 : goto InvalidInstruction;
3851 :
3852 0 : if (o0.as<Reg>().type() != o1.as<Reg>().type() || !o2.as<Reg>().isVecV())
3853 0 : goto InvalidInstruction;
3854 :
3855 0 : if (o0.as<Vec>().elementType() != opData.tA ||
3856 0 : o1.as<Vec>().elementType() != opData.tB ||
3857 0 : o2.as<Vec>().elementType() != opData.tElement)
3858 0 : goto InvalidInstruction;
3859 :
3860 : uint32_t elementIndex = o2.as<Vec>().elementIndex();
3861 : LMHImm lmh;
3862 :
3863 0 : if (!encodeLMH(size, elementIndex, &lmh))
3864 0 : goto InvalidElementIndex;
3865 :
3866 0 : if (o2.as<Reg>().id() > lmh.maxRmId)
3867 0 : goto InvalidPhysId;
3868 :
3869 0 : opcode.reset(uint32_t(opData.elementOp) << 10);
3870 : opcode.addImm(q, 30);
3871 0 : opcode.addImm(lmh.lm, 20);
3872 0 : opcode.addImm(lmh.h, 11);
3873 0 : goto EmitOp_Rd0_Rn5_Rm16;
3874 : }
3875 : }
3876 :
3877 : break;
3878 : }
3879 :
3880 0 : case InstDB::kEncodingSimdDup: SimdDup: {
3881 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
3882 : // Truth table of valid encodings of `Q:1|ElementType:3`
3883 : uint32_t kValidEncodings = B(Vec::kElementTypeB + 0) |
3884 : B(Vec::kElementTypeH + 0) |
3885 : B(Vec::kElementTypeS + 0) |
3886 : B(Vec::kElementTypeB + 8) |
3887 : B(Vec::kElementTypeH + 8) |
3888 : B(Vec::kElementTypeS + 8) |
3889 : B(Vec::kElementTypeD + 8) ;
3890 :
3891 : uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
3892 :
3893 0 : if (o1.as<Reg>().isGp()) {
3894 : // DUP - Vec (scalar|vector) <- GP register.
3895 : //
3896 : // NOTE: This is only scalar for `dup d, x` case, otherwise the value
3897 : // would be duplicated across all vector elements (1, 2, 4, 8, or 16).
3898 : uint32_t elementType = o0.as<Vec>().elementType();
3899 0 : if (q > 1 || !Support::bitTest(kValidEncodings, (q << 3) | elementType))
3900 0 : goto InvalidInstruction;
3901 :
3902 0 : uint32_t lsbIndex = elementType - 1u;
3903 0 : uint32_t imm5 = 1u << lsbIndex;
3904 :
3905 : opcode.reset(0b0000111000000000000011 << 10);
3906 : opcode.addImm(q, 30);
3907 : opcode.addImm(imm5, 16);
3908 0 : goto EmitOp_Rd0_Rn5;
3909 : }
3910 :
3911 0 : if (!o1.as<Reg>().isVec() || !o1.as<Vec>().hasElementIndex())
3912 0 : goto InvalidInstruction;
3913 :
3914 : uint32_t dstIndex = o1.as<Vec>().elementIndex();
3915 0 : if (!o0.as<Vec>().hasElementType()) {
3916 : // DUP - Vec (scalar) <- Vec[N].
3917 : uint32_t lsbIndex = diff(o0.as<Reg>().type(), RegType::kARM_VecB);
3918 :
3919 0 : if (lsbIndex != o1.as<Vec>().elementType() - Vec::kElementTypeB || lsbIndex > 3)
3920 0 : goto InvalidInstruction;
3921 :
3922 0 : uint32_t imm5 = ((dstIndex << 1) | 1u) << lsbIndex;
3923 0 : if (imm5 > 31)
3924 0 : goto InvalidElementIndex;
3925 :
3926 : opcode.reset(0b0101111000000000000001 << 10);
3927 : opcode.addImm(imm5, 16);
3928 0 : goto EmitOp_Rd0_Rn5;
3929 : }
3930 : else {
3931 : // DUP - Vec (all) <- Vec[N].
3932 : uint32_t elementType = o0.as<Vec>().elementType();
3933 0 : if (q > 1 || !Support::bitTest(kValidEncodings, (q << 3) | elementType))
3934 0 : goto InvalidInstruction;
3935 :
3936 0 : uint32_t lsbIndex = elementType - 1u;
3937 0 : uint32_t imm5 = ((dstIndex << 1) | 1u) << lsbIndex;
3938 :
3939 0 : if (imm5 > 31)
3940 0 : goto InvalidElementIndex;
3941 :
3942 : opcode.reset(0b0000111000000000000001 << 10);
3943 : opcode.addImm(q, 30);
3944 : opcode.addImm(imm5, 16);
3945 0 : goto EmitOp_Rd0_Rn5;
3946 : }
3947 : }
3948 :
3949 : break;
3950 : }
3951 :
3952 0 : case InstDB::kEncodingSimdIns: SimdIns: {
3953 0 : if (isign4 == ENC_OPS2(Reg, Reg) && o0.as<Reg>().isVecV()) {
3954 0 : if (!o0.as<Vec>().hasElementIndex())
3955 0 : goto InvalidInstruction;
3956 :
3957 : uint32_t elementType = o0.as<Vec>().elementType();
3958 : uint32_t dstIndex = o0.as<Vec>().elementIndex();
3959 0 : uint32_t lsbIndex = elementType - 1u;
3960 :
3961 0 : uint32_t imm5 = ((dstIndex << 1) | 1u) << lsbIndex;
3962 0 : if (imm5 > 31)
3963 0 : goto InvalidElementIndex;
3964 :
3965 0 : if (o1.as<Reg>().isGp()) {
3966 : // INS - Vec[N] <- GP register.
3967 : opcode.reset(0b0100111000000000000111 << 10);
3968 : opcode.addImm(imm5, 16);
3969 0 : goto EmitOp_Rd0_Rn5;
3970 : }
3971 0 : else if (o1.as<Reg>().isVecV() && o1.as<Vec>().hasElementIndex()) {
3972 : // INS - Vec[N] <- Vec[M].
3973 0 : if (o0.as<Vec>().elementType() != o1.as<Vec>().elementType())
3974 0 : goto InvalidInstruction;
3975 :
3976 : uint32_t srcIndex = o1.as<Vec>().elementIndex();
3977 0 : if (o0.as<Reg>().type() != o1.as<Reg>().type())
3978 0 : goto InvalidInstruction;
3979 :
3980 0 : uint32_t imm4 = srcIndex << lsbIndex;
3981 0 : if (imm4 > 15)
3982 0 : goto InvalidElementIndex;
3983 :
3984 : opcode.reset(0b0110111000000000000001 << 10);
3985 : opcode.addImm(imm5, 16);
3986 : opcode.addImm(imm4, 11);
3987 0 : goto EmitOp_Rd0_Rn5;
3988 : }
3989 : }
3990 :
3991 : break;
3992 : }
3993 :
3994 0 : case InstDB::kEncodingSimdMov: {
3995 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
3996 0 : if (o0.as<Reg>().isVec() && o1.as<Reg>().isVec()) {
3997 : // INS v.x[index], v.x[index].
3998 0 : if (o0.as<Vec>().hasElementIndex() && o1.as<Vec>().hasElementIndex())
3999 0 : goto SimdIns;
4000 :
4001 : // DUP {b|h|s|d}, v.{b|h|s|d}[index].
4002 0 : if (o1.as<Vec>().hasElementIndex())
4003 0 : goto SimdDup;
4004 :
4005 0 : if (!checkSignature(o0, o1))
4006 0 : goto InvalidInstruction;
4007 :
4008 : // ORR Vd, Vn, Vm
4009 : uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
4010 0 : if (q > 1)
4011 0 : goto InvalidInstruction;
4012 :
4013 : opcode.reset(0b0000111010100000000111 << 10);
4014 : opcode.addImm(q, 30);
4015 : opcode.addReg(o1, 16); // Vn == Vm.
4016 0 : goto EmitOp_Rd0_Rn5;
4017 : }
4018 :
4019 0 : if (o0.as<Reg>().isVec() && o1.as<Reg>().isGp()) {
4020 : // INS v.x[index], Rn.
4021 0 : if (o0.as<Vec>().hasElementIndex())
4022 0 : goto SimdIns;
4023 :
4024 0 : goto InvalidInstruction;
4025 : }
4026 :
4027 0 : if (o0.as<Reg>().isGp() && o1.as<Reg>().isVec()) {
4028 : // UMOV Rd, V.{s|d}[index].
4029 : encodingIndex = 1;
4030 0 : goto SimdUmov;
4031 : }
4032 : }
4033 :
4034 : break;
4035 : }
4036 :
4037 0 : case InstDB::kEncodingSimdMoviMvni: {
4038 : const InstDB::EncodingData::SimdMoviMvni& opData = InstDB::EncodingData::simdMoviMvni[encodingIndex];
4039 :
4040 0 : if (isign4 == ENC_OPS2(Reg, Imm) || isign4 == ENC_OPS3(Reg, Imm, Imm)) {
4041 0 : SizeOp sizeOp = armElementTypeToSizeOp(InstDB::kVO_V_Any, o0.as<Reg>().type(), o0.as<Vec>().elementType());
4042 0 : if (!sizeOp.isValid())
4043 0 : goto InvalidInstruction;
4044 :
4045 : uint64_t imm64 = o1.as<Imm>().valueAs<uint64_t>();
4046 : uint32_t imm8 = 0;
4047 : uint32_t cmode = 0;
4048 0 : uint32_t inverted = opData.inverted;
4049 : uint32_t op = 0;
4050 : uint32_t shift = 0;
4051 : uint32_t shiftOp = uint32_t(ShiftOp::kLSL);
4052 :
4053 0 : if (sizeOp.size() == 3u) {
4054 : // The second immediate should not be present, however, we accept
4055 : // an immediate value of zero as some user code may still pass it.
4056 0 : if (o2.isImm() && o0.as<Imm>().value() != 0)
4057 0 : goto InvalidImmediate;
4058 :
4059 0 : if (Utils::isByteMaskImm8(imm64)) {
4060 0 : imm8 = encodeImm64ByteMaskToImm8(imm64);
4061 : }
4062 : else {
4063 : // Change from D to S and from 64-bit imm to 32-bit imm if this
4064 : // is not a byte-mask pattern.
4065 0 : if ((imm64 >> 32) == (imm64 & 0xFFFFFFFFu)) {
4066 : imm64 &= 0xFFFFFFFFu;
4067 : sizeOp.decrementSize();
4068 : }
4069 : else {
4070 0 : goto InvalidImmediate;
4071 : }
4072 : }
4073 : }
4074 :
4075 0 : if (sizeOp.size() < 3u) {
4076 0 : if (imm64 > 0xFFFFFFFFu)
4077 0 : goto InvalidImmediate;
4078 0 : imm8 = uint32_t(imm64);
4079 :
4080 0 : if (sizeOp.size() == 2) {
4081 0 : if ((imm8 >> 16) == (imm8 & 0xFFFFu)) {
4082 : imm8 >>= 16;
4083 : sizeOp.decrementSize();
4084 : }
4085 : }
4086 :
4087 0 : if (sizeOp.size() == 1) {
4088 0 : if (imm8 > 0xFFFFu)
4089 0 : goto InvalidImmediate;
4090 :
4091 0 : if ((imm8 >> 8) == (imm8 & 0xFFu)) {
4092 : imm8 >>= 8;
4093 : sizeOp.decrementSize();
4094 : }
4095 : }
4096 :
4097 0 : uint32_t maxShift = (8u << sizeOp.size()) - 8u;
4098 0 : if (o2.isImm()) {
4099 0 : if (imm8 > 0xFFu || o2.as<Imm>().valueAs<uint64_t>() > maxShift)
4100 0 : goto InvalidImmediate;
4101 :
4102 : shift = o2.as<Imm>().valueAs<uint32_t>();
4103 : shiftOp = o2.as<Imm>().predicate();
4104 : }
4105 0 : else if (imm8) {
4106 0 : shift = Support::ctz(imm8) & ~0x7u;
4107 0 : imm8 >>= shift;
4108 :
4109 0 : if (imm8 > 0xFFu || shift > maxShift)
4110 0 : goto InvalidImmediate;
4111 : }
4112 :
4113 0 : if ((shift & 0x7u) != 0u)
4114 0 : goto InvalidImmediate;
4115 : }
4116 :
4117 0 : shift /= 8u;
4118 :
4119 0 : switch (sizeOp.size()) {
4120 0 : case 0:
4121 0 : if (shiftOp != uint32_t(ShiftOp::kLSL))
4122 0 : goto InvalidImmediate;
4123 :
4124 0 : if (inverted) {
4125 0 : imm8 = ~imm8 & 0xFFu;
4126 : inverted = 0;
4127 : }
4128 :
4129 : cmode = B(3) | B(2) | B(1);
4130 : break;
4131 :
4132 0 : case 1:
4133 0 : if (shiftOp != uint32_t(ShiftOp::kLSL))
4134 0 : goto InvalidImmediate;
4135 :
4136 0 : cmode = B(3) | (shift << 1);
4137 : op = inverted;
4138 0 : break;
4139 :
4140 0 : case 2:
4141 0 : if (shiftOp == uint32_t(ShiftOp::kLSL)) {
4142 0 : cmode = shift << 1;
4143 : }
4144 0 : else if (shiftOp == uint32_t(ShiftOp::kMSL)) {
4145 0 : if (shift == 0 || shift > 2)
4146 0 : goto InvalidImmediate;
4147 0 : cmode = B(3) | B(2) | (shift - 1u);
4148 : }
4149 : else {
4150 0 : goto InvalidImmediate;
4151 : }
4152 :
4153 : op = inverted;
4154 : break;
4155 :
4156 0 : case 3:
4157 0 : if (inverted) {
4158 0 : imm8 = ~imm8 & 0xFFu;
4159 : inverted = 0;
4160 : }
4161 :
4162 : op = 1;
4163 : cmode = B(3) | B(2) | B(1);
4164 : break;
4165 : }
4166 :
4167 : // The immediate value is split into ABC and DEFGH parts.
4168 0 : uint32_t abc = (imm8 >> 5) & 0x7u;
4169 : uint32_t defgh = imm8 & 0x1Fu;
4170 :
4171 0 : opcode.reset(uint32_t(opData.opcode) << 10);
4172 : opcode.addImm(sizeOp.q(), 30);
4173 : opcode.addImm(op, 29);
4174 : opcode.addImm(abc, 16);
4175 : opcode.addImm(cmode, 12);
4176 : opcode.addImm(defgh, 5);
4177 0 : goto EmitOp_Rd0;
4178 : }
4179 :
4180 : break;
4181 : }
4182 :
4183 0 : case InstDB::kEncodingSimdShift: {
4184 : const InstDB::EncodingData::SimdShift& opData = InstDB::EncodingData::simdShift[encodingIndex];
4185 :
4186 0 : const Operand_& sop = significantSimdOp(o0, o1, instFlags);
4187 0 : SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as<Reg>().type(), sop.as<Vec>().elementType());
4188 :
4189 0 : if (!sizeOp.isValid())
4190 0 : goto InvalidInstruction;
4191 :
4192 0 : if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.immediateOp) {
4193 0 : if (!matchSignature(o0, o1, instFlags))
4194 0 : goto InvalidInstruction;
4195 :
4196 0 : if (o2.as<Imm>().valueAs<uint64_t>() > 63)
4197 0 : goto InvalidImmediate;
4198 :
4199 0 : uint32_t lsbShift = sizeOp.size() + 3u;
4200 0 : uint32_t lsbMask = (1u << lsbShift) - 1u;
4201 : uint32_t imm = o2.as<Imm>().valueAs<uint32_t>();
4202 :
4203 : // Some instructions use IMM and some X - IMM, so negate if required.
4204 0 : if (opData.invertedImm) {
4205 0 : if (imm == 0 || imm > (1u << lsbShift))
4206 0 : goto InvalidImmediate;
4207 0 : imm = Support::neg(imm) & lsbMask;
4208 : }
4209 :
4210 0 : if (imm > lsbMask)
4211 0 : goto InvalidImmediate;
4212 0 : imm |= (1u << lsbShift);
4213 :
4214 0 : opcode.reset(uint32_t(opData.immediateOp) << 10);
4215 : opcode.addImm(sizeOp.qs(), 30);
4216 : opcode.addImm(sizeOp.scalar(), 28);
4217 : opcode.addImm(imm, 16);
4218 0 : goto EmitOp_Rd0_Rn5;
4219 : }
4220 :
4221 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg) && opData.registerOp) {
4222 : if (!matchSignature(o0, o1, o2, instFlags))
4223 0 : goto InvalidInstruction;
4224 :
4225 0 : opcode.reset(uint32_t(opData.registerOp) << 10);
4226 : opcode.addImm(sizeOp.qs(), 30);
4227 : opcode.addImm(sizeOp.scalar(), 28);
4228 : opcode.addImm(sizeOp.size(), 22);
4229 0 : goto EmitOp_Rd0_Rn5_Rm16;
4230 : }
4231 :
4232 : break;
4233 : }
4234 :
4235 0 : case InstDB::kEncodingSimdShiftES: {
4236 : const InstDB::EncodingData::SimdShiftES& opData = InstDB::EncodingData::simdShiftES[encodingIndex];
4237 :
4238 0 : if (isign4 == ENC_OPS3(Reg, Reg, Imm)) {
4239 0 : SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as<Reg>().type(), o1.as<Vec>().elementType());
4240 0 : if (!sizeOp.isValid())
4241 0 : goto InvalidInstruction;
4242 :
4243 0 : if (!matchSignature(o0, o1, instFlags))
4244 0 : goto InvalidInstruction;
4245 :
4246 : // The immediate value must match the element size.
4247 : uint64_t shift = o2.as<Imm>().valueAs<uint64_t>();
4248 : uint32_t shiftOp = o2.as<Imm>().predicate();
4249 :
4250 0 : if (shift != (8u << sizeOp.size()) || shiftOp != uint32_t(ShiftOp::kLSL))
4251 0 : goto InvalidImmediate;
4252 :
4253 0 : opcode.reset(uint32_t(opData.opcode) << 10);
4254 : opcode.addImm(sizeOp.q(), 30);
4255 : opcode.addImm(sizeOp.size(), 22);
4256 0 : goto EmitOp_Rd0_Rn5;
4257 : }
4258 :
4259 : break;
4260 : }
4261 :
4262 0 : case InstDB::kEncodingSimdSm3tt: {
4263 : const InstDB::EncodingData::SimdSm3tt& opData = InstDB::EncodingData::simdSm3tt[encodingIndex];
4264 :
4265 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
4266 0 : if (o0.as<Vec>().isVecS4() && o1.as<Vec>().isVecS4() && o2.as<Vec>().isVecS4() && o2.as<Vec>().hasElementIndex()) {
4267 : uint32_t imm2 = o2.as<Vec>().elementIndex();
4268 0 : if (imm2 > 3)
4269 0 : goto InvalidElementIndex;
4270 :
4271 0 : opcode.reset(uint32_t(opData.opcode) << 10);
4272 : opcode.addImm(imm2, 12);
4273 0 : goto EmitOp_Rd0_Rn5_Rm16;
4274 : }
4275 : }
4276 :
4277 : break;
4278 : }
4279 :
4280 :
4281 0 : case InstDB::kEncodingSimdSmovUmov: SimdUmov: {
4282 : const InstDB::EncodingData::SimdSmovUmov& opData = InstDB::EncodingData::simdSmovUmov[encodingIndex];
4283 :
4284 0 : if (isign4 == ENC_OPS2(Reg, Reg) && o0.as<Reg>().isGp() && o1.as<Reg>().isVec()) {
4285 0 : SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as<Reg>().type(), o1.as<Vec>().elementType());
4286 0 : if (!sizeOp.isValid())
4287 0 : goto InvalidInstruction;
4288 :
4289 0 : if (!o1.as<Vec>().hasElementIndex())
4290 0 : goto InvalidInstruction;
4291 :
4292 0 : uint32_t x = o0.as<Gp>().isGpX();
4293 0 : uint32_t gpMustBeX = uint32_t(sizeOp.size() >= 3u - opData.isSigned);
4294 :
4295 0 : if (opData.isSigned) {
4296 0 : if (gpMustBeX && !x)
4297 0 : goto InvalidInstruction;
4298 : }
4299 : else {
4300 0 : if (x != gpMustBeX)
4301 0 : goto InvalidInstruction;
4302 : }
4303 :
4304 : uint32_t elementIndex = o1.as<Vec>().elementIndex();
4305 0 : uint32_t maxElementIndex = 15u >> sizeOp.size();
4306 :
4307 0 : if (elementIndex > maxElementIndex)
4308 0 : goto InvalidElementIndex;
4309 :
4310 0 : uint32_t imm5 = (1u | (elementIndex << 1)) << sizeOp.size();
4311 :
4312 0 : opcode.reset(uint32_t(opData.opcode) << 10);
4313 : opcode.addImm(x, 30);
4314 : opcode.addImm(imm5, 16);
4315 0 : goto EmitOp_Rd0_Rn5;
4316 : }
4317 :
4318 : break;
4319 : }
4320 :
4321 0 : case InstDB::kEncodingSimdSxtlUxtl: {
4322 : const InstDB::EncodingData::SimdSxtlUxtl& opData = InstDB::EncodingData::simdSxtlUxtl[encodingIndex];
4323 :
4324 0 : if (isign4 == ENC_OPS2(Reg, Reg)) {
4325 0 : SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as<Reg>().type(), o1.as<Vec>().elementType());
4326 0 : if (!sizeOp.isValid())
4327 0 : goto InvalidInstruction;
4328 :
4329 0 : if (!matchSignature(o0, o1, instFlags))
4330 0 : goto InvalidInstruction;
4331 :
4332 0 : opcode.reset(uint32_t(opData.opcode) << 10);
4333 : opcode.addImm(sizeOp.q(), 30);
4334 0 : opcode.addImm(1u, sizeOp.size() + 19);
4335 0 : goto EmitOp_Rd0_Rn5;
4336 : }
4337 :
4338 : break;
4339 : }
4340 :
4341 0 : case InstDB::kEncodingSimdTblTbx: {
4342 : const InstDB::EncodingData::SimdTblTbx& opData = InstDB::EncodingData::simdTblTbx[encodingIndex];
4343 :
4344 0 : if (isign4 == ENC_OPS3(Reg, Reg, Reg) || isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
4345 : // TBL/TBX <Vd>.<Ta>, { <Vn>.16B }, <Vm>.<Ta>
4346 : // TBL/TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B }, <Vm>.<Ta>
4347 : // TBL/TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B, <Vn+2>.16B }, <Vm>.<Ta>
4348 : // TBL/TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B, <Vn+2>.16B, <Vn+3>.16B }, <Vm>.<Ta>
4349 0 : opcode.reset(uint32_t(opData.opcode) << 10);
4350 :
4351 : const Operand_& o4 = opExt[EmitterUtils::kOp4];
4352 : const Operand_& o5 = opExt[EmitterUtils::kOp5];
4353 :
4354 : uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
4355 0 : if (q > 1 || o0.as<Vec>().hasElementIndex())
4356 0 : goto InvalidInstruction;
4357 :
4358 0 : if (!o1.as<Vec>().isVecB16() || o1.as<Vec>().hasElementIndex())
4359 0 : goto InvalidInstruction;
4360 :
4361 0 : uint32_t len = uint32_t(!o3.isNone()) + uint32_t(!o4.isNone()) + uint32_t(!o5.isNone());
4362 : opcode.addImm(q, 30);
4363 : opcode.addImm(len, 13);
4364 :
4365 0 : switch (len) {
4366 : case 0:
4367 0 : if (!checkSignature(o0, o2))
4368 0 : goto InvalidInstruction;
4369 :
4370 0 : if (o2.id() > 31)
4371 0 : goto InvalidPhysId;
4372 :
4373 : opcode.addReg(o2, 16);
4374 0 : goto EmitOp_Rd0_Rn5;
4375 :
4376 : case 1:
4377 0 : if (!checkSignature(o0, o3))
4378 0 : goto InvalidInstruction;
4379 :
4380 0 : if (o3.id() > 31)
4381 0 : goto InvalidPhysId;
4382 :
4383 : opcode.addReg(o3, 16);
4384 0 : goto EmitOp_Rd0_Rn5;
4385 :
4386 : case 2:
4387 0 : if (!checkSignature(o0, o4))
4388 0 : goto InvalidInstruction;
4389 :
4390 0 : if (o4.id() > 31)
4391 0 : goto InvalidPhysId;
4392 :
4393 : opcode.addReg(o4, 16);
4394 0 : goto EmitOp_Rd0_Rn5;
4395 :
4396 : case 3:
4397 0 : if (!checkSignature(o0, o5))
4398 0 : goto InvalidInstruction;
4399 :
4400 0 : if (o5.id() > 31)
4401 0 : goto InvalidPhysId;
4402 :
4403 : opcode.addReg(o5, 16);
4404 0 : goto EmitOp_Rd0_Rn5;
4405 :
4406 0 : default:
4407 : // Should never happen.
4408 0 : goto InvalidInstruction;
4409 : }
4410 : }
4411 :
4412 : break;
4413 : }
4414 :
4415 : // ------------------------------------------------------------------------
4416 : // [Simd - Load / Store]
4417 : // ------------------------------------------------------------------------
4418 :
4419 0 : case InstDB::kEncodingSimdLdSt: {
4420 : const InstDB::EncodingData::SimdLdSt& opData = InstDB::EncodingData::simdLdSt[encodingIndex];
4421 :
4422 0 : if (isign4 == ENC_OPS2(Reg, Mem)) {
4423 : const Mem& m = o1.as<Mem>();
4424 0 : rmRel = &m;
4425 :
4426 : // Width | SZ | XY | XSZ
4427 : // -------+----------+-----------+-----
4428 : // 8-bit | size==00 | opc == 01 | 000
4429 : // 16-bit | size==01 | opc == 01 | 001
4430 : // 32-bit | size==10 | opc == 01 | 010
4431 : // 64-bit | size==11 | opc == 01 | 011
4432 : // 128-bit| size==00 | opc == 11 | 100
4433 : uint32_t xsz = diff(o0.as<Reg>().type(), RegType::kARM_VecB);
4434 0 : if (xsz > 4u || o0.as<Vec>().hasElementIndex())
4435 0 : goto InvalidRegType;
4436 :
4437 0 : if (!checkVecId(o0))
4438 0 : goto InvalidPhysId;
4439 :
4440 0 : if (!armCheckMemBaseIndexRel(m))
4441 0 : goto InvalidAddress;
4442 :
4443 : int64_t offset = m.offset();
4444 0 : if (m.hasBaseReg()) {
4445 : // [Base {Offset | Index}]
4446 0 : if (m.hasIndex()) {
4447 0 : uint32_t opt = armShiftOpToLdStOptMap[m.predicate()];
4448 0 : if (opt == 0xFFu)
4449 0 : goto InvalidAddress;
4450 :
4451 : uint32_t shift = m.shift();
4452 0 : uint32_t s = (shift != 0);
4453 :
4454 0 : if (s && shift != xsz)
4455 0 : goto InvalidAddressScale;
4456 :
4457 0 : opcode.reset(uint32_t(opData.registerOp) << 21);
4458 : opcode.addImm(xsz & 3u, 30);
4459 0 : opcode.addImm(xsz >> 2, 23);
4460 : opcode.addImm(opt, 13);
4461 : opcode.addImm(s, 12);
4462 : opcode |= B(11);
4463 : opcode.addReg(o0, 0);
4464 0 : goto EmitOp_MemBaseIndex_Rn5_Rm16;
4465 : }
4466 :
4467 : // Makes it easier to work with the offset especially on 32-bit arch.
4468 : if (!Support::isInt32(offset))
4469 0 : goto InvalidDisplacement;
4470 0 : int32_t offset32 = int32_t(offset);
4471 :
4472 0 : if (m.isPreOrPost()) {
4473 : if (!Support::isInt9(offset32))
4474 0 : goto InvalidDisplacement;
4475 :
4476 0 : opcode.reset(uint32_t(opData.prePostOp) << 21);
4477 : opcode.addImm(xsz & 3u, 30);
4478 0 : opcode.addImm(xsz >> 2, 23);
4479 : opcode.addImm(offset32 & 0x1FF, 12);
4480 : opcode.addImm(m.isPreIndex(), 11);
4481 : opcode |= B(10);
4482 : opcode.addReg(o0, 0);
4483 0 : goto EmitOp_MemBase_Rn5;
4484 : }
4485 : else {
4486 0 : uint32_t imm12 = uint32_t(offset32) >> xsz;
4487 :
4488 : // If this instruction is not encodable with scaled unsigned offset, try unscaled signed offset.
4489 0 : if (!Support::isUInt12(imm12) || (imm12 << xsz) != uint32_t(offset32)) {
4490 0 : instId = opData.uAltInstId;
4491 : instInfo = &InstDB::_instInfoTable[instId];
4492 0 : encodingIndex = instInfo->_encodingDataIndex;
4493 0 : goto Case_SimdLdurStur;
4494 : }
4495 :
4496 0 : opcode.reset(uint32_t(opData.uOffsetOp) << 22);
4497 : opcode.addImm(xsz & 3u, 30);
4498 0 : opcode.addImm(xsz >> 2, 23);
4499 : opcode.addImm(imm12, 10);
4500 : opcode.addReg(o0, 0);
4501 0 : goto EmitOp_MemBase_Rn5;
4502 : }
4503 : }
4504 : else {
4505 0 : if (!opData.literalOp)
4506 0 : goto InvalidAddress;
4507 :
4508 0 : if (xsz < 2u)
4509 0 : goto InvalidRegType;
4510 :
4511 0 : uint32_t opc = xsz - 2u;
4512 0 : opcode.reset(uint32_t(opData.literalOp) << 24);
4513 : opcode.addImm(opc, 30);
4514 : opcode.addReg(o0, 0);
4515 : offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2);
4516 0 : goto EmitOp_Rel;
4517 : }
4518 : }
4519 :
4520 : break;
4521 : }
4522 :
4523 0 : case InstDB::kEncodingSimdLdpStp: {
4524 : const InstDB::EncodingData::SimdLdpStp& opData = InstDB::EncodingData::simdLdpStp[encodingIndex];
4525 :
4526 0 : if (isign4 == ENC_OPS3(Reg, Reg, Mem)) {
4527 : const Mem& m = o2.as<Mem>();
4528 0 : rmRel = &m;
4529 :
4530 : uint32_t opc = diff(o0.as<Reg>().type(), RegType::kARM_VecS);
4531 0 : if (opc > 2u || o0.as<Vec>().hasElementTypeOrIndex())
4532 0 : goto InvalidInstruction;
4533 :
4534 0 : if (!checkSignature(o0, o1))
4535 0 : goto InvalidInstruction;
4536 :
4537 0 : if (!checkVecId(o0, o1))
4538 0 : goto InvalidPhysId;
4539 :
4540 0 : if (m.baseType() != RegType::kARM_GpX || m.hasIndex())
4541 0 : goto InvalidAddress;
4542 :
4543 0 : if (m.isOffset64Bit())
4544 0 : goto InvalidDisplacement;
4545 :
4546 0 : uint32_t offsetShift = 2u + opc;
4547 0 : int32_t offset32 = m.offsetLo32() >> offsetShift;
4548 :
4549 : // Make sure we didn't lose bits by applying the mandatory offset shift.
4550 0 : if (Support::shl(offset32, offsetShift) != m.offsetLo32())
4551 0 : goto InvalidDisplacement;
4552 :
4553 : // Offset is encoded as a 7-bit immediate.
4554 : if (!Support::isInt7(offset32))
4555 0 : goto InvalidDisplacement;
4556 :
4557 0 : if (m.isPreOrPost() && offset32 != 0) {
4558 0 : if (!opData.prePostOp)
4559 0 : goto InvalidAddress;
4560 :
4561 0 : opcode.reset(uint32_t(opData.prePostOp) << 22);
4562 : opcode.addImm(m.isPreIndex(), 24);
4563 : }
4564 : else {
4565 0 : opcode.reset(uint32_t(opData.offsetOp) << 22);
4566 : }
4567 :
4568 : opcode.addImm(opc, 30);
4569 : opcode.addImm(offset32 & 0x7F, 15);
4570 : opcode.addReg(o1, 10);
4571 : opcode.addReg(o0, 0);
4572 0 : goto EmitOp_MemBase_Rn5;
4573 : }
4574 :
4575 : break;
4576 : }
4577 :
4578 : case InstDB::kEncodingSimdLdurStur: {
4579 0 : Case_SimdLdurStur:
4580 : const InstDB::EncodingData::SimdLdurStur& opData = InstDB::EncodingData::simdLdurStur[encodingIndex];
4581 :
4582 0 : if (isign4 == ENC_OPS2(Reg, Mem)) {
4583 : const Mem& m = o1.as<Mem>();
4584 0 : rmRel = &m;
4585 :
4586 : uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecB);
4587 0 : if (sz > 4 || o0.as<Vec>().hasElementTypeOrIndex())
4588 0 : goto InvalidInstruction;
4589 :
4590 0 : if (!checkVecId(o0))
4591 0 : goto InvalidPhysId;
4592 :
4593 0 : if (!armCheckMemBaseIndexRel(m))
4594 0 : goto InvalidAddress;
4595 :
4596 0 : if (m.hasBaseReg() && !m.hasIndex() && !m.isPreOrPost()) {
4597 0 : if (m.isOffset64Bit())
4598 0 : goto InvalidDisplacement;
4599 :
4600 : int32_t offset32 = m.offsetLo32();
4601 : if (!Support::isInt9(offset32))
4602 0 : goto InvalidDisplacement;
4603 :
4604 0 : opcode.reset(uint32_t(opData.opcode) << 10);
4605 : opcode.addImm(sz & 3u, 30);
4606 0 : opcode.addImm(sz >> 2, 23);
4607 : opcode.addImm(offset32 & 0x1FF, 12);
4608 : opcode.addReg(o0, 0);
4609 0 : goto EmitOp_MemBase_Rn5;
4610 : }
4611 :
4612 0 : goto InvalidAddress;
4613 : }
4614 :
4615 : break;
4616 : }
4617 :
4618 0 : case InstDB::kEncodingSimdLdNStN: {
4619 : const InstDB::EncodingData::SimdLdNStN& opData = InstDB::EncodingData::simdLdNStN[encodingIndex];
4620 0 : const Operand_& o4 = opExt[EmitterUtils::kOp4];
4621 :
4622 : uint32_t n = 1;
4623 :
4624 0 : if (isign4 == ENC_OPS2(Reg, Mem)) {
4625 0 : if (opData.n != 1)
4626 0 : goto InvalidInstruction;
4627 :
4628 : rmRel = &o1;
4629 : }
4630 0 : else if (isign4 == ENC_OPS3(Reg, Reg, Mem)) {
4631 0 : if (opData.n != 1 && opData.n != 2)
4632 0 : goto InvalidInstruction;
4633 :
4634 0 : if (!checkSignature(o0, o1) || !checkConsecutive(o0, o1))
4635 0 : goto InvalidInstruction;
4636 :
4637 : n = 2;
4638 : rmRel = &o2;
4639 : }
4640 0 : else if (isign4 == ENC_OPS4(Reg, Reg, Reg, Mem) && o4.isNone()) {
4641 0 : if (opData.n != 1 && opData.n != 3)
4642 0 : goto InvalidInstruction;
4643 :
4644 : if (!checkSignature(o0, o1, o2) || !checkConsecutive(o0, o1, o2))
4645 0 : goto InvalidInstruction;
4646 :
4647 : n = 3;
4648 : rmRel = &o3;
4649 : }
4650 0 : else if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg) && o4.isMem()) {
4651 0 : if (opData.n != 1 && opData.n != 4)
4652 0 : goto InvalidInstruction;
4653 :
4654 0 : if (!checkSignature(o0, o1, o2, o3) || !checkConsecutive(o0, o1, o2, o3))
4655 0 : goto InvalidInstruction;
4656 :
4657 : n = 4;
4658 : rmRel = &o4;
4659 : }
4660 : else {
4661 0 : goto InvalidInstruction;
4662 : }
4663 :
4664 : // We will use `v` and `m` from now as those are relevant for encoding.
4665 : const Vec& v = o0.as<Vec>();
4666 : const Mem& m = rmRel->as<Mem>();
4667 :
4668 : uint32_t q = 0;
4669 : uint32_t rm = 0;
4670 : uint32_t rn = m.baseId();
4671 0 : uint32_t sz = v.elementType() - Vec::kElementTypeB;
4672 : uint32_t opcSsize = sz;
4673 : uint32_t offsetPossibility = 0;
4674 :
4675 0 : if (sz > 3)
4676 0 : goto InvalidInstruction;
4677 :
4678 0 : if (m.baseType() != RegType::kARM_GpX)
4679 0 : goto InvalidAddress;
4680 :
4681 : // Rn cannot be ZR, but can be SP.
4682 0 : if (rn > 30 && rn != Gp::kIdSp)
4683 0 : goto InvalidAddress;
4684 :
4685 : rn &= 31;
4686 :
4687 0 : if (opData.replicate) {
4688 0 : if (n != opData.n)
4689 0 : goto InvalidInstruction;
4690 :
4691 : // Replicates to the whole register, element index cannot be used.
4692 0 : if (v.hasElementIndex())
4693 0 : goto InvalidInstruction;
4694 :
4695 : q = diff(v.type(), RegType::kARM_VecD);
4696 0 : if (q > 1)
4697 0 : goto InvalidInstruction;
4698 :
4699 0 : opcode.reset(uint32_t(opData.singleOp) << 10);
4700 0 : offsetPossibility = (1u << sz) * n;
4701 : }
4702 0 : else if (v.hasElementIndex()) {
4703 0 : if (n != opData.n)
4704 0 : goto InvalidInstruction;
4705 :
4706 : // LDx/STx (single structure).
4707 : static const uint8_t opcSsizeBySzS[] = { 0x0u << 3, 0x2u << 3, 0x4u << 3, (0x4u << 3) | 1u };
4708 :
4709 0 : opcode.reset(uint32_t(opData.singleOp) << 10);
4710 0 : opcSsize = opcSsizeBySzS[sz];
4711 0 : offsetPossibility = (1u << sz) * opData.n;
4712 :
4713 : uint32_t elementIndex = v.elementIndex();
4714 0 : uint32_t maxElementIndex = 15 >> sz;
4715 :
4716 0 : if (elementIndex > maxElementIndex)
4717 0 : goto InvalidElementIndex;
4718 :
4719 0 : elementIndex <<= sz;
4720 0 : q = elementIndex >> 3;
4721 0 : opcSsize |= elementIndex & 0x7u;
4722 : }
4723 : else {
4724 : // LDx/STx (multiple structures).
4725 : static const uint8_t opcSsizeByN[] = { 0u, 0x7u << 2, 0xAu << 2, 0x6u << 2, 0x2u << 2 };
4726 :
4727 : q = diff(v.type(), RegType::kARM_VecD);
4728 0 : if (q > 1)
4729 0 : goto InvalidInstruction;
4730 :
4731 0 : if (opData.n == 1)
4732 0 : opcSsize |= opcSsizeByN[n];
4733 :
4734 0 : opcode.reset(uint32_t(opData.multipleOp) << 10);
4735 0 : offsetPossibility = (8u << q) * n;
4736 : }
4737 :
4738 0 : if (m.hasIndex()) {
4739 0 : if (m.hasOffset() || !m.isPostIndex())
4740 0 : goto InvalidAddress;
4741 :
4742 : rm = m.indexId();
4743 0 : if (rm > 30)
4744 0 : goto InvalidAddress;
4745 :
4746 : // Bit 23 - PostIndex.
4747 : opcode |= B(23);
4748 : }
4749 : else {
4750 0 : if (m.hasOffset()) {
4751 0 : if (m.offset() != int32_t(offsetPossibility) || !m.isPostIndex())
4752 0 : goto InvalidAddress;
4753 : rm = 31;
4754 :
4755 : // Bit 23 - PostIndex.
4756 : opcode |= B(23);
4757 : }
4758 : }
4759 :
4760 : opcode.addImm(q, 30);
4761 : opcode.addImm(rm, 16);
4762 : opcode.addImm(opcSsize, 10);
4763 : opcode.addImm(rn, 5);
4764 0 : goto EmitOp_Rd0;
4765 : }
4766 :
4767 : default:
4768 : break;
4769 : }
4770 :
4771 0 : goto InvalidInstruction;
4772 :
4773 : // --------------------------------------------------------------------------
4774 : // [EmitGp - Single]
4775 : // --------------------------------------------------------------------------
4776 :
4777 0 : EmitOp_Rd0:
4778 0 : if (!checkValidRegs(o0))
4779 0 : goto InvalidPhysId;
4780 :
4781 : opcode.addReg(o0, 0);
4782 0 : goto EmitOp;
4783 :
4784 : EmitOp_Rn5:
4785 0 : if (!checkValidRegs(o0))
4786 0 : goto InvalidPhysId;
4787 :
4788 : opcode.addReg(o0, 5);
4789 0 : goto EmitOp;
4790 :
4791 0 : EmitOp_Rn5_Rm16:
4792 0 : if (!checkValidRegs(o0, o1))
4793 0 : goto InvalidPhysId;
4794 :
4795 : opcode.addReg(o0, 5);
4796 : opcode.addReg(o1, 16);
4797 0 : goto EmitOp;
4798 :
4799 0 : EmitOp_Rd0_Rn5:
4800 0 : if (!checkValidRegs(o0, o1))
4801 0 : goto InvalidPhysId;
4802 :
4803 : opcode.addReg(o0, 0);
4804 : opcode.addReg(o1, 5);
4805 0 : goto EmitOp;
4806 :
4807 0 : EmitOp_Rd0_Rn5_Rm16_Ra10:
4808 0 : if (!checkValidRegs(o0, o1, o2, o3))
4809 0 : goto InvalidPhysId;
4810 :
4811 : opcode.addReg(o0, 0);
4812 : opcode.addReg(o1, 5);
4813 : opcode.addReg(o2, 16);
4814 : opcode.addReg(o3, 10);
4815 0 : goto EmitOp;
4816 :
4817 0 : EmitOp_Rd0_Rn5_Rm16:
4818 0 : if (!checkValidRegs(o0, o1, o3))
4819 0 : goto InvalidPhysId;
4820 :
4821 : opcode.addReg(o0, 0);
4822 : opcode.addReg(o1, 5);
4823 : opcode.addReg(o2, 16);
4824 0 : goto EmitOp;
4825 :
4826 : // --------------------------------------------------------------------------
4827 : // [EmitGp - Multiple]
4828 : // --------------------------------------------------------------------------
4829 :
4830 : EmitOp_Multiple:
4831 : {
4832 : ASMJIT_ASSERT(multipleOpCount > 0);
4833 0 : err = writer.ensureSpace(this, multipleOpCount * 4u);
4834 0 : if (ASMJIT_UNLIKELY(err))
4835 0 : goto Failed;
4836 :
4837 0 : for (uint32_t i = 0; i < multipleOpCount; i++)
4838 0 : writer.emit32uLE(multipleOpData[i]);
4839 :
4840 0 : goto EmitDone;
4841 : }
4842 :
4843 : // --------------------------------------------------------------------------
4844 : // [EmitGp - Memory]
4845 : // --------------------------------------------------------------------------
4846 :
4847 0 : EmitOp_MemBase_Rn5:
4848 : if (!checkMemBase(rmRel->as<Mem>()))
4849 0 : goto InvalidAddress;
4850 :
4851 : opcode.addReg(rmRel->as<Mem>().baseId(), 5);
4852 0 : goto EmitOp;
4853 :
4854 0 : EmitOp_MemBaseNoImm_Rn5:
4855 0 : if (!checkMemBase(rmRel->as<Mem>()) || rmRel->as<Mem>().hasIndex())
4856 0 : goto InvalidAddress;
4857 :
4858 0 : if (rmRel->as<Mem>().hasOffset())
4859 0 : goto InvalidDisplacement;
4860 :
4861 : opcode.addReg(rmRel->as<Mem>().baseId(), 5);
4862 0 : goto EmitOp;
4863 :
4864 0 : EmitOp_MemBaseIndex_Rn5_Rm16:
4865 0 : if (!rmRel->as<Mem>().hasBaseReg())
4866 0 : goto InvalidAddress;
4867 :
4868 0 : if (rmRel->as<Mem>().indexId() > 30 && rmRel->as<Mem>().indexId() != Gp::kIdZr)
4869 0 : goto InvalidPhysId;
4870 :
4871 : opcode.addReg(rmRel->as<Mem>().indexId(), 16);
4872 : opcode.addReg(rmRel->as<Mem>().baseId(), 5);
4873 0 : goto EmitOp;
4874 :
4875 : // --------------------------------------------------------------------------
4876 : // [EmitOp - PC Relative]
4877 : // --------------------------------------------------------------------------
4878 :
4879 0 : EmitOp_Rel:
4880 : {
4881 0 : if (rmRel->isLabel() || rmRel->isMem()) {
4882 : uint32_t labelId;
4883 : int64_t labelOffset = 0;
4884 :
4885 0 : if (rmRel->isLabel()) {
4886 : labelId = rmRel->as<Label>().id();
4887 : }
4888 : else {
4889 : labelId = rmRel->as<Mem>().baseId();
4890 : labelOffset = rmRel->as<Mem>().offset();
4891 : }
4892 :
4893 0 : LabelEntry* label = _code->labelEntry(labelId);
4894 0 : if (ASMJIT_UNLIKELY(!label))
4895 0 : goto InvalidLabel;
4896 :
4897 : if (offsetFormat.type() == OffsetType::kAArch64_ADRP) {
4898 : // TODO: [ARM] Always create relocation entry.
4899 : }
4900 :
4901 0 : if (label->isBoundTo(_section)) {
4902 : // Label bound to the current section.
4903 0 : offsetValue = label->offset() - uint64_t(offset()) + uint64_t(labelOffset);
4904 0 : goto EmitOp_DispImm;
4905 : }
4906 : else {
4907 : // Record non-bound label.
4908 0 : size_t codeOffset = writer.offsetFrom(_bufferData);
4909 0 : LabelLink* link = _code->newLabelLink(label, _section->id(), codeOffset, intptr_t(labelOffset), offsetFormat);
4910 :
4911 0 : if (ASMJIT_UNLIKELY(!link))
4912 0 : goto OutOfMemory;
4913 :
4914 0 : goto EmitOp;
4915 : }
4916 : }
4917 : }
4918 :
4919 0 : if (rmRel->isImm()) {
4920 0 : uint64_t baseAddress = _code->baseAddress();
4921 : uint64_t targetOffset = rmRel->as<Imm>().valueAs<uint64_t>();
4922 :
4923 0 : size_t codeOffset = writer.offsetFrom(_bufferData);
4924 :
4925 0 : if (baseAddress == Globals::kNoBaseAddress || _section->id() != 0) {
4926 : // Create a new RelocEntry as we cannot calculate the offset right now.
4927 : RelocEntry* re;
4928 0 : err = _code->newRelocEntry(&re, RelocType::kAbsToRel);
4929 0 : if (err)
4930 0 : goto Failed;
4931 :
4932 0 : re->_sourceSectionId = _section->id();
4933 0 : re->_sourceOffset = codeOffset;
4934 0 : re->_format = offsetFormat;
4935 0 : re->_payload = rmRel->as<Imm>().valueAs<uint64_t>() + 4u;
4936 0 : goto EmitOp;
4937 : }
4938 : else {
4939 0 : uint64_t pc = baseAddress + codeOffset;
4940 :
4941 0 : if (offsetFormat.type() == OffsetType::kAArch64_ADRP)
4942 0 : pc &= ~uint64_t(4096 - 1);
4943 :
4944 0 : offsetValue = targetOffset - pc;
4945 0 : goto EmitOp_DispImm;
4946 : }
4947 : }
4948 :
4949 0 : goto InvalidInstruction;
4950 :
4951 0 : EmitOp_DispImm:
4952 : {
4953 0 : if ((offsetValue & Support::lsbMask<uint32_t>(offsetFormat.immDiscardLsb())) != 0)
4954 0 : goto InvalidDisplacement;
4955 :
4956 0 : int64_t dispImm64 = int64_t(offsetValue) >> offsetFormat.immDiscardLsb();
4957 0 : if (!Support::isEncodableOffset64(dispImm64, offsetFormat.immBitCount()))
4958 0 : goto InvalidDisplacement;
4959 :
4960 0 : uint32_t dispImm32 = uint32_t(dispImm64 & Support::lsbMask<uint32_t>(offsetFormat.immBitCount()));
4961 0 : switch (offsetFormat.type()) {
4962 : case OffsetType::kSignedOffset: {
4963 : opcode.addImm(dispImm32, offsetFormat.immBitShift());
4964 0 : goto EmitOp;
4965 : }
4966 :
4967 0 : case OffsetType::kAArch64_ADR:
4968 : case OffsetType::kAArch64_ADRP: {
4969 : uint32_t immLo = dispImm32 & 0x3u;
4970 0 : uint32_t immHi = dispImm32 >> 2;
4971 : opcode.addImm(immLo, 29);
4972 : opcode.addImm(immHi, 5);
4973 0 : goto EmitOp;
4974 : }
4975 :
4976 0 : default:
4977 0 : goto InvalidDisplacement;
4978 : }
4979 : }
4980 :
4981 : // --------------------------------------------------------------------------
4982 : // [EmitOp - Opcode]
4983 : // --------------------------------------------------------------------------
4984 :
4985 0 : EmitOp:
4986 : writer.emit32uLE(opcode.get());
4987 0 : goto EmitDone;
4988 :
4989 : // --------------------------------------------------------------------------
4990 : // [Done]
4991 : // --------------------------------------------------------------------------
4992 :
4993 0 : EmitDone:
4994 0 : if (Support::test(options, InstOptions::kReserved)) {
4995 : #ifndef ASMJIT_NO_LOGGING
4996 0 : if (_logger)
4997 0 : EmitterUtils::logInstructionEmitted(this, BaseInst::composeARMInstId(instId, instCC), options, o0, o1, o2, opExt, 0, 0, writer.cursor());
4998 : #endif
4999 : }
5000 :
5001 : resetExtraReg();
5002 : resetInstOptions();
5003 : resetInlineComment();
5004 :
5005 : writer.done(this);
5006 0 : return kErrorOk;
5007 :
5008 : // --------------------------------------------------------------------------
5009 : // [Error Handler]
5010 : // --------------------------------------------------------------------------
5011 :
5012 : #define ERROR_HANDLER(ERR) ERR: err = DebugUtils::errored(kError##ERR); goto Failed;
5013 0 : ERROR_HANDLER(OutOfMemory)
5014 0 : ERROR_HANDLER(InvalidAddress)
5015 0 : ERROR_HANDLER(InvalidAddressScale)
5016 0 : ERROR_HANDLER(InvalidDisplacement)
5017 0 : ERROR_HANDLER(InvalidElementIndex)
5018 0 : ERROR_HANDLER(InvalidLabel)
5019 0 : ERROR_HANDLER(InvalidImmediate)
5020 0 : ERROR_HANDLER(InvalidInstruction)
5021 0 : ERROR_HANDLER(InvalidPhysId)
5022 0 : ERROR_HANDLER(InvalidRegType)
5023 : #undef ERROR_HANDLER
5024 :
5025 0 : Failed:
5026 : #ifndef ASMJIT_NO_LOGGING
5027 0 : return EmitterUtils::logInstructionFailed(this, err, instId, options, o0, o1, o2, opExt);
5028 : #else
5029 : resetExtraReg();
5030 : resetInstOptions();
5031 : resetInlineComment();
5032 : return reportError(err);
5033 : #endif
5034 : }
5035 :
5036 : #undef ENC_OPS1
5037 : #undef ENC_OPS2
5038 : #undef ENC_OPS3
5039 : #undef ENC_OPS4
5040 :
5041 : // a64::Assembler - Align
5042 : // ======================
5043 :
5044 0 : Error Assembler::align(AlignMode alignMode, uint32_t alignment) {
5045 : constexpr uint32_t kNopA64 = 0xD503201Fu; // [11010101|00000011|00100000|00011111].
5046 :
5047 0 : if (ASMJIT_UNLIKELY(!_code))
5048 0 : return reportError(DebugUtils::errored(kErrorNotInitialized));
5049 :
5050 0 : if (ASMJIT_UNLIKELY(uint32_t(alignMode) > uint32_t(AlignMode::kMaxValue)))
5051 0 : return reportError(DebugUtils::errored(kErrorInvalidArgument));
5052 :
5053 0 : if (alignment <= 1)
5054 : return kErrorOk;
5055 :
5056 0 : if (ASMJIT_UNLIKELY(alignment > Globals::kMaxAlignment || !Support::isPowerOf2(alignment)))
5057 0 : return reportError(DebugUtils::errored(kErrorInvalidArgument));
5058 :
5059 0 : uint32_t i = uint32_t(Support::alignUpDiff<size_t>(offset(), alignment));
5060 0 : if (i == 0)
5061 : return kErrorOk;
5062 :
5063 : CodeWriter writer(this);
5064 0 : ASMJIT_PROPAGATE(writer.ensureSpace(this, i));
5065 :
5066 0 : switch (alignMode) {
5067 0 : case AlignMode::kCode: {
5068 : uint32_t pattern = kNopA64;
5069 :
5070 0 : if (ASMJIT_UNLIKELY(offset() & 0x3u))
5071 : return DebugUtils::errored(kErrorInvalidState);
5072 :
5073 0 : while (i >= 4) {
5074 : writer.emit32uLE(pattern);
5075 0 : i -= 4;
5076 : }
5077 :
5078 : ASMJIT_ASSERT(i == 0);
5079 : break;
5080 : }
5081 :
5082 0 : case AlignMode::kData:
5083 : case AlignMode::kZero:
5084 : writer.emitZeros(i);
5085 : break;
5086 : }
5087 :
5088 : writer.done(this);
5089 :
5090 : #ifndef ASMJIT_NO_LOGGING
5091 0 : if (_logger) {
5092 : StringTmp<128> sb;
5093 0 : sb.appendChars(' ', _logger->indentation(FormatIndentationGroup::kCode));
5094 : sb.appendFormat("align %u\n", alignment);
5095 0 : _logger->log(sb);
5096 : }
5097 : #endif
5098 :
5099 : return kErrorOk;
5100 : }
5101 :
5102 : // a64::Assembler - Events
5103 : // =======================
5104 :
5105 0 : Error Assembler::onAttach(CodeHolder* code) noexcept {
5106 0 : ASMJIT_PROPAGATE(Base::onAttach(code));
5107 : return kErrorOk;
5108 : }
5109 :
5110 0 : Error Assembler::onDetach(CodeHolder* code) noexcept {
5111 0 : return Base::onDetach(code);
5112 : }
5113 :
5114 : ASMJIT_END_SUB_NAMESPACE
5115 :
5116 : #endif // !ASMJIT_NO_AARCH64
5117 :
5118 : #endif // __PLUMED_HAS_ASMJIT
|