LLVM API Documentation

AArch64AddressingModes.h
Go to the documentation of this file.
00001 //===- AArch64AddressingModes.h - AArch64 Addressing Modes ------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file contains the AArch64 addressing mode implementation stuff.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64ADDRESSINGMODES_H
00015 #define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64ADDRESSINGMODES_H
00016 
00017 #include "llvm/ADT/APFloat.h"
00018 #include "llvm/ADT/APInt.h"
00019 #include "llvm/Support/ErrorHandling.h"
00020 #include "llvm/Support/MathExtras.h"
00021 #include <cassert>
00022 
00023 namespace llvm {
00024 
00025 /// AArch64_AM - AArch64 Addressing Mode Stuff
00026 namespace AArch64_AM {
00027 
00028 //===----------------------------------------------------------------------===//
00029 // Shifts
00030 //
00031 
00032 enum ShiftExtendType {
00033   InvalidShiftExtend = -1,
00034   LSL = 0,
00035   LSR,
00036   ASR,
00037   ROR,
00038   MSL,
00039 
00040   UXTB,
00041   UXTH,
00042   UXTW,
00043   UXTX,
00044 
00045   SXTB,
00046   SXTH,
00047   SXTW,
00048   SXTX,
00049 };
00050 
00051 /// getShiftName - Get the string encoding for the shift type.
00052 static inline const char *getShiftExtendName(AArch64_AM::ShiftExtendType ST) {
00053   switch (ST) {
00054   default: assert(false && "unhandled shift type!");
00055   case AArch64_AM::LSL: return "lsl";
00056   case AArch64_AM::LSR: return "lsr";
00057   case AArch64_AM::ASR: return "asr";
00058   case AArch64_AM::ROR: return "ror";
00059   case AArch64_AM::MSL: return "msl";
00060   case AArch64_AM::UXTB: return "uxtb";
00061   case AArch64_AM::UXTH: return "uxth";
00062   case AArch64_AM::UXTW: return "uxtw";
00063   case AArch64_AM::UXTX: return "uxtx";
00064   case AArch64_AM::SXTB: return "sxtb";
00065   case AArch64_AM::SXTH: return "sxth";
00066   case AArch64_AM::SXTW: return "sxtw";
00067   case AArch64_AM::SXTX: return "sxtx";
00068   }
00069   return nullptr;
00070 }
00071 
00072 /// getShiftType - Extract the shift type.
00073 static inline AArch64_AM::ShiftExtendType getShiftType(unsigned Imm) {
00074   switch ((Imm >> 6) & 0x7) {
00075   default: return AArch64_AM::InvalidShiftExtend;
00076   case 0: return AArch64_AM::LSL;
00077   case 1: return AArch64_AM::LSR;
00078   case 2: return AArch64_AM::ASR;
00079   case 3: return AArch64_AM::ROR;
00080   case 4: return AArch64_AM::MSL;
00081   }
00082 }
00083 
00084 /// getShiftValue - Extract the shift value.
00085 static inline unsigned getShiftValue(unsigned Imm) {
00086   return Imm & 0x3f;
00087 }
00088 
00089 /// getShifterImm - Encode the shift type and amount:
00090 ///   imm:     6-bit shift amount
00091 ///   shifter: 000 ==> lsl
00092 ///            001 ==> lsr
00093 ///            010 ==> asr
00094 ///            011 ==> ror
00095 ///            100 ==> msl
00096 ///   {8-6}  = shifter
00097 ///   {5-0}  = imm
00098 static inline unsigned getShifterImm(AArch64_AM::ShiftExtendType ST,
00099                                      unsigned Imm) {
00100   assert((Imm & 0x3f) == Imm && "Illegal shifted immedate value!");
00101   unsigned STEnc = 0;
00102   switch (ST) {
00103   default:  llvm_unreachable("Invalid shift requested");
00104   case AArch64_AM::LSL: STEnc = 0; break;
00105   case AArch64_AM::LSR: STEnc = 1; break;
00106   case AArch64_AM::ASR: STEnc = 2; break;
00107   case AArch64_AM::ROR: STEnc = 3; break;
00108   case AArch64_AM::MSL: STEnc = 4; break;
00109   }
00110   return (STEnc << 6) | (Imm & 0x3f);
00111 }
00112 
00113 //===----------------------------------------------------------------------===//
00114 // Extends
00115 //
00116 
00117 /// getArithShiftValue - get the arithmetic shift value.
00118 static inline unsigned getArithShiftValue(unsigned Imm) {
00119   return Imm & 0x7;
00120 }
00121 
00122 /// getExtendType - Extract the extend type for operands of arithmetic ops.
00123 static inline AArch64_AM::ShiftExtendType getExtendType(unsigned Imm) {
00124   assert((Imm & 0x7) == Imm && "invalid immediate!");
00125   switch (Imm) {
00126   default: llvm_unreachable("Compiler bug!");
00127   case 0: return AArch64_AM::UXTB;
00128   case 1: return AArch64_AM::UXTH;
00129   case 2: return AArch64_AM::UXTW;
00130   case 3: return AArch64_AM::UXTX;
00131   case 4: return AArch64_AM::SXTB;
00132   case 5: return AArch64_AM::SXTH;
00133   case 6: return AArch64_AM::SXTW;
00134   case 7: return AArch64_AM::SXTX;
00135   }
00136 }
00137 
00138 static inline AArch64_AM::ShiftExtendType getArithExtendType(unsigned Imm) {
00139   return getExtendType((Imm >> 3) & 0x7);
00140 }
00141 
00142 /// Mapping from extend bits to required operation:
00143 ///   shifter: 000 ==> uxtb
00144 ///            001 ==> uxth
00145 ///            010 ==> uxtw
00146 ///            011 ==> uxtx
00147 ///            100 ==> sxtb
00148 ///            101 ==> sxth
00149 ///            110 ==> sxtw
00150 ///            111 ==> sxtx
00151 inline unsigned getExtendEncoding(AArch64_AM::ShiftExtendType ET) {
00152   switch (ET) {
00153   default: llvm_unreachable("Invalid extend type requested");
00154   case AArch64_AM::UXTB: return 0; break;
00155   case AArch64_AM::UXTH: return 1; break;
00156   case AArch64_AM::UXTW: return 2; break;
00157   case AArch64_AM::UXTX: return 3; break;
00158   case AArch64_AM::SXTB: return 4; break;
00159   case AArch64_AM::SXTH: return 5; break;
00160   case AArch64_AM::SXTW: return 6; break;
00161   case AArch64_AM::SXTX: return 7; break;
00162   }
00163 }
00164 
00165 /// getArithExtendImm - Encode the extend type and shift amount for an
00166 ///                     arithmetic instruction:
00167 ///   imm:     3-bit extend amount
00168 ///   {5-3}  = shifter
00169 ///   {2-0}  = imm3
00170 static inline unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET,
00171                                          unsigned Imm) {
00172   assert((Imm & 0x7) == Imm && "Illegal shifted immedate value!");
00173   return (getExtendEncoding(ET) << 3) | (Imm & 0x7);
00174 }
00175 
00176 /// getMemDoShift - Extract the "do shift" flag value for load/store
00177 /// instructions.
00178 static inline bool getMemDoShift(unsigned Imm) {
00179   return (Imm & 0x1) != 0;
00180 }
00181 
00182 /// getExtendType - Extract the extend type for the offset operand of
00183 /// loads/stores.
00184 static inline AArch64_AM::ShiftExtendType getMemExtendType(unsigned Imm) {
00185   return getExtendType((Imm >> 1) & 0x7);
00186 }
00187 
00188 /// getExtendImm - Encode the extend type and amount for a load/store inst:
00189 ///   doshift:     should the offset be scaled by the access size
00190 ///   shifter: 000 ==> uxtb
00191 ///            001 ==> uxth
00192 ///            010 ==> uxtw
00193 ///            011 ==> uxtx
00194 ///            100 ==> sxtb
00195 ///            101 ==> sxth
00196 ///            110 ==> sxtw
00197 ///            111 ==> sxtx
00198 ///   {3-1}  = shifter
00199 ///   {0}  = doshift
00200 static inline unsigned getMemExtendImm(AArch64_AM::ShiftExtendType ET,
00201                                        bool DoShift) {
00202   return (getExtendEncoding(ET) << 1) | unsigned(DoShift);
00203 }
00204 
00205 static inline uint64_t ror(uint64_t elt, unsigned size) {
00206   return ((elt & 1) << (size-1)) | (elt >> 1);
00207 }
00208 
00209 /// processLogicalImmediate - Determine if an immediate value can be encoded
00210 /// as the immediate operand of a logical instruction for the given register
00211 /// size.  If so, return true with "encoding" set to the encoded value in
00212 /// the form N:immr:imms.
00213 static inline bool processLogicalImmediate(uint64_t imm, unsigned regSize,
00214                                            uint64_t &encoding) {
00215   if (imm == 0ULL || imm == ~0ULL ||
00216       (regSize != 64 && (imm >> regSize != 0 || imm == ~0U)))
00217     return false;
00218 
00219   unsigned size = 2;
00220   uint64_t eltVal = imm;
00221 
00222   // First, determine the element size.
00223   while (size < regSize) {
00224     unsigned numElts = regSize / size;
00225     unsigned mask = (1ULL << size) - 1;
00226     uint64_t lowestEltVal = imm & mask;
00227 
00228     bool allMatched = true;
00229     for (unsigned i = 1; i < numElts; ++i) {
00230      uint64_t currEltVal = (imm >> (i*size)) & mask;
00231       if (currEltVal != lowestEltVal) {
00232         allMatched = false;
00233         break;
00234       }
00235     }
00236 
00237     if (allMatched) {
00238       eltVal = lowestEltVal;
00239       break;
00240     }
00241 
00242     size *= 2;
00243   }
00244 
00245   // Second, determine the rotation to make the element be: 0^m 1^n.
00246   for (unsigned i = 0; i < size; ++i) {
00247     eltVal = ror(eltVal, size);
00248     uint32_t clz = countLeadingZeros(eltVal) - (64 - size);
00249     uint32_t cto = CountTrailingOnes_64(eltVal);
00250 
00251     if (clz + cto == size) {
00252       // Encode in immr the number of RORs it would take to get *from* this
00253       // element value to our target value, where i+1 is the number of RORs
00254       // to go the opposite direction.
00255       unsigned immr = size - (i + 1);
00256 
00257       // If size has a 1 in the n'th bit, create a value that has zeroes in
00258       // bits [0, n] and ones above that.
00259       uint64_t nimms = ~(size-1) << 1;
00260 
00261       // Or the CTO value into the low bits, which must be below the Nth bit
00262       // bit mentioned above.
00263       nimms |= (cto-1);
00264 
00265       // Extract the seventh bit and toggle it to create the N field.
00266       unsigned N = ((nimms >> 6) & 1) ^ 1;
00267 
00268       encoding = (N << 12) | (immr << 6) | (nimms & 0x3f);
00269       return true;
00270     }
00271   }
00272 
00273   return false;
00274 }
00275 
00276 /// isLogicalImmediate - Return true if the immediate is valid for a logical
00277 /// immediate instruction of the given register size. Return false otherwise.
00278 static inline bool isLogicalImmediate(uint64_t imm, unsigned regSize) {
00279   uint64_t encoding;
00280   return processLogicalImmediate(imm, regSize, encoding);
00281 }
00282 
00283 /// encodeLogicalImmediate - Return the encoded immediate value for a logical
00284 /// immediate instruction of the given register size.
00285 static inline uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize) {
00286   uint64_t encoding = 0;
00287   bool res = processLogicalImmediate(imm, regSize, encoding);
00288   assert(res && "invalid logical immediate");
00289   (void)res;
00290   return encoding;
00291 }
00292 
00293 /// decodeLogicalImmediate - Decode a logical immediate value in the form
00294 /// "N:immr:imms" (where the immr and imms fields are each 6 bits) into the
00295 /// integer value it represents with regSize bits.
00296 static inline uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize) {
00297   // Extract the N, imms, and immr fields.
00298   unsigned N = (val >> 12) & 1;
00299   unsigned immr = (val >> 6) & 0x3f;
00300   unsigned imms = val & 0x3f;
00301 
00302   assert((regSize == 64 || N == 0) && "undefined logical immediate encoding");
00303   int len = 31 - countLeadingZeros((N << 6) | (~imms & 0x3f));
00304   assert(len >= 0 && "undefined logical immediate encoding");
00305   unsigned size = (1 << len);
00306   unsigned R = immr & (size - 1);
00307   unsigned S = imms & (size - 1);
00308   assert(S != size - 1 && "undefined logical immediate encoding");
00309   uint64_t pattern = (1ULL << (S + 1)) - 1;
00310   for (unsigned i = 0; i < R; ++i)
00311     pattern = ror(pattern, size);
00312 
00313   // Replicate the pattern to fill the regSize.
00314   while (size != regSize) {
00315     pattern |= (pattern << size);
00316     size *= 2;
00317   }
00318   return pattern;
00319 }
00320 
00321 /// isValidDecodeLogicalImmediate - Check to see if the logical immediate value
00322 /// in the form "N:immr:imms" (where the immr and imms fields are each 6 bits)
00323 /// is a valid encoding for an integer value with regSize bits.
00324 static inline bool isValidDecodeLogicalImmediate(uint64_t val,
00325                                                  unsigned regSize) {
00326   // Extract the N and imms fields needed for checking.
00327   unsigned N = (val >> 12) & 1;
00328   unsigned imms = val & 0x3f;
00329 
00330   if (regSize == 32 && N != 0) // undefined logical immediate encoding
00331     return false;
00332   int len = 31 - countLeadingZeros((N << 6) | (~imms & 0x3f));
00333   if (len < 0) // undefined logical immediate encoding
00334     return false;
00335   unsigned size = (1 << len);
00336   unsigned S = imms & (size - 1);
00337   if (S == size - 1) // undefined logical immediate encoding
00338     return false;
00339 
00340   return true;
00341 }
00342 
00343 //===----------------------------------------------------------------------===//
00344 // Floating-point Immediates
00345 //
00346 static inline float getFPImmFloat(unsigned Imm) {
00347   // We expect an 8-bit binary encoding of a floating-point number here.
00348   union {
00349     uint32_t I;
00350     float F;
00351   } FPUnion;
00352 
00353   uint8_t Sign = (Imm >> 7) & 0x1;
00354   uint8_t Exp = (Imm >> 4) & 0x7;
00355   uint8_t Mantissa = Imm & 0xf;
00356 
00357   //   8-bit FP    iEEEE Float Encoding
00358   //   abcd efgh   aBbbbbbc defgh000 00000000 00000000
00359   //
00360   // where B = NOT(b);
00361 
00362   FPUnion.I = 0;
00363   FPUnion.I |= Sign << 31;
00364   FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30;
00365   FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25;
00366   FPUnion.I |= (Exp & 0x3) << 23;
00367   FPUnion.I |= Mantissa << 19;
00368   return FPUnion.F;
00369 }
00370 
00371 /// getFP32Imm - Return an 8-bit floating-point version of the 32-bit
00372 /// floating-point value. If the value cannot be represented as an 8-bit
00373 /// floating-point value, then return -1.
00374 static inline int getFP32Imm(const APInt &Imm) {
00375   uint32_t Sign = Imm.lshr(31).getZExtValue() & 1;
00376   int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127;  // -126 to 127
00377   int64_t Mantissa = Imm.getZExtValue() & 0x7fffff;  // 23 bits
00378 
00379   // We can handle 4 bits of mantissa.
00380   // mantissa = (16+UInt(e:f:g:h))/16.
00381   if (Mantissa & 0x7ffff)
00382     return -1;
00383   Mantissa >>= 19;
00384   if ((Mantissa & 0xf) != Mantissa)
00385     return -1;
00386 
00387   // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3
00388   if (Exp < -3 || Exp > 4)
00389     return -1;
00390   Exp = ((Exp+3) & 0x7) ^ 4;
00391 
00392   return ((int)Sign << 7) | (Exp << 4) | Mantissa;
00393 }
00394 
00395 static inline int getFP32Imm(const APFloat &FPImm) {
00396   return getFP32Imm(FPImm.bitcastToAPInt());
00397 }
00398 
00399 /// getFP64Imm - Return an 8-bit floating-point version of the 64-bit
00400 /// floating-point value. If the value cannot be represented as an 8-bit
00401 /// floating-point value, then return -1.
00402 static inline int getFP64Imm(const APInt &Imm) {
00403   uint64_t Sign = Imm.lshr(63).getZExtValue() & 1;
00404   int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023;   // -1022 to 1023
00405   uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffULL;
00406 
00407   // We can handle 4 bits of mantissa.
00408   // mantissa = (16+UInt(e:f:g:h))/16.
00409   if (Mantissa & 0xffffffffffffULL)
00410     return -1;
00411   Mantissa >>= 48;
00412   if ((Mantissa & 0xf) != Mantissa)
00413     return -1;
00414 
00415   // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3
00416   if (Exp < -3 || Exp > 4)
00417     return -1;
00418   Exp = ((Exp+3) & 0x7) ^ 4;
00419 
00420   return ((int)Sign << 7) | (Exp << 4) | Mantissa;
00421 }
00422 
00423 static inline int getFP64Imm(const APFloat &FPImm) {
00424   return getFP64Imm(FPImm.bitcastToAPInt());
00425 }
00426 
00427 //===--------------------------------------------------------------------===//
00428 // AdvSIMD Modified Immediates
00429 //===--------------------------------------------------------------------===//
00430 
00431 // 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh
00432 static inline bool isAdvSIMDModImmType1(uint64_t Imm) {
00433   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
00434          ((Imm & 0xffffff00ffffff00ULL) == 0);
00435 }
00436 
00437 static inline uint8_t encodeAdvSIMDModImmType1(uint64_t Imm) {
00438   return (Imm & 0xffULL);
00439 }
00440 
00441 static inline uint64_t decodeAdvSIMDModImmType1(uint8_t Imm) {
00442   uint64_t EncVal = Imm;
00443   return (EncVal << 32) | EncVal;
00444 }
00445 
00446 // 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00
00447 static inline bool isAdvSIMDModImmType2(uint64_t Imm) {
00448   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
00449          ((Imm & 0xffff00ffffff00ffULL) == 0);
00450 }
00451 
00452 static inline uint8_t encodeAdvSIMDModImmType2(uint64_t Imm) {
00453   return (Imm & 0xff00ULL) >> 8;
00454 }
00455 
00456 static inline uint64_t decodeAdvSIMDModImmType2(uint8_t Imm) {
00457   uint64_t EncVal = Imm;
00458   return (EncVal << 40) | (EncVal << 8);
00459 }
00460 
00461 // 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00
00462 static inline bool isAdvSIMDModImmType3(uint64_t Imm) {
00463   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
00464          ((Imm & 0xff00ffffff00ffffULL) == 0);
00465 }
00466 
00467 static inline uint8_t encodeAdvSIMDModImmType3(uint64_t Imm) {
00468   return (Imm & 0xff0000ULL) >> 16;
00469 }
00470 
00471 static inline uint64_t decodeAdvSIMDModImmType3(uint8_t Imm) {
00472   uint64_t EncVal = Imm;
00473   return (EncVal << 48) | (EncVal << 16);
00474 }
00475 
00476 // abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00
00477 static inline bool isAdvSIMDModImmType4(uint64_t Imm) {
00478   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
00479          ((Imm & 0x00ffffff00ffffffULL) == 0);
00480 }
00481 
00482 static inline uint8_t encodeAdvSIMDModImmType4(uint64_t Imm) {
00483   return (Imm & 0xff000000ULL) >> 24;
00484 }
00485 
00486 static inline uint64_t decodeAdvSIMDModImmType4(uint8_t Imm) {
00487   uint64_t EncVal = Imm;
00488   return (EncVal << 56) | (EncVal << 24);
00489 }
00490 
00491 // 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh
00492 static inline bool isAdvSIMDModImmType5(uint64_t Imm) {
00493   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
00494          (((Imm & 0x00ff0000ULL) >> 16) == (Imm & 0x000000ffULL)) &&
00495          ((Imm & 0xff00ff00ff00ff00ULL) == 0);
00496 }
00497 
00498 static inline uint8_t encodeAdvSIMDModImmType5(uint64_t Imm) {
00499   return (Imm & 0xffULL);
00500 }
00501 
00502 static inline uint64_t decodeAdvSIMDModImmType5(uint8_t Imm) {
00503   uint64_t EncVal = Imm;
00504   return (EncVal << 48) | (EncVal << 32) | (EncVal << 16) | EncVal;
00505 }
00506 
00507 // abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00
00508 static inline bool isAdvSIMDModImmType6(uint64_t Imm) {
00509   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
00510          (((Imm & 0xff000000ULL) >> 16) == (Imm & 0x0000ff00ULL)) &&
00511          ((Imm & 0x00ff00ff00ff00ffULL) == 0);
00512 }
00513 
00514 static inline uint8_t encodeAdvSIMDModImmType6(uint64_t Imm) {
00515   return (Imm & 0xff00ULL) >> 8;
00516 }
00517 
00518 static inline uint64_t decodeAdvSIMDModImmType6(uint8_t Imm) {
00519   uint64_t EncVal = Imm;
00520   return (EncVal << 56) | (EncVal << 40) | (EncVal << 24) | (EncVal << 8);
00521 }
00522 
00523 // 0x00 0x00 abcdefgh 0xFF 0x00 0x00 abcdefgh 0xFF
00524 static inline bool isAdvSIMDModImmType7(uint64_t Imm) {
00525   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
00526          ((Imm & 0xffff00ffffff00ffULL) == 0x000000ff000000ffULL);
00527 }
00528 
00529 static inline uint8_t encodeAdvSIMDModImmType7(uint64_t Imm) {
00530   return (Imm & 0xff00ULL) >> 8;
00531 }
00532 
00533 static inline uint64_t decodeAdvSIMDModImmType7(uint8_t Imm) {
00534   uint64_t EncVal = Imm;
00535   return (EncVal << 40) | (EncVal << 8) | 0x000000ff000000ffULL;
00536 }
00537 
00538 // 0x00 abcdefgh 0xFF 0xFF 0x00 abcdefgh 0xFF 0xFF
00539 static inline bool isAdvSIMDModImmType8(uint64_t Imm) {
00540   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
00541          ((Imm & 0xff00ffffff00ffffULL) == 0x0000ffff0000ffffULL);
00542 }
00543 
00544 static inline uint64_t decodeAdvSIMDModImmType8(uint8_t Imm) {
00545   uint64_t EncVal = Imm;
00546   return (EncVal << 48) | (EncVal << 16) | 0x0000ffff0000ffffULL;
00547 }
00548 
00549 static inline uint8_t encodeAdvSIMDModImmType8(uint64_t Imm) {
00550   return (Imm & 0x00ff0000ULL) >> 16;
00551 }
00552 
00553 // abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh
00554 static inline bool isAdvSIMDModImmType9(uint64_t Imm) {
00555   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
00556          ((Imm >> 48) == (Imm & 0x0000ffffULL)) &&
00557          ((Imm >> 56) == (Imm & 0x000000ffULL));
00558 }
00559 
00560 static inline uint8_t encodeAdvSIMDModImmType9(uint64_t Imm) {
00561   return (Imm & 0xffULL);
00562 }
00563 
00564 static inline uint64_t decodeAdvSIMDModImmType9(uint8_t Imm) {
00565   uint64_t EncVal = Imm;
00566   EncVal |= (EncVal << 8);
00567   EncVal |= (EncVal << 16);
00568   EncVal |= (EncVal << 32);
00569   return EncVal;
00570 }
00571 
00572 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
00573 // cmode: 1110, op: 1
00574 static inline bool isAdvSIMDModImmType10(uint64_t Imm) {
00575   uint64_t ByteA = Imm & 0xff00000000000000ULL;
00576   uint64_t ByteB = Imm & 0x00ff000000000000ULL;
00577   uint64_t ByteC = Imm & 0x0000ff0000000000ULL;
00578   uint64_t ByteD = Imm & 0x000000ff00000000ULL;
00579   uint64_t ByteE = Imm & 0x00000000ff000000ULL;
00580   uint64_t ByteF = Imm & 0x0000000000ff0000ULL;
00581   uint64_t ByteG = Imm & 0x000000000000ff00ULL;
00582   uint64_t ByteH = Imm & 0x00000000000000ffULL;
00583 
00584   return (ByteA == 0ULL || ByteA == 0xff00000000000000ULL) &&
00585          (ByteB == 0ULL || ByteB == 0x00ff000000000000ULL) &&
00586          (ByteC == 0ULL || ByteC == 0x0000ff0000000000ULL) &&
00587          (ByteD == 0ULL || ByteD == 0x000000ff00000000ULL) &&
00588          (ByteE == 0ULL || ByteE == 0x00000000ff000000ULL) &&
00589          (ByteF == 0ULL || ByteF == 0x0000000000ff0000ULL) &&
00590          (ByteG == 0ULL || ByteG == 0x000000000000ff00ULL) &&
00591          (ByteH == 0ULL || ByteH == 0x00000000000000ffULL);
00592 }
00593 
00594 static inline uint8_t encodeAdvSIMDModImmType10(uint64_t Imm) {
00595   uint8_t BitA = (Imm & 0xff00000000000000ULL) != 0;
00596   uint8_t BitB = (Imm & 0x00ff000000000000ULL) != 0;
00597   uint8_t BitC = (Imm & 0x0000ff0000000000ULL) != 0;
00598   uint8_t BitD = (Imm & 0x000000ff00000000ULL) != 0;
00599   uint8_t BitE = (Imm & 0x00000000ff000000ULL) != 0;
00600   uint8_t BitF = (Imm & 0x0000000000ff0000ULL) != 0;
00601   uint8_t BitG = (Imm & 0x000000000000ff00ULL) != 0;
00602   uint8_t BitH = (Imm & 0x00000000000000ffULL) != 0;
00603 
00604   uint8_t EncVal = BitA;
00605   EncVal <<= 1;
00606   EncVal |= BitB;
00607   EncVal <<= 1;
00608   EncVal |= BitC;
00609   EncVal <<= 1;
00610   EncVal |= BitD;
00611   EncVal <<= 1;
00612   EncVal |= BitE;
00613   EncVal <<= 1;
00614   EncVal |= BitF;
00615   EncVal <<= 1;
00616   EncVal |= BitG;
00617   EncVal <<= 1;
00618   EncVal |= BitH;
00619   return EncVal;
00620 }
00621 
00622 static inline uint64_t decodeAdvSIMDModImmType10(uint8_t Imm) {
00623   uint64_t EncVal = 0;
00624   if (Imm & 0x80) EncVal |= 0xff00000000000000ULL;
00625   if (Imm & 0x40) EncVal |= 0x00ff000000000000ULL;
00626   if (Imm & 0x20) EncVal |= 0x0000ff0000000000ULL;
00627   if (Imm & 0x10) EncVal |= 0x000000ff00000000ULL;
00628   if (Imm & 0x08) EncVal |= 0x00000000ff000000ULL;
00629   if (Imm & 0x04) EncVal |= 0x0000000000ff0000ULL;
00630   if (Imm & 0x02) EncVal |= 0x000000000000ff00ULL;
00631   if (Imm & 0x01) EncVal |= 0x00000000000000ffULL;
00632   return EncVal;
00633 }
00634 
00635 // aBbbbbbc defgh000 0x00 0x00 aBbbbbbc defgh000 0x00 0x00
00636 static inline bool isAdvSIMDModImmType11(uint64_t Imm) {
00637   uint64_t BString = (Imm & 0x7E000000ULL) >> 25;
00638   return ((Imm >> 32) == (Imm & 0xffffffffULL)) &&
00639          (BString == 0x1f || BString == 0x20) &&
00640          ((Imm & 0x0007ffff0007ffffULL) == 0);
00641 }
00642 
00643 static inline uint8_t encodeAdvSIMDModImmType11(uint64_t Imm) {
00644   uint8_t BitA = (Imm & 0x80000000ULL) != 0;
00645   uint8_t BitB = (Imm & 0x20000000ULL) != 0;
00646   uint8_t BitC = (Imm & 0x01000000ULL) != 0;
00647   uint8_t BitD = (Imm & 0x00800000ULL) != 0;
00648   uint8_t BitE = (Imm & 0x00400000ULL) != 0;
00649   uint8_t BitF = (Imm & 0x00200000ULL) != 0;
00650   uint8_t BitG = (Imm & 0x00100000ULL) != 0;
00651   uint8_t BitH = (Imm & 0x00080000ULL) != 0;
00652 
00653   uint8_t EncVal = BitA;
00654   EncVal <<= 1;
00655   EncVal |= BitB;
00656   EncVal <<= 1;
00657   EncVal |= BitC;
00658   EncVal <<= 1;
00659   EncVal |= BitD;
00660   EncVal <<= 1;
00661   EncVal |= BitE;
00662   EncVal <<= 1;
00663   EncVal |= BitF;
00664   EncVal <<= 1;
00665   EncVal |= BitG;
00666   EncVal <<= 1;
00667   EncVal |= BitH;
00668   return EncVal;
00669 }
00670 
00671 static inline uint64_t decodeAdvSIMDModImmType11(uint8_t Imm) {
00672   uint64_t EncVal = 0;
00673   if (Imm & 0x80) EncVal |= 0x80000000ULL;
00674   if (Imm & 0x40) EncVal |= 0x3e000000ULL;
00675   else            EncVal |= 0x40000000ULL;
00676   if (Imm & 0x20) EncVal |= 0x01000000ULL;
00677   if (Imm & 0x10) EncVal |= 0x00800000ULL;
00678   if (Imm & 0x08) EncVal |= 0x00400000ULL;
00679   if (Imm & 0x04) EncVal |= 0x00200000ULL;
00680   if (Imm & 0x02) EncVal |= 0x00100000ULL;
00681   if (Imm & 0x01) EncVal |= 0x00080000ULL;
00682   return (EncVal << 32) | EncVal;
00683 }
00684 
00685 // aBbbbbbb bbcdefgh 0x00 0x00 0x00 0x00 0x00 0x00
00686 static inline bool isAdvSIMDModImmType12(uint64_t Imm) {
00687   uint64_t BString = (Imm & 0x7fc0000000000000ULL) >> 54;
00688   return ((BString == 0xff || BString == 0x100) &&
00689          ((Imm & 0x0000ffffffffffffULL) == 0));
00690 }
00691 
00692 static inline uint8_t encodeAdvSIMDModImmType12(uint64_t Imm) {
00693   uint8_t BitA = (Imm & 0x8000000000000000ULL) != 0;
00694   uint8_t BitB = (Imm & 0x0040000000000000ULL) != 0;
00695   uint8_t BitC = (Imm & 0x0020000000000000ULL) != 0;
00696   uint8_t BitD = (Imm & 0x0010000000000000ULL) != 0;
00697   uint8_t BitE = (Imm & 0x0008000000000000ULL) != 0;
00698   uint8_t BitF = (Imm & 0x0004000000000000ULL) != 0;
00699   uint8_t BitG = (Imm & 0x0002000000000000ULL) != 0;
00700   uint8_t BitH = (Imm & 0x0001000000000000ULL) != 0;
00701 
00702   uint8_t EncVal = BitA;
00703   EncVal <<= 1;
00704   EncVal |= BitB;
00705   EncVal <<= 1;
00706   EncVal |= BitC;
00707   EncVal <<= 1;
00708   EncVal |= BitD;
00709   EncVal <<= 1;
00710   EncVal |= BitE;
00711   EncVal <<= 1;
00712   EncVal |= BitF;
00713   EncVal <<= 1;
00714   EncVal |= BitG;
00715   EncVal <<= 1;
00716   EncVal |= BitH;
00717   return EncVal;
00718 }
00719 
00720 static inline uint64_t decodeAdvSIMDModImmType12(uint8_t Imm) {
00721   uint64_t EncVal = 0;
00722   if (Imm & 0x80) EncVal |= 0x8000000000000000ULL;
00723   if (Imm & 0x40) EncVal |= 0x3fc0000000000000ULL;
00724   else            EncVal |= 0x4000000000000000ULL;
00725   if (Imm & 0x20) EncVal |= 0x0020000000000000ULL;
00726   if (Imm & 0x10) EncVal |= 0x0010000000000000ULL;
00727   if (Imm & 0x08) EncVal |= 0x0008000000000000ULL;
00728   if (Imm & 0x04) EncVal |= 0x0004000000000000ULL;
00729   if (Imm & 0x02) EncVal |= 0x0002000000000000ULL;
00730   if (Imm & 0x01) EncVal |= 0x0001000000000000ULL;
00731   return (EncVal << 32) | EncVal;
00732 }
00733 
00734 } // end namespace AArch64_AM
00735 
00736 } // end namespace llvm
00737 
00738 #endif