1 //===-- ARMAddressingModes.h - ARM Addressing Modes -------------*- C++ -*-===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains the ARM addressing mode implementation stuff. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMADDRESSINGMODES_H 14 #define LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMADDRESSINGMODES_H 15 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" 21 #include <cassert> 22 23 namespace llvm { 24 25 /// ARM_AM - ARM Addressing Mode Stuff 26 namespace ARM_AM { 27 enum ShiftOpc { 28 no_shift = 0, 29 asr, 30 lsl, 31 lsr, 32 ror, 33 rrx, 34 uxtw 35 }; 36 37 enum AddrOpc { 38 sub = 0, 39 add 40 }; 41 getAddrOpcStr(AddrOpc Op)42 inline const char *getAddrOpcStr(AddrOpc Op) { return Op == sub ? "-" : ""; } 43 getShiftOpcStr(ShiftOpc Op)44 inline const StringRef getShiftOpcStr(ShiftOpc Op) { 45 switch (Op) { 46 default: llvm_unreachable("Unknown shift opc!"); 47 case ARM_AM::asr: return "asr"; 48 case ARM_AM::lsl: return "lsl"; 49 case ARM_AM::lsr: return "lsr"; 50 case ARM_AM::ror: return "ror"; 51 case ARM_AM::rrx: return "rrx"; 52 case ARM_AM::uxtw: return "uxtw"; 53 } 54 } 55 getShiftOpcEncoding(ShiftOpc Op)56 inline unsigned getShiftOpcEncoding(ShiftOpc Op) { 57 switch (Op) { 58 default: llvm_unreachable("Unknown shift opc!"); 59 case ARM_AM::asr: return 2; 60 case ARM_AM::lsl: return 0; 61 case ARM_AM::lsr: return 1; 62 case ARM_AM::ror: return 3; 63 } 64 } 65 66 enum AMSubMode { 67 bad_am_submode = 0, 68 ia, 69 ib, 70 da, 71 db 72 }; 73 getAMSubModeStr(AMSubMode Mode)74 inline const char *getAMSubModeStr(AMSubMode Mode) { 75 switch (Mode) { 76 default: llvm_unreachable("Unknown addressing sub-mode!"); 77 case ARM_AM::ia: return "ia"; 78 case ARM_AM::ib: return "ib"; 79 case ARM_AM::da: return "da"; 80 case ARM_AM::db: return "db"; 81 } 82 } 83 84 //===--------------------------------------------------------------------===// 85 // Addressing Mode #1: shift_operand with registers 86 //===--------------------------------------------------------------------===// 87 // 88 // This 'addressing mode' is used for arithmetic instructions. It can 89 // represent things like: 90 // reg 91 // reg [asr|lsl|lsr|ror|rrx] reg 92 // reg [asr|lsl|lsr|ror|rrx] imm 93 // 94 // This is stored three operands [rega, regb, opc]. The first is the base 95 // reg, the second is the shift amount (or reg0 if not present or imm). The 96 // third operand encodes the shift opcode and the imm if a reg isn't present. 97 // getSORegOpc(ShiftOpc ShOp,unsigned Imm)98 inline unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm) { 99 return ShOp | (Imm << 3); 100 } getSORegOffset(unsigned Op)101 inline unsigned getSORegOffset(unsigned Op) { return Op >> 3; } getSORegShOp(unsigned Op)102 inline ShiftOpc getSORegShOp(unsigned Op) { return (ShiftOpc)(Op & 7); } 103 104 /// getSOImmValImm - Given an encoded imm field for the reg/imm form, return 105 /// the 8-bit imm value. getSOImmValImm(unsigned Imm)106 inline unsigned getSOImmValImm(unsigned Imm) { return Imm & 0xFF; } 107 /// getSOImmValRot - Given an encoded imm field for the reg/imm form, return 108 /// the rotate amount. getSOImmValRot(unsigned Imm)109 inline unsigned getSOImmValRot(unsigned Imm) { return (Imm >> 8) * 2; } 110 111 /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand, 112 /// computing the rotate amount to use. If this immediate value cannot be 113 /// handled with a single shifter-op, determine a good rotate amount that will 114 /// take a maximal chunk of bits out of the immediate. getSOImmValRotate(unsigned Imm)115 inline unsigned getSOImmValRotate(unsigned Imm) { 116 // 8-bit (or less) immediates are trivially shifter_operands with a rotate 117 // of zero. 118 if ((Imm & ~255U) == 0) return 0; 119 120 // Use CTZ to compute the rotate amount. 121 unsigned TZ = llvm::countr_zero(Imm); 122 123 // Rotate amount must be even. Something like 0x200 must be rotated 8 bits, 124 // not 9. 125 unsigned RotAmt = TZ & ~1; 126 127 // If we can handle this spread, return it. 128 if ((llvm::rotr<uint32_t>(Imm, RotAmt) & ~255U) == 0) 129 return (32-RotAmt)&31; // HW rotates right, not left. 130 131 // For values like 0xF000000F, we should ignore the low 6 bits, then 132 // retry the hunt. 133 if (Imm & 63U) { 134 unsigned TZ2 = llvm::countr_zero(Imm & ~63U); 135 unsigned RotAmt2 = TZ2 & ~1; 136 if ((llvm::rotr<uint32_t>(Imm, RotAmt2) & ~255U) == 0) 137 return (32-RotAmt2)&31; // HW rotates right, not left. 138 } 139 140 // Otherwise, we have no way to cover this span of bits with a single 141 // shifter_op immediate. Return a chunk of bits that will be useful to 142 // handle. 143 return (32-RotAmt)&31; // HW rotates right, not left. 144 } 145 146 /// getSOImmVal - Given a 32-bit immediate, if it is something that can fit 147 /// into an shifter_operand immediate operand, return the 12-bit encoding for 148 /// it. If not, return -1. getSOImmVal(unsigned Arg)149 inline int getSOImmVal(unsigned Arg) { 150 // 8-bit (or less) immediates are trivially shifter_operands with a rotate 151 // of zero. 152 if ((Arg & ~255U) == 0) return Arg; 153 154 unsigned RotAmt = getSOImmValRotate(Arg); 155 156 // If this cannot be handled with a single shifter_op, bail out. 157 if (llvm::rotr<uint32_t>(~255U, RotAmt) & Arg) 158 return -1; 159 160 // Encode this correctly. 161 return llvm::rotl<uint32_t>(Arg, RotAmt) | ((RotAmt >> 1) << 8); 162 } 163 164 /// isSOImmTwoPartVal - Return true if the specified value can be obtained by 165 /// or'ing together two SOImmVal's. isSOImmTwoPartVal(unsigned V)166 inline bool isSOImmTwoPartVal(unsigned V) { 167 // If this can be handled with a single shifter_op, bail out. 168 V = llvm::rotr<uint32_t>(~255U, getSOImmValRotate(V)) & V; 169 if (V == 0) 170 return false; 171 172 // If this can be handled with two shifter_op's, accept. 173 V = llvm::rotr<uint32_t>(~255U, getSOImmValRotate(V)) & V; 174 return V == 0; 175 } 176 177 /// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, 178 /// return the first chunk of it. getSOImmTwoPartFirst(unsigned V)179 inline unsigned getSOImmTwoPartFirst(unsigned V) { 180 return llvm::rotr<uint32_t>(255U, getSOImmValRotate(V)) & V; 181 } 182 183 /// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, 184 /// return the second chunk of it. getSOImmTwoPartSecond(unsigned V)185 inline unsigned getSOImmTwoPartSecond(unsigned V) { 186 // Mask out the first hunk. 187 V = llvm::rotr<uint32_t>(~255U, getSOImmValRotate(V)) & V; 188 189 // Take what's left. 190 assert(V == (llvm::rotr<uint32_t>(255U, getSOImmValRotate(V)) & V)); 191 return V; 192 } 193 194 /// isSOImmTwoPartValNeg - Return true if the specified value can be obtained 195 /// by two SOImmVal, that -V = First + Second. 196 /// "R+V" can be optimized to (sub (sub R, First), Second). 197 /// "R=V" can be optimized to (sub (mvn R, ~(-First)), Second). isSOImmTwoPartValNeg(unsigned V)198 inline bool isSOImmTwoPartValNeg(unsigned V) { 199 unsigned First; 200 if (!isSOImmTwoPartVal(-V)) 201 return false; 202 // Return false if ~(-First) is not a SoImmval. 203 First = getSOImmTwoPartFirst(-V); 204 First = ~(-First); 205 return !(llvm::rotr<uint32_t>(~255U, getSOImmValRotate(First)) & First); 206 } 207 208 /// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed 209 /// by a left shift. Returns the shift amount to use. getThumbImmValShift(unsigned Imm)210 inline unsigned getThumbImmValShift(unsigned Imm) { 211 // 8-bit (or less) immediates are trivially immediate operand with a shift 212 // of zero. 213 if ((Imm & ~255U) == 0) return 0; 214 215 // Use CTZ to compute the shift amount. 216 return llvm::countr_zero(Imm); 217 } 218 219 /// isThumbImmShiftedVal - Return true if the specified value can be obtained 220 /// by left shifting a 8-bit immediate. isThumbImmShiftedVal(unsigned V)221 inline bool isThumbImmShiftedVal(unsigned V) { 222 // If this can be handled with 223 V = (~255U << getThumbImmValShift(V)) & V; 224 return V == 0; 225 } 226 227 /// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed 228 /// by a left shift. Returns the shift amount to use. getThumbImm16ValShift(unsigned Imm)229 inline unsigned getThumbImm16ValShift(unsigned Imm) { 230 // 16-bit (or less) immediates are trivially immediate operand with a shift 231 // of zero. 232 if ((Imm & ~65535U) == 0) return 0; 233 234 // Use CTZ to compute the shift amount. 235 return llvm::countr_zero(Imm); 236 } 237 238 /// isThumbImm16ShiftedVal - Return true if the specified value can be 239 /// obtained by left shifting a 16-bit immediate. isThumbImm16ShiftedVal(unsigned V)240 inline bool isThumbImm16ShiftedVal(unsigned V) { 241 // If this can be handled with 242 V = (~65535U << getThumbImm16ValShift(V)) & V; 243 return V == 0; 244 } 245 246 /// getThumbImmNonShiftedVal - If V is a value that satisfies 247 /// isThumbImmShiftedVal, return the non-shiftd value. getThumbImmNonShiftedVal(unsigned V)248 inline unsigned getThumbImmNonShiftedVal(unsigned V) { 249 return V >> getThumbImmValShift(V); 250 } 251 252 253 /// getT2SOImmValSplat - Return the 12-bit encoded representation 254 /// if the specified value can be obtained by splatting the low 8 bits 255 /// into every other byte or every byte of a 32-bit value. i.e., 256 /// 00000000 00000000 00000000 abcdefgh control = 0 257 /// 00000000 abcdefgh 00000000 abcdefgh control = 1 258 /// abcdefgh 00000000 abcdefgh 00000000 control = 2 259 /// abcdefgh abcdefgh abcdefgh abcdefgh control = 3 260 /// Return -1 if none of the above apply. 261 /// See ARM Reference Manual A6.3.2. getT2SOImmValSplatVal(unsigned V)262 inline int getT2SOImmValSplatVal(unsigned V) { 263 unsigned u, Vs, Imm; 264 // control = 0 265 if ((V & 0xffffff00) == 0) 266 return V; 267 268 // If the value is zeroes in the first byte, just shift those off 269 Vs = ((V & 0xff) == 0) ? V >> 8 : V; 270 // Any passing value only has 8 bits of payload, splatted across the word 271 Imm = Vs & 0xff; 272 // Likewise, any passing values have the payload splatted into the 3rd byte 273 u = Imm | (Imm << 16); 274 275 // control = 1 or 2 276 if (Vs == u) 277 return (((Vs == V) ? 1 : 2) << 8) | Imm; 278 279 // control = 3 280 if (Vs == (u | (u << 8))) 281 return (3 << 8) | Imm; 282 283 return -1; 284 } 285 286 /// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the 287 /// specified value is a rotated 8-bit value. Return -1 if no rotation 288 /// encoding is possible. 289 /// See ARM Reference Manual A6.3.2. getT2SOImmValRotateVal(unsigned V)290 inline int getT2SOImmValRotateVal(unsigned V) { 291 unsigned RotAmt = llvm::countl_zero(V); 292 if (RotAmt >= 24) 293 return -1; 294 295 // If 'Arg' can be handled with a single shifter_op return the value. 296 if ((llvm::rotr<uint32_t>(0xff000000U, RotAmt) & V) == V) 297 return (llvm::rotr<uint32_t>(V, 24 - RotAmt) & 0x7f) | 298 ((RotAmt + 8) << 7); 299 300 return -1; 301 } 302 303 /// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit 304 /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit 305 /// encoding for it. If not, return -1. 306 /// See ARM Reference Manual A6.3.2. getT2SOImmVal(unsigned Arg)307 inline int getT2SOImmVal(unsigned Arg) { 308 // If 'Arg' is an 8-bit splat, then get the encoded value. 309 int Splat = getT2SOImmValSplatVal(Arg); 310 if (Splat != -1) 311 return Splat; 312 313 // If 'Arg' can be handled with a single shifter_op return the value. 314 int Rot = getT2SOImmValRotateVal(Arg); 315 if (Rot != -1) 316 return Rot; 317 318 return -1; 319 } 320 getT2SOImmValRotate(unsigned V)321 inline unsigned getT2SOImmValRotate(unsigned V) { 322 if ((V & ~255U) == 0) return 0; 323 // Use CTZ to compute the rotate amount. 324 unsigned RotAmt = llvm::countr_zero(V); 325 return (32 - RotAmt) & 31; 326 } 327 isT2SOImmTwoPartVal(unsigned Imm)328 inline bool isT2SOImmTwoPartVal(unsigned Imm) { 329 unsigned V = Imm; 330 // Passing values can be any combination of splat values and shifter 331 // values. If this can be handled with a single shifter or splat, bail 332 // out. Those should be handled directly, not with a two-part val. 333 if (getT2SOImmValSplatVal(V) != -1) 334 return false; 335 V = llvm::rotr<uint32_t>(~255U, getT2SOImmValRotate(V)) & V; 336 if (V == 0) 337 return false; 338 339 // If this can be handled as an immediate, accept. 340 if (getT2SOImmVal(V) != -1) return true; 341 342 // Likewise, try masking out a splat value first. 343 V = Imm; 344 if (getT2SOImmValSplatVal(V & 0xff00ff00U) != -1) 345 V &= ~0xff00ff00U; 346 else if (getT2SOImmValSplatVal(V & 0x00ff00ffU) != -1) 347 V &= ~0x00ff00ffU; 348 // If what's left can be handled as an immediate, accept. 349 if (getT2SOImmVal(V) != -1) return true; 350 351 // Otherwise, do not accept. 352 return false; 353 } 354 getT2SOImmTwoPartFirst(unsigned Imm)355 inline unsigned getT2SOImmTwoPartFirst(unsigned Imm) { 356 assert (isT2SOImmTwoPartVal(Imm) && 357 "Immedate cannot be encoded as two part immediate!"); 358 // Try a shifter operand as one part 359 unsigned V = llvm::rotr<uint32_t>(~255, getT2SOImmValRotate(Imm)) & Imm; 360 // If the rest is encodable as an immediate, then return it. 361 if (getT2SOImmVal(V) != -1) return V; 362 363 // Try masking out a splat value first. 364 if (getT2SOImmValSplatVal(Imm & 0xff00ff00U) != -1) 365 return Imm & 0xff00ff00U; 366 367 // The other splat is all that's left as an option. 368 assert (getT2SOImmValSplatVal(Imm & 0x00ff00ffU) != -1); 369 return Imm & 0x00ff00ffU; 370 } 371 getT2SOImmTwoPartSecond(unsigned Imm)372 inline unsigned getT2SOImmTwoPartSecond(unsigned Imm) { 373 // Mask out the first hunk 374 Imm ^= getT2SOImmTwoPartFirst(Imm); 375 // Return what's left 376 assert (getT2SOImmVal(Imm) != -1 && 377 "Unable to encode second part of T2 two part SO immediate"); 378 return Imm; 379 } 380 381 382 //===--------------------------------------------------------------------===// 383 // Addressing Mode #2 384 //===--------------------------------------------------------------------===// 385 // 386 // This is used for most simple load/store instructions. 387 // 388 // addrmode2 := reg +/- reg shop imm 389 // addrmode2 := reg +/- imm12 390 // 391 // The first operand is always a Reg. The second operand is a reg if in 392 // reg/reg form, otherwise it's reg#0. The third field encodes the operation 393 // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The 394 // fourth operand 16-17 encodes the index mode. 395 // 396 // If this addressing mode is a frame index (before prolog/epilog insertion 397 // and code rewriting), this operand will have the form: FI#, reg0, <offs> 398 // with no shift amount for the frame offset. 399 // 400 inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, 401 unsigned IdxMode = 0) { 402 assert(Imm12 < (1 << 12) && "Imm too large!"); 403 bool isSub = Opc == sub; 404 return Imm12 | ((int)isSub << 12) | (SO << 13) | (IdxMode << 16) ; 405 } getAM2Offset(unsigned AM2Opc)406 inline unsigned getAM2Offset(unsigned AM2Opc) { 407 return AM2Opc & ((1 << 12)-1); 408 } getAM2Op(unsigned AM2Opc)409 inline AddrOpc getAM2Op(unsigned AM2Opc) { 410 return ((AM2Opc >> 12) & 1) ? sub : add; 411 } getAM2ShiftOpc(unsigned AM2Opc)412 inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) { 413 return (ShiftOpc)((AM2Opc >> 13) & 7); 414 } getAM2IdxMode(unsigned AM2Opc)415 inline unsigned getAM2IdxMode(unsigned AM2Opc) { return (AM2Opc >> 16); } 416 417 //===--------------------------------------------------------------------===// 418 // Addressing Mode #3 419 //===--------------------------------------------------------------------===// 420 // 421 // This is used for sign-extending loads, and load/store-pair instructions. 422 // 423 // addrmode3 := reg +/- reg 424 // addrmode3 := reg +/- imm8 425 // 426 // The first operand is always a Reg. The second operand is a reg if in 427 // reg/reg form, otherwise it's reg#0. The third field encodes the operation 428 // in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the 429 // index mode. 430 431 /// getAM3Opc - This function encodes the addrmode3 opc field. 432 inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset, 433 unsigned IdxMode = 0) { 434 bool isSub = Opc == sub; 435 return ((int)isSub << 8) | Offset | (IdxMode << 9); 436 } getAM3Offset(unsigned AM3Opc)437 inline unsigned char getAM3Offset(unsigned AM3Opc) { return AM3Opc & 0xFF; } getAM3Op(unsigned AM3Opc)438 inline AddrOpc getAM3Op(unsigned AM3Opc) { 439 return ((AM3Opc >> 8) & 1) ? sub : add; 440 } getAM3IdxMode(unsigned AM3Opc)441 inline unsigned getAM3IdxMode(unsigned AM3Opc) { return (AM3Opc >> 9); } 442 443 //===--------------------------------------------------------------------===// 444 // Addressing Mode #4 445 //===--------------------------------------------------------------------===// 446 // 447 // This is used for load / store multiple instructions. 448 // 449 // addrmode4 := reg, <mode> 450 // 451 // The four modes are: 452 // IA - Increment after 453 // IB - Increment before 454 // DA - Decrement after 455 // DB - Decrement before 456 // For VFP instructions, only the IA and DB modes are valid. 457 getAM4SubMode(unsigned Mode)458 inline AMSubMode getAM4SubMode(unsigned Mode) { 459 return (AMSubMode)(Mode & 0x7); 460 } 461 getAM4ModeImm(AMSubMode SubMode)462 inline unsigned getAM4ModeImm(AMSubMode SubMode) { return (int)SubMode; } 463 464 //===--------------------------------------------------------------------===// 465 // Addressing Mode #5 466 //===--------------------------------------------------------------------===// 467 // 468 // This is used for coprocessor instructions, such as FP load/stores. 469 // 470 // addrmode5 := reg +/- imm8*4 471 // 472 // The first operand is always a Reg. The second operand encodes the 473 // operation (add or subtract) in bit 8 and the immediate in bits 0-7. 474 475 /// getAM5Opc - This function encodes the addrmode5 opc field. getAM5Opc(AddrOpc Opc,unsigned char Offset)476 inline unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset) { 477 bool isSub = Opc == sub; 478 return ((int)isSub << 8) | Offset; 479 } getAM5Offset(unsigned AM5Opc)480 inline unsigned char getAM5Offset(unsigned AM5Opc) { return AM5Opc & 0xFF; } getAM5Op(unsigned AM5Opc)481 inline AddrOpc getAM5Op(unsigned AM5Opc) { 482 return ((AM5Opc >> 8) & 1) ? sub : add; 483 } 484 485 //===--------------------------------------------------------------------===// 486 // Addressing Mode #5 FP16 487 //===--------------------------------------------------------------------===// 488 // 489 // This is used for coprocessor instructions, such as 16-bit FP load/stores. 490 // 491 // addrmode5fp16 := reg +/- imm8*2 492 // 493 // The first operand is always a Reg. The second operand encodes the 494 // operation (add or subtract) in bit 8 and the immediate in bits 0-7. 495 496 /// getAM5FP16Opc - This function encodes the addrmode5fp16 opc field. getAM5FP16Opc(AddrOpc Opc,unsigned char Offset)497 inline unsigned getAM5FP16Opc(AddrOpc Opc, unsigned char Offset) { 498 bool isSub = Opc == sub; 499 return ((int)isSub << 8) | Offset; 500 } getAM5FP16Offset(unsigned AM5Opc)501 inline unsigned char getAM5FP16Offset(unsigned AM5Opc) { 502 return AM5Opc & 0xFF; 503 } getAM5FP16Op(unsigned AM5Opc)504 inline AddrOpc getAM5FP16Op(unsigned AM5Opc) { 505 return ((AM5Opc >> 8) & 1) ? sub : add; 506 } 507 508 //===--------------------------------------------------------------------===// 509 // Addressing Mode #6 510 //===--------------------------------------------------------------------===// 511 // 512 // This is used for NEON load / store instructions. 513 // 514 // addrmode6 := reg with optional alignment 515 // 516 // This is stored in two operands [regaddr, align]. The first is the 517 // address register. The second operand is the value of the alignment 518 // specifier in bytes or zero if no explicit alignment. 519 // Valid alignments depend on the specific instruction. 520 521 //===--------------------------------------------------------------------===// 522 // NEON/MVE Modified Immediates 523 //===--------------------------------------------------------------------===// 524 // 525 // Several NEON and MVE instructions (e.g., VMOV) take a "modified immediate" 526 // vector operand, where a small immediate encoded in the instruction 527 // specifies a full NEON vector value. These modified immediates are 528 // represented here as encoded integers. The low 8 bits hold the immediate 529 // value; bit 12 holds the "Op" field of the instruction, and bits 11-8 hold 530 // the "Cmode" field of the instruction. The interfaces below treat the 531 // Op and Cmode values as a single 5-bit value. 532 createVMOVModImm(unsigned OpCmode,unsigned Val)533 inline unsigned createVMOVModImm(unsigned OpCmode, unsigned Val) { 534 return (OpCmode << 8) | Val; 535 } getVMOVModImmOpCmode(unsigned ModImm)536 inline unsigned getVMOVModImmOpCmode(unsigned ModImm) { 537 return (ModImm >> 8) & 0x1f; 538 } getVMOVModImmVal(unsigned ModImm)539 inline unsigned getVMOVModImmVal(unsigned ModImm) { return ModImm & 0xff; } 540 541 /// decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the 542 /// element value and the element size in bits. (If the element size is 543 /// smaller than the vector, it is splatted into all the elements.) decodeVMOVModImm(unsigned ModImm,unsigned & EltBits)544 inline uint64_t decodeVMOVModImm(unsigned ModImm, unsigned &EltBits) { 545 unsigned OpCmode = getVMOVModImmOpCmode(ModImm); 546 unsigned Imm8 = getVMOVModImmVal(ModImm); 547 uint64_t Val = 0; 548 549 if (OpCmode == 0xe) { 550 // 8-bit vector elements 551 Val = Imm8; 552 EltBits = 8; 553 } else if ((OpCmode & 0xc) == 0x8) { 554 // 16-bit vector elements 555 unsigned ByteNum = (OpCmode & 0x6) >> 1; 556 Val = Imm8 << (8 * ByteNum); 557 EltBits = 16; 558 } else if ((OpCmode & 0x8) == 0) { 559 // 32-bit vector elements, zero with one byte set 560 unsigned ByteNum = (OpCmode & 0x6) >> 1; 561 Val = Imm8 << (8 * ByteNum); 562 EltBits = 32; 563 } else if ((OpCmode & 0xe) == 0xc) { 564 // 32-bit vector elements, one byte with low bits set 565 unsigned ByteNum = 1 + (OpCmode & 0x1); 566 Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum))); 567 EltBits = 32; 568 } else if (OpCmode == 0x1e) { 569 // 64-bit vector elements 570 for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) { 571 if ((ModImm >> ByteNum) & 1) 572 Val |= (uint64_t)0xff << (8 * ByteNum); 573 } 574 EltBits = 64; 575 } else { 576 llvm_unreachable("Unsupported VMOV immediate"); 577 } 578 return Val; 579 } 580 581 // Generic validation for single-byte immediate (0X00, 00X0, etc). isNEONBytesplat(unsigned Value,unsigned Size)582 inline bool isNEONBytesplat(unsigned Value, unsigned Size) { 583 assert(Size >= 1 && Size <= 4 && "Invalid size"); 584 unsigned count = 0; 585 for (unsigned i = 0; i < Size; ++i) { 586 if (Value & 0xff) count++; 587 Value >>= 8; 588 } 589 return count == 1; 590 } 591 592 /// Checks if Value is a correct immediate for instructions like VBIC/VORR. isNEONi16splat(unsigned Value)593 inline bool isNEONi16splat(unsigned Value) { 594 if (Value > 0xffff) 595 return false; 596 // i16 value with set bits only in one byte X0 or 0X. 597 return Value == 0 || isNEONBytesplat(Value, 2); 598 } 599 600 // Encode NEON 16 bits Splat immediate for instructions like VBIC/VORR encodeNEONi16splat(unsigned Value)601 inline unsigned encodeNEONi16splat(unsigned Value) { 602 assert(isNEONi16splat(Value) && "Invalid NEON splat value"); 603 if (Value >= 0x100) 604 Value = (Value >> 8) | 0xa00; 605 else 606 Value |= 0x800; 607 return Value; 608 } 609 610 /// Checks if Value is a correct immediate for instructions like VBIC/VORR. isNEONi32splat(unsigned Value)611 inline bool isNEONi32splat(unsigned Value) { 612 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X. 613 return Value == 0 || isNEONBytesplat(Value, 4); 614 } 615 616 /// Encode NEON 32 bits Splat immediate for instructions like VBIC/VORR. encodeNEONi32splat(unsigned Value)617 inline unsigned encodeNEONi32splat(unsigned Value) { 618 assert(isNEONi32splat(Value) && "Invalid NEON splat value"); 619 if (Value >= 0x100 && Value <= 0xff00) 620 Value = (Value >> 8) | 0x200; 621 else if (Value > 0xffff && Value <= 0xff0000) 622 Value = (Value >> 16) | 0x400; 623 else if (Value > 0xffffff) 624 Value = (Value >> 24) | 0x600; 625 return Value; 626 } 627 628 //===--------------------------------------------------------------------===// 629 // Floating-point Immediates 630 // getFPImmFloat(unsigned Imm)631 inline float getFPImmFloat(unsigned Imm) { 632 // We expect an 8-bit binary encoding of a floating-point number here. 633 634 uint8_t Sign = (Imm >> 7) & 0x1; 635 uint8_t Exp = (Imm >> 4) & 0x7; 636 uint8_t Mantissa = Imm & 0xf; 637 638 // 8-bit FP IEEE Float Encoding 639 // abcd efgh aBbbbbbc defgh000 00000000 00000000 640 // 641 // where B = NOT(b); 642 uint32_t I = 0; 643 I |= Sign << 31; 644 I |= ((Exp & 0x4) != 0 ? 0 : 1) << 30; 645 I |= ((Exp & 0x4) != 0 ? 0x1f : 0) << 25; 646 I |= (Exp & 0x3) << 23; 647 I |= Mantissa << 19; 648 return bit_cast<float>(I); 649 } 650 651 /// getFP16Imm - Return an 8-bit floating-point version of the 16-bit 652 /// floating-point value. If the value cannot be represented as an 8-bit 653 /// floating-point value, then return -1. getFP16Imm(const APInt & Imm)654 inline int getFP16Imm(const APInt &Imm) { 655 uint32_t Sign = Imm.lshr(15).getZExtValue() & 1; 656 int32_t Exp = (Imm.lshr(10).getSExtValue() & 0x1f) - 15; // -14 to 15 657 int64_t Mantissa = Imm.getZExtValue() & 0x3ff; // 10 bits 658 659 // We can handle 4 bits of mantissa. 660 // mantissa = (16+UInt(e:f:g:h))/16. 661 if (Mantissa & 0x3f) 662 return -1; 663 Mantissa >>= 6; 664 665 // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 666 if (Exp < -3 || Exp > 4) 667 return -1; 668 Exp = ((Exp+3) & 0x7) ^ 4; 669 670 return ((int)Sign << 7) | (Exp << 4) | Mantissa; 671 } 672 getFP16Imm(const APFloat & FPImm)673 inline int getFP16Imm(const APFloat &FPImm) { 674 return getFP16Imm(FPImm.bitcastToAPInt()); 675 } 676 677 /// If this is a FP16Imm encoded as a fp32 value, return the 8-bit encoding 678 /// for it. Otherwise return -1 like getFP16Imm. getFP32FP16Imm(const APInt & Imm)679 inline int getFP32FP16Imm(const APInt &Imm) { 680 if (Imm.getActiveBits() > 16) 681 return -1; 682 return ARM_AM::getFP16Imm(Imm.trunc(16)); 683 } 684 getFP32FP16Imm(const APFloat & FPImm)685 inline int getFP32FP16Imm(const APFloat &FPImm) { 686 return getFP32FP16Imm(FPImm.bitcastToAPInt()); 687 } 688 689 /// getFP32Imm - Return an 8-bit floating-point version of the 32-bit 690 /// floating-point value. If the value cannot be represented as an 8-bit 691 /// floating-point value, then return -1. getFP32Imm(const APInt & Imm)692 inline int getFP32Imm(const APInt &Imm) { 693 uint32_t Sign = Imm.lshr(31).getZExtValue() & 1; 694 int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127; // -126 to 127 695 int64_t Mantissa = Imm.getZExtValue() & 0x7fffff; // 23 bits 696 697 // We can handle 4 bits of mantissa. 698 // mantissa = (16+UInt(e:f:g:h))/16. 699 if (Mantissa & 0x7ffff) 700 return -1; 701 Mantissa >>= 19; 702 if ((Mantissa & 0xf) != Mantissa) 703 return -1; 704 705 // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 706 if (Exp < -3 || Exp > 4) 707 return -1; 708 Exp = ((Exp+3) & 0x7) ^ 4; 709 710 return ((int)Sign << 7) | (Exp << 4) | Mantissa; 711 } 712 getFP32Imm(const APFloat & FPImm)713 inline int getFP32Imm(const APFloat &FPImm) { 714 return getFP32Imm(FPImm.bitcastToAPInt()); 715 } 716 717 /// getFP64Imm - Return an 8-bit floating-point version of the 64-bit 718 /// floating-point value. If the value cannot be represented as an 8-bit 719 /// floating-point value, then return -1. getFP64Imm(const APInt & Imm)720 inline int getFP64Imm(const APInt &Imm) { 721 uint64_t Sign = Imm.lshr(63).getZExtValue() & 1; 722 int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023; // -1022 to 1023 723 uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffULL; 724 725 // We can handle 4 bits of mantissa. 726 // mantissa = (16+UInt(e:f:g:h))/16. 727 if (Mantissa & 0xffffffffffffULL) 728 return -1; 729 Mantissa >>= 48; 730 if ((Mantissa & 0xf) != Mantissa) 731 return -1; 732 733 // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 734 if (Exp < -3 || Exp > 4) 735 return -1; 736 Exp = ((Exp+3) & 0x7) ^ 4; 737 738 return ((int)Sign << 7) | (Exp << 4) | Mantissa; 739 } 740 getFP64Imm(const APFloat & FPImm)741 inline int getFP64Imm(const APFloat &FPImm) { 742 return getFP64Imm(FPImm.bitcastToAPInt()); 743 } 744 745 } // end namespace ARM_AM 746 } // end namespace llvm 747 748 #endif 749