1 //===- AArch64AddressingModes.h - AArch64 Addressing Modes ------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains the AArch64 addressing mode implementation stuff. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64ADDRESSINGMODES_H 15 #define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64ADDRESSINGMODES_H 16 17 #include "llvm/ADT/APFloat.h" 18 #include "llvm/ADT/APInt.h" 19 #include "llvm/Support/ErrorHandling.h" 20 #include "llvm/Support/MathExtras.h" 21 #include <cassert> 22 23 namespace llvm { 24 25 /// AArch64_AM - AArch64 Addressing Mode Stuff 26 namespace AArch64_AM { 27 28 //===----------------------------------------------------------------------===// 29 // Shifts 30 // 31 32 enum ShiftExtendType { 33 InvalidShiftExtend = -1, 34 LSL = 0, 35 LSR, 36 ASR, 37 ROR, 38 MSL, 39 40 UXTB, 41 UXTH, 42 UXTW, 43 UXTX, 44 45 SXTB, 46 SXTH, 47 SXTW, 48 SXTX, 49 }; 50 51 /// getShiftName - Get the string encoding for the shift type. 52 static inline const char *getShiftExtendName(AArch64_AM::ShiftExtendType ST) { 53 switch (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"; 68 } 69 return nullptr; 70 } 71 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; 81 } 82 } 83 84 /// getShiftValue - Extract the shift value. 85 static inline unsigned getShiftValue(unsigned Imm) { 86 return Imm & 0x3f; 87 } 88 89 /// getShifterImm - Encode the shift type and amount: 90 /// imm: 6-bit shift amount 91 /// shifter: 000 ==> lsl 92 /// 001 ==> lsr 93 /// 010 ==> asr 94 /// 011 ==> ror 95 /// 100 ==> msl 96 /// {8-6} = shifter 97 /// {5-0} = imm 98 static inline unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, 99 unsigned Imm) { 100 assert((Imm & 0x3f) == Imm && "Illegal shifted immedate value!"); 101 unsigned STEnc = 0; 102 switch (ST) { 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; 109 } 110 return (STEnc << 6) | (Imm & 0x3f); 111 } 112 113 //===----------------------------------------------------------------------===// 114 // Extends 115 // 116 117 /// getArithShiftValue - get the arithmetic shift value. 118 static inline unsigned getArithShiftValue(unsigned Imm) { 119 return Imm & 0x7; 120 } 121 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!"); 125 switch (Imm) { 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; 135 } 136 } 137 138 static inline AArch64_AM::ShiftExtendType getArithExtendType(unsigned Imm) { 139 return getExtendType((Imm >> 3) & 0x7); 140 } 141 142 /// Mapping from extend bits to required operation: 143 /// shifter: 000 ==> uxtb 144 /// 001 ==> uxth 145 /// 010 ==> uxtw 146 /// 011 ==> uxtx 147 /// 100 ==> sxtb 148 /// 101 ==> sxth 149 /// 110 ==> sxtw 150 /// 111 ==> sxtx 151 inline unsigned getExtendEncoding(AArch64_AM::ShiftExtendType ET) { 152 switch (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; 162 } 163 } 164 165 /// getArithExtendImm - Encode the extend type and shift amount for an 166 /// arithmetic instruction: 167 /// imm: 3-bit extend amount 168 /// {5-3} = shifter 169 /// {2-0} = imm3 170 static inline unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET, 171 unsigned Imm) { 172 assert((Imm & 0x7) == Imm && "Illegal shifted immedate value!"); 173 return (getExtendEncoding(ET) << 3) | (Imm & 0x7); 174 } 175 176 /// getMemDoShift - Extract the "do shift" flag value for load/store 177 /// instructions. 178 static inline bool getMemDoShift(unsigned Imm) { 179 return (Imm & 0x1) != 0; 180 } 181 182 /// getExtendType - Extract the extend type for the offset operand of 183 /// loads/stores. 184 static inline AArch64_AM::ShiftExtendType getMemExtendType(unsigned Imm) { 185 return getExtendType((Imm >> 1) & 0x7); 186 } 187 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 191 /// 001 ==> uxth 192 /// 010 ==> uxtw 193 /// 011 ==> uxtx 194 /// 100 ==> sxtb 195 /// 101 ==> sxth 196 /// 110 ==> sxtw 197 /// 111 ==> sxtx 198 /// {3-1} = shifter 199 /// {0} = doshift 200 static inline unsigned getMemExtendImm(AArch64_AM::ShiftExtendType ET, 201 bool DoShift) { 202 return (getExtendEncoding(ET) << 1) | unsigned(DoShift); 203 } 204 205 static inline uint64_t ror(uint64_t elt, unsigned size) { 206 return ((elt & 1) << (size-1)) | (elt >> 1); 207 } 208 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 || 216 (RegSize != 64 && (Imm >> RegSize != 0 || Imm == ~0U))) 217 return false; 218 219 // First, determine the element size. 220 unsigned Size = RegSize; 221 222 do { 223 Size /= 2; 224 uint64_t Mask = (1ULL << Size) - 1; 225 226 if ((Imm & Mask) != ((Imm >> Size) & Mask)) { 227 Size *= 2; 228 break; 229 } 230 } while (Size > 2); 231 232 // Second, determine the rotation to make the element be: 0^m 1^n. 233 uint32_t CTO, I; 234 uint64_t Mask = ((uint64_t)-1LL) >> (64 - Size); 235 Imm &= Mask; 236 237 if (isShiftedMask_64(Imm)) { 238 I = countTrailingZeros(Imm); 239 assert(I < 64 && "undefined behavior"); 240 CTO = countTrailingOnes(Imm >> I); 241 } else { 242 Imm |= ~Mask; 243 if (!isShiftedMask_64(~Imm)) 244 return false; 245 246 unsigned CLO = countLeadingOnes(Imm); 247 I = 64 - CLO; 248 CTO = CLO + countTrailingOnes(Imm) - (64 - Size); 249 } 250 251 // Encode in Immr the number of RORs it would take to get *from* 0^m 1^n 252 // to our target value, where I is the number of RORs to go the opposite 253 // direction. 254 assert(Size > I && "I should be smaller than element size"); 255 unsigned Immr = (Size - I) & (Size - 1); 256 257 // If size has a 1 in the n'th bit, create a value that has zeroes in 258 // bits [0, n] and ones above that. 259 uint64_t NImms = ~(Size-1) << 1; 260 261 // Or the CTO value into the low bits, which must be below the Nth bit 262 // bit mentioned above. 263 NImms |= (CTO-1); 264 265 // Extract the seventh bit and toggle it to create the N field. 266 unsigned N = ((NImms >> 6) & 1) ^ 1; 267 268 Encoding = (N << 12) | (Immr << 6) | (NImms & 0x3f); 269 return true; 270 } 271 272 /// isLogicalImmediate - Return true if the immediate is valid for a logical 273 /// immediate instruction of the given register size. Return false otherwise. 274 static inline bool isLogicalImmediate(uint64_t imm, unsigned regSize) { 275 uint64_t encoding; 276 return processLogicalImmediate(imm, regSize, encoding); 277 } 278 279 /// encodeLogicalImmediate - Return the encoded immediate value for a logical 280 /// immediate instruction of the given register size. 281 static inline uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize) { 282 uint64_t encoding = 0; 283 bool res = processLogicalImmediate(imm, regSize, encoding); 284 assert(res && "invalid logical immediate"); 285 (void)res; 286 return encoding; 287 } 288 289 /// decodeLogicalImmediate - Decode a logical immediate value in the form 290 /// "N:immr:imms" (where the immr and imms fields are each 6 bits) into the 291 /// integer value it represents with regSize bits. 292 static inline uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize) { 293 // Extract the N, imms, and immr fields. 294 unsigned N = (val >> 12) & 1; 295 unsigned immr = (val >> 6) & 0x3f; 296 unsigned imms = val & 0x3f; 297 298 assert((regSize == 64 || N == 0) && "undefined logical immediate encoding"); 299 int len = 31 - countLeadingZeros((N << 6) | (~imms & 0x3f)); 300 assert(len >= 0 && "undefined logical immediate encoding"); 301 unsigned size = (1 << len); 302 unsigned R = immr & (size - 1); 303 unsigned S = imms & (size - 1); 304 assert(S != size - 1 && "undefined logical immediate encoding"); 305 uint64_t pattern = (1ULL << (S + 1)) - 1; 306 for (unsigned i = 0; i < R; ++i) 307 pattern = ror(pattern, size); 308 309 // Replicate the pattern to fill the regSize. 310 while (size != regSize) { 311 pattern |= (pattern << size); 312 size *= 2; 313 } 314 return pattern; 315 } 316 317 /// isValidDecodeLogicalImmediate - Check to see if the logical immediate value 318 /// in the form "N:immr:imms" (where the immr and imms fields are each 6 bits) 319 /// is a valid encoding for an integer value with regSize bits. 320 static inline bool isValidDecodeLogicalImmediate(uint64_t val, 321 unsigned regSize) { 322 // Extract the N and imms fields needed for checking. 323 unsigned N = (val >> 12) & 1; 324 unsigned imms = val & 0x3f; 325 326 if (regSize == 32 && N != 0) // undefined logical immediate encoding 327 return false; 328 int len = 31 - countLeadingZeros((N << 6) | (~imms & 0x3f)); 329 if (len < 0) // undefined logical immediate encoding 330 return false; 331 unsigned size = (1 << len); 332 unsigned S = imms & (size - 1); 333 if (S == size - 1) // undefined logical immediate encoding 334 return false; 335 336 return true; 337 } 338 339 //===----------------------------------------------------------------------===// 340 // Floating-point Immediates 341 // 342 static inline float getFPImmFloat(unsigned Imm) { 343 // We expect an 8-bit binary encoding of a floating-point number here. 344 union { 345 uint32_t I; 346 float F; 347 } FPUnion; 348 349 uint8_t Sign = (Imm >> 7) & 0x1; 350 uint8_t Exp = (Imm >> 4) & 0x7; 351 uint8_t Mantissa = Imm & 0xf; 352 353 // 8-bit FP iEEEE Float Encoding 354 // abcd efgh aBbbbbbc defgh000 00000000 00000000 355 // 356 // where B = NOT(b); 357 358 FPUnion.I = 0; 359 FPUnion.I |= Sign << 31; 360 FPUnion.I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30; 361 FPUnion.I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25; 362 FPUnion.I |= (Exp & 0x3) << 23; 363 FPUnion.I |= Mantissa << 19; 364 return FPUnion.F; 365 } 366 367 /// getFP32Imm - Return an 8-bit floating-point version of the 32-bit 368 /// floating-point value. If the value cannot be represented as an 8-bit 369 /// floating-point value, then return -1. 370 static inline int getFP32Imm(const APInt &Imm) { 371 uint32_t Sign = Imm.lshr(31).getZExtValue() & 1; 372 int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127; // -126 to 127 373 int64_t Mantissa = Imm.getZExtValue() & 0x7fffff; // 23 bits 374 375 // We can handle 4 bits of mantissa. 376 // mantissa = (16+UInt(e:f:g:h))/16. 377 if (Mantissa & 0x7ffff) 378 return -1; 379 Mantissa >>= 19; 380 if ((Mantissa & 0xf) != Mantissa) 381 return -1; 382 383 // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 384 if (Exp < -3 || Exp > 4) 385 return -1; 386 Exp = ((Exp+3) & 0x7) ^ 4; 387 388 return ((int)Sign << 7) | (Exp << 4) | Mantissa; 389 } 390 391 static inline int getFP32Imm(const APFloat &FPImm) { 392 return getFP32Imm(FPImm.bitcastToAPInt()); 393 } 394 395 /// getFP64Imm - Return an 8-bit floating-point version of the 64-bit 396 /// floating-point value. If the value cannot be represented as an 8-bit 397 /// floating-point value, then return -1. 398 static inline int getFP64Imm(const APInt &Imm) { 399 uint64_t Sign = Imm.lshr(63).getZExtValue() & 1; 400 int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023; // -1022 to 1023 401 uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffULL; 402 403 // We can handle 4 bits of mantissa. 404 // mantissa = (16+UInt(e:f:g:h))/16. 405 if (Mantissa & 0xffffffffffffULL) 406 return -1; 407 Mantissa >>= 48; 408 if ((Mantissa & 0xf) != Mantissa) 409 return -1; 410 411 // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 412 if (Exp < -3 || Exp > 4) 413 return -1; 414 Exp = ((Exp+3) & 0x7) ^ 4; 415 416 return ((int)Sign << 7) | (Exp << 4) | Mantissa; 417 } 418 419 static inline int getFP64Imm(const APFloat &FPImm) { 420 return getFP64Imm(FPImm.bitcastToAPInt()); 421 } 422 423 //===--------------------------------------------------------------------===// 424 // AdvSIMD Modified Immediates 425 //===--------------------------------------------------------------------===// 426 427 // 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 428 static inline bool isAdvSIMDModImmType1(uint64_t Imm) { 429 return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 430 ((Imm & 0xffffff00ffffff00ULL) == 0); 431 } 432 433 static inline uint8_t encodeAdvSIMDModImmType1(uint64_t Imm) { 434 return (Imm & 0xffULL); 435 } 436 437 static inline uint64_t decodeAdvSIMDModImmType1(uint8_t Imm) { 438 uint64_t EncVal = Imm; 439 return (EncVal << 32) | EncVal; 440 } 441 442 // 0x00 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 443 static inline bool isAdvSIMDModImmType2(uint64_t Imm) { 444 return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 445 ((Imm & 0xffff00ffffff00ffULL) == 0); 446 } 447 448 static inline uint8_t encodeAdvSIMDModImmType2(uint64_t Imm) { 449 return (Imm & 0xff00ULL) >> 8; 450 } 451 452 static inline uint64_t decodeAdvSIMDModImmType2(uint8_t Imm) { 453 uint64_t EncVal = Imm; 454 return (EncVal << 40) | (EncVal << 8); 455 } 456 457 // 0x00 abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00 458 static inline bool isAdvSIMDModImmType3(uint64_t Imm) { 459 return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 460 ((Imm & 0xff00ffffff00ffffULL) == 0); 461 } 462 463 static inline uint8_t encodeAdvSIMDModImmType3(uint64_t Imm) { 464 return (Imm & 0xff0000ULL) >> 16; 465 } 466 467 static inline uint64_t decodeAdvSIMDModImmType3(uint8_t Imm) { 468 uint64_t EncVal = Imm; 469 return (EncVal << 48) | (EncVal << 16); 470 } 471 472 // abcdefgh 0x00 0x00 0x00 abcdefgh 0x00 0x00 0x00 473 static inline bool isAdvSIMDModImmType4(uint64_t Imm) { 474 return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 475 ((Imm & 0x00ffffff00ffffffULL) == 0); 476 } 477 478 static inline uint8_t encodeAdvSIMDModImmType4(uint64_t Imm) { 479 return (Imm & 0xff000000ULL) >> 24; 480 } 481 482 static inline uint64_t decodeAdvSIMDModImmType4(uint8_t Imm) { 483 uint64_t EncVal = Imm; 484 return (EncVal << 56) | (EncVal << 24); 485 } 486 487 // 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 488 static inline bool isAdvSIMDModImmType5(uint64_t Imm) { 489 return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 490 (((Imm & 0x00ff0000ULL) >> 16) == (Imm & 0x000000ffULL)) && 491 ((Imm & 0xff00ff00ff00ff00ULL) == 0); 492 } 493 494 static inline uint8_t encodeAdvSIMDModImmType5(uint64_t Imm) { 495 return (Imm & 0xffULL); 496 } 497 498 static inline uint64_t decodeAdvSIMDModImmType5(uint8_t Imm) { 499 uint64_t EncVal = Imm; 500 return (EncVal << 48) | (EncVal << 32) | (EncVal << 16) | EncVal; 501 } 502 503 // abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 abcdefgh 0x00 504 static inline bool isAdvSIMDModImmType6(uint64_t Imm) { 505 return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 506 (((Imm & 0xff000000ULL) >> 16) == (Imm & 0x0000ff00ULL)) && 507 ((Imm & 0x00ff00ff00ff00ffULL) == 0); 508 } 509 510 static inline uint8_t encodeAdvSIMDModImmType6(uint64_t Imm) { 511 return (Imm & 0xff00ULL) >> 8; 512 } 513 514 static inline uint64_t decodeAdvSIMDModImmType6(uint8_t Imm) { 515 uint64_t EncVal = Imm; 516 return (EncVal << 56) | (EncVal << 40) | (EncVal << 24) | (EncVal << 8); 517 } 518 519 // 0x00 0x00 abcdefgh 0xFF 0x00 0x00 abcdefgh 0xFF 520 static inline bool isAdvSIMDModImmType7(uint64_t Imm) { 521 return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 522 ((Imm & 0xffff00ffffff00ffULL) == 0x000000ff000000ffULL); 523 } 524 525 static inline uint8_t encodeAdvSIMDModImmType7(uint64_t Imm) { 526 return (Imm & 0xff00ULL) >> 8; 527 } 528 529 static inline uint64_t decodeAdvSIMDModImmType7(uint8_t Imm) { 530 uint64_t EncVal = Imm; 531 return (EncVal << 40) | (EncVal << 8) | 0x000000ff000000ffULL; 532 } 533 534 // 0x00 abcdefgh 0xFF 0xFF 0x00 abcdefgh 0xFF 0xFF 535 static inline bool isAdvSIMDModImmType8(uint64_t Imm) { 536 return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 537 ((Imm & 0xff00ffffff00ffffULL) == 0x0000ffff0000ffffULL); 538 } 539 540 static inline uint64_t decodeAdvSIMDModImmType8(uint8_t Imm) { 541 uint64_t EncVal = Imm; 542 return (EncVal << 48) | (EncVal << 16) | 0x0000ffff0000ffffULL; 543 } 544 545 static inline uint8_t encodeAdvSIMDModImmType8(uint64_t Imm) { 546 return (Imm & 0x00ff0000ULL) >> 16; 547 } 548 549 // abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh abcdefgh 550 static inline bool isAdvSIMDModImmType9(uint64_t Imm) { 551 return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 552 ((Imm >> 48) == (Imm & 0x0000ffffULL)) && 553 ((Imm >> 56) == (Imm & 0x000000ffULL)); 554 } 555 556 static inline uint8_t encodeAdvSIMDModImmType9(uint64_t Imm) { 557 return (Imm & 0xffULL); 558 } 559 560 static inline uint64_t decodeAdvSIMDModImmType9(uint8_t Imm) { 561 uint64_t EncVal = Imm; 562 EncVal |= (EncVal << 8); 563 EncVal |= (EncVal << 16); 564 EncVal |= (EncVal << 32); 565 return EncVal; 566 } 567 568 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh 569 // cmode: 1110, op: 1 570 static inline bool isAdvSIMDModImmType10(uint64_t Imm) { 571 uint64_t ByteA = Imm & 0xff00000000000000ULL; 572 uint64_t ByteB = Imm & 0x00ff000000000000ULL; 573 uint64_t ByteC = Imm & 0x0000ff0000000000ULL; 574 uint64_t ByteD = Imm & 0x000000ff00000000ULL; 575 uint64_t ByteE = Imm & 0x00000000ff000000ULL; 576 uint64_t ByteF = Imm & 0x0000000000ff0000ULL; 577 uint64_t ByteG = Imm & 0x000000000000ff00ULL; 578 uint64_t ByteH = Imm & 0x00000000000000ffULL; 579 580 return (ByteA == 0ULL || ByteA == 0xff00000000000000ULL) && 581 (ByteB == 0ULL || ByteB == 0x00ff000000000000ULL) && 582 (ByteC == 0ULL || ByteC == 0x0000ff0000000000ULL) && 583 (ByteD == 0ULL || ByteD == 0x000000ff00000000ULL) && 584 (ByteE == 0ULL || ByteE == 0x00000000ff000000ULL) && 585 (ByteF == 0ULL || ByteF == 0x0000000000ff0000ULL) && 586 (ByteG == 0ULL || ByteG == 0x000000000000ff00ULL) && 587 (ByteH == 0ULL || ByteH == 0x00000000000000ffULL); 588 } 589 590 static inline uint8_t encodeAdvSIMDModImmType10(uint64_t Imm) { 591 uint8_t BitA = (Imm & 0xff00000000000000ULL) != 0; 592 uint8_t BitB = (Imm & 0x00ff000000000000ULL) != 0; 593 uint8_t BitC = (Imm & 0x0000ff0000000000ULL) != 0; 594 uint8_t BitD = (Imm & 0x000000ff00000000ULL) != 0; 595 uint8_t BitE = (Imm & 0x00000000ff000000ULL) != 0; 596 uint8_t BitF = (Imm & 0x0000000000ff0000ULL) != 0; 597 uint8_t BitG = (Imm & 0x000000000000ff00ULL) != 0; 598 uint8_t BitH = (Imm & 0x00000000000000ffULL) != 0; 599 600 uint8_t EncVal = BitA; 601 EncVal <<= 1; 602 EncVal |= BitB; 603 EncVal <<= 1; 604 EncVal |= BitC; 605 EncVal <<= 1; 606 EncVal |= BitD; 607 EncVal <<= 1; 608 EncVal |= BitE; 609 EncVal <<= 1; 610 EncVal |= BitF; 611 EncVal <<= 1; 612 EncVal |= BitG; 613 EncVal <<= 1; 614 EncVal |= BitH; 615 return EncVal; 616 } 617 618 static inline uint64_t decodeAdvSIMDModImmType10(uint8_t Imm) { 619 uint64_t EncVal = 0; 620 if (Imm & 0x80) EncVal |= 0xff00000000000000ULL; 621 if (Imm & 0x40) EncVal |= 0x00ff000000000000ULL; 622 if (Imm & 0x20) EncVal |= 0x0000ff0000000000ULL; 623 if (Imm & 0x10) EncVal |= 0x000000ff00000000ULL; 624 if (Imm & 0x08) EncVal |= 0x00000000ff000000ULL; 625 if (Imm & 0x04) EncVal |= 0x0000000000ff0000ULL; 626 if (Imm & 0x02) EncVal |= 0x000000000000ff00ULL; 627 if (Imm & 0x01) EncVal |= 0x00000000000000ffULL; 628 return EncVal; 629 } 630 631 // aBbbbbbc defgh000 0x00 0x00 aBbbbbbc defgh000 0x00 0x00 632 static inline bool isAdvSIMDModImmType11(uint64_t Imm) { 633 uint64_t BString = (Imm & 0x7E000000ULL) >> 25; 634 return ((Imm >> 32) == (Imm & 0xffffffffULL)) && 635 (BString == 0x1f || BString == 0x20) && 636 ((Imm & 0x0007ffff0007ffffULL) == 0); 637 } 638 639 static inline uint8_t encodeAdvSIMDModImmType11(uint64_t Imm) { 640 uint8_t BitA = (Imm & 0x80000000ULL) != 0; 641 uint8_t BitB = (Imm & 0x20000000ULL) != 0; 642 uint8_t BitC = (Imm & 0x01000000ULL) != 0; 643 uint8_t BitD = (Imm & 0x00800000ULL) != 0; 644 uint8_t BitE = (Imm & 0x00400000ULL) != 0; 645 uint8_t BitF = (Imm & 0x00200000ULL) != 0; 646 uint8_t BitG = (Imm & 0x00100000ULL) != 0; 647 uint8_t BitH = (Imm & 0x00080000ULL) != 0; 648 649 uint8_t EncVal = BitA; 650 EncVal <<= 1; 651 EncVal |= BitB; 652 EncVal <<= 1; 653 EncVal |= BitC; 654 EncVal <<= 1; 655 EncVal |= BitD; 656 EncVal <<= 1; 657 EncVal |= BitE; 658 EncVal <<= 1; 659 EncVal |= BitF; 660 EncVal <<= 1; 661 EncVal |= BitG; 662 EncVal <<= 1; 663 EncVal |= BitH; 664 return EncVal; 665 } 666 667 static inline uint64_t decodeAdvSIMDModImmType11(uint8_t Imm) { 668 uint64_t EncVal = 0; 669 if (Imm & 0x80) EncVal |= 0x80000000ULL; 670 if (Imm & 0x40) EncVal |= 0x3e000000ULL; 671 else EncVal |= 0x40000000ULL; 672 if (Imm & 0x20) EncVal |= 0x01000000ULL; 673 if (Imm & 0x10) EncVal |= 0x00800000ULL; 674 if (Imm & 0x08) EncVal |= 0x00400000ULL; 675 if (Imm & 0x04) EncVal |= 0x00200000ULL; 676 if (Imm & 0x02) EncVal |= 0x00100000ULL; 677 if (Imm & 0x01) EncVal |= 0x00080000ULL; 678 return (EncVal << 32) | EncVal; 679 } 680 681 // aBbbbbbb bbcdefgh 0x00 0x00 0x00 0x00 0x00 0x00 682 static inline bool isAdvSIMDModImmType12(uint64_t Imm) { 683 uint64_t BString = (Imm & 0x7fc0000000000000ULL) >> 54; 684 return ((BString == 0xff || BString == 0x100) && 685 ((Imm & 0x0000ffffffffffffULL) == 0)); 686 } 687 688 static inline uint8_t encodeAdvSIMDModImmType12(uint64_t Imm) { 689 uint8_t BitA = (Imm & 0x8000000000000000ULL) != 0; 690 uint8_t BitB = (Imm & 0x0040000000000000ULL) != 0; 691 uint8_t BitC = (Imm & 0x0020000000000000ULL) != 0; 692 uint8_t BitD = (Imm & 0x0010000000000000ULL) != 0; 693 uint8_t BitE = (Imm & 0x0008000000000000ULL) != 0; 694 uint8_t BitF = (Imm & 0x0004000000000000ULL) != 0; 695 uint8_t BitG = (Imm & 0x0002000000000000ULL) != 0; 696 uint8_t BitH = (Imm & 0x0001000000000000ULL) != 0; 697 698 uint8_t EncVal = BitA; 699 EncVal <<= 1; 700 EncVal |= BitB; 701 EncVal <<= 1; 702 EncVal |= BitC; 703 EncVal <<= 1; 704 EncVal |= BitD; 705 EncVal <<= 1; 706 EncVal |= BitE; 707 EncVal <<= 1; 708 EncVal |= BitF; 709 EncVal <<= 1; 710 EncVal |= BitG; 711 EncVal <<= 1; 712 EncVal |= BitH; 713 return EncVal; 714 } 715 716 static inline uint64_t decodeAdvSIMDModImmType12(uint8_t Imm) { 717 uint64_t EncVal = 0; 718 if (Imm & 0x80) EncVal |= 0x8000000000000000ULL; 719 if (Imm & 0x40) EncVal |= 0x3fc0000000000000ULL; 720 else EncVal |= 0x4000000000000000ULL; 721 if (Imm & 0x20) EncVal |= 0x0020000000000000ULL; 722 if (Imm & 0x10) EncVal |= 0x0010000000000000ULL; 723 if (Imm & 0x08) EncVal |= 0x0008000000000000ULL; 724 if (Imm & 0x04) EncVal |= 0x0004000000000000ULL; 725 if (Imm & 0x02) EncVal |= 0x0002000000000000ULL; 726 if (Imm & 0x01) EncVal |= 0x0001000000000000ULL; 727 return (EncVal << 32) | EncVal; 728 } 729 730 } // end namespace AArch64_AM 731 732 } // end namespace llvm 733 734 #endif 735