Path: blob/master/libs/capstone/arch/AArch64/AArch64AddressingModes.h
4393 views
//===- AArch64AddressingModes.h - AArch64 Addressing Modes ------*- C++ -*-===//1//2// The LLVM Compiler Infrastructure3//4// This file is distributed under the University of Illinois Open Source5// License. See LICENSE.TXT for details.6//7//===----------------------------------------------------------------------===//8//9// This file contains the AArch64 addressing mode implementation stuff.10//11//===----------------------------------------------------------------------===//1213#ifndef CS_AARCH64_ADDRESSINGMODES_H14#define CS_AARCH64_ADDRESSINGMODES_H1516/* Capstone Disassembly Engine */17/* By Nguyen Anh Quynh <[email protected]>, 2013-2019 */1819#include "../../MathExtras.h"2021/// AArch64_AM - AArch64 Addressing Mode Stuff2223//===----------------------------------------------------------------------===//24// Shifts25//26typedef enum AArch64_AM_ShiftExtendType {27AArch64_AM_InvalidShiftExtend = -1,28AArch64_AM_LSL = 0,29AArch64_AM_LSR,30AArch64_AM_ASR,31AArch64_AM_ROR,32AArch64_AM_MSL,3334AArch64_AM_UXTB,35AArch64_AM_UXTH,36AArch64_AM_UXTW,37AArch64_AM_UXTX,3839AArch64_AM_SXTB,40AArch64_AM_SXTH,41AArch64_AM_SXTW,42AArch64_AM_SXTX,43} AArch64_AM_ShiftExtendType;4445/// getShiftName - Get the string encoding for the shift type.46static inline const char *AArch64_AM_getShiftExtendName(AArch64_AM_ShiftExtendType ST)47{48switch (ST) {49default: return NULL; // never reach50case AArch64_AM_LSL: return "lsl";51case AArch64_AM_LSR: return "lsr";52case AArch64_AM_ASR: return "asr";53case AArch64_AM_ROR: return "ror";54case AArch64_AM_MSL: return "msl";55case AArch64_AM_UXTB: return "uxtb";56case AArch64_AM_UXTH: return "uxth";57case AArch64_AM_UXTW: return "uxtw";58case AArch64_AM_UXTX: return "uxtx";59case AArch64_AM_SXTB: return "sxtb";60case AArch64_AM_SXTH: return "sxth";61case AArch64_AM_SXTW: return "sxtw";62case AArch64_AM_SXTX: return "sxtx";63}64}6566/// getShiftType - Extract the shift type.67static inline AArch64_AM_ShiftExtendType AArch64_AM_getShiftType(unsigned Imm)68{69switch ((Imm >> 6) & 0x7) {70default: return AArch64_AM_InvalidShiftExtend;71case 0: return AArch64_AM_LSL;72case 1: return AArch64_AM_LSR;73case 2: return AArch64_AM_ASR;74case 3: return AArch64_AM_ROR;75case 4: return AArch64_AM_MSL;76}77}7879/// getShiftValue - Extract the shift value.80static inline unsigned AArch64_AM_getShiftValue(unsigned Imm)81{82return Imm & 0x3f;83}8485static inline unsigned AArch64_AM_getShifterImm(AArch64_AM_ShiftExtendType ST, unsigned Imm)86{87// assert((Imm & 0x3f) == Imm && "Illegal shifted immedate value!");88unsigned STEnc = 0;8990switch (ST) {91default: // llvm_unreachable("Invalid shift requested");92case AArch64_AM_LSL: STEnc = 0; break;93case AArch64_AM_LSR: STEnc = 1; break;94case AArch64_AM_ASR: STEnc = 2; break;95case AArch64_AM_ROR: STEnc = 3; break;96case AArch64_AM_MSL: STEnc = 4; break;97}9899return (STEnc << 6) | (Imm & 0x3f);100}101102//===----------------------------------------------------------------------===//103// Extends104//105106/// getArithShiftValue - get the arithmetic shift value.107static inline unsigned AArch64_AM_getArithShiftValue(unsigned Imm)108{109return Imm & 0x7;110}111112/// getExtendType - Extract the extend type for operands of arithmetic ops.113static inline AArch64_AM_ShiftExtendType AArch64_AM_getExtendType(unsigned Imm)114{115// assert((Imm & 0x7) == Imm && "invalid immediate!");116switch (Imm) {117default: // llvm_unreachable("Compiler bug!");118case 0: return AArch64_AM_UXTB;119case 1: return AArch64_AM_UXTH;120case 2: return AArch64_AM_UXTW;121case 3: return AArch64_AM_UXTX;122case 4: return AArch64_AM_SXTB;123case 5: return AArch64_AM_SXTH;124case 6: return AArch64_AM_SXTW;125case 7: return AArch64_AM_SXTX;126}127}128129static inline AArch64_AM_ShiftExtendType AArch64_AM_getArithExtendType(unsigned Imm)130{131return AArch64_AM_getExtendType((Imm >> 3) & 0x7);132}133134/// Mapping from extend bits to required operation:135/// shifter: 000 ==> uxtb136/// 001 ==> uxth137/// 010 ==> uxtw138/// 011 ==> uxtx139/// 100 ==> sxtb140/// 101 ==> sxth141/// 110 ==> sxtw142/// 111 ==> sxtx143static inline unsigned AArch64_AM_getExtendEncoding(AArch64_AM_ShiftExtendType ET)144{145switch (ET) {146default: // llvm_unreachable("Invalid extend type requested");147case AArch64_AM_UXTB: return 0; break;148case AArch64_AM_UXTH: return 1; break;149case AArch64_AM_UXTW: return 2; break;150case AArch64_AM_UXTX: return 3; break;151case AArch64_AM_SXTB: return 4; break;152case AArch64_AM_SXTH: return 5; break;153case AArch64_AM_SXTW: return 6; break;154case AArch64_AM_SXTX: return 7; break;155}156}157158/// getArithExtendImm - Encode the extend type and shift amount for an159/// arithmetic instruction:160/// imm: 3-bit extend amount161/// {5-3} = shifter162/// {2-0} = imm3163static inline unsigned AArch64_AM_getArithExtendImm(AArch64_AM_ShiftExtendType ET, unsigned Imm)164{165// assert((Imm & 0x7) == Imm && "Illegal shifted immedate value!");166return (AArch64_AM_getExtendEncoding(ET) << 3) | (Imm & 0x7);167}168169/// getMemDoShift - Extract the "do shift" flag value for load/store170/// instructions.171static inline bool AArch64_AM_getMemDoShift(unsigned Imm)172{173return (Imm & 0x1) != 0;174}175176/// getExtendType - Extract the extend type for the offset operand of177/// loads/stores.178static inline AArch64_AM_ShiftExtendType AArch64_AM_getMemExtendType(unsigned Imm)179{180return AArch64_AM_getExtendType((Imm >> 1) & 0x7);181}182183static inline uint64_t ror(uint64_t elt, unsigned size)184{185return ((elt & 1) << (size-1)) | (elt >> 1);186}187188/// processLogicalImmediate - Determine if an immediate value can be encoded189/// as the immediate operand of a logical instruction for the given register190/// size. If so, return true with "encoding" set to the encoded value in191/// the form N:immr:imms.192static inline bool AArch64_AM_processLogicalImmediate(uint64_t Imm, unsigned RegSize, uint64_t *Encoding)193{194unsigned Size, Immr, N;195uint32_t CTO, I;196uint64_t Mask, NImms;197198if (Imm == 0ULL || Imm == ~0ULL ||199(RegSize != 64 && (Imm >> RegSize != 0 || Imm == (~0ULL >> (64 - RegSize))))) {200return false;201}202203// First, determine the element size.204Size = RegSize;205do {206uint64_t Mask;207208Size /= 2;209Mask = (1ULL << Size) - 1;210if ((Imm & Mask) != ((Imm >> Size) & Mask)) {211Size *= 2;212break;213}214} while (Size > 2);215216// Second, determine the rotation to make the element be: 0^m 1^n.217Mask = ((uint64_t)-1LL) >> (64 - Size);218Imm &= Mask;219220if (isShiftedMask_64(Imm)) {221I = CountTrailingZeros_32(Imm);222// assert(I < 64 && "undefined behavior");223CTO = CountTrailingOnes_32(Imm >> I);224} else {225unsigned CLO;226227Imm |= ~Mask;228if (!isShiftedMask_64(~Imm))229return false;230231CLO = CountLeadingOnes_32(Imm);232I = 64 - CLO;233CTO = CLO + CountTrailingOnes_32(Imm) - (64 - Size);234}235236// Encode in Immr the number of RORs it would take to get *from* 0^m 1^n237// to our target value, where I is the number of RORs to go the opposite238// direction.239// assert(Size > I && "I should be smaller than element size");240Immr = (Size - I) & (Size - 1);241242// If size has a 1 in the n'th bit, create a value that has zeroes in243// bits [0, n] and ones above that.244NImms = ~(Size-1) << 1;245246// Or the CTO value into the low bits, which must be below the Nth bit247// bit mentioned above.248NImms |= (CTO-1);249250// Extract the seventh bit and toggle it to create the N field.251N = ((NImms >> 6) & 1) ^ 1;252253*Encoding = (N << 12) | (Immr << 6) | (NImms & 0x3f);254255return true;256}257258/// isLogicalImmediate - Return true if the immediate is valid for a logical259/// immediate instruction of the given register size. Return false otherwise.260static inline bool isLogicalImmediate(uint64_t imm, unsigned regSize)261{262uint64_t encoding;263return AArch64_AM_processLogicalImmediate(imm, regSize, &encoding);264}265266/// encodeLogicalImmediate - Return the encoded immediate value for a logical267/// immediate instruction of the given register size.268static inline uint64_t AArch64_AM_encodeLogicalImmediate(uint64_t imm, unsigned regSize)269{270uint64_t encoding = 0;271272bool res = AArch64_AM_processLogicalImmediate(imm, regSize, &encoding);273// assert(res && "invalid logical immediate");274(void)res;275276return encoding;277}278279/// decodeLogicalImmediate - Decode a logical immediate value in the form280/// "N:immr:imms" (where the immr and imms fields are each 6 bits) into the281/// integer value it represents with regSize bits.282static inline uint64_t AArch64_AM_decodeLogicalImmediate(uint64_t val, unsigned regSize)283{284// Extract the N, imms, and immr fields.285unsigned N = (val >> 12) & 1;286unsigned immr = (val >> 6) & 0x3f;287unsigned imms = val & 0x3f;288unsigned i, size, R, S;289uint64_t pattern;290291// assert((regSize == 64 || N == 0) && "undefined logical immediate encoding");292int len = 31 - CountLeadingZeros_32((N << 6) | (~imms & 0x3f));293294// assert(len >= 0 && "undefined logical immediate encoding");295size = (1 << len);296R = immr & (size - 1);297S = imms & (size - 1);298299// assert(S != size - 1 && "undefined logical immediate encoding");300pattern = (1ULL << (S + 1)) - 1;301302for (i = 0; i < R; ++i)303pattern = ror(pattern, size);304305// Replicate the pattern to fill the regSize.306while (size != regSize) {307pattern |= (pattern << size);308size *= 2;309}310311return pattern;312}313314/// isValidDecodeLogicalImmediate - Check to see if the logical immediate value315/// in the form "N:immr:imms" (where the immr and imms fields are each 6 bits)316/// is a valid encoding for an integer value with regSize bits.317static inline bool AArch64_AM_isValidDecodeLogicalImmediate(uint64_t val, unsigned regSize)318{319unsigned size, S;320int len;321// Extract the N and imms fields needed for checking.322unsigned N = (val >> 12) & 1;323unsigned imms = val & 0x3f;324325if (regSize == 32 && N != 0) // undefined logical immediate encoding326return false;327len = 31 - CountLeadingZeros_32((N << 6) | (~imms & 0x3f));328if (len < 0) // undefined logical immediate encoding329return false;330size = (1 << len);331S = imms & (size - 1);332if (S == size - 1) // undefined logical immediate encoding333return false;334335return true;336}337338//===----------------------------------------------------------------------===//339// Floating-point Immediates340//341static inline float AArch64_AM_getFPImmFloat(unsigned Imm)342{343// We expect an 8-bit binary encoding of a floating-point number here.344union {345uint32_t I;346float F;347} FPUnion;348349uint8_t Sign = (Imm >> 7) & 0x1;350uint8_t Exp = (Imm >> 4) & 0x7;351uint8_t Mantissa = Imm & 0xf;352353// 8-bit FP iEEEE Float Encoding354// abcd efgh aBbbbbbc defgh000 00000000 00000000355//356// where B = NOT(b);357358FPUnion.I = 0;359FPUnion.I |= ((uint32_t)Sign) << 31;360FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;361FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;362FPUnion.I |= (Exp & 0x3) << 23;363FPUnion.I |= Mantissa << 19;364365return FPUnion.F;366}367368//===--------------------------------------------------------------------===//369// AdvSIMD Modified Immediates370//===--------------------------------------------------------------------===//371372// 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh373static inline bool AArch64_AM_isAdvSIMDModImmType1(uint64_t Imm)374{375return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&376((Imm & 0xffffff00ffffff00ULL) == 0);377}378379static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType1(uint64_t Imm)380{381return (Imm & 0xffULL);382}383384static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType1(uint8_t Imm)385{386uint64_t EncVal = Imm;387388return (EncVal << 32) | EncVal;389}390391// 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00392static inline bool AArch64_AM_isAdvSIMDModImmType2(uint64_t Imm)393{394return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&395((Imm & 0xffff00ffffff00ffULL) == 0);396}397398static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType2(uint64_t Imm)399{400return (Imm & 0xff00ULL) >> 8;401}402403static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType2(uint8_t Imm)404{405uint64_t EncVal = Imm;406return (EncVal << 40) | (EncVal << 8);407}408409// 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00410static inline bool AArch64_AM_isAdvSIMDModImmType3(uint64_t Imm)411{412return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&413((Imm & 0xff00ffffff00ffffULL) == 0);414}415416static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType3(uint64_t Imm)417{418return (Imm & 0xff0000ULL) >> 16;419}420421static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType3(uint8_t Imm)422{423uint64_t EncVal = Imm;424return (EncVal << 48) | (EncVal << 16);425}426427// abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00428static inline bool AArch64_AM_isAdvSIMDModImmType4(uint64_t Imm)429{430return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&431((Imm & 0x00ffffff00ffffffULL) == 0);432}433434static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType4(uint64_t Imm)435{436return (Imm & 0xff000000ULL) >> 24;437}438439static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType4(uint8_t Imm)440{441uint64_t EncVal = Imm;442return (EncVal << 56) | (EncVal << 24);443}444445// 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh446static inline bool AArch64_AM_isAdvSIMDModImmType5(uint64_t Imm)447{448return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&449(((Imm & 0x00ff0000ULL) >> 16) == (Imm & 0x000000ffULL)) &&450((Imm & 0xff00ff00ff00ff00ULL) == 0);451}452453static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType5(uint64_t Imm)454{455return (Imm & 0xffULL);456}457458static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType5(uint8_t Imm)459{460uint64_t EncVal = Imm;461return (EncVal << 48) | (EncVal << 32) | (EncVal << 16) | EncVal;462}463464// abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00465static inline bool AArch64_AM_isAdvSIMDModImmType6(uint64_t Imm)466{467return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&468(((Imm & 0xff000000ULL) >> 16) == (Imm & 0x0000ff00ULL)) &&469((Imm & 0x00ff00ff00ff00ffULL) == 0);470}471472static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType6(uint64_t Imm)473{474return (Imm & 0xff00ULL) >> 8;475}476477static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType6(uint8_t Imm)478{479uint64_t EncVal = Imm;480return (EncVal << 56) | (EncVal << 40) | (EncVal << 24) | (EncVal << 8);481}482483// 0x00 0x00 abcdefgh 0xFF 0x00 0x00 abcdefgh 0xFF484static inline bool AArch64_AM_isAdvSIMDModImmType7(uint64_t Imm)485{486return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&487((Imm & 0xffff00ffffff00ffULL) == 0x000000ff000000ffULL);488}489490static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType7(uint64_t Imm)491{492return (Imm & 0xff00ULL) >> 8;493}494495static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType7(uint8_t Imm)496{497uint64_t EncVal = Imm;498return (EncVal << 40) | (EncVal << 8) | 0x000000ff000000ffULL;499}500501// 0x00 abcdefgh 0xFF 0xFF 0x00 abcdefgh 0xFF 0xFF502static inline bool AArch64_AM_isAdvSIMDModImmType8(uint64_t Imm)503{504return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&505((Imm & 0xff00ffffff00ffffULL) == 0x0000ffff0000ffffULL);506}507508static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType8(uint8_t Imm)509{510uint64_t EncVal = Imm;511return (EncVal << 48) | (EncVal << 16) | 0x0000ffff0000ffffULL;512}513514static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType8(uint64_t Imm)515{516return (Imm & 0x00ff0000ULL) >> 16;517}518519// abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh520static inline bool AArch64_AM_isAdvSIMDModImmType9(uint64_t Imm)521{522return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&523((Imm >> 48) == (Imm & 0x0000ffffULL)) &&524((Imm >> 56) == (Imm & 0x000000ffULL));525}526527static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType9(uint64_t Imm)528{529return (Imm & 0xffULL);530}531532static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType9(uint8_t Imm)533{534uint64_t EncVal = Imm;535EncVal |= (EncVal << 8);536EncVal |= (EncVal << 16);537EncVal |= (EncVal << 32);538539return EncVal;540}541542// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh543// cmode: 1110, op: 1544static inline bool AArch64_AM_isAdvSIMDModImmType10(uint64_t Imm)545{546uint64_t ByteA = Imm & 0xff00000000000000ULL;547uint64_t ByteB = Imm & 0x00ff000000000000ULL;548uint64_t ByteC = Imm & 0x0000ff0000000000ULL;549uint64_t ByteD = Imm & 0x000000ff00000000ULL;550uint64_t ByteE = Imm & 0x00000000ff000000ULL;551uint64_t ByteF = Imm & 0x0000000000ff0000ULL;552uint64_t ByteG = Imm & 0x000000000000ff00ULL;553uint64_t ByteH = Imm & 0x00000000000000ffULL;554555return (ByteA == 0ULL || ByteA == 0xff00000000000000ULL) &&556(ByteB == 0ULL || ByteB == 0x00ff000000000000ULL) &&557(ByteC == 0ULL || ByteC == 0x0000ff0000000000ULL) &&558(ByteD == 0ULL || ByteD == 0x000000ff00000000ULL) &&559(ByteE == 0ULL || ByteE == 0x00000000ff000000ULL) &&560(ByteF == 0ULL || ByteF == 0x0000000000ff0000ULL) &&561(ByteG == 0ULL || ByteG == 0x000000000000ff00ULL) &&562(ByteH == 0ULL || ByteH == 0x00000000000000ffULL);563}564565static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType10(uint64_t Imm)566{567uint8_t BitA = (Imm & 0xff00000000000000ULL) != 0;568uint8_t BitB = (Imm & 0x00ff000000000000ULL) != 0;569uint8_t BitC = (Imm & 0x0000ff0000000000ULL) != 0;570uint8_t BitD = (Imm & 0x000000ff00000000ULL) != 0;571uint8_t BitE = (Imm & 0x00000000ff000000ULL) != 0;572uint8_t BitF = (Imm & 0x0000000000ff0000ULL) != 0;573uint8_t BitG = (Imm & 0x000000000000ff00ULL) != 0;574uint8_t BitH = (Imm & 0x00000000000000ffULL) != 0;575576uint8_t EncVal = BitA;577578EncVal <<= 1;579EncVal |= BitB;580EncVal <<= 1;581EncVal |= BitC;582EncVal <<= 1;583EncVal |= BitD;584EncVal <<= 1;585EncVal |= BitE;586EncVal <<= 1;587EncVal |= BitF;588EncVal <<= 1;589EncVal |= BitG;590EncVal <<= 1;591EncVal |= BitH;592593return EncVal;594}595596static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType10(uint8_t Imm)597{598uint64_t EncVal = 0;599600if (Imm & 0x80)601EncVal |= 0xff00000000000000ULL;602603if (Imm & 0x40)604EncVal |= 0x00ff000000000000ULL;605606if (Imm & 0x20)607EncVal |= 0x0000ff0000000000ULL;608609if (Imm & 0x10)610EncVal |= 0x000000ff00000000ULL;611612if (Imm & 0x08)613EncVal |= 0x00000000ff000000ULL;614615if (Imm & 0x04)616EncVal |= 0x0000000000ff0000ULL;617618if (Imm & 0x02)619EncVal |= 0x000000000000ff00ULL;620621if (Imm & 0x01)622EncVal |= 0x00000000000000ffULL;623624return EncVal;625}626627// aBbbbbbc defgh000 0x00 0x00 aBbbbbbc defgh000 0x00 0x00628static inline bool AArch64_AM_isAdvSIMDModImmType11(uint64_t Imm)629{630uint64_t BString = (Imm & 0x7E000000ULL) >> 25;631632return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&633(BString == 0x1f || BString == 0x20) &&634((Imm & 0x0007ffff0007ffffULL) == 0);635}636637static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType11(uint64_t Imm)638{639uint8_t BitA = (Imm & 0x80000000ULL) != 0;640uint8_t BitB = (Imm & 0x20000000ULL) != 0;641uint8_t BitC = (Imm & 0x01000000ULL) != 0;642uint8_t BitD = (Imm & 0x00800000ULL) != 0;643uint8_t BitE = (Imm & 0x00400000ULL) != 0;644uint8_t BitF = (Imm & 0x00200000ULL) != 0;645uint8_t BitG = (Imm & 0x00100000ULL) != 0;646uint8_t BitH = (Imm & 0x00080000ULL) != 0;647648uint8_t EncVal = BitA;649EncVal <<= 1;650EncVal |= BitB;651EncVal <<= 1;652EncVal |= BitC;653EncVal <<= 1;654EncVal |= BitD;655EncVal <<= 1;656EncVal |= BitE;657EncVal <<= 1;658EncVal |= BitF;659EncVal <<= 1;660EncVal |= BitG;661EncVal <<= 1;662EncVal |= BitH;663664return EncVal;665}666667static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType11(uint8_t Imm)668{669uint64_t EncVal = 0;670671if (Imm & 0x80)672EncVal |= 0x80000000ULL;673674if (Imm & 0x40)675EncVal |= 0x3e000000ULL;676else677EncVal |= 0x40000000ULL;678679if (Imm & 0x20)680EncVal |= 0x01000000ULL;681682if (Imm & 0x10)683EncVal |= 0x00800000ULL;684685if (Imm & 0x08)686EncVal |= 0x00400000ULL;687688if (Imm & 0x04)689EncVal |= 0x00200000ULL;690691if (Imm & 0x02)692EncVal |= 0x00100000ULL;693694if (Imm & 0x01)695EncVal |= 0x00080000ULL;696697return (EncVal << 32) | EncVal;698}699700// aBbbbbbb bbcdefgh 0x00 0x00 0x00 0x00 0x00 0x00701static inline bool AArch64_AM_isAdvSIMDModImmType12(uint64_t Imm)702{703uint64_t BString = (Imm & 0x7fc0000000000000ULL) >> 54;704return ((BString == 0xff || BString == 0x100) &&705((Imm & 0x0000ffffffffffffULL) == 0));706}707708static inline uint8_t AArch64_AM_encodeAdvSIMDModImmType12(uint64_t Imm)709{710uint8_t BitA = (Imm & 0x8000000000000000ULL) != 0;711uint8_t BitB = (Imm & 0x0040000000000000ULL) != 0;712uint8_t BitC = (Imm & 0x0020000000000000ULL) != 0;713uint8_t BitD = (Imm & 0x0010000000000000ULL) != 0;714uint8_t BitE = (Imm & 0x0008000000000000ULL) != 0;715uint8_t BitF = (Imm & 0x0004000000000000ULL) != 0;716uint8_t BitG = (Imm & 0x0002000000000000ULL) != 0;717uint8_t BitH = (Imm & 0x0001000000000000ULL) != 0;718719uint8_t EncVal = BitA;720EncVal <<= 1;721EncVal |= BitB;722EncVal <<= 1;723EncVal |= BitC;724EncVal <<= 1;725EncVal |= BitD;726EncVal <<= 1;727EncVal |= BitE;728EncVal <<= 1;729EncVal |= BitF;730EncVal <<= 1;731EncVal |= BitG;732EncVal <<= 1;733EncVal |= BitH;734735return EncVal;736}737738static inline uint64_t AArch64_AM_decodeAdvSIMDModImmType12(uint8_t Imm)739{740uint64_t EncVal = 0;741if (Imm & 0x80)742EncVal |= 0x8000000000000000ULL;743744if (Imm & 0x40)745EncVal |= 0x3fc0000000000000ULL;746else747EncVal |= 0x4000000000000000ULL;748749if (Imm & 0x20)750EncVal |= 0x0020000000000000ULL;751752if (Imm & 0x10)753EncVal |= 0x0010000000000000ULL;754755if (Imm & 0x08)756EncVal |= 0x0008000000000000ULL;757758if (Imm & 0x04)759EncVal |= 0x0004000000000000ULL;760761if (Imm & 0x02)762EncVal |= 0x0002000000000000ULL;763764if (Imm & 0x01)765EncVal |= 0x0001000000000000ULL;766767return (EncVal << 32) | EncVal;768}769770/// Returns true if Imm is the concatenation of a repeating pattern of type T.771static inline bool AArch64_AM_isSVEMaskOfIdenticalElements8(int64_t Imm)772{773#define _VECSIZE (sizeof(int64_t)/sizeof(int8_t))774unsigned int i;775union {776int64_t Whole;777int8_t Parts[_VECSIZE];778} Vec;779780Vec.Whole = Imm;781782for(i = 1; i < _VECSIZE; i++) {783if (Vec.Parts[i] != Vec.Parts[0])784return false;785}786#undef _VECSIZE787788return true;789}790791static inline bool AArch64_AM_isSVEMaskOfIdenticalElements16(int64_t Imm)792{793#define _VECSIZE (sizeof(int64_t)/sizeof(int16_t))794unsigned int i;795union {796int64_t Whole;797int16_t Parts[_VECSIZE];798} Vec;799800Vec.Whole = Imm;801802for(i = 1; i < _VECSIZE; i++) {803if (Vec.Parts[i] != Vec.Parts[0])804return false;805}806#undef _VECSIZE807808return true;809}810811static inline bool AArch64_AM_isSVEMaskOfIdenticalElements32(int64_t Imm)812{813#define _VECSIZE (sizeof(int64_t)/sizeof(int32_t))814unsigned int i;815union {816int64_t Whole;817int32_t Parts[_VECSIZE];818} Vec;819820Vec.Whole = Imm;821822for(i = 1; i < _VECSIZE; i++) {823if (Vec.Parts[i] != Vec.Parts[0])824return false;825}826#undef _VECSIZE827828return true;829}830831static inline bool AArch64_AM_isSVEMaskOfIdenticalElements64(int64_t Imm)832{833return true;834}835836static inline bool isSVECpyImm8(int64_t Imm)837{838bool IsImm8 = (int8_t)Imm == Imm;839840return IsImm8 || (uint8_t)Imm == Imm;841}842843static inline bool isSVECpyImm16(int64_t Imm)844{845bool IsImm8 = (int8_t)Imm == Imm;846bool IsImm16 = (int16_t)(Imm & ~0xff) == Imm;847848return IsImm8 || IsImm16 || (uint16_t)(Imm & ~0xff) == Imm;849}850851static inline bool isSVECpyImm32(int64_t Imm)852{853bool IsImm8 = (int8_t)Imm == Imm;854bool IsImm16 = (int16_t)(Imm & ~0xff) == Imm;855856return IsImm8 || IsImm16;857}858859static inline bool isSVECpyImm64(int64_t Imm)860{861bool IsImm8 = (int8_t)Imm == Imm;862bool IsImm16 = (int16_t)(Imm & ~0xff) == Imm;863864return IsImm8 || IsImm16;865}866867/// Return true if Imm is valid for DUPM and has no single CPY/DUP equivalent.868static inline bool AArch64_AM_isSVEMoveMaskPreferredLogicalImmediate(int64_t Imm)869{870union {871int64_t D;872int32_t S[2];873int16_t H[4];874int8_t B[8];875} Vec = {Imm};876877if (isSVECpyImm64(Vec.D))878return false;879880if (AArch64_AM_isSVEMaskOfIdenticalElements32(Imm) &&881isSVECpyImm32(Vec.S[0]))882return false;883884if (AArch64_AM_isSVEMaskOfIdenticalElements16(Imm) &&885isSVECpyImm16(Vec.H[0]))886return false;887888if (AArch64_AM_isSVEMaskOfIdenticalElements8(Imm) &&889isSVECpyImm8(Vec.B[0]))890return false;891892return isLogicalImmediate(Vec.D, 64);893}894895inline static bool isAnyMOVZMovAlias(uint64_t Value, int RegWidth)896{897int Shift;898899for (Shift = 0; Shift <= RegWidth - 16; Shift += 16)900if ((Value & ~(0xffffULL << Shift)) == 0)901return true;902903return false;904}905906inline static bool isMOVZMovAlias(uint64_t Value, int Shift, int RegWidth)907{908if (RegWidth == 32)909Value &= 0xffffffffULL;910911// "lsl #0" takes precedence: in practice this only affects "#0, lsl #0".912if (Value == 0 && Shift != 0)913return false;914915return (Value & ~(0xffffULL << Shift)) == 0;916}917918inline static bool AArch64_AM_isMOVNMovAlias(uint64_t Value, int Shift, int RegWidth)919{920// MOVZ takes precedence over MOVN.921if (isAnyMOVZMovAlias(Value, RegWidth))922return false;923924Value = ~Value;925if (RegWidth == 32)926Value &= 0xffffffffULL;927928return isMOVZMovAlias(Value, Shift, RegWidth);929}930931inline static bool AArch64_AM_isAnyMOVWMovAlias(uint64_t Value, int RegWidth)932{933if (isAnyMOVZMovAlias(Value, RegWidth))934return true;935936// It's not a MOVZ, but it might be a MOVN.937Value = ~Value;938if (RegWidth == 32)939Value &= 0xffffffffULL;940941return isAnyMOVZMovAlias(Value, RegWidth);942}943944#endif945946947