1 //===- AArch64AddressingModes.h - AArch64 Addressing Modes ------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file contains the AArch64 addressing mode implementation stuff.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64ADDRESSINGMODES_H
14 #define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64ADDRESSINGMODES_H
16 #include "llvm/ADT/APFloat.h"
17 #include "llvm/ADT/APInt.h"
18 #include "llvm/ADT/bit.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include "llvm/Support/MathExtras.h"
25 /// AArch64_AM - AArch64 Addressing Mode Stuff
26 namespace AArch64_AM
{
28 //===----------------------------------------------------------------------===//
32 enum ShiftExtendType
{
33 InvalidShiftExtend
= -1,
51 /// getShiftName - Get the string encoding for the shift type.
52 static inline const char *getShiftExtendName(AArch64_AM::ShiftExtendType ST
) {
54 default: llvm_unreachable("unhandled shift type!");
55 case AArch64_AM::LSL
: return "lsl";
56 case AArch64_AM::LSR
: return "lsr";
57 case AArch64_AM::ASR
: return "asr";
58 case AArch64_AM::ROR
: return "ror";
59 case AArch64_AM::MSL
: return "msl";
60 case AArch64_AM::UXTB
: return "uxtb";
61 case AArch64_AM::UXTH
: return "uxth";
62 case AArch64_AM::UXTW
: return "uxtw";
63 case AArch64_AM::UXTX
: return "uxtx";
64 case AArch64_AM::SXTB
: return "sxtb";
65 case AArch64_AM::SXTH
: return "sxth";
66 case AArch64_AM::SXTW
: return "sxtw";
67 case AArch64_AM::SXTX
: return "sxtx";
72 /// getShiftType - Extract the shift type.
73 static inline AArch64_AM::ShiftExtendType
getShiftType(unsigned Imm
) {
74 switch ((Imm
>> 6) & 0x7) {
75 default: return AArch64_AM::InvalidShiftExtend
;
76 case 0: return AArch64_AM::LSL
;
77 case 1: return AArch64_AM::LSR
;
78 case 2: return AArch64_AM::ASR
;
79 case 3: return AArch64_AM::ROR
;
80 case 4: return AArch64_AM::MSL
;
84 /// getShiftValue - Extract the shift value.
85 static inline unsigned getShiftValue(unsigned Imm
) {
89 /// getShifterImm - Encode the shift type and amount:
90 /// imm: 6-bit shift amount
91 /// shifter: 000 ==> lsl
98 static inline unsigned getShifterImm(AArch64_AM::ShiftExtendType ST
,
100 assert((Imm
& 0x3f) == Imm
&& "Illegal shifted immedate value!");
103 default: llvm_unreachable("Invalid shift requested");
104 case AArch64_AM::LSL
: STEnc
= 0; break;
105 case AArch64_AM::LSR
: STEnc
= 1; break;
106 case AArch64_AM::ASR
: STEnc
= 2; break;
107 case AArch64_AM::ROR
: STEnc
= 3; break;
108 case AArch64_AM::MSL
: STEnc
= 4; break;
110 return (STEnc
<< 6) | (Imm
& 0x3f);
113 //===----------------------------------------------------------------------===//
117 /// getArithShiftValue - get the arithmetic shift value.
118 static inline unsigned getArithShiftValue(unsigned Imm
) {
122 /// getExtendType - Extract the extend type for operands of arithmetic ops.
123 static inline AArch64_AM::ShiftExtendType
getExtendType(unsigned Imm
) {
124 assert((Imm
& 0x7) == Imm
&& "invalid immediate!");
126 default: llvm_unreachable("Compiler bug!");
127 case 0: return AArch64_AM::UXTB
;
128 case 1: return AArch64_AM::UXTH
;
129 case 2: return AArch64_AM::UXTW
;
130 case 3: return AArch64_AM::UXTX
;
131 case 4: return AArch64_AM::SXTB
;
132 case 5: return AArch64_AM::SXTH
;
133 case 6: return AArch64_AM::SXTW
;
134 case 7: return AArch64_AM::SXTX
;
138 static inline AArch64_AM::ShiftExtendType
getArithExtendType(unsigned Imm
) {
139 return getExtendType((Imm
>> 3) & 0x7);
142 /// Mapping from extend bits to required operation:
143 /// shifter: 000 ==> uxtb
151 inline unsigned getExtendEncoding(AArch64_AM::ShiftExtendType ET
) {
153 default: llvm_unreachable("Invalid extend type requested");
154 case AArch64_AM::UXTB
: return 0; break;
155 case AArch64_AM::UXTH
: return 1; break;
156 case AArch64_AM::UXTW
: return 2; break;
157 case AArch64_AM::UXTX
: return 3; break;
158 case AArch64_AM::SXTB
: return 4; break;
159 case AArch64_AM::SXTH
: return 5; break;
160 case AArch64_AM::SXTW
: return 6; break;
161 case AArch64_AM::SXTX
: return 7; break;
165 /// getArithExtendImm - Encode the extend type and shift amount for an
166 /// arithmetic instruction:
167 /// imm: 3-bit extend amount
170 static inline unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET
,
172 assert((Imm
& 0x7) == Imm
&& "Illegal shifted immedate value!");
173 return (getExtendEncoding(ET
) << 3) | (Imm
& 0x7);
176 /// getMemDoShift - Extract the "do shift" flag value for load/store
178 static inline bool getMemDoShift(unsigned Imm
) {
179 return (Imm
& 0x1) != 0;
182 /// getExtendType - Extract the extend type for the offset operand of
184 static inline AArch64_AM::ShiftExtendType
getMemExtendType(unsigned Imm
) {
185 return getExtendType((Imm
>> 1) & 0x7);
188 /// getExtendImm - Encode the extend type and amount for a load/store inst:
189 /// doshift: should the offset be scaled by the access size
190 /// shifter: 000 ==> uxtb
200 static inline unsigned getMemExtendImm(AArch64_AM::ShiftExtendType ET
,
202 return (getExtendEncoding(ET
) << 1) | unsigned(DoShift
);
205 static inline uint64_t ror(uint64_t elt
, unsigned size
) {
206 return ((elt
& 1) << (size
-1)) | (elt
>> 1);
209 /// processLogicalImmediate - Determine if an immediate value can be encoded
210 /// as the immediate operand of a logical instruction for the given register
211 /// size. If so, return true with "encoding" set to the encoded value in
212 /// the form N:immr:imms.
213 static inline bool processLogicalImmediate(uint64_t Imm
, unsigned RegSize
,
214 uint64_t &Encoding
) {
215 if (Imm
== 0ULL || Imm
== ~0ULL ||
217 (Imm
>> RegSize
!= 0 || Imm
== (~0ULL >> (64 - RegSize
)))))
220 // First, determine the element size.
221 unsigned Size
= RegSize
;
225 uint64_t Mask
= (1ULL << Size
) - 1;
227 if ((Imm
& Mask
) != ((Imm
>> Size
) & Mask
)) {
233 // Second, determine the rotation to make the element be: 0^m 1^n.
235 uint64_t Mask
= ((uint64_t)-1LL) >> (64 - Size
);
238 if (isShiftedMask_64(Imm
)) {
239 I
= countTrailingZeros(Imm
);
240 assert(I
< 64 && "undefined behavior");
241 CTO
= countTrailingOnes(Imm
>> I
);
244 if (!isShiftedMask_64(~Imm
))
247 unsigned CLO
= countLeadingOnes(Imm
);
249 CTO
= CLO
+ countTrailingOnes(Imm
) - (64 - Size
);
252 // Encode in Immr the number of RORs it would take to get *from* 0^m 1^n
253 // to our target value, where I is the number of RORs to go the opposite
255 assert(Size
> I
&& "I should be smaller than element size");
256 unsigned Immr
= (Size
- I
) & (Size
- 1);
258 // If size has a 1 in the n'th bit, create a value that has zeroes in
259 // bits [0, n] and ones above that.
260 uint64_t NImms
= ~(Size
-1) << 1;
262 // Or the CTO value into the low bits, which must be below the Nth bit
263 // bit mentioned above.
266 // Extract the seventh bit and toggle it to create the N field.
267 unsigned N
= ((NImms
>> 6) & 1) ^ 1;
269 Encoding
= (N
<< 12) | (Immr
<< 6) | (NImms
& 0x3f);
273 /// isLogicalImmediate - Return true if the immediate is valid for a logical
274 /// immediate instruction of the given register size. Return false otherwise.
275 static inline bool isLogicalImmediate(uint64_t imm
, unsigned regSize
) {
277 return processLogicalImmediate(imm
, regSize
, encoding
);
280 /// encodeLogicalImmediate - Return the encoded immediate value for a logical
281 /// immediate instruction of the given register size.
282 static inline uint64_t encodeLogicalImmediate(uint64_t imm
, unsigned regSize
) {
283 uint64_t encoding
= 0;
284 bool res
= processLogicalImmediate(imm
, regSize
, encoding
);
285 assert(res
&& "invalid logical immediate");
290 /// decodeLogicalImmediate - Decode a logical immediate value in the form
291 /// "N:immr:imms" (where the immr and imms fields are each 6 bits) into the
292 /// integer value it represents with regSize bits.
293 static inline uint64_t decodeLogicalImmediate(uint64_t val
, unsigned regSize
) {
294 // Extract the N, imms, and immr fields.
295 unsigned N
= (val
>> 12) & 1;
296 unsigned immr
= (val
>> 6) & 0x3f;
297 unsigned imms
= val
& 0x3f;
299 assert((regSize
== 64 || N
== 0) && "undefined logical immediate encoding");
300 int len
= 31 - countLeadingZeros((N
<< 6) | (~imms
& 0x3f));
301 assert(len
>= 0 && "undefined logical immediate encoding");
302 unsigned size
= (1 << len
);
303 unsigned R
= immr
& (size
- 1);
304 unsigned S
= imms
& (size
- 1);
305 assert(S
!= size
- 1 && "undefined logical immediate encoding");
306 uint64_t pattern
= (1ULL << (S
+ 1)) - 1;
307 for (unsigned i
= 0; i
< R
; ++i
)
308 pattern
= ror(pattern
, size
);
310 // Replicate the pattern to fill the regSize.
311 while (size
!= regSize
) {
312 pattern
|= (pattern
<< size
);
318 /// isValidDecodeLogicalImmediate - Check to see if the logical immediate value
319 /// in the form "N:immr:imms" (where the immr and imms fields are each 6 bits)
320 /// is a valid encoding for an integer value with regSize bits.
321 static inline bool isValidDecodeLogicalImmediate(uint64_t val
,
323 // Extract the N and imms fields needed for checking.
324 unsigned N
= (val
>> 12) & 1;
325 unsigned imms
= val
& 0x3f;
327 if (regSize
== 32 && N
!= 0) // undefined logical immediate encoding
329 int len
= 31 - countLeadingZeros((N
<< 6) | (~imms
& 0x3f));
330 if (len
< 0) // undefined logical immediate encoding
332 unsigned size
= (1 << len
);
333 unsigned S
= imms
& (size
- 1);
334 if (S
== size
- 1) // undefined logical immediate encoding
340 //===----------------------------------------------------------------------===//
341 // Floating-point Immediates
343 static inline float getFPImmFloat(unsigned Imm
) {
344 // We expect an 8-bit binary encoding of a floating-point number here.
346 uint8_t Sign
= (Imm
>> 7) & 0x1;
347 uint8_t Exp
= (Imm
>> 4) & 0x7;
348 uint8_t Mantissa
= Imm
& 0xf;
350 // 8-bit FP IEEE Float Encoding
351 // abcd efgh aBbbbbbc defgh000 00000000 00000000
357 I
|= ((Exp
& 0x4) != 0 ? 0 : 1) << 30;
358 I
|= ((Exp
& 0x4) != 0 ? 0x1f : 0) << 25;
359 I
|= (Exp
& 0x3) << 23;
361 return bit_cast
<float>(I
);
364 /// getFP16Imm - Return an 8-bit floating-point version of the 16-bit
365 /// floating-point value. If the value cannot be represented as an 8-bit
366 /// floating-point value, then return -1.
367 static inline int getFP16Imm(const APInt
&Imm
) {
368 uint32_t Sign
= Imm
.lshr(15).getZExtValue() & 1;
369 int32_t Exp
= (Imm
.lshr(10).getSExtValue() & 0x1f) - 15; // -14 to 15
370 int32_t Mantissa
= Imm
.getZExtValue() & 0x3ff; // 10 bits
372 // We can handle 4 bits of mantissa.
373 // mantissa = (16+UInt(e:f:g:h))/16.
378 // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3
379 if (Exp
< -3 || Exp
> 4)
381 Exp
= ((Exp
+3) & 0x7) ^ 4;
383 return ((int)Sign
<< 7) | (Exp
<< 4) | Mantissa
;
386 static inline int getFP16Imm(const APFloat
&FPImm
) {
387 return getFP16Imm(FPImm
.bitcastToAPInt());
390 /// getFP32Imm - Return an 8-bit floating-point version of the 32-bit
391 /// floating-point value. If the value cannot be represented as an 8-bit
392 /// floating-point value, then return -1.
393 static inline int getFP32Imm(const APInt
&Imm
) {
394 uint32_t Sign
= Imm
.lshr(31).getZExtValue() & 1;
395 int32_t Exp
= (Imm
.lshr(23).getSExtValue() & 0xff) - 127; // -126 to 127
396 int64_t Mantissa
= Imm
.getZExtValue() & 0x7fffff; // 23 bits
398 // We can handle 4 bits of mantissa.
399 // mantissa = (16+UInt(e:f:g:h))/16.
400 if (Mantissa
& 0x7ffff)
403 if ((Mantissa
& 0xf) != Mantissa
)
406 // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3
407 if (Exp
< -3 || Exp
> 4)
409 Exp
= ((Exp
+3) & 0x7) ^ 4;
411 return ((int)Sign
<< 7) | (Exp
<< 4) | Mantissa
;
414 static inline int getFP32Imm(const APFloat
&FPImm
) {
415 return getFP32Imm(FPImm
.bitcastToAPInt());
418 /// getFP64Imm - Return an 8-bit floating-point version of the 64-bit
419 /// floating-point value. If the value cannot be represented as an 8-bit
420 /// floating-point value, then return -1.
421 static inline int getFP64Imm(const APInt
&Imm
) {
422 uint64_t Sign
= Imm
.lshr(63).getZExtValue() & 1;
423 int64_t Exp
= (Imm
.lshr(52).getSExtValue() & 0x7ff) - 1023; // -1022 to 1023
424 uint64_t Mantissa
= Imm
.getZExtValue() & 0xfffffffffffffULL
;
426 // We can handle 4 bits of mantissa.
427 // mantissa = (16+UInt(e:f:g:h))/16.
428 if (Mantissa
& 0xffffffffffffULL
)
431 if ((Mantissa
& 0xf) != Mantissa
)
434 // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3
435 if (Exp
< -3 || Exp
> 4)
437 Exp
= ((Exp
+3) & 0x7) ^ 4;
439 return ((int)Sign
<< 7) | (Exp
<< 4) | Mantissa
;
442 static inline int getFP64Imm(const APFloat
&FPImm
) {
443 return getFP64Imm(FPImm
.bitcastToAPInt());
446 //===--------------------------------------------------------------------===//
447 // AdvSIMD Modified Immediates
448 //===--------------------------------------------------------------------===//
450 // 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh
451 static inline bool isAdvSIMDModImmType1(uint64_t Imm
) {
452 return ((Imm
>> 32) == (Imm
& 0xffffffffULL
)) &&
453 ((Imm
& 0xffffff00ffffff00ULL
) == 0);
456 static inline uint8_t encodeAdvSIMDModImmType1(uint64_t Imm
) {
457 return (Imm
& 0xffULL
);
460 static inline uint64_t decodeAdvSIMDModImmType1(uint8_t Imm
) {
461 uint64_t EncVal
= Imm
;
462 return (EncVal
<< 32) | EncVal
;
465 // 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00
466 static inline bool isAdvSIMDModImmType2(uint64_t Imm
) {
467 return ((Imm
>> 32) == (Imm
& 0xffffffffULL
)) &&
468 ((Imm
& 0xffff00ffffff00ffULL
) == 0);
471 static inline uint8_t encodeAdvSIMDModImmType2(uint64_t Imm
) {
472 return (Imm
& 0xff00ULL
) >> 8;
475 static inline uint64_t decodeAdvSIMDModImmType2(uint8_t Imm
) {
476 uint64_t EncVal
= Imm
;
477 return (EncVal
<< 40) | (EncVal
<< 8);
480 // 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00
481 static inline bool isAdvSIMDModImmType3(uint64_t Imm
) {
482 return ((Imm
>> 32) == (Imm
& 0xffffffffULL
)) &&
483 ((Imm
& 0xff00ffffff00ffffULL
) == 0);
486 static inline uint8_t encodeAdvSIMDModImmType3(uint64_t Imm
) {
487 return (Imm
& 0xff0000ULL
) >> 16;
490 static inline uint64_t decodeAdvSIMDModImmType3(uint8_t Imm
) {
491 uint64_t EncVal
= Imm
;
492 return (EncVal
<< 48) | (EncVal
<< 16);
495 // abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00
496 static inline bool isAdvSIMDModImmType4(uint64_t Imm
) {
497 return ((Imm
>> 32) == (Imm
& 0xffffffffULL
)) &&
498 ((Imm
& 0x00ffffff00ffffffULL
) == 0);
501 static inline uint8_t encodeAdvSIMDModImmType4(uint64_t Imm
) {
502 return (Imm
& 0xff000000ULL
) >> 24;
505 static inline uint64_t decodeAdvSIMDModImmType4(uint8_t Imm
) {
506 uint64_t EncVal
= Imm
;
507 return (EncVal
<< 56) | (EncVal
<< 24);
510 // 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh
511 static inline bool isAdvSIMDModImmType5(uint64_t Imm
) {
512 return ((Imm
>> 32) == (Imm
& 0xffffffffULL
)) &&
513 (((Imm
& 0x00ff0000ULL
) >> 16) == (Imm
& 0x000000ffULL
)) &&
514 ((Imm
& 0xff00ff00ff00ff00ULL
) == 0);
517 static inline uint8_t encodeAdvSIMDModImmType5(uint64_t Imm
) {
518 return (Imm
& 0xffULL
);
521 static inline uint64_t decodeAdvSIMDModImmType5(uint8_t Imm
) {
522 uint64_t EncVal
= Imm
;
523 return (EncVal
<< 48) | (EncVal
<< 32) | (EncVal
<< 16) | EncVal
;
526 // abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00
527 static inline bool isAdvSIMDModImmType6(uint64_t Imm
) {
528 return ((Imm
>> 32) == (Imm
& 0xffffffffULL
)) &&
529 (((Imm
& 0xff000000ULL
) >> 16) == (Imm
& 0x0000ff00ULL
)) &&
530 ((Imm
& 0x00ff00ff00ff00ffULL
) == 0);
533 static inline uint8_t encodeAdvSIMDModImmType6(uint64_t Imm
) {
534 return (Imm
& 0xff00ULL
) >> 8;
537 static inline uint64_t decodeAdvSIMDModImmType6(uint8_t Imm
) {
538 uint64_t EncVal
= Imm
;
539 return (EncVal
<< 56) | (EncVal
<< 40) | (EncVal
<< 24) | (EncVal
<< 8);
542 // 0x00 0x00 abcdefgh 0xFF 0x00 0x00 abcdefgh 0xFF
543 static inline bool isAdvSIMDModImmType7(uint64_t Imm
) {
544 return ((Imm
>> 32) == (Imm
& 0xffffffffULL
)) &&
545 ((Imm
& 0xffff00ffffff00ffULL
) == 0x000000ff000000ffULL
);
548 static inline uint8_t encodeAdvSIMDModImmType7(uint64_t Imm
) {
549 return (Imm
& 0xff00ULL
) >> 8;
552 static inline uint64_t decodeAdvSIMDModImmType7(uint8_t Imm
) {
553 uint64_t EncVal
= Imm
;
554 return (EncVal
<< 40) | (EncVal
<< 8) | 0x000000ff000000ffULL
;
557 // 0x00 abcdefgh 0xFF 0xFF 0x00 abcdefgh 0xFF 0xFF
558 static inline bool isAdvSIMDModImmType8(uint64_t Imm
) {
559 return ((Imm
>> 32) == (Imm
& 0xffffffffULL
)) &&
560 ((Imm
& 0xff00ffffff00ffffULL
) == 0x0000ffff0000ffffULL
);
563 static inline uint64_t decodeAdvSIMDModImmType8(uint8_t Imm
) {
564 uint64_t EncVal
= Imm
;
565 return (EncVal
<< 48) | (EncVal
<< 16) | 0x0000ffff0000ffffULL
;
568 static inline uint8_t encodeAdvSIMDModImmType8(uint64_t Imm
) {
569 return (Imm
& 0x00ff0000ULL
) >> 16;
572 // abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh
573 static inline bool isAdvSIMDModImmType9(uint64_t Imm
) {
574 return ((Imm
>> 32) == (Imm
& 0xffffffffULL
)) &&
575 ((Imm
>> 48) == (Imm
& 0x0000ffffULL
)) &&
576 ((Imm
>> 56) == (Imm
& 0x000000ffULL
));
579 static inline uint8_t encodeAdvSIMDModImmType9(uint64_t Imm
) {
580 return (Imm
& 0xffULL
);
583 static inline uint64_t decodeAdvSIMDModImmType9(uint8_t Imm
) {
584 uint64_t EncVal
= Imm
;
585 EncVal
|= (EncVal
<< 8);
586 EncVal
|= (EncVal
<< 16);
587 EncVal
|= (EncVal
<< 32);
591 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
592 // cmode: 1110, op: 1
593 static inline bool isAdvSIMDModImmType10(uint64_t Imm
) {
594 uint64_t ByteA
= Imm
& 0xff00000000000000ULL
;
595 uint64_t ByteB
= Imm
& 0x00ff000000000000ULL
;
596 uint64_t ByteC
= Imm
& 0x0000ff0000000000ULL
;
597 uint64_t ByteD
= Imm
& 0x000000ff00000000ULL
;
598 uint64_t ByteE
= Imm
& 0x00000000ff000000ULL
;
599 uint64_t ByteF
= Imm
& 0x0000000000ff0000ULL
;
600 uint64_t ByteG
= Imm
& 0x000000000000ff00ULL
;
601 uint64_t ByteH
= Imm
& 0x00000000000000ffULL
;
603 return (ByteA
== 0ULL || ByteA
== 0xff00000000000000ULL
) &&
604 (ByteB
== 0ULL || ByteB
== 0x00ff000000000000ULL
) &&
605 (ByteC
== 0ULL || ByteC
== 0x0000ff0000000000ULL
) &&
606 (ByteD
== 0ULL || ByteD
== 0x000000ff00000000ULL
) &&
607 (ByteE
== 0ULL || ByteE
== 0x00000000ff000000ULL
) &&
608 (ByteF
== 0ULL || ByteF
== 0x0000000000ff0000ULL
) &&
609 (ByteG
== 0ULL || ByteG
== 0x000000000000ff00ULL
) &&
610 (ByteH
== 0ULL || ByteH
== 0x00000000000000ffULL
);
613 static inline uint8_t encodeAdvSIMDModImmType10(uint64_t Imm
) {
614 uint8_t BitA
= (Imm
& 0xff00000000000000ULL
) != 0;
615 uint8_t BitB
= (Imm
& 0x00ff000000000000ULL
) != 0;
616 uint8_t BitC
= (Imm
& 0x0000ff0000000000ULL
) != 0;
617 uint8_t BitD
= (Imm
& 0x000000ff00000000ULL
) != 0;
618 uint8_t BitE
= (Imm
& 0x00000000ff000000ULL
) != 0;
619 uint8_t BitF
= (Imm
& 0x0000000000ff0000ULL
) != 0;
620 uint8_t BitG
= (Imm
& 0x000000000000ff00ULL
) != 0;
621 uint8_t BitH
= (Imm
& 0x00000000000000ffULL
) != 0;
623 uint8_t EncVal
= BitA
;
641 static inline uint64_t decodeAdvSIMDModImmType10(uint8_t Imm
) {
643 if (Imm
& 0x80) EncVal
|= 0xff00000000000000ULL
;
644 if (Imm
& 0x40) EncVal
|= 0x00ff000000000000ULL
;
645 if (Imm
& 0x20) EncVal
|= 0x0000ff0000000000ULL
;
646 if (Imm
& 0x10) EncVal
|= 0x000000ff00000000ULL
;
647 if (Imm
& 0x08) EncVal
|= 0x00000000ff000000ULL
;
648 if (Imm
& 0x04) EncVal
|= 0x0000000000ff0000ULL
;
649 if (Imm
& 0x02) EncVal
|= 0x000000000000ff00ULL
;
650 if (Imm
& 0x01) EncVal
|= 0x00000000000000ffULL
;
654 // aBbbbbbc defgh000 0x00 0x00 aBbbbbbc defgh000 0x00 0x00
655 static inline bool isAdvSIMDModImmType11(uint64_t Imm
) {
656 uint64_t BString
= (Imm
& 0x7E000000ULL
) >> 25;
657 return ((Imm
>> 32) == (Imm
& 0xffffffffULL
)) &&
658 (BString
== 0x1f || BString
== 0x20) &&
659 ((Imm
& 0x0007ffff0007ffffULL
) == 0);
662 static inline uint8_t encodeAdvSIMDModImmType11(uint64_t Imm
) {
663 uint8_t BitA
= (Imm
& 0x80000000ULL
) != 0;
664 uint8_t BitB
= (Imm
& 0x20000000ULL
) != 0;
665 uint8_t BitC
= (Imm
& 0x01000000ULL
) != 0;
666 uint8_t BitD
= (Imm
& 0x00800000ULL
) != 0;
667 uint8_t BitE
= (Imm
& 0x00400000ULL
) != 0;
668 uint8_t BitF
= (Imm
& 0x00200000ULL
) != 0;
669 uint8_t BitG
= (Imm
& 0x00100000ULL
) != 0;
670 uint8_t BitH
= (Imm
& 0x00080000ULL
) != 0;
672 uint8_t EncVal
= BitA
;
690 static inline uint64_t decodeAdvSIMDModImmType11(uint8_t Imm
) {
692 if (Imm
& 0x80) EncVal
|= 0x80000000ULL
;
693 if (Imm
& 0x40) EncVal
|= 0x3e000000ULL
;
694 else EncVal
|= 0x40000000ULL
;
695 if (Imm
& 0x20) EncVal
|= 0x01000000ULL
;
696 if (Imm
& 0x10) EncVal
|= 0x00800000ULL
;
697 if (Imm
& 0x08) EncVal
|= 0x00400000ULL
;
698 if (Imm
& 0x04) EncVal
|= 0x00200000ULL
;
699 if (Imm
& 0x02) EncVal
|= 0x00100000ULL
;
700 if (Imm
& 0x01) EncVal
|= 0x00080000ULL
;
701 return (EncVal
<< 32) | EncVal
;
704 // aBbbbbbb bbcdefgh 0x00 0x00 0x00 0x00 0x00 0x00
705 static inline bool isAdvSIMDModImmType12(uint64_t Imm
) {
706 uint64_t BString
= (Imm
& 0x7fc0000000000000ULL
) >> 54;
707 return ((BString
== 0xff || BString
== 0x100) &&
708 ((Imm
& 0x0000ffffffffffffULL
) == 0));
711 static inline uint8_t encodeAdvSIMDModImmType12(uint64_t Imm
) {
712 uint8_t BitA
= (Imm
& 0x8000000000000000ULL
) != 0;
713 uint8_t BitB
= (Imm
& 0x0040000000000000ULL
) != 0;
714 uint8_t BitC
= (Imm
& 0x0020000000000000ULL
) != 0;
715 uint8_t BitD
= (Imm
& 0x0010000000000000ULL
) != 0;
716 uint8_t BitE
= (Imm
& 0x0008000000000000ULL
) != 0;
717 uint8_t BitF
= (Imm
& 0x0004000000000000ULL
) != 0;
718 uint8_t BitG
= (Imm
& 0x0002000000000000ULL
) != 0;
719 uint8_t BitH
= (Imm
& 0x0001000000000000ULL
) != 0;
721 uint8_t EncVal
= BitA
;
739 static inline uint64_t decodeAdvSIMDModImmType12(uint8_t Imm
) {
741 if (Imm
& 0x80) EncVal
|= 0x8000000000000000ULL
;
742 if (Imm
& 0x40) EncVal
|= 0x3fc0000000000000ULL
;
743 else EncVal
|= 0x4000000000000000ULL
;
744 if (Imm
& 0x20) EncVal
|= 0x0020000000000000ULL
;
745 if (Imm
& 0x10) EncVal
|= 0x0010000000000000ULL
;
746 if (Imm
& 0x08) EncVal
|= 0x0008000000000000ULL
;
747 if (Imm
& 0x04) EncVal
|= 0x0004000000000000ULL
;
748 if (Imm
& 0x02) EncVal
|= 0x0002000000000000ULL
;
749 if (Imm
& 0x01) EncVal
|= 0x0001000000000000ULL
;
750 return (EncVal
<< 32) | EncVal
;
753 /// Returns true if Imm is the concatenation of a repeating pattern of type T.
754 template <typename T
>
755 static inline bool isSVEMaskOfIdenticalElements(int64_t Imm
) {
756 auto Parts
= bit_cast
<std::array
<T
, sizeof(int64_t) / sizeof(T
)>>(Imm
);
757 return all_of(Parts
, [&](T Elem
) { return Elem
== Parts
[0]; });
760 /// Returns true if Imm is valid for CPY/DUP.
761 template <typename T
>
762 static inline bool isSVECpyImm(int64_t Imm
) {
763 bool IsImm8
= int8_t(Imm
) == Imm
;
764 bool IsImm16
= int16_t(Imm
& ~0xff) == Imm
;
766 if (std::is_same
<int8_t, typename
std::make_signed
<T
>::type
>::value
)
767 return IsImm8
|| uint8_t(Imm
) == Imm
;
769 if (std::is_same
<int16_t, typename
std::make_signed
<T
>::type
>::value
)
770 return IsImm8
|| IsImm16
|| uint16_t(Imm
& ~0xff) == Imm
;
772 return IsImm8
|| IsImm16
;
775 /// Returns true if Imm is valid for ADD/SUB.
776 template <typename T
>
777 static inline bool isSVEAddSubImm(int64_t Imm
) {
779 std::is_same
<int8_t, typename
std::make_signed
<T
>::type
>::value
;
780 return uint8_t(Imm
) == Imm
|| (!IsInt8t
&& uint16_t(Imm
& ~0xff) == Imm
);
783 /// Return true if Imm is valid for DUPM and has no single CPY/DUP equivalent.
784 static inline bool isSVEMoveMaskPreferredLogicalImmediate(int64_t Imm
) {
785 if (isSVECpyImm
<int64_t>(Imm
))
788 auto S
= bit_cast
<std::array
<int32_t, 2>>(Imm
);
789 auto H
= bit_cast
<std::array
<int16_t, 4>>(Imm
);
790 auto B
= bit_cast
<std::array
<int8_t, 8>>(Imm
);
792 if (isSVEMaskOfIdenticalElements
<int32_t>(Imm
) && isSVECpyImm
<int32_t>(S
[0]))
794 if (isSVEMaskOfIdenticalElements
<int16_t>(Imm
) && isSVECpyImm
<int16_t>(H
[0]))
796 if (isSVEMaskOfIdenticalElements
<int8_t>(Imm
) && isSVECpyImm
<int8_t>(B
[0]))
798 return isLogicalImmediate(Imm
, 64);
801 inline static bool isAnyMOVZMovAlias(uint64_t Value
, int RegWidth
) {
802 for (int Shift
= 0; Shift
<= RegWidth
- 16; Shift
+= 16)
803 if ((Value
& ~(0xffffULL
<< Shift
)) == 0)
809 inline static bool isMOVZMovAlias(uint64_t Value
, int Shift
, int RegWidth
) {
811 Value
&= 0xffffffffULL
;
813 // "lsl #0" takes precedence: in practice this only affects "#0, lsl #0".
814 if (Value
== 0 && Shift
!= 0)
817 return (Value
& ~(0xffffULL
<< Shift
)) == 0;
820 inline static bool isMOVNMovAlias(uint64_t Value
, int Shift
, int RegWidth
) {
821 // MOVZ takes precedence over MOVN.
822 if (isAnyMOVZMovAlias(Value
, RegWidth
))
827 Value
&= 0xffffffffULL
;
829 return isMOVZMovAlias(Value
, Shift
, RegWidth
);
832 inline static bool isAnyMOVWMovAlias(uint64_t Value
, int RegWidth
) {
833 if (isAnyMOVZMovAlias(Value
, RegWidth
))
836 // It's not a MOVZ, but it might be a MOVN.
839 Value
&= 0xffffffffULL
;
841 return isAnyMOVZMovAlias(Value
, RegWidth
);
844 } // end namespace AArch64_AM
846 } // end namespace llvm