1 //===- subzero/src/IceAssemblerARM32.cpp - Assembler for ARM32 --*- C++ -*-===// 2 // 3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 4 // for details. All rights reserved. Use of this source code is governed by a 5 // BSD-style license that can be found in the LICENSE file. 6 // 7 // Modified by the Subzero authors. 8 // 9 //===----------------------------------------------------------------------===// 10 // 11 // The Subzero Code Generator 12 // 13 // This file is distributed under the University of Illinois Open Source 14 // License. See LICENSE.TXT for details. 15 // 16 //===----------------------------------------------------------------------===// 17 /// 18 /// \file 19 /// \brief Implements the Assembler class for ARM32. 20 /// 21 //===----------------------------------------------------------------------===// 22 23 #include "IceAssemblerARM32.h" 24 #include "IceCfgNode.h" 25 #include "IceUtils.h" 26 27 namespace { 28 29 using namespace Ice; 30 using namespace Ice::ARM32; 31 32 using WordType = uint32_t; 33 static constexpr IValueT kWordSize = sizeof(WordType); 34 35 // The following define individual bits. 36 static constexpr IValueT B0 = 1; 37 static constexpr IValueT B1 = 1 << 1; 38 static constexpr IValueT B2 = 1 << 2; 39 static constexpr IValueT B3 = 1 << 3; 40 static constexpr IValueT B4 = 1 << 4; 41 static constexpr IValueT B5 = 1 << 5; 42 static constexpr IValueT B6 = 1 << 6; 43 static constexpr IValueT B7 = 1 << 7; 44 static constexpr IValueT B8 = 1 << 8; 45 static constexpr IValueT B9 = 1 << 9; 46 static constexpr IValueT B10 = 1 << 10; 47 static constexpr IValueT B11 = 1 << 11; 48 static constexpr IValueT B12 = 1 << 12; 49 static constexpr IValueT B13 = 1 << 13; 50 static constexpr IValueT B14 = 1 << 14; 51 static constexpr IValueT B15 = 1 << 15; 52 static constexpr IValueT B16 = 1 << 16; 53 static constexpr IValueT B17 = 1 << 17; 54 static constexpr IValueT B18 = 1 << 18; 55 static constexpr IValueT B19 = 1 << 19; 56 static constexpr IValueT B20 = 1 << 20; 57 static constexpr IValueT B21 = 1 << 21; 58 static constexpr IValueT B22 = 1 << 22; 59 static constexpr IValueT B23 = 1 << 23; 60 static constexpr IValueT B24 = 1 << 24; 61 static constexpr IValueT B25 = 1 << 25; 62 static constexpr IValueT B26 = 1 << 26; 63 static constexpr IValueT B27 = 1 << 27; 64 65 // Constants used for the decoding or encoding of the individual fields of 66 // instructions. Based on ARM section A5.1. 67 static constexpr IValueT L = 1 << 20; // load (or store) 68 static constexpr IValueT W = 1 << 21; // writeback base register 69 // (or leave unchanged) 70 static constexpr IValueT B = 1 << 22; // unsigned byte (or word) 71 static constexpr IValueT U = 1 << 23; // positive (or negative) 72 // offset/index 73 static constexpr IValueT P = 1 << 24; // offset/pre-indexed 74 // addressing (or 75 // post-indexed addressing) 76 77 static constexpr IValueT kConditionShift = 28; 78 static constexpr IValueT kLinkShift = 24; 79 static constexpr IValueT kOpcodeShift = 21; 80 static constexpr IValueT kRdShift = 12; 81 static constexpr IValueT kRmShift = 0; 82 static constexpr IValueT kRnShift = 16; 83 static constexpr IValueT kRsShift = 8; 84 static constexpr IValueT kSShift = 20; 85 static constexpr IValueT kTypeShift = 25; 86 87 // Immediate instruction fields encoding. 88 static constexpr IValueT kImmed8Bits = 8; 89 static constexpr IValueT kImmed8Shift = 0; 90 static constexpr IValueT kRotateBits = 4; 91 static constexpr IValueT kRotateShift = 8; 92 93 // Shift instruction register fields encodings. 94 static constexpr IValueT kShiftImmShift = 7; 95 static constexpr IValueT kShiftImmBits = 5; 96 static constexpr IValueT kShiftShift = 5; 97 static constexpr IValueT kImmed12Bits = 12; 98 static constexpr IValueT kImm12Shift = 0; 99 100 // Rotation instructions (uxtb etc.). 101 static constexpr IValueT kRotationShift = 10; 102 103 // MemEx instructions. 104 static constexpr IValueT kMemExOpcodeShift = 20; 105 106 // Div instruction register field encodings. 107 static constexpr IValueT kDivRdShift = 16; 108 static constexpr IValueT kDivRmShift = 8; 109 static constexpr IValueT kDivRnShift = 0; 110 111 // Type of instruction encoding (bits 25-27). See ARM section A5.1 112 static constexpr IValueT kInstTypeDataRegister = 0; // i.e. 000 113 static constexpr IValueT kInstTypeDataRegShift = 0; // i.e. 000 114 static constexpr IValueT kInstTypeDataImmediate = 1; // i.e. 001 115 static constexpr IValueT kInstTypeMemImmediate = 2; // i.e. 010 116 static constexpr IValueT kInstTypeRegisterShift = 3; // i.e. 011 117 118 // Limit on number of registers in a vpush/vpop. 119 static constexpr SizeT VpushVpopMaxConsecRegs = 16; 120 121 // Offset modifier to current PC for next instruction. The offset is off by 8 122 // due to the way the ARM CPUs read PC. 123 static constexpr IOffsetT kPCReadOffset = 8; 124 125 // Mask to pull out PC offset from branch (b) instruction. 126 static constexpr int kBranchOffsetBits = 24; 127 static constexpr IOffsetT kBranchOffsetMask = 0x00ffffff; 128 129 IValueT encodeBool(bool B) { return B ? 1 : 0; } 130 131 IValueT encodeRotation(ARM32::AssemblerARM32::RotationValue Value) { 132 return static_cast<IValueT>(Value); 133 } 134 135 IValueT encodeGPRRegister(RegARM32::GPRRegister Rn) { 136 return static_cast<IValueT>(Rn); 137 } 138 139 RegARM32::GPRRegister decodeGPRRegister(IValueT R) { 140 return static_cast<RegARM32::GPRRegister>(R); 141 } 142 143 IValueT encodeCondition(CondARM32::Cond Cond) { 144 return static_cast<IValueT>(Cond); 145 } 146 147 IValueT encodeShift(OperandARM32::ShiftKind Shift) { 148 // Follows encoding in ARM section A8.4.1 "Constant shifts". 149 switch (Shift) { 150 case OperandARM32::kNoShift: 151 case OperandARM32::LSL: 152 return 0; // 0b00 153 case OperandARM32::LSR: 154 return 1; // 0b01 155 case OperandARM32::ASR: 156 return 2; // 0b10 157 case OperandARM32::ROR: 158 case OperandARM32::RRX: 159 return 3; // 0b11 160 } 161 llvm::report_fatal_error("Unknown Shift value"); 162 return 0; 163 } 164 165 // Returns the bits in the corresponding masked value. 166 IValueT mask(IValueT Value, IValueT Shift, IValueT Bits) { 167 return (Value >> Shift) & ((1 << Bits) - 1); 168 } 169 170 // Extract out a Bit in Value. 171 bool isBitSet(IValueT Bit, IValueT Value) { return (Value & Bit) == Bit; } 172 173 // Returns the GPR register at given Shift in Value. 174 RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) { 175 return decodeGPRRegister((Value >> Shift) & 0xF); 176 } 177 178 IValueT getEncodedGPRegNum(const Variable *Var) { 179 assert(Var->hasReg()); 180 const auto Reg = Var->getRegNum(); 181 return llvm::isa<Variable64On32>(Var) ? RegARM32::getI64PairFirstGPRNum(Reg) 182 : RegARM32::getEncodedGPR(Reg); 183 } 184 185 IValueT getEncodedSRegNum(const Variable *Var) { 186 assert(Var->hasReg()); 187 return RegARM32::getEncodedSReg(Var->getRegNum()); 188 } 189 190 IValueT getEncodedDRegNum(const Variable *Var) { 191 return RegARM32::getEncodedDReg(Var->getRegNum()); 192 } 193 194 IValueT getEncodedQRegNum(const Variable *Var) { 195 return RegARM32::getEncodedQReg(Var->getRegNum()); 196 } 197 198 IValueT mapQRegToDReg(IValueT EncodedQReg) { 199 IValueT DReg = EncodedQReg << 1; 200 assert(DReg < RegARM32::getNumDRegs()); 201 return DReg; 202 } 203 204 IValueT mapQRegToSReg(IValueT EncodedQReg) { 205 IValueT SReg = EncodedQReg << 2; 206 assert(SReg < RegARM32::getNumSRegs()); 207 return SReg; 208 } 209 210 IValueT getYInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY & 0x1; } 211 212 IValueT getXXXXInRegXXXXY(IValueT RegXXXXY) { return RegXXXXY >> 1; } 213 214 IValueT getYInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX >> 4; } 215 216 IValueT getXXXXInRegYXXXX(IValueT RegYXXXX) { return RegYXXXX & 0x0f; } 217 218 // Figures out Op/Cmode values for given Value. Returns true if able to encode. 219 bool encodeAdvSIMDExpandImm(IValueT Value, Type ElmtTy, IValueT &Op, 220 IValueT &Cmode, IValueT &Imm8) { 221 // TODO(kschimpf): Handle other shifted 8-bit values. 222 constexpr IValueT Imm8Mask = 0xFF; 223 if ((Value & IValueT(~Imm8Mask)) != 0) 224 return false; 225 Imm8 = Value; 226 switch (ElmtTy) { 227 case IceType_i8: 228 Op = 0; 229 Cmode = 14; // 0b1110 230 return true; 231 case IceType_i16: 232 Op = 0; 233 Cmode = 8; // 0b1000 234 return true; 235 case IceType_i32: 236 Op = 0; 237 Cmode = 0; // 0b0000 238 return true; 239 default: 240 return false; 241 } 242 } 243 244 // Defines layouts of an operand representing a (register) memory address, 245 // possibly modified by an immediate value. 246 enum EncodedImmAddress { 247 // Address modified by a rotated immediate 8-bit value. 248 RotatedImm8Address, 249 250 // Alternate encoding for RotatedImm8Address, where the offset is divided by 4 251 // before encoding. 252 RotatedImm8Div4Address, 253 254 // Address modified by an immediate 12-bit value. 255 Imm12Address, 256 257 // Alternate encoding 3, for an address modified by a rotated immediate 8-bit 258 // value. 259 RotatedImm8Enc3Address, 260 261 // Encoding where no immediate offset is used. 262 NoImmOffsetAddress 263 }; 264 265 // The way an operand is encoded into a sequence of bits in functions 266 // encodeOperand and encodeAddress below. 267 enum EncodedOperand { 268 // Unable to encode, value left undefined. 269 CantEncode = 0, 270 271 // Value is register found. 272 EncodedAsRegister, 273 274 // Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8 275 // value. 276 EncodedAsRotatedImm8, 277 278 // EncodedAsImmRegOffset is a memory operand that can take three forms, based 279 // on type EncodedImmAddress: 280 // 281 // ***** RotatedImm8Address ***** 282 // 283 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, 284 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to 285 // Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value. 286 // 287 // ***** RotatedImm8Div4Address ***** 288 // 289 // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1 290 // if pre-indexed addressing, u=1 if offset positive, and w=1 if writeback to 291 // Rn. 292 // 293 // ***** Imm12Address ***** 294 // 295 // Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn, 296 // p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to 297 // Rn should be used, and iiiiiiiiiiii defines the immediate 12-bit value. 298 // 299 // ***** NoImmOffsetAddress ***** 300 // 301 // Value=000000001000nnnn0000000000000000 where nnnn=Rn. 302 EncodedAsImmRegOffset, 303 304 // Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn, 305 // mmmm is the index register Rm, iiiii is the shift amount, ss is the shift 306 // kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if 307 // writeback to Rn. 308 EncodedAsShiftRotateImm5, 309 310 // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value 311 // to shift. 312 EncodedAsShiftImm5, 313 314 // Value=iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift 315 // kind, and iiiii is the shift amount. 316 EncodedAsShiftedRegister, 317 318 // Value=ssss0tt1mmmm where mmmm=Rm, tt is an encoded ShiftKind, and ssss=Rms. 319 EncodedAsRegShiftReg, 320 321 // Value is 32bit integer constant. 322 EncodedAsConstI32 323 }; 324 325 // Sets Encoding to a rotated Imm8 encoding of Value, if possible. 326 IValueT encodeRotatedImm8(IValueT RotateAmt, IValueT Immed8) { 327 assert(RotateAmt < (1 << kRotateBits)); 328 assert(Immed8 < (1 << kImmed8Bits)); 329 return (RotateAmt << kRotateShift) | (Immed8 << kImmed8Shift); 330 } 331 332 // Encodes iiiiitt0mmmm for data-processing (2nd) operands where iiiii=Imm5, 333 // tt=Shift, and mmmm=Rm. 334 IValueT encodeShiftRotateImm5(IValueT Rm, OperandARM32::ShiftKind Shift, 335 IOffsetT imm5) { 336 (void)kShiftImmBits; 337 assert(imm5 < (1 << kShiftImmBits)); 338 return (imm5 << kShiftImmShift) | (encodeShift(Shift) << kShiftShift) | Rm; 339 } 340 341 // Encodes mmmmtt01ssss for data-processing operands where mmmm=Rm, ssss=Rs, and 342 // tt=Shift. 343 IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift, 344 IValueT Rs) { 345 return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 | 346 (Rm << kRmShift); 347 } 348 349 // Defines the set of registers expected in an operand. 350 enum RegSetWanted { WantGPRegs, WantSRegs, WantDRegs, WantQRegs }; 351 352 EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value, 353 RegSetWanted WantedRegSet) { 354 Value = 0; // Make sure initialized. 355 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { 356 if (Var->hasReg()) { 357 switch (WantedRegSet) { 358 case WantGPRegs: 359 Value = getEncodedGPRegNum(Var); 360 break; 361 case WantSRegs: 362 Value = getEncodedSRegNum(Var); 363 break; 364 case WantDRegs: 365 Value = getEncodedDRegNum(Var); 366 break; 367 case WantQRegs: 368 Value = getEncodedQRegNum(Var); 369 break; 370 } 371 return EncodedAsRegister; 372 } 373 return CantEncode; 374 } 375 if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) { 376 const IValueT Immed8 = FlexImm->getImm(); 377 const IValueT Rotate = FlexImm->getRotateAmt(); 378 if (!((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)))) 379 return CantEncode; 380 Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift); 381 return EncodedAsRotatedImm8; 382 } 383 if (const auto *Const = llvm::dyn_cast<ConstantInteger32>(Opnd)) { 384 Value = Const->getValue(); 385 return EncodedAsConstI32; 386 } 387 if (const auto *FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Opnd)) { 388 Operand *Amt = FlexReg->getShiftAmt(); 389 IValueT Rm; 390 if (encodeOperand(FlexReg->getReg(), Rm, WantGPRegs) != EncodedAsRegister) 391 return CantEncode; 392 if (const auto *Var = llvm::dyn_cast<Variable>(Amt)) { 393 IValueT Rs; 394 if (encodeOperand(Var, Rs, WantGPRegs) != EncodedAsRegister) 395 return CantEncode; 396 Value = encodeShiftRotateReg(Rm, FlexReg->getShiftOp(), Rs); 397 return EncodedAsRegShiftReg; 398 } 399 // If reached, the amount is a shifted amount by some 5-bit immediate. 400 uint32_t Imm5; 401 if (const auto *ShAmt = llvm::dyn_cast<OperandARM32ShAmtImm>(Amt)) { 402 Imm5 = ShAmt->getShAmtImm(); 403 } else if (const auto *IntConst = llvm::dyn_cast<ConstantInteger32>(Amt)) { 404 int32_t Val = IntConst->getValue(); 405 if (Val < 0) 406 return CantEncode; 407 Imm5 = static_cast<uint32_t>(Val); 408 } else 409 return CantEncode; 410 Value = encodeShiftRotateImm5(Rm, FlexReg->getShiftOp(), Imm5); 411 return EncodedAsShiftedRegister; 412 } 413 if (const auto *ShImm = llvm::dyn_cast<OperandARM32ShAmtImm>(Opnd)) { 414 const IValueT Immed5 = ShImm->getShAmtImm(); 415 assert(Immed5 < (1 << kShiftImmBits)); 416 Value = (Immed5 << kShiftImmShift); 417 return EncodedAsShiftImm5; 418 } 419 return CantEncode; 420 } 421 422 IValueT encodeImmRegOffset(IValueT Reg, IOffsetT Offset, 423 OperandARM32Mem::AddrMode Mode, IOffsetT MaxOffset, 424 IValueT OffsetShift) { 425 IValueT Value = Mode | (Reg << kRnShift); 426 if (Offset < 0) { 427 Offset = -Offset; 428 Value ^= U; // Flip U to adjust sign. 429 } 430 assert(Offset <= MaxOffset); 431 (void)MaxOffset; 432 return Value | (Offset >> OffsetShift); 433 } 434 435 // Encodes immediate register offset using encoding 3. 436 IValueT encodeImmRegOffsetEnc3(IValueT Rn, IOffsetT Imm8, 437 OperandARM32Mem::AddrMode Mode) { 438 IValueT Value = Mode | (Rn << kRnShift); 439 if (Imm8 < 0) { 440 Imm8 = -Imm8; 441 Value = (Value ^ U); 442 } 443 assert(Imm8 < (1 << 8)); 444 Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f); 445 return Value; 446 } 447 448 IValueT encodeImmRegOffset(EncodedImmAddress ImmEncoding, IValueT Reg, 449 IOffsetT Offset, OperandARM32Mem::AddrMode Mode) { 450 switch (ImmEncoding) { 451 case RotatedImm8Address: { 452 constexpr IOffsetT MaxOffset = (1 << 8) - 1; 453 constexpr IValueT NoRightShift = 0; 454 return encodeImmRegOffset(Reg, Offset, Mode, MaxOffset, NoRightShift); 455 } 456 case RotatedImm8Div4Address: { 457 assert((Offset & 0x3) == 0); 458 constexpr IOffsetT MaxOffset = (1 << 8) - 1; 459 constexpr IValueT RightShift2 = 2; 460 return encodeImmRegOffset(Reg, Offset, Mode, MaxOffset, RightShift2); 461 } 462 case Imm12Address: { 463 constexpr IOffsetT MaxOffset = (1 << 12) - 1; 464 constexpr IValueT NoRightShift = 0; 465 return encodeImmRegOffset(Reg, Offset, Mode, MaxOffset, NoRightShift); 466 } 467 case RotatedImm8Enc3Address: 468 return encodeImmRegOffsetEnc3(Reg, Offset, Mode); 469 case NoImmOffsetAddress: { 470 assert(Offset == 0); 471 assert(Mode == OperandARM32Mem::Offset); 472 return Reg << kRnShift; 473 } 474 } 475 llvm_unreachable("(silence g++ warning)"); 476 } 477 478 // Encodes memory address Opnd, and encodes that information into Value, based 479 // on how ARM represents the address. Returns how the value was encoded. 480 EncodedOperand encodeAddress(const Operand *Opnd, IValueT &Value, 481 const AssemblerARM32::TargetInfo &TInfo, 482 EncodedImmAddress ImmEncoding) { 483 Value = 0; // Make sure initialized. 484 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { 485 // Should be a stack variable, with an offset. 486 if (Var->hasReg()) 487 return CantEncode; 488 IOffsetT Offset = Var->getStackOffset(); 489 if (!Utils::IsAbsoluteUint(12, Offset)) 490 return CantEncode; 491 const auto BaseRegNum = 492 Var->hasReg() ? Var->getBaseRegNum() : TInfo.FrameOrStackReg; 493 Value = encodeImmRegOffset(ImmEncoding, BaseRegNum, Offset, 494 OperandARM32Mem::Offset); 495 return EncodedAsImmRegOffset; 496 } 497 if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) { 498 Variable *Var = Mem->getBase(); 499 if (!Var->hasReg()) 500 return CantEncode; 501 IValueT Rn = getEncodedGPRegNum(Var); 502 if (Mem->isRegReg()) { 503 const Variable *Index = Mem->getIndex(); 504 if (Var == nullptr) 505 return CantEncode; 506 Value = (Rn << kRnShift) | Mem->getAddrMode() | 507 encodeShiftRotateImm5(getEncodedGPRegNum(Index), 508 Mem->getShiftOp(), Mem->getShiftAmt()); 509 return EncodedAsShiftRotateImm5; 510 } 511 // Encoded as immediate register offset. 512 ConstantInteger32 *Offset = Mem->getOffset(); 513 Value = encodeImmRegOffset(ImmEncoding, Rn, Offset->getValue(), 514 Mem->getAddrMode()); 515 return EncodedAsImmRegOffset; 516 } 517 return CantEncode; 518 } 519 520 // Checks that Offset can fit in imm24 constant of branch (b) instruction. 521 void assertCanEncodeBranchOffset(IOffsetT Offset) { 522 (void)Offset; 523 (void)kBranchOffsetBits; 524 assert(Utils::IsAligned(Offset, 4) && 525 Utils::IsInt(kBranchOffsetBits, Offset >> 2)); 526 } 527 528 IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) { 529 // Adjust offset to the way ARM CPUs read PC. 530 Offset -= kPCReadOffset; 531 532 assertCanEncodeBranchOffset(Offset); 533 534 // Properly preserve only the bits supported in the instruction. 535 Offset >>= 2; 536 Offset &= kBranchOffsetMask; 537 return (Inst & ~kBranchOffsetMask) | Offset; 538 } 539 540 IValueT encodeRegister(const Operand *OpReg, RegSetWanted WantedRegSet, 541 const char *RegName, const char *InstName) { 542 IValueT Reg = 0; 543 if (encodeOperand(OpReg, Reg, WantedRegSet) != EncodedAsRegister) 544 llvm::report_fatal_error(std::string(InstName) + ": Can't find register " + 545 RegName); 546 return Reg; 547 } 548 549 IValueT encodeGPRegister(const Operand *OpReg, const char *RegName, 550 const char *InstName) { 551 return encodeRegister(OpReg, WantGPRegs, RegName, InstName); 552 } 553 554 IValueT encodeSRegister(const Operand *OpReg, const char *RegName, 555 const char *InstName) { 556 return encodeRegister(OpReg, WantSRegs, RegName, InstName); 557 } 558 559 IValueT encodeDRegister(const Operand *OpReg, const char *RegName, 560 const char *InstName) { 561 return encodeRegister(OpReg, WantDRegs, RegName, InstName); 562 } 563 564 IValueT encodeQRegister(const Operand *OpReg, const char *RegName, 565 const char *InstName) { 566 return encodeRegister(OpReg, WantQRegs, RegName, InstName); 567 } 568 569 void verifyPOrNotW(IValueT Address, const char *InstName) { 570 if (BuildDefs::minimal()) 571 return; 572 if (!isBitSet(P, Address) && isBitSet(W, Address)) 573 llvm::report_fatal_error(std::string(InstName) + 574 ": P=0 when W=1 not allowed"); 575 } 576 577 void verifyRegsNotEq(IValueT Reg1, const char *Reg1Name, IValueT Reg2, 578 const char *Reg2Name, const char *InstName) { 579 if (BuildDefs::minimal()) 580 return; 581 if (Reg1 == Reg2) 582 llvm::report_fatal_error(std::string(InstName) + ": " + Reg1Name + "=" + 583 Reg2Name + " not allowed"); 584 } 585 586 void verifyRegNotPc(IValueT Reg, const char *RegName, const char *InstName) { 587 verifyRegsNotEq(Reg, RegName, RegARM32::Encoded_Reg_pc, "pc", InstName); 588 } 589 590 void verifyAddrRegNotPc(IValueT RegShift, IValueT Address, const char *RegName, 591 const char *InstName) { 592 if (BuildDefs::minimal()) 593 return; 594 if (getGPRReg(RegShift, Address) == RegARM32::Encoded_Reg_pc) 595 llvm::report_fatal_error(std::string(InstName) + ": " + RegName + 596 "=pc not allowed"); 597 } 598 599 void verifyRegNotPcWhenSetFlags(IValueT Reg, bool SetFlags, 600 const char *InstName) { 601 if (BuildDefs::minimal()) 602 return; 603 if (SetFlags && (Reg == RegARM32::Encoded_Reg_pc)) 604 llvm::report_fatal_error(std::string(InstName) + ": " + 605 RegARM32::getRegName(RegARM32::Reg_pc) + 606 "=pc not allowed when CC=1"); 607 } 608 609 } // end of anonymous namespace 610 611 namespace Ice { 612 namespace ARM32 { 613 614 size_t MoveRelocatableFixup::emit(GlobalContext *Ctx, 615 const Assembler &Asm) const { 616 if (!BuildDefs::dump()) 617 return InstARM32::InstSize; 618 Ostream &Str = Ctx->getStrEmit(); 619 IValueT Inst = Asm.load<IValueT>(position()); 620 const bool IsMovw = kind() == llvm::ELF::R_ARM_MOVW_ABS_NC || 621 kind() == llvm::ELF::R_ARM_MOVW_PREL_NC; 622 const auto Symbol = symbol().toString(); 623 const bool NeedsPCRelSuffix = 624 (Asm.fixupIsPCRel(kind()) || Symbol == GlobalOffsetTable); 625 Str << "\t" 626 "mov" << (IsMovw ? "w" : "t") << "\t" 627 << RegARM32::getRegName(RegNumT::fixme((Inst >> kRdShift) & 0xF)) 628 << ", #:" << (IsMovw ? "lower" : "upper") << "16:" << Symbol 629 << (NeedsPCRelSuffix ? " - ." : "") << "\t@ .word " 630 // TODO(jpp): This is broken, it also needs to add a magic constant. 631 << llvm::format_hex_no_prefix(Inst, 8) << "\n"; 632 return InstARM32::InstSize; 633 } 634 635 IValueT AssemblerARM32::encodeElmtType(Type ElmtTy) { 636 switch (ElmtTy) { 637 case IceType_i8: 638 return 0; 639 case IceType_i16: 640 return 1; 641 case IceType_i32: 642 case IceType_f32: 643 return 2; 644 case IceType_i64: 645 return 3; 646 default: 647 llvm::report_fatal_error("SIMD op: Don't understand element type " + 648 typeStdString(ElmtTy)); 649 } 650 } 651 652 // This fixup points to an ARM32 instruction with the following format: 653 void MoveRelocatableFixup::emitOffset(Assembler *Asm) const { 654 // cccc00110T00iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, 655 // iiiiiiiiiiiiiiii = Imm16, and T=1 for movt. 656 657 const IValueT Inst = Asm->load<IValueT>(position()); 658 constexpr IValueT Imm16Mask = 0x000F0FFF; 659 const IValueT Imm16 = offset() & 0xffff; 660 Asm->store(position(), 661 (Inst & ~Imm16Mask) | ((Imm16 >> 12) << 16) | (Imm16 & 0xfff)); 662 } 663 664 MoveRelocatableFixup *AssemblerARM32::createMoveFixup(bool IsMovW, 665 const Constant *Value) { 666 MoveRelocatableFixup *F = 667 new (allocate<MoveRelocatableFixup>()) MoveRelocatableFixup(); 668 F->set_kind(IsMovW ? (IsNonsfi ? llvm::ELF::R_ARM_MOVW_PREL_NC 669 : llvm::ELF::R_ARM_MOVW_ABS_NC) 670 : (IsNonsfi ? llvm::ELF::R_ARM_MOVT_PREL 671 : llvm::ELF::R_ARM_MOVT_ABS)); 672 F->set_value(Value); 673 Buffer.installFixup(F); 674 return F; 675 } 676 677 size_t BlRelocatableFixup::emit(GlobalContext *Ctx, 678 const Assembler &Asm) const { 679 if (!BuildDefs::dump()) 680 return InstARM32::InstSize; 681 Ostream &Str = Ctx->getStrEmit(); 682 IValueT Inst = Asm.load<IValueT>(position()); 683 Str << "\t" 684 "bl\t" << symbol() << "\t@ .word " 685 << llvm::format_hex_no_prefix(Inst, 8) << "\n"; 686 return InstARM32::InstSize; 687 } 688 689 void BlRelocatableFixup::emitOffset(Assembler *Asm) const { 690 // cccc101liiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond, l=Link, and 691 // iiiiiiiiiiiiiiiiiiiiiiii= 692 // EncodedBranchOffset(cccc101l000000000000000000000000, Offset); 693 const IValueT Inst = Asm->load<IValueT>(position()); 694 constexpr IValueT OffsetMask = 0x00FFFFFF; 695 Asm->store(position(), encodeBranchOffset(offset(), Inst & ~OffsetMask)); 696 } 697 698 void AssemblerARM32::padWithNop(intptr_t Padding) { 699 constexpr intptr_t InstWidth = sizeof(IValueT); 700 assert(Padding % InstWidth == 0 && 701 "Padding not multiple of instruction size"); 702 for (intptr_t i = 0; i < Padding; i += InstWidth) 703 nop(); 704 } 705 706 BlRelocatableFixup * 707 AssemblerARM32::createBlFixup(const ConstantRelocatable *BlTarget) { 708 BlRelocatableFixup *F = 709 new (allocate<BlRelocatableFixup>()) BlRelocatableFixup(); 710 F->set_kind(llvm::ELF::R_ARM_CALL); 711 F->set_value(BlTarget); 712 Buffer.installFixup(F); 713 return F; 714 } 715 716 void AssemblerARM32::bindCfgNodeLabel(const CfgNode *Node) { 717 if (BuildDefs::dump() && !getFlags().getDisableHybridAssembly()) { 718 // Generate label name so that branches can find it. 719 constexpr SizeT InstSize = 0; 720 emitTextInst(Node->getAsmName() + ":", InstSize); 721 } 722 SizeT NodeNumber = Node->getIndex(); 723 assert(!getPreliminary()); 724 Label *L = getOrCreateCfgNodeLabel(NodeNumber); 725 this->bind(L); 726 } 727 728 Label *AssemblerARM32::getOrCreateLabel(SizeT Number, LabelVector &Labels) { 729 Label *L = nullptr; 730 if (Number == Labels.size()) { 731 L = new (this->allocate<Label>()) Label(); 732 Labels.push_back(L); 733 return L; 734 } 735 if (Number > Labels.size()) { 736 Labels.resize(Number + 1); 737 } 738 L = Labels[Number]; 739 if (!L) { 740 L = new (this->allocate<Label>()) Label(); 741 Labels[Number] = L; 742 } 743 return L; 744 } 745 746 // Pull out offset from branch Inst. 747 IOffsetT AssemblerARM32::decodeBranchOffset(IValueT Inst) { 748 // Sign-extend, left-shift by 2, and adjust to the way ARM CPUs read PC. 749 const IOffsetT Offset = (Inst & kBranchOffsetMask) << 8; 750 return (Offset >> 6) + kPCReadOffset; 751 } 752 753 void AssemblerARM32::bind(Label *L) { 754 IOffsetT BoundPc = Buffer.size(); 755 assert(!L->isBound()); // Labels can only be bound once. 756 while (L->isLinked()) { 757 IOffsetT Position = L->getLinkPosition(); 758 IOffsetT Dest = BoundPc - Position; 759 IValueT Inst = Buffer.load<IValueT>(Position); 760 Buffer.store<IValueT>(Position, encodeBranchOffset(Dest, Inst)); 761 L->setPosition(decodeBranchOffset(Inst)); 762 } 763 L->bindTo(BoundPc); 764 } 765 766 void AssemblerARM32::emitTextInst(const std::string &Text, SizeT InstSize) { 767 AssemblerFixup *F = createTextFixup(Text, InstSize); 768 emitFixup(F); 769 for (SizeT I = 0; I < InstSize; ++I) { 770 AssemblerBuffer::EnsureCapacity ensured(&Buffer); 771 Buffer.emit<char>(0); 772 } 773 } 774 775 void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT InstType, 776 IValueT Opcode, bool SetFlags, IValueT Rn, 777 IValueT Rd, IValueT Imm12, 778 EmitChecks RuleChecks, const char *InstName) { 779 switch (RuleChecks) { 780 case NoChecks: 781 break; 782 case RdIsPcAndSetFlags: 783 verifyRegNotPcWhenSetFlags(Rd, SetFlags, InstName); 784 break; 785 } 786 assert(Rd < RegARM32::getNumGPRegs()); 787 assert(CondARM32::isDefined(Cond)); 788 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | 789 (InstType << kTypeShift) | (Opcode << kOpcodeShift) | 790 (encodeBool(SetFlags) << kSShift) | 791 (Rn << kRnShift) | (Rd << kRdShift) | Imm12; 792 emitInst(Encoding); 793 } 794 795 void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Opcode, 796 const Operand *OpRd, const Operand *OpRn, 797 const Operand *OpSrc1, bool SetFlags, 798 EmitChecks RuleChecks, const char *InstName) { 799 IValueT Rd = encodeGPRegister(OpRd, "Rd", InstName); 800 IValueT Rn = encodeGPRegister(OpRn, "Rn", InstName); 801 emitType01(Cond, Opcode, Rd, Rn, OpSrc1, SetFlags, RuleChecks, InstName); 802 } 803 804 void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Opcode, 805 IValueT Rd, IValueT Rn, const Operand *OpSrc1, 806 bool SetFlags, EmitChecks RuleChecks, 807 const char *InstName) { 808 IValueT Src1Value; 809 // TODO(kschimpf) Other possible decodings of data operations. 810 switch (encodeOperand(OpSrc1, Src1Value, WantGPRegs)) { 811 default: 812 llvm::report_fatal_error(std::string(InstName) + 813 ": Can't encode instruction"); 814 return; 815 case EncodedAsRegister: { 816 // XXX (register) 817 // xxx{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} 818 // 819 // cccc000xxxxsnnnnddddiiiiitt0mmmm where cccc=Cond, xxxx=Opcode, dddd=Rd, 820 // nnnn=Rn, mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. 821 constexpr IValueT Imm5 = 0; 822 Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, Imm5); 823 emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value, 824 RuleChecks, InstName); 825 return; 826 } 827 case EncodedAsShiftedRegister: { 828 // Form is defined in case EncodedAsRegister. (i.e. XXX (register)). 829 emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value, 830 RuleChecks, InstName); 831 return; 832 } 833 case EncodedAsConstI32: { 834 // See if we can convert this to an XXX (immediate). 835 IValueT RotateAmt; 836 IValueT Imm8; 837 if (!OperandARM32FlexImm::canHoldImm(Src1Value, &RotateAmt, &Imm8)) 838 llvm::report_fatal_error(std::string(InstName) + 839 ": Immediate rotated constant not valid"); 840 Src1Value = encodeRotatedImm8(RotateAmt, Imm8); 841 // Intentionally fall to next case! 842 } 843 case EncodedAsRotatedImm8: { 844 // XXX (Immediate) 845 // xxx{s}<c> <Rd>, <Rn>, #<RotatedImm8> 846 // 847 // cccc001xxxxsnnnnddddiiiiiiiiiiii where cccc=Cond, xxxx=Opcode, dddd=Rd, 848 // nnnn=Rn, s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. 849 emitType01(Cond, kInstTypeDataImmediate, Opcode, SetFlags, Rn, Rd, 850 Src1Value, RuleChecks, InstName); 851 return; 852 } 853 case EncodedAsRegShiftReg: { 854 // XXX (register-shifted reg) 855 // xxx{s}<c> <Rd>, <Rn>, <Rm>, <type> <Rs> 856 // 857 // cccc000xxxxfnnnnddddssss0tt1mmmm where cccc=Cond, xxxx=Opcode, dddd=Rd, 858 // nnnn=Rn, ssss=Rs, f=SetFlags, tt is encoding of type, and 859 // Src1Value=ssss01tt1mmmm. 860 emitType01(Cond, kInstTypeDataRegShift, Opcode, SetFlags, Rn, Rd, Src1Value, 861 RuleChecks, InstName); 862 return; 863 } 864 } 865 } 866 867 void AssemblerARM32::emitType05(CondARM32::Cond Cond, IOffsetT Offset, 868 bool Link) { 869 // cccc101liiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond, l=Link, and 870 // iiiiiiiiiiiiiiiiiiiiiiii= 871 // EncodedBranchOffset(cccc101l000000000000000000000000, Offset); 872 assert(CondARM32::isDefined(Cond)); 873 IValueT Encoding = static_cast<int32_t>(Cond) << kConditionShift | 874 5 << kTypeShift | (Link ? 1 : 0) << kLinkShift; 875 Encoding = encodeBranchOffset(Offset, Encoding); 876 emitInst(Encoding); 877 } 878 879 void AssemblerARM32::emitBranch(Label *L, CondARM32::Cond Cond, bool Link) { 880 // TODO(kschimpf): Handle far jumps. 881 if (L->isBound()) { 882 const int32_t Dest = L->getPosition() - Buffer.size(); 883 emitType05(Cond, Dest, Link); 884 return; 885 } 886 const IOffsetT Position = Buffer.size(); 887 // Use the offset field of the branch instruction for linking the sites. 888 emitType05(Cond, L->getEncodedPosition(), Link); 889 L->linkTo(*this, Position); 890 } 891 892 void AssemblerARM32::emitCompareOp(CondARM32::Cond Cond, IValueT Opcode, 893 const Operand *OpRn, const Operand *OpSrc1, 894 const char *InstName) { 895 // XXX (register) 896 // XXX<c> <Rn>, <Rm>{, <shift>} 897 // 898 // ccccyyyxxxx1nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, iiiii 899 // defines shift constant, tt=ShiftKind, yyy=kInstTypeDataRegister, and 900 // xxxx=Opcode. 901 // 902 // XXX (immediate) 903 // XXX<c> <Rn>, #<RotatedImm8> 904 // 905 // ccccyyyxxxx1nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, 906 // yyy=kInstTypeDataImmdiate, xxxx=Opcode, and iiiiiiiiiiii=Src1Value 907 // defining RotatedImm8. 908 constexpr bool SetFlags = true; 909 constexpr IValueT Rd = RegARM32::Encoded_Reg_r0; 910 IValueT Rn = encodeGPRegister(OpRn, "Rn", InstName); 911 emitType01(Cond, Opcode, Rd, Rn, OpSrc1, SetFlags, NoChecks, InstName); 912 } 913 914 void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, IValueT InstType, 915 bool IsLoad, bool IsByte, IValueT Rt, 916 IValueT Address) { 917 assert(Rt < RegARM32::getNumGPRegs()); 918 assert(CondARM32::isDefined(Cond)); 919 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | 920 (InstType << kTypeShift) | (IsLoad ? L : 0) | 921 (IsByte ? B : 0) | (Rt << kRdShift) | Address; 922 emitInst(Encoding); 923 } 924 925 void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte, 926 IValueT Rt, const Operand *OpAddress, 927 const TargetInfo &TInfo, const char *InstName) { 928 IValueT Address; 929 switch (encodeAddress(OpAddress, Address, TInfo, Imm12Address)) { 930 default: 931 llvm::report_fatal_error(std::string(InstName) + 932 ": Memory address not understood"); 933 case EncodedAsImmRegOffset: { 934 // XXX{B} (immediate): 935 // xxx{b}<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 936 // xxx{b}<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 937 // xxx{b}<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 938 // 939 // cccc010pubwlnnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, 940 // iiiiiiiiiiii=imm12, b=IsByte, pu0w<<21 is a BlockAddr, l=IsLoad, and 941 // pu0w0nnnn0000iiiiiiiiiiii=Address. 942 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); 943 944 // Check if conditions of rules violated. 945 verifyRegNotPc(Rn, "Rn", InstName); 946 verifyPOrNotW(Address, InstName); 947 if (!IsByte && (Rn == RegARM32::Encoded_Reg_sp) && !isBitSet(P, Address) && 948 isBitSet(U, Address) && !isBitSet(W, Address) && 949 (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */)) 950 llvm::report_fatal_error(std::string(InstName) + 951 ": Use push/pop instead"); 952 953 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); 954 return; 955 } 956 case EncodedAsShiftRotateImm5: { 957 // XXX{B} (register) 958 // xxx{b}<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} 959 // xxx{b}<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} 960 // 961 // cccc011pubwlnnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, 962 // b=IsByte, U=1 if +, pu0b is a BlockAddr, l=IsLoad, and 963 // pu0w0nnnn0000iiiiiss0mmmm=Address. 964 RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); 965 RegARM32::GPRRegister Rm = getGPRReg(kRmShift, Address); 966 967 // Check if conditions of rules violated. 968 verifyPOrNotW(Address, InstName); 969 verifyRegNotPc(Rm, "Rm", InstName); 970 if (IsByte) 971 verifyRegNotPc(Rt, "Rt", InstName); 972 if (isBitSet(W, Address)) { 973 verifyRegNotPc(Rn, "Rn", InstName); 974 verifyRegsNotEq(Rn, "Rn", Rt, "Rt", InstName); 975 } 976 emitMemOp(Cond, kInstTypeRegisterShift, IsLoad, IsByte, Rt, Address); 977 return; 978 } 979 } 980 } 981 982 void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, 983 IValueT Rt, const Operand *OpAddress, 984 const TargetInfo &TInfo, 985 const char *InstName) { 986 IValueT Address; 987 switch (encodeAddress(OpAddress, Address, TInfo, RotatedImm8Enc3Address)) { 988 default: 989 llvm::report_fatal_error(std::string(InstName) + 990 ": Memory address not understood"); 991 case EncodedAsImmRegOffset: { 992 // XXXH (immediate) 993 // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}] 994 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>] 995 // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]! 996 // 997 // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt, 998 // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, 999 // and pu0w0nnnn0000iiii0000jjjj=Address. 1000 assert(Rt < RegARM32::getNumGPRegs()); 1001 assert(CondARM32::isDefined(Cond)); 1002 verifyPOrNotW(Address, InstName); 1003 verifyRegNotPc(Rt, "Rt", InstName); 1004 if (isBitSet(W, Address)) 1005 verifyRegsNotEq(getGPRReg(kRnShift, Address), "Rn", Rt, "Rt", InstName); 1006 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | 1007 Opcode | (Rt << kRdShift) | Address; 1008 emitInst(Encoding); 1009 return; 1010 } 1011 case EncodedAsShiftRotateImm5: { 1012 // XXXH (register) 1013 // xxxh<c> <Rt>, [<Rn>, +/-<Rm>]{!} 1014 // xxxh<c> <Rt>, [<Rn>], +/-<Rm> 1015 // 1016 // cccc000pu0wxnnnntttt00001011mmmm where cccc=Cond, tttt=Rt, nnnn=Rn, 1017 // mmmm=Rm, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, and 1018 // pu0w0nnnn000000000000mmmm=Address. 1019 assert(Rt < RegARM32::getNumGPRegs()); 1020 assert(CondARM32::isDefined(Cond)); 1021 verifyPOrNotW(Address, InstName); 1022 verifyRegNotPc(Rt, "Rt", InstName); 1023 verifyAddrRegNotPc(kRmShift, Address, "Rm", InstName); 1024 const RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address); 1025 if (isBitSet(W, Address)) { 1026 verifyRegNotPc(Rn, "Rn", InstName); 1027 verifyRegsNotEq(Rn, "Rn", Rt, "Rt", InstName); 1028 } 1029 if (mask(Address, kShiftImmShift, 5) != 0) 1030 // For encoding 3, no shift is allowed. 1031 llvm::report_fatal_error(std::string(InstName) + 1032 ": Shift constant not allowed"); 1033 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | 1034 Opcode | (Rt << kRdShift) | Address; 1035 emitInst(Encoding); 1036 return; 1037 } 1038 } 1039 } 1040 1041 void AssemblerARM32::emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, 1042 IValueT Rn, IValueT Rm) { 1043 assert(Rd < RegARM32::getNumGPRegs()); 1044 assert(Rn < RegARM32::getNumGPRegs()); 1045 assert(Rm < RegARM32::getNumGPRegs()); 1046 assert(CondARM32::isDefined(Cond)); 1047 const IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | 1048 (Rn << kDivRnShift) | (Rd << kDivRdShift) | B26 | 1049 B25 | B24 | B20 | B15 | B14 | B13 | B12 | B4 | 1050 (Rm << kDivRmShift); 1051 emitInst(Encoding); 1052 } 1053 1054 void AssemblerARM32::emitInsertExtractInt(CondARM32::Cond Cond, 1055 const Operand *OpQn, uint32_t Index, 1056 const Operand *OpRt, bool IsExtract, 1057 const char *InstName) { 1058 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InstName); 1059 IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", InstName)); 1060 assert(Rt != RegARM32::Encoded_Reg_pc); 1061 assert(Rt != RegARM32::Encoded_Reg_sp); 1062 assert(CondARM32::isDefined(Cond)); 1063 const uint32_t BitSize = typeWidthInBytes(OpRt->getType()) * CHAR_BIT; 1064 IValueT Opcode1 = 0; 1065 IValueT Opcode2 = 0; 1066 switch (BitSize) { 1067 default: 1068 llvm::report_fatal_error(std::string(InstName) + 1069 ": Unable to process type " + 1070 typeStdString(OpRt->getType())); 1071 case 8: 1072 assert(Index < 16); 1073 Dn = Dn | mask(Index, 3, 1); 1074 Opcode1 = B1 | mask(Index, 2, 1); 1075 Opcode2 = mask(Index, 0, 2); 1076 break; 1077 case 16: 1078 assert(Index < 8); 1079 Dn = Dn | mask(Index, 2, 1); 1080 Opcode1 = mask(Index, 1, 1); 1081 Opcode2 = (mask(Index, 0, 1) << 1) | B0; 1082 break; 1083 case 32: 1084 assert(Index < 4); 1085 Dn = Dn | mask(Index, 1, 1); 1086 Opcode1 = mask(Index, 0, 1); 1087 break; 1088 } 1089 const IValueT Encoding = B27 | B26 | B25 | B11 | B9 | B8 | B4 | 1090 (encodeCondition(Cond) << kConditionShift) | 1091 (Opcode1 << 21) | 1092 (getXXXXInRegYXXXX(Dn) << kRnShift) | (Rt << 12) | 1093 (encodeBool(IsExtract) << 20) | 1094 (getYInRegYXXXX(Dn) << 7) | (Opcode2 << 5); 1095 emitInst(Encoding); 1096 } 1097 1098 void AssemblerARM32::emitMoveSS(CondARM32::Cond Cond, IValueT Sd, IValueT Sm) { 1099 // VMOV (register) - ARM section A8.8.340, encoding A2: 1100 // vmov<c>.f32 <Sd>, <Sm> 1101 // 1102 // cccc11101D110000dddd101001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm. 1103 constexpr IValueT VmovssOpcode = B23 | B21 | B20 | B6; 1104 constexpr IValueT S0 = 0; 1105 emitVFPsss(Cond, VmovssOpcode, Sd, S0, Sm); 1106 } 1107 1108 void AssemblerARM32::emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, 1109 IValueT Rn, IValueT Rm, IValueT Rs, 1110 bool SetFlags) { 1111 assert(Rd < RegARM32::getNumGPRegs()); 1112 assert(Rn < RegARM32::getNumGPRegs()); 1113 assert(Rm < RegARM32::getNumGPRegs()); 1114 assert(Rs < RegARM32::getNumGPRegs()); 1115 assert(CondARM32::isDefined(Cond)); 1116 IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | 1117 (encodeBool(SetFlags) << kSShift) | (Rn << kRnShift) | 1118 (Rd << kRdShift) | (Rs << kRsShift) | B7 | B4 | 1119 (Rm << kRmShift); 1120 emitInst(Encoding); 1121 } 1122 1123 void AssemblerARM32::emitMultiMemOp(CondARM32::Cond Cond, 1124 BlockAddressMode AddressMode, bool IsLoad, 1125 IValueT BaseReg, IValueT Registers) { 1126 assert(CondARM32::isDefined(Cond)); 1127 assert(BaseReg < RegARM32::getNumGPRegs()); 1128 assert(Registers < (1 << RegARM32::getNumGPRegs())); 1129 IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B27 | 1130 AddressMode | (IsLoad ? L : 0) | (BaseReg << kRnShift) | 1131 Registers; 1132 emitInst(Encoding); 1133 } 1134 1135 void AssemblerARM32::emitSignExtend(CondARM32::Cond Cond, IValueT Opcode, 1136 const Operand *OpRd, const Operand *OpSrc0, 1137 const char *InstName) { 1138 IValueT Rd = encodeGPRegister(OpRd, "Rd", InstName); 1139 IValueT Rm = encodeGPRegister(OpSrc0, "Rm", InstName); 1140 // Note: For the moment, we assume no rotation is specified. 1141 RotationValue Rotation = kRotateNone; 1142 constexpr IValueT Rn = RegARM32::Encoded_Reg_pc; 1143 const Type Ty = OpSrc0->getType(); 1144 switch (Ty) { 1145 default: 1146 llvm::report_fatal_error(std::string(InstName) + ": Type " + 1147 typeString(Ty) + " not allowed"); 1148 break; 1149 case IceType_i1: 1150 case IceType_i8: { 1151 // SXTB/UXTB - Arm sections A8.8.233 and A8.8.274, encoding A1: 1152 // sxtb<c> <Rd>, <Rm>{, <rotate>} 1153 // uxtb<c> <Rd>, <Rm>{, <rotate>} 1154 // 1155 // ccccxxxxxxxx1111ddddrr000111mmmm where cccc=Cond, xxxxxxxx<<20=Opcode, 1156 // dddd=Rd, mmmm=Rm, and rr defined (RotationValue) rotate. 1157 break; 1158 } 1159 case IceType_i16: { 1160 // SXTH/UXTH - ARM sections A8.8.235 and A8.8.276, encoding A1: 1161 // uxth<c> <Rd>< <Rm>{, <rotate>} 1162 // 1163 // cccc01101111nnnnddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and 1164 // rr defined (RotationValue) rotate. 1165 Opcode |= B20; 1166 break; 1167 } 1168 } 1169 1170 assert(CondARM32::isDefined(Cond)); 1171 IValueT Rot = encodeRotation(Rotation); 1172 if (!Utils::IsUint(2, Rot)) 1173 llvm::report_fatal_error(std::string(InstName) + 1174 ": Illegal rotation value"); 1175 IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | Opcode | 1176 (Rn << kRnShift) | (Rd << kRdShift) | 1177 (Rot << kRotationShift) | B6 | B5 | B4 | (Rm << kRmShift); 1178 emitInst(Encoding); 1179 } 1180 1181 void AssemblerARM32::emitSIMDBase(IValueT Opcode, IValueT Dd, IValueT Dn, 1182 IValueT Dm, bool UseQRegs, bool IsFloatTy) { 1183 const IValueT Encoding = 1184 Opcode | B25 | (encodeCondition(CondARM32::kNone) << kConditionShift) | 1185 (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) | 1186 (getXXXXInRegYXXXX(Dd) << 12) | (IsFloatTy ? B10 : 0) | 1187 (getYInRegYXXXX(Dn) << 7) | (encodeBool(UseQRegs) << 6) | 1188 (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm); 1189 emitInst(Encoding); 1190 } 1191 1192 void AssemblerARM32::emitSIMD(IValueT Opcode, Type ElmtTy, IValueT Dd, 1193 IValueT Dn, IValueT Dm, bool UseQRegs) { 1194 constexpr IValueT ElmtShift = 20; 1195 const IValueT ElmtSize = encodeElmtType(ElmtTy); 1196 assert(Utils::IsUint(2, ElmtSize)); 1197 emitSIMDBase(Opcode | (ElmtSize << ElmtShift), Dd, Dn, Dm, UseQRegs, 1198 isFloatingType(ElmtTy)); 1199 } 1200 1201 void AssemblerARM32::emitSIMDqqqBase(IValueT Opcode, const Operand *OpQd, 1202 const Operand *OpQn, const Operand *OpQm, 1203 bool IsFloatTy, const char *OpcodeName) { 1204 const IValueT Qd = encodeQRegister(OpQd, "Qd", OpcodeName); 1205 const IValueT Qn = encodeQRegister(OpQn, "Qn", OpcodeName); 1206 const IValueT Qm = encodeQRegister(OpQm, "Qm", OpcodeName); 1207 constexpr bool UseQRegs = true; 1208 emitSIMDBase(Opcode, mapQRegToDReg(Qd), mapQRegToDReg(Qn), mapQRegToDReg(Qm), 1209 UseQRegs, IsFloatTy); 1210 } 1211 1212 void AssemblerARM32::emitSIMDqqq(IValueT Opcode, Type ElmtTy, 1213 const Operand *OpQd, const Operand *OpQn, 1214 const Operand *OpQm, const char *OpcodeName) { 1215 constexpr IValueT ElmtShift = 20; 1216 const IValueT ElmtSize = encodeElmtType(ElmtTy); 1217 assert(Utils::IsUint(2, ElmtSize)); 1218 emitSIMDqqqBase(Opcode | (ElmtSize << ElmtShift), OpQd, OpQn, OpQm, 1219 isFloatingType(ElmtTy), OpcodeName); 1220 } 1221 1222 void AssemblerARM32::emitSIMDShiftqqc(IValueT Opcode, const Operand *OpQd, 1223 const Operand *OpQm, const IValueT Imm6, 1224 const char *OpcodeName) { 1225 const IValueT Qd = encodeQRegister(OpQd, "Qd", OpcodeName); 1226 const IValueT Qn = 0; 1227 const IValueT Qm = encodeQRegister(OpQm, "Qm", OpcodeName); 1228 constexpr bool UseQRegs = true; 1229 constexpr bool IsFloatTy = false; 1230 constexpr IValueT ElmtShift = 16; 1231 emitSIMDBase(Opcode | (Imm6 << ElmtShift), mapQRegToDReg(Qd), 1232 mapQRegToDReg(Qn), mapQRegToDReg(Qm), UseQRegs, IsFloatTy); 1233 } 1234 1235 void AssemblerARM32::emitSIMDCvtqq(IValueT Opcode, const Operand *OpQd, 1236 const Operand *OpQm, 1237 const char *OpcodeName) { 1238 const IValueT SIMDOpcode = 1239 B24 | B23 | B21 | B20 | B19 | B17 | B16 | B10 | B9 | Opcode; 1240 constexpr bool UseQRegs = true; 1241 constexpr bool IsFloatTy = false; 1242 const IValueT Qd = encodeQRegister(OpQd, "Qd", OpcodeName); 1243 constexpr IValueT Qn = 0; 1244 const IValueT Qm = encodeQRegister(OpQm, "Qm", OpcodeName); 1245 emitSIMDBase(SIMDOpcode, mapQRegToDReg(Qd), mapQRegToDReg(Qn), 1246 mapQRegToDReg(Qm), UseQRegs, IsFloatTy); 1247 } 1248 1249 void AssemblerARM32::emitVFPddd(CondARM32::Cond Cond, IValueT Opcode, 1250 IValueT Dd, IValueT Dn, IValueT Dm) { 1251 assert(Dd < RegARM32::getNumDRegs()); 1252 assert(Dn < RegARM32::getNumDRegs()); 1253 assert(Dm < RegARM32::getNumDRegs()); 1254 assert(CondARM32::isDefined(Cond)); 1255 constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9 | B8; 1256 const IValueT Encoding = 1257 Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) | 1258 (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) | 1259 (getXXXXInRegYXXXX(Dd) << 12) | (getYInRegYXXXX(Dn) << 7) | 1260 (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm); 1261 emitInst(Encoding); 1262 } 1263 1264 void AssemblerARM32::emitVFPddd(CondARM32::Cond Cond, IValueT Opcode, 1265 const Operand *OpDd, const Operand *OpDn, 1266 const Operand *OpDm, const char *InstName) { 1267 IValueT Dd = encodeDRegister(OpDd, "Dd", InstName); 1268 IValueT Dn = encodeDRegister(OpDn, "Dn", InstName); 1269 IValueT Dm = encodeDRegister(OpDm, "Dm", InstName); 1270 emitVFPddd(Cond, Opcode, Dd, Dn, Dm); 1271 } 1272 1273 void AssemblerARM32::emitVFPsss(CondARM32::Cond Cond, IValueT Opcode, 1274 IValueT Sd, IValueT Sn, IValueT Sm) { 1275 assert(Sd < RegARM32::getNumSRegs()); 1276 assert(Sn < RegARM32::getNumSRegs()); 1277 assert(Sm < RegARM32::getNumSRegs()); 1278 assert(CondARM32::isDefined(Cond)); 1279 constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9; 1280 const IValueT Encoding = 1281 Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) | 1282 (getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sn) << 16) | 1283 (getXXXXInRegXXXXY(Sd) << 12) | (getYInRegXXXXY(Sn) << 7) | 1284 (getYInRegXXXXY(Sm) << 5) | getXXXXInRegXXXXY(Sm); 1285 emitInst(Encoding); 1286 } 1287 1288 void AssemblerARM32::emitVFPsss(CondARM32::Cond Cond, IValueT Opcode, 1289 const Operand *OpSd, const Operand *OpSn, 1290 const Operand *OpSm, const char *InstName) { 1291 const IValueT Sd = encodeSRegister(OpSd, "Sd", InstName); 1292 const IValueT Sn = encodeSRegister(OpSn, "Sn", InstName); 1293 const IValueT Sm = encodeSRegister(OpSm, "Sm", InstName); 1294 emitVFPsss(Cond, Opcode, Sd, Sn, Sm); 1295 } 1296 1297 void AssemblerARM32::adc(const Operand *OpRd, const Operand *OpRn, 1298 const Operand *OpSrc1, bool SetFlags, 1299 CondARM32::Cond Cond) { 1300 // ADC (register) - ARM section 18.8.2, encoding A1: 1301 // adc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} 1302 // 1303 // cccc0000101snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, 1304 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. 1305 // 1306 // ADC (Immediate) - ARM section A8.8.1, encoding A1: 1307 // adc{s}<c> <Rd>, <Rn>, #<RotatedImm8> 1308 // 1309 // cccc0010101snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, 1310 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. 1311 constexpr const char *AdcName = "adc"; 1312 constexpr IValueT AdcOpcode = B2 | B0; // 0101 1313 emitType01(Cond, AdcOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, 1314 AdcName); 1315 } 1316 1317 void AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn, 1318 const Operand *OpSrc1, bool SetFlags, 1319 CondARM32::Cond Cond) { 1320 // ADD (register) - ARM section A8.8.7, encoding A1: 1321 // add{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} 1322 // ADD (Sp plus register) - ARM section A8.8.11, encoding A1: 1323 // add{s}<c> sp, <Rn>, <Rm>{, <shiff>} 1324 // 1325 // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, 1326 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. 1327 // 1328 // ADD (Immediate) - ARM section A8.8.5, encoding A1: 1329 // add{s}<c> <Rd>, <Rn>, #<RotatedImm8> 1330 // ADD (SP plus immediate) - ARM section A8.8.9, encoding A1. 1331 // add{s}<c> <Rd>, sp, #<RotatedImm8> 1332 // 1333 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, 1334 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. 1335 constexpr const char *AddName = "add"; 1336 constexpr IValueT Add = B2; // 0100 1337 emitType01(Cond, Add, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, 1338 AddName); 1339 } 1340 1341 void AssemblerARM32::and_(const Operand *OpRd, const Operand *OpRn, 1342 const Operand *OpSrc1, bool SetFlags, 1343 CondARM32::Cond Cond) { 1344 // AND (register) - ARM section A8.8.14, encoding A1: 1345 // and{s}<c> <Rd>, <Rn>{, <shift>} 1346 // 1347 // cccc0000000snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, 1348 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. 1349 // 1350 // AND (Immediate) - ARM section A8.8.13, encoding A1: 1351 // and{s}<c> <Rd>, <Rn>, #<RotatedImm8> 1352 // 1353 // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, 1354 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. 1355 constexpr const char *AndName = "and"; 1356 constexpr IValueT And = 0; // 0000 1357 emitType01(Cond, And, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, 1358 AndName); 1359 } 1360 1361 void AssemblerARM32::b(Label *L, CondARM32::Cond Cond) { 1362 emitBranch(L, Cond, false); 1363 } 1364 1365 void AssemblerARM32::bkpt(uint16_t Imm16) { 1366 // BKPT - ARM section A*.8.24 - encoding A1: 1367 // bkpt #<Imm16> 1368 // 1369 // cccc00010010iiiiiiiiiiii0111iiii where cccc=AL and iiiiiiiiiiiiiiii=Imm16 1370 const IValueT Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 | 1371 ((Imm16 >> 4) << 8) | B6 | B5 | B4 | (Imm16 & 0xf); 1372 emitInst(Encoding); 1373 } 1374 1375 void AssemblerARM32::bic(const Operand *OpRd, const Operand *OpRn, 1376 const Operand *OpSrc1, bool SetFlags, 1377 CondARM32::Cond Cond) { 1378 // BIC (register) - ARM section A8.8.22, encoding A1: 1379 // bic{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} 1380 // 1381 // cccc0001110snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, 1382 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. 1383 // 1384 // BIC (immediate) - ARM section A8.8.21, encoding A1: 1385 // bic{s}<c> <Rd>, <Rn>, #<RotatedImm8> 1386 // 1387 // cccc0011110snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rn, nnnn=Rn, 1388 // s=SetFlags, and iiiiiiiiiiii=Src1Value defining RotatedImm8. 1389 constexpr const char *BicName = "bic"; 1390 constexpr IValueT BicOpcode = B3 | B2 | B1; // i.e. 1110 1391 emitType01(Cond, BicOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, 1392 BicName); 1393 } 1394 1395 void AssemblerARM32::bl(const ConstantRelocatable *Target) { 1396 // BL (immediate) - ARM section A8.8.25, encoding A1: 1397 // bl<c> <label> 1398 // 1399 // cccc1011iiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond (not currently allowed) 1400 // and iiiiiiiiiiiiiiiiiiiiiiii is the (encoded) Target to branch to. 1401 emitFixup(createBlFixup(Target)); 1402 constexpr CondARM32::Cond Cond = CondARM32::AL; 1403 constexpr IValueT Immed = 0; 1404 constexpr bool Link = true; 1405 emitType05(Cond, Immed, Link); 1406 } 1407 1408 void AssemblerARM32::blx(const Operand *Target) { 1409 // BLX (register) - ARM section A8.8.26, encoding A1: 1410 // blx<c> <Rm> 1411 // 1412 // cccc000100101111111111110011mmmm where cccc=Cond (not currently allowed) 1413 // and mmmm=Rm. 1414 constexpr const char *BlxName = "Blx"; 1415 IValueT Rm = encodeGPRegister(Target, "Rm", BlxName); 1416 verifyRegNotPc(Rm, "Rm", BlxName); 1417 constexpr CondARM32::Cond Cond = CondARM32::AL; 1418 int32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | B21 | 1419 (0xfff << 8) | B5 | B4 | (Rm << kRmShift); 1420 emitInst(Encoding); 1421 } 1422 1423 void AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { 1424 // BX - ARM section A8.8.27, encoding A1: 1425 // bx<c> <Rm> 1426 // 1427 // cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. 1428 assert(CondARM32::isDefined(Cond)); 1429 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | 1430 B21 | (0xfff << 8) | B4 | 1431 (encodeGPRRegister(Rm) << kRmShift); 1432 emitInst(Encoding); 1433 } 1434 1435 void AssemblerARM32::clz(const Operand *OpRd, const Operand *OpSrc, 1436 CondARM32::Cond Cond) { 1437 // CLZ - ARM section A8.8.33, encoding A1: 1438 // clz<c> <Rd> <Rm> 1439 // 1440 // cccc000101101111dddd11110001mmmm where cccc=Cond, dddd=Rd, and mmmm=Rm. 1441 constexpr const char *ClzName = "clz"; 1442 constexpr const char *RdName = "Rd"; 1443 constexpr const char *RmName = "Rm"; 1444 IValueT Rd = encodeGPRegister(OpRd, RdName, ClzName); 1445 assert(Rd < RegARM32::getNumGPRegs()); 1446 verifyRegNotPc(Rd, RdName, ClzName); 1447 IValueT Rm = encodeGPRegister(OpSrc, RmName, ClzName); 1448 assert(Rm < RegARM32::getNumGPRegs()); 1449 verifyRegNotPc(Rm, RmName, ClzName); 1450 assert(CondARM32::isDefined(Cond)); 1451 constexpr IValueT PredefinedBits = 1452 B24 | B22 | B21 | (0xF << 16) | (0xf << 8) | B4; 1453 const IValueT Encoding = PredefinedBits | (Cond << kConditionShift) | 1454 (Rd << kRdShift) | (Rm << kRmShift); 1455 emitInst(Encoding); 1456 } 1457 1458 void AssemblerARM32::cmn(const Operand *OpRn, const Operand *OpSrc1, 1459 CondARM32::Cond Cond) { 1460 // CMN (immediate) - ARM section A8.8.34, encoding A1: 1461 // cmn<c> <Rn>, #<RotatedImm8> 1462 // 1463 // cccc00110111nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, 1464 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. 1465 // 1466 // CMN (register) - ARM section A8.8.35, encodeing A1: 1467 // cmn<c> <Rn>, <Rm>{, <shift>} 1468 // 1469 // cccc00010111nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, 1470 // iiiii=Shift, and tt=ShiftKind. 1471 constexpr const char *CmnName = "cmn"; 1472 constexpr IValueT CmnOpcode = B3 | B1 | B0; // ie. 1011 1473 emitCompareOp(Cond, CmnOpcode, OpRn, OpSrc1, CmnName); 1474 } 1475 1476 void AssemblerARM32::cmp(const Operand *OpRn, const Operand *OpSrc1, 1477 CondARM32::Cond Cond) { 1478 // CMP (register) - ARM section A8.8.38, encoding A1: 1479 // cmp<c> <Rn>, <Rm>{, <shift>} 1480 // 1481 // cccc00010101nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, 1482 // iiiii=Shift, and tt=ShiftKind. 1483 // 1484 // CMP (immediate) - ARM section A8.8.37 1485 // cmp<c: <Rn>, #<RotatedImm8> 1486 // 1487 // cccc00110101nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, 1488 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. 1489 constexpr const char *CmpName = "cmp"; 1490 constexpr IValueT CmpOpcode = B3 | B1; // ie. 1010 1491 emitCompareOp(Cond, CmpOpcode, OpRn, OpSrc1, CmpName); 1492 } 1493 1494 void AssemblerARM32::dmb(IValueT Option) { 1495 // DMB - ARM section A8.8.43, encoding A1: 1496 // dmb <option> 1497 // 1498 // 1111010101111111111100000101xxxx where xxxx=Option. 1499 assert(Utils::IsUint(4, Option) && "Bad dmb option"); 1500 const IValueT Encoding = 1501 (encodeCondition(CondARM32::kNone) << kConditionShift) | B26 | B24 | B22 | 1502 B21 | B20 | B19 | B18 | B17 | B16 | B15 | B14 | B13 | B12 | B6 | B4 | 1503 Option; 1504 emitInst(Encoding); 1505 } 1506 1507 void AssemblerARM32::eor(const Operand *OpRd, const Operand *OpRn, 1508 const Operand *OpSrc1, bool SetFlags, 1509 CondARM32::Cond Cond) { 1510 // EOR (register) - ARM section A*.8.47, encoding A1: 1511 // eor{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} 1512 // 1513 // cccc0000001snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, 1514 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. 1515 // 1516 // EOR (Immediate) - ARM section A8.*.46, encoding A1: 1517 // eor{s}<c> <Rd>, <Rn>, #RotatedImm8 1518 // 1519 // cccc0010001snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, 1520 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. 1521 constexpr const char *EorName = "eor"; 1522 constexpr IValueT EorOpcode = B0; // 0001 1523 emitType01(Cond, EorOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, 1524 EorName); 1525 } 1526 1527 void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, 1528 CondARM32::Cond Cond, const TargetInfo &TInfo) { 1529 constexpr const char *LdrName = "ldr"; 1530 constexpr bool IsLoad = true; 1531 IValueT Rt = encodeGPRegister(OpRt, "Rt", LdrName); 1532 const Type Ty = OpRt->getType(); 1533 switch (Ty) { 1534 case IceType_i64: 1535 // LDRD is not implemented because target lowering handles i64 and double by 1536 // using two (32-bit) load instructions. Note: Intentionally drop to default 1537 // case. 1538 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) + 1539 " not implemented"); 1540 default: 1541 llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) + 1542 " not allowed"); 1543 case IceType_i1: 1544 case IceType_i8: { 1545 // LDRB (immediate) - ARM section A8.8.68, encoding A1: 1546 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 1547 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 1548 // ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 1549 // 1550 // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, 1551 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and 1552 // pu0w0nnnn0000iiiiiiiiiiii=Address. 1553 // 1554 // LDRB (register) - ARM section A8.8.66, encoding A1: 1555 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} 1556 // ldrb<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>} 1557 // 1558 // cccc011pu1w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b 1559 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. 1560 constexpr bool IsByte = true; 1561 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); 1562 return; 1563 } 1564 case IceType_i16: { 1565 // LDRH (immediate) - ARM section A8.8.80, encoding A1: 1566 // ldrh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] 1567 // ldrh<c> <Rt>, [<Rn>], #+/-<Imm8> 1568 // ldrh<c> <Rt>, [<Rn>, #+/-<Imm8>]! 1569 // 1570 // cccc000pu1w1nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, 1571 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and 1572 // pu0w0nnnn0000iiiiiiiiiiii=Address. 1573 constexpr const char *Ldrh = "ldrh"; 1574 emitMemOpEnc3(Cond, L | B7 | B5 | B4, Rt, OpAddress, TInfo, Ldrh); 1575 return; 1576 } 1577 case IceType_i32: { 1578 // LDR (immediate) - ARM section A8.8.63, encoding A1: 1579 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 1580 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 1581 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 1582 // 1583 // cccc010pu0w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, 1584 // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and 1585 // 1586 // LDR (register) - ARM section A8.8.70, encoding A1: 1587 // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!} 1588 // ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>} 1589 // 1590 // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b 1591 // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address. 1592 constexpr bool IsByte = false; 1593 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName); 1594 return; 1595 } 1596 } 1597 } 1598 1599 void AssemblerARM32::emitMemExOp(CondARM32::Cond Cond, Type Ty, bool IsLoad, 1600 const Operand *OpRd, IValueT Rt, 1601 const Operand *OpAddress, 1602 const TargetInfo &TInfo, 1603 const char *InstName) { 1604 IValueT Rd = encodeGPRegister(OpRd, "Rd", InstName); 1605 IValueT MemExOpcode = IsLoad ? B0 : 0; 1606 switch (Ty) { 1607 default: 1608 llvm::report_fatal_error(std::string(InstName) + ": Type " + 1609 typeString(Ty) + " not allowed"); 1610 case IceType_i1: 1611 case IceType_i8: 1612 MemExOpcode |= B2; 1613 break; 1614 case IceType_i16: 1615 MemExOpcode |= B2 | B1; 1616 break; 1617 case IceType_i32: 1618 break; 1619 case IceType_i64: 1620 MemExOpcode |= B1; 1621 } 1622 IValueT AddressRn; 1623 if (encodeAddress(OpAddress, AddressRn, TInfo, NoImmOffsetAddress) != 1624 EncodedAsImmRegOffset) 1625 llvm::report_fatal_error(std::string(InstName) + 1626 ": Can't extract Rn from address"); 1627 assert(Utils::IsAbsoluteUint(3, MemExOpcode)); 1628 assert(Rd < RegARM32::getNumGPRegs()); 1629 assert(Rt < RegARM32::getNumGPRegs()); 1630 assert(CondARM32::isDefined(Cond)); 1631 IValueT Encoding = (Cond << kConditionShift) | B24 | B23 | B11 | B10 | B9 | 1632 B8 | B7 | B4 | (MemExOpcode << kMemExOpcodeShift) | 1633 AddressRn | (Rd << kRdShift) | (Rt << kRmShift); 1634 emitInst(Encoding); 1635 return; 1636 } 1637 1638 void AssemblerARM32::ldrex(const Operand *OpRt, const Operand *OpAddress, 1639 CondARM32::Cond Cond, const TargetInfo &TInfo) { 1640 // LDREXB - ARM section A8.8.76, encoding A1: 1641 // ldrexb<c> <Rt>, [<Rn>] 1642 // 1643 // cccc00011101nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn. 1644 // 1645 // LDREXH - ARM section A8.8.78, encoding A1: 1646 // ldrexh<c> <Rt>, [<Rn>] 1647 // 1648 // cccc00011111nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn. 1649 // 1650 // LDREX - ARM section A8.8.75, encoding A1: 1651 // ldrex<c> <Rt>, [<Rn>] 1652 // 1653 // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn. 1654 // 1655 // LDREXD - ARM section A8. 1656 // ldrexd<c> <Rt>, [<Rn>] 1657 // 1658 // cccc00011001nnnntttt111110011111 where cccc=Cond, tttt=Rt, and nnnn=Rn. 1659 constexpr const char *LdrexName = "ldrex"; 1660 const Type Ty = OpRt->getType(); 1661 constexpr bool IsLoad = true; 1662 constexpr IValueT Rm = RegARM32::Encoded_Reg_pc; 1663 emitMemExOp(Cond, Ty, IsLoad, OpRt, Rm, OpAddress, TInfo, LdrexName); 1664 } 1665 1666 void AssemblerARM32::emitShift(const CondARM32::Cond Cond, 1667 const OperandARM32::ShiftKind Shift, 1668 const Operand *OpRd, const Operand *OpRm, 1669 const Operand *OpSrc1, const bool SetFlags, 1670 const char *InstName) { 1671 constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101 1672 IValueT Rd = encodeGPRegister(OpRd, "Rd", InstName); 1673 IValueT Rm = encodeGPRegister(OpRm, "Rm", InstName); 1674 IValueT Value; 1675 switch (encodeOperand(OpSrc1, Value, WantGPRegs)) { 1676 default: 1677 llvm::report_fatal_error(std::string(InstName) + 1678 ": Last operand not understood"); 1679 case EncodedAsShiftImm5: { 1680 // XXX (immediate) 1681 // xxx{s}<c> <Rd>, <Rm>, #imm5 1682 // 1683 // cccc0001101s0000ddddiiiii000mmmm where cccc=Cond, s=SetFlags, dddd=Rd, 1684 // iiiii=imm5, and mmmm=Rm. 1685 constexpr IValueT Rn = 0; // Rn field is not used. 1686 Value = Value | (Rm << kRmShift) | (Shift << kShiftShift); 1687 emitType01(Cond, kInstTypeDataRegShift, ShiftOpcode, SetFlags, Rn, Rd, 1688 Value, RdIsPcAndSetFlags, InstName); 1689 return; 1690 } 1691 case EncodedAsRegister: { 1692 // XXX (register) 1693 // xxx{S}<c> <Rd>, <Rm>, <Rs> 1694 // 1695 // cccc0001101s0000ddddssss0001mmmm where cccc=Cond, s=SetFlags, dddd=Rd, 1696 // mmmm=Rm, and ssss=Rs. 1697 constexpr IValueT Rn = 0; // Rn field is not used. 1698 IValueT Rs = encodeGPRegister(OpSrc1, "Rs", InstName); 1699 verifyRegNotPc(Rd, "Rd", InstName); 1700 verifyRegNotPc(Rm, "Rm", InstName); 1701 verifyRegNotPc(Rs, "Rs", InstName); 1702 emitType01(Cond, kInstTypeDataRegShift, ShiftOpcode, SetFlags, Rn, Rd, 1703 encodeShiftRotateReg(Rm, Shift, Rs), NoChecks, InstName); 1704 return; 1705 } 1706 } 1707 } 1708 1709 void AssemblerARM32::asr(const Operand *OpRd, const Operand *OpRm, 1710 const Operand *OpSrc1, bool SetFlags, 1711 CondARM32::Cond Cond) { 1712 constexpr const char *AsrName = "asr"; 1713 emitShift(Cond, OperandARM32::ASR, OpRd, OpRm, OpSrc1, SetFlags, AsrName); 1714 } 1715 1716 void AssemblerARM32::lsl(const Operand *OpRd, const Operand *OpRm, 1717 const Operand *OpSrc1, bool SetFlags, 1718 CondARM32::Cond Cond) { 1719 constexpr const char *LslName = "lsl"; 1720 emitShift(Cond, OperandARM32::LSL, OpRd, OpRm, OpSrc1, SetFlags, LslName); 1721 } 1722 1723 void AssemblerARM32::lsr(const Operand *OpRd, const Operand *OpRm, 1724 const Operand *OpSrc1, bool SetFlags, 1725 CondARM32::Cond Cond) { 1726 constexpr const char *LsrName = "lsr"; 1727 emitShift(Cond, OperandARM32::LSR, OpRd, OpRm, OpSrc1, SetFlags, LsrName); 1728 } 1729 1730 void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, 1731 CondARM32::Cond Cond) { 1732 // MOV (register) - ARM section A8.8.104, encoding A1: 1733 // mov{S}<c> <Rd>, <Rn> 1734 // 1735 // cccc0001101s0000dddd00000000mmmm where cccc=Cond, s=SetFlags, dddd=Rd, 1736 // and nnnn=Rn. 1737 // 1738 // MOV (immediate) - ARM section A8.8.102, encoding A1: 1739 // mov{S}<c> <Rd>, #<RotatedImm8> 1740 // 1741 // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, 1742 // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this 1743 // assembler. 1744 constexpr const char *MovName = "mov"; 1745 IValueT Rd = encodeGPRegister(OpRd, "Rd", MovName); 1746 constexpr bool SetFlags = false; 1747 constexpr IValueT Rn = 0; 1748 constexpr IValueT MovOpcode = B3 | B2 | B0; // 1101. 1749 emitType01(Cond, MovOpcode, Rd, Rn, OpSrc, SetFlags, RdIsPcAndSetFlags, 1750 MovName); 1751 } 1752 1753 void AssemblerARM32::emitMovwt(CondARM32::Cond Cond, bool IsMovW, 1754 const Operand *OpRd, const Operand *OpSrc, 1755 const char *MovName) { 1756 IValueT Opcode = B25 | B24 | (IsMovW ? 0 : B22); 1757 IValueT Rd = encodeGPRegister(OpRd, "Rd", MovName); 1758 IValueT Imm16; 1759 if (const auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc)) { 1760 emitFixup(createMoveFixup(IsMovW, Src)); 1761 // Use 0 for the lower 16 bits of the relocatable, and add a fixup to 1762 // install the correct bits. 1763 Imm16 = 0; 1764 } else if (encodeOperand(OpSrc, Imm16, WantGPRegs) != EncodedAsConstI32) { 1765 llvm::report_fatal_error(std::string(MovName) + ": Not i32 constant"); 1766 } 1767 assert(CondARM32::isDefined(Cond)); 1768 if (!Utils::IsAbsoluteUint(16, Imm16)) 1769 llvm::report_fatal_error(std::string(MovName) + ": Constant not i16"); 1770 const IValueT Encoding = encodeCondition(Cond) << kConditionShift | Opcode | 1771 ((Imm16 >> 12) << 16) | Rd << kRdShift | 1772 (Imm16 & 0xfff); 1773 emitInst(Encoding); 1774 } 1775 1776 void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc, 1777 CondARM32::Cond Cond) { 1778 // MOV (immediate) - ARM section A8.8.102, encoding A2: 1779 // movw<c> <Rd>, #<imm16> 1780 // 1781 // cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and 1782 // iiiiiiiiiiiiiiii=imm16. 1783 constexpr const char *MovwName = "movw"; 1784 constexpr bool IsMovW = true; 1785 emitMovwt(Cond, IsMovW, OpRd, OpSrc, MovwName); 1786 } 1787 1788 void AssemblerARM32::movt(const Operand *OpRd, const Operand *OpSrc, 1789 CondARM32::Cond Cond) { 1790 // MOVT - ARM section A8.8.106, encoding A1: 1791 // movt<c> <Rd>, #<imm16> 1792 // 1793 // cccc00110100iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and 1794 // iiiiiiiiiiiiiiii=imm16. 1795 constexpr const char *MovtName = "movt"; 1796 constexpr bool IsMovW = false; 1797 emitMovwt(Cond, IsMovW, OpRd, OpSrc, MovtName); 1798 } 1799 1800 void AssemblerARM32::mvn(const Operand *OpRd, const Operand *OpSrc, 1801 CondARM32::Cond Cond) { 1802 // MVN (immediate) - ARM section A8.8.115, encoding A1: 1803 // mvn{s}<c> <Rd>, #<const> 1804 // 1805 // cccc0011111s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags=0, dddd=Rd, 1806 // and iiiiiiiiiiii=const 1807 // 1808 // MVN (register) - ARM section A8.8.116, encoding A1: 1809 // mvn{s}<c> <Rd>, <Rm>{, <shift> 1810 // 1811 // cccc0001111s0000ddddiiiiitt0mmmm where cccc=Cond, s=SetFlags=0, dddd=Rd, 1812 // mmmm=Rm, iiii defines shift constant, and tt=ShiftKind. 1813 constexpr const char *MvnName = "mvn"; 1814 IValueT Rd = encodeGPRegister(OpRd, "Rd", MvnName); 1815 constexpr IValueT MvnOpcode = B3 | B2 | B1 | B0; // i.e. 1111 1816 constexpr IValueT Rn = 0; 1817 constexpr bool SetFlags = false; 1818 emitType01(Cond, MvnOpcode, Rd, Rn, OpSrc, SetFlags, RdIsPcAndSetFlags, 1819 MvnName); 1820 } 1821 1822 void AssemblerARM32::nop() { 1823 // NOP - Section A8.8.119, encoding A1: 1824 // nop<c> 1825 // 1826 // cccc0011001000001111000000000000 where cccc=Cond. 1827 constexpr CondARM32::Cond Cond = CondARM32::AL; 1828 const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B25 | 1829 B24 | B21 | B15 | B14 | B13 | B12; 1830 emitInst(Encoding); 1831 } 1832 1833 void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn, 1834 const Operand *OpSrc1, bool SetFlags, 1835 CondARM32::Cond Cond) { 1836 // SBC (register) - ARM section 18.8.162, encoding A1: 1837 // sbc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} 1838 // 1839 // cccc0000110snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, 1840 // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. 1841 // 1842 // SBC (Immediate) - ARM section A8.8.161, encoding A1: 1843 // sbc{s}<c> <Rd>, <Rn>, #<RotatedImm8> 1844 // 1845 // cccc0010110snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, 1846 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. 1847 constexpr const char *SbcName = "sbc"; 1848 constexpr IValueT SbcOpcode = B2 | B1; // 0110 1849 emitType01(Cond, SbcOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, 1850 SbcName); 1851 } 1852 1853 void AssemblerARM32::sdiv(const Operand *OpRd, const Operand *OpRn, 1854 const Operand *OpSrc1, CondARM32::Cond Cond) { 1855 // SDIV - ARM section A8.8.165, encoding A1. 1856 // sdiv<c> <Rd>, <Rn>, <Rm> 1857 // 1858 // cccc01110001dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and 1859 // mmmm=Rm. 1860 constexpr const char *SdivName = "sdiv"; 1861 IValueT Rd = encodeGPRegister(OpRd, "Rd", SdivName); 1862 IValueT Rn = encodeGPRegister(OpRn, "Rn", SdivName); 1863 IValueT Rm = encodeGPRegister(OpSrc1, "Rm", SdivName); 1864 verifyRegNotPc(Rd, "Rd", SdivName); 1865 verifyRegNotPc(Rn, "Rn", SdivName); 1866 verifyRegNotPc(Rm, "Rm", SdivName); 1867 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. 1868 constexpr IValueT SdivOpcode = 0; 1869 emitDivOp(Cond, SdivOpcode, Rd, Rn, Rm); 1870 } 1871 1872 void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, 1873 CondARM32::Cond Cond, const TargetInfo &TInfo) { 1874 constexpr const char *StrName = "str"; 1875 constexpr bool IsLoad = false; 1876 IValueT Rt = encodeGPRegister(OpRt, "Rt", StrName); 1877 const Type Ty = OpRt->getType(); 1878 switch (Ty) { 1879 case IceType_i64: 1880 // STRD is not implemented because target lowering handles i64 and double by 1881 // using two (32-bit) store instructions. Note: Intentionally drop to 1882 // default case. 1883 llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) + 1884 " not implemented"); 1885 default: 1886 llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) + 1887 " not allowed"); 1888 case IceType_i1: 1889 case IceType_i8: { 1890 // STRB (immediate) - ARM section A8.8.207, encoding A1: 1891 // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 1892 // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 1893 // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 1894 // 1895 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, 1896 // iiiiiiiiiiii=imm12, u=1 if +. 1897 constexpr bool IsByte = true; 1898 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); 1899 return; 1900 } 1901 case IceType_i16: { 1902 // STRH (immediate) - ARM section A8.*.217, encoding A1: 1903 // strh<c> <Rt>, [<Rn>{, #+/-<Imm8>}] 1904 // strh<c> <Rt>, [<Rn>], #+/-<Imm8> 1905 // strh<c> <Rt>, [<Rn>, #+/-<Imm8>]! 1906 // 1907 // cccc000pu1w0nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn, 1908 // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and 1909 // pu0w0nnnn0000iiiiiiiiiiii=Address. 1910 constexpr const char *Strh = "strh"; 1911 emitMemOpEnc3(Cond, B7 | B5 | B4, Rt, OpAddress, TInfo, Strh); 1912 return; 1913 } 1914 case IceType_i32: { 1915 // Note: Handles i32 and float stores. Target lowering handles i64 and 1916 // double by using two (32 bit) store instructions. 1917 // 1918 // STR (immediate) - ARM section A8.8.207, encoding A1: 1919 // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 1920 // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 1921 // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 1922 // 1923 // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn, 1924 // iiiiiiiiiiii=imm12, u=1 if +. 1925 constexpr bool IsByte = false; 1926 emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName); 1927 return; 1928 } 1929 } 1930 } 1931 1932 void AssemblerARM32::strex(const Operand *OpRd, const Operand *OpRt, 1933 const Operand *OpAddress, CondARM32::Cond Cond, 1934 const TargetInfo &TInfo) { 1935 // STREXB - ARM section A8.8.213, encoding A1: 1936 // strexb<c> <Rd>, <Rt>, [<Rn>] 1937 // 1938 // cccc00011100nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and 1939 // nnnn=Rn. 1940 // 1941 // STREXH - ARM section A8.8.215, encoding A1: 1942 // strexh<c> <Rd>, <Rt>, [<Rn>] 1943 // 1944 // cccc00011110nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and 1945 // nnnn=Rn. 1946 // 1947 // STREX - ARM section A8.8.212, encoding A1: 1948 // strex<c> <Rd>, <Rt>, [<Rn>] 1949 // 1950 // cccc00011000nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and 1951 // nnnn=Rn. 1952 // 1953 // STREXD - ARM section A8.8.214, encoding A1: 1954 // strexd<c> <Rd>, <Rt>, [<Rn>] 1955 // 1956 // cccc00011010nnnndddd11111001tttt where cccc=Cond, dddd=Rd, tttt=Rt, and 1957 // nnnn=Rn. 1958 constexpr const char *StrexName = "strex"; 1959 // Note: Rt uses Rm shift in encoding. 1960 IValueT Rt = encodeGPRegister(OpRt, "Rt", StrexName); 1961 const Type Ty = OpRt->getType(); 1962 constexpr bool IsLoad = true; 1963 emitMemExOp(Cond, Ty, !IsLoad, OpRd, Rt, OpAddress, TInfo, StrexName); 1964 } 1965 1966 void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, 1967 const Operand *OpSrc1, bool SetFlags, 1968 CondARM32::Cond Cond) { 1969 // ORR (register) - ARM Section A8.8.123, encoding A1: 1970 // orr{s}<c> <Rd>, <Rn>, <Rm> 1971 // 1972 // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, 1973 // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. 1974 // 1975 // ORR (register) - ARM Section A8.8.123, encoding A1: 1976 // orr{s}<c> <Rd>, <Rn>, #<RotatedImm8> 1977 // 1978 // cccc0001100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, 1979 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. 1980 constexpr const char *OrrName = "orr"; 1981 constexpr IValueT OrrOpcode = B3 | B2; // i.e. 1100 1982 emitType01(Cond, OrrOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, 1983 OrrName); 1984 } 1985 1986 void AssemblerARM32::pop(const Variable *OpRt, CondARM32::Cond Cond) { 1987 // POP - ARM section A8.8.132, encoding A2: 1988 // pop<c> {Rt} 1989 // 1990 // cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond. 1991 constexpr const char *Pop = "pop"; 1992 IValueT Rt = encodeGPRegister(OpRt, "Rt", Pop); 1993 verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Pop); 1994 // Same as load instruction. 1995 constexpr bool IsLoad = true; 1996 constexpr bool IsByte = false; 1997 constexpr IOffsetT MaxOffset = (1 << 8) - 1; 1998 constexpr IValueT NoShiftRight = 0; 1999 IValueT Address = 2000 encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize, 2001 OperandARM32Mem::PostIndex, MaxOffset, NoShiftRight); 2002 emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); 2003 } 2004 2005 void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) { 2006 // POP - ARM section A8.*.131, encoding A1: 2007 // pop<c> <registers> 2008 // 2009 // cccc100010111101rrrrrrrrrrrrrrrr where cccc=Cond and 2010 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). 2011 constexpr bool IsLoad = true; 2012 emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers); 2013 } 2014 2015 void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) { 2016 // PUSH - ARM section A8.8.133, encoding A2: 2017 // push<c> {Rt} 2018 // 2019 // cccc010100101101dddd000000000100 where dddd=Rt and cccc=Cond. 2020 constexpr const char *Push = "push"; 2021 IValueT Rt = encodeGPRegister(OpRt, "Rt", Push); 2022 verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Push); 2023 // Same as store instruction. 2024 constexpr bool isLoad = false; 2025 constexpr bool isByte = false; 2026 constexpr IOffsetT MaxOffset = (1 << 8) - 1; 2027 constexpr IValueT NoShiftRight = 0; 2028 IValueT Address = 2029 encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize, 2030 OperandARM32Mem::PreIndex, MaxOffset, NoShiftRight); 2031 emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address); 2032 } 2033 2034 void AssemblerARM32::pushList(const IValueT Registers, CondARM32::Cond Cond) { 2035 // PUSH - ARM section A8.8.133, encoding A1: 2036 // push<c> <Registers> 2037 // 2038 // cccc100100101101rrrrrrrrrrrrrrrr where cccc=Cond and 2039 // rrrrrrrrrrrrrrrr=Registers (one bit for each GP register). 2040 constexpr bool IsLoad = false; 2041 emitMultiMemOp(Cond, DB_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers); 2042 } 2043 2044 void AssemblerARM32::mla(const Operand *OpRd, const Operand *OpRn, 2045 const Operand *OpRm, const Operand *OpRa, 2046 CondARM32::Cond Cond) { 2047 // MLA - ARM section A8.8.114, encoding A1. 2048 // mla{s}<c> <Rd>, <Rn>, <Rm>, <Ra> 2049 // 2050 // cccc0000001sddddaaaammmm1001nnnn where cccc=Cond, s=SetFlags, dddd=Rd, 2051 // aaaa=Ra, mmmm=Rm, and nnnn=Rn. 2052 constexpr const char *MlaName = "mla"; 2053 IValueT Rd = encodeGPRegister(OpRd, "Rd", MlaName); 2054 IValueT Rn = encodeGPRegister(OpRn, "Rn", MlaName); 2055 IValueT Rm = encodeGPRegister(OpRm, "Rm", MlaName); 2056 IValueT Ra = encodeGPRegister(OpRa, "Ra", MlaName); 2057 verifyRegNotPc(Rd, "Rd", MlaName); 2058 verifyRegNotPc(Rn, "Rn", MlaName); 2059 verifyRegNotPc(Rm, "Rm", MlaName); 2060 verifyRegNotPc(Ra, "Ra", MlaName); 2061 constexpr IValueT MlaOpcode = B21; 2062 constexpr bool SetFlags = true; 2063 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd. 2064 emitMulOp(Cond, MlaOpcode, Ra, Rd, Rn, Rm, !SetFlags); 2065 } 2066 2067 void AssemblerARM32::mls(const Operand *OpRd, const Operand *OpRn, 2068 const Operand *OpRm, const Operand *OpRa, 2069 CondARM32::Cond Cond) { 2070 constexpr const char *MlsName = "mls"; 2071 IValueT Rd = encodeGPRegister(OpRd, "Rd", MlsName); 2072 IValueT Rn = encodeGPRegister(OpRn, "Rn", MlsName); 2073 IValueT Rm = encodeGPRegister(OpRm, "Rm", MlsName); 2074 IValueT Ra = encodeGPRegister(OpRa, "Ra", MlsName); 2075 verifyRegNotPc(Rd, "Rd", MlsName); 2076 verifyRegNotPc(Rn, "Rn", MlsName); 2077 verifyRegNotPc(Rm, "Rm", MlsName); 2078 verifyRegNotPc(Ra, "Ra", MlsName); 2079 constexpr IValueT MlsOpcode = B22 | B21; 2080 constexpr bool SetFlags = true; 2081 // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd. 2082 emitMulOp(Cond, MlsOpcode, Ra, Rd, Rn, Rm, !SetFlags); 2083 } 2084 2085 void AssemblerARM32::mul(const Operand *OpRd, const Operand *OpRn, 2086 const Operand *OpSrc1, bool SetFlags, 2087 CondARM32::Cond Cond) { 2088 // MUL - ARM section A8.8.114, encoding A1. 2089 // mul{s}<c> <Rd>, <Rn>, <Rm> 2090 // 2091 // cccc0000000sdddd0000mmmm1001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, 2092 // mmmm=Rm, and s=SetFlags. 2093 constexpr const char *MulName = "mul"; 2094 IValueT Rd = encodeGPRegister(OpRd, "Rd", MulName); 2095 IValueT Rn = encodeGPRegister(OpRn, "Rn", MulName); 2096 IValueT Rm = encodeGPRegister(OpSrc1, "Rm", MulName); 2097 verifyRegNotPc(Rd, "Rd", MulName); 2098 verifyRegNotPc(Rn, "Rn", MulName); 2099 verifyRegNotPc(Rm, "Rm", MulName); 2100 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. 2101 constexpr IValueT MulOpcode = 0; 2102 emitMulOp(Cond, MulOpcode, RegARM32::Encoded_Reg_r0, Rd, Rn, Rm, SetFlags); 2103 } 2104 2105 void AssemblerARM32::emitRdRm(CondARM32::Cond Cond, IValueT Opcode, 2106 const Operand *OpRd, const Operand *OpRm, 2107 const char *InstName) { 2108 IValueT Rd = encodeGPRegister(OpRd, "Rd", InstName); 2109 IValueT Rm = encodeGPRegister(OpRm, "Rm", InstName); 2110 IValueT Encoding = 2111 (Cond << kConditionShift) | Opcode | (Rd << kRdShift) | (Rm << kRmShift); 2112 emitInst(Encoding); 2113 } 2114 2115 void AssemblerARM32::rbit(const Operand *OpRd, const Operand *OpRm, 2116 CondARM32::Cond Cond) { 2117 // RBIT - ARM section A8.8.144, encoding A1: 2118 // rbit<c> <Rd>, <Rm> 2119 // 2120 // cccc011011111111dddd11110011mmmm where cccc=Cond, dddd=Rn, and mmmm=Rm. 2121 constexpr const char *RbitName = "rev"; 2122 constexpr IValueT RbitOpcode = B26 | B25 | B23 | B22 | B21 | B20 | B19 | B18 | 2123 B17 | B16 | B11 | B10 | B9 | B8 | B5 | B4; 2124 emitRdRm(Cond, RbitOpcode, OpRd, OpRm, RbitName); 2125 } 2126 2127 void AssemblerARM32::rev(const Operand *OpRd, const Operand *OpRm, 2128 CondARM32::Cond Cond) { 2129 // REV - ARM section A8.8.145, encoding A1: 2130 // rev<c> <Rd>, <Rm> 2131 // 2132 // cccc011010111111dddd11110011mmmm where cccc=Cond, dddd=Rn, and mmmm=Rm. 2133 constexpr const char *RevName = "rev"; 2134 constexpr IValueT RevOpcode = B26 | B25 | B23 | B21 | B20 | B19 | B18 | B17 | 2135 B16 | B11 | B10 | B9 | B8 | B5 | B4; 2136 emitRdRm(Cond, RevOpcode, OpRd, OpRm, RevName); 2137 } 2138 2139 void AssemblerARM32::rsb(const Operand *OpRd, const Operand *OpRn, 2140 const Operand *OpSrc1, bool SetFlags, 2141 CondARM32::Cond Cond) { 2142 // RSB (immediate) - ARM section A8.8.152, encoding A1. 2143 // rsb{s}<c> <Rd>, <Rn>, #<RotatedImm8> 2144 // 2145 // cccc0010011snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, 2146 // s=setFlags and iiiiiiiiiiii defines the RotatedImm8 value. 2147 // 2148 // RSB (register) - ARM section A8.8.163, encoding A1. 2149 // rsb{s}<c> <Rd>, <Rn>, <Rm>{, <Shift>} 2150 // 2151 // cccc0000011snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, 2152 // mmmm=Rm, iiiii=shift, tt==ShiftKind, and s=SetFlags. 2153 constexpr const char *RsbName = "rsb"; 2154 constexpr IValueT RsbOpcode = B1 | B0; // 0011 2155 emitType01(Cond, RsbOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, 2156 RsbName); 2157 } 2158 2159 void AssemblerARM32::rsc(const Operand *OpRd, const Operand *OpRn, 2160 const Operand *OpSrc1, bool SetFlags, 2161 CondARM32::Cond Cond) { 2162 // RSC (immediate) - ARM section A8.8.155, encoding A1: 2163 // rsc{s}<c> <Rd>, <Rn>, #<RotatedImm8> 2164 // 2165 // cccc0010111snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, 2166 // mmmm=Rm, iiiii=shift, tt=ShiftKind, and s=SetFlags. 2167 // 2168 // RSC (register) - ARM section A8.8.156, encoding A1: 2169 // rsc{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} 2170 // 2171 // cccc0000111snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, 2172 // mmmm=Rm, iiiii=shift, tt=ShiftKind, and s=SetFlags. 2173 // 2174 // RSC (register-shifted register) - ARM section A8.8.157, encoding A1: 2175 // rsc{s}<c> <Rd>, <Rn>, <Rm>, <type> <Rs> 2176 // 2177 // cccc0000111fnnnnddddssss0tt1mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, 2178 // mmmm=Rm, ssss=Rs, tt defined <type>, and f=SetFlags. 2179 constexpr const char *RscName = "rsc"; 2180 constexpr IValueT RscOpcode = B2 | B1 | B0; // i.e. 0111. 2181 emitType01(Cond, RscOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, 2182 RscName); 2183 } 2184 2185 void AssemblerARM32::sxt(const Operand *OpRd, const Operand *OpSrc0, 2186 CondARM32::Cond Cond) { 2187 constexpr const char *SxtName = "sxt"; 2188 constexpr IValueT SxtOpcode = B26 | B25 | B23 | B21; 2189 emitSignExtend(Cond, SxtOpcode, OpRd, OpSrc0, SxtName); 2190 } 2191 2192 void AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, 2193 const Operand *OpSrc1, bool SetFlags, 2194 CondARM32::Cond Cond) { 2195 // SUB (register) - ARM section A8.8.223, encoding A1: 2196 // sub{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} 2197 // SUB (SP minus register): See ARM section 8.8.226, encoding A1: 2198 // sub{s}<c> <Rd>, sp, <Rm>{, <Shift>} 2199 // 2200 // cccc0000010snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, 2201 // mmmm=Rm, iiiii=shift, tt=ShiftKind, and s=SetFlags. 2202 // 2203 // Sub (Immediate) - ARM section A8.8.222, encoding A1: 2204 // sub{s}<c> <Rd>, <Rn>, #<RotatedImm8> 2205 // Sub (Sp minus immediate) - ARM section A8.8.225, encoding A1: 2206 // sub{s}<c> sp, <Rn>, #<RotatedImm8> 2207 // 2208 // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, 2209 // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8 2210 constexpr const char *SubName = "sub"; 2211 constexpr IValueT SubOpcode = B1; // 0010 2212 emitType01(Cond, SubOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags, 2213 SubName); 2214 } 2215 2216 namespace { 2217 2218 // Use a particular UDF encoding -- TRAPNaCl in LLVM: 0xE7FEDEF0 2219 // http://llvm.org/viewvc/llvm-project?view=revision&revision=173943 2220 const uint8_t TrapBytesRaw[] = {0xE7, 0xFE, 0xDE, 0xF0}; 2221 2222 const auto TrapBytes = 2223 llvm::ArrayRef<uint8_t>(TrapBytesRaw, llvm::array_lengthof(TrapBytesRaw)); 2224 2225 } // end of anonymous namespace 2226 2227 llvm::ArrayRef<uint8_t> AssemblerARM32::getNonExecBundlePadding() const { 2228 return TrapBytes; 2229 } 2230 2231 void AssemblerARM32::trap() { 2232 AssemblerBuffer::EnsureCapacity ensured(&Buffer); 2233 for (const uint8_t &Byte : reverse_range(TrapBytes)) 2234 Buffer.emit<uint8_t>(Byte); 2235 } 2236 2237 void AssemblerARM32::tst(const Operand *OpRn, const Operand *OpSrc1, 2238 CondARM32::Cond Cond) { 2239 // TST (register) - ARM section A8.8.241, encoding A1: 2240 // tst<c> <Rn>, <Rm>(, <shift>} 2241 // 2242 // cccc00010001nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, 2243 // iiiii=Shift, and tt=ShiftKind. 2244 // 2245 // TST (immediate) - ARM section A8.8.240, encoding A1: 2246 // tst<c> <Rn>, #<RotatedImm8> 2247 // 2248 // cccc00110001nnnn0000iiiiiiiiiiii where cccc=Cond, nnnn=Rn, and 2249 // iiiiiiiiiiii defines RotatedImm8. 2250 constexpr const char *TstName = "tst"; 2251 constexpr IValueT TstOpcode = B3; // ie. 1000 2252 emitCompareOp(Cond, TstOpcode, OpRn, OpSrc1, TstName); 2253 } 2254 2255 void AssemblerARM32::udiv(const Operand *OpRd, const Operand *OpRn, 2256 const Operand *OpSrc1, CondARM32::Cond Cond) { 2257 // UDIV - ARM section A8.8.248, encoding A1. 2258 // udiv<c> <Rd>, <Rn>, <Rm> 2259 // 2260 // cccc01110011dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and 2261 // mmmm=Rm. 2262 constexpr const char *UdivName = "udiv"; 2263 IValueT Rd = encodeGPRegister(OpRd, "Rd", UdivName); 2264 IValueT Rn = encodeGPRegister(OpRn, "Rn", UdivName); 2265 IValueT Rm = encodeGPRegister(OpSrc1, "Rm", UdivName); 2266 verifyRegNotPc(Rd, "Rd", UdivName); 2267 verifyRegNotPc(Rn, "Rn", UdivName); 2268 verifyRegNotPc(Rm, "Rm", UdivName); 2269 // Assembler registers rd, rn, rm are encoded as rn, rm, rs. 2270 constexpr IValueT UdivOpcode = B21; 2271 emitDivOp(Cond, UdivOpcode, Rd, Rn, Rm); 2272 } 2273 2274 void AssemblerARM32::umull(const Operand *OpRdLo, const Operand *OpRdHi, 2275 const Operand *OpRn, const Operand *OpRm, 2276 CondARM32::Cond Cond) { 2277 // UMULL - ARM section A8.8.257, encoding A1: 2278 // umull<c> <RdLo>, <RdHi>, <Rn>, <Rm> 2279 // 2280 // cccc0000100shhhhllllmmmm1001nnnn where hhhh=RdHi, llll=RdLo, nnnn=Rn, 2281 // mmmm=Rm, and s=SetFlags 2282 constexpr const char *UmullName = "umull"; 2283 IValueT RdLo = encodeGPRegister(OpRdLo, "RdLo", UmullName); 2284 IValueT RdHi = encodeGPRegister(OpRdHi, "RdHi", UmullName); 2285 IValueT Rn = encodeGPRegister(OpRn, "Rn", UmullName); 2286 IValueT Rm = encodeGPRegister(OpRm, "Rm", UmullName); 2287 verifyRegNotPc(RdLo, "RdLo", UmullName); 2288 verifyRegNotPc(RdHi, "RdHi", UmullName); 2289 verifyRegNotPc(Rn, "Rn", UmullName); 2290 verifyRegNotPc(Rm, "Rm", UmullName); 2291 verifyRegsNotEq(RdHi, "RdHi", RdLo, "RdLo", UmullName); 2292 constexpr IValueT UmullOpcode = B23; 2293 constexpr bool SetFlags = false; 2294 emitMulOp(Cond, UmullOpcode, RdLo, RdHi, Rn, Rm, SetFlags); 2295 } 2296 2297 void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0, 2298 CondARM32::Cond Cond) { 2299 constexpr const char *UxtName = "uxt"; 2300 constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21; 2301 emitSignExtend(Cond, UxtOpcode, OpRd, OpSrc0, UxtName); 2302 } 2303 2304 void AssemblerARM32::vabss(const Operand *OpSd, const Operand *OpSm, 2305 CondARM32::Cond Cond) { 2306 // VABS - ARM section A8.8.280, encoding A2: 2307 // vabs<c>.f32 <Sd>, <Sm> 2308 // 2309 // cccc11101D110000dddd101011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm. 2310 constexpr const char *Vabss = "vabss"; 2311 IValueT Sd = encodeSRegister(OpSd, "Sd", Vabss); 2312 IValueT Sm = encodeSRegister(OpSm, "Sm", Vabss); 2313 constexpr IValueT S0 = 0; 2314 constexpr IValueT VabssOpcode = B23 | B21 | B20 | B7 | B6; 2315 emitVFPsss(Cond, VabssOpcode, Sd, S0, Sm); 2316 } 2317 2318 void AssemblerARM32::vabsd(const Operand *OpDd, const Operand *OpDm, 2319 CondARM32::Cond Cond) { 2320 // VABS - ARM section A8.8.280, encoding A2: 2321 // vabs<c>.f64 <Dd>, <Dm> 2322 // 2323 // cccc11101D110000dddd101111M0mmmm where cccc=Cond, Ddddd=Dd, and Mmmmm=Dm. 2324 constexpr const char *Vabsd = "vabsd"; 2325 const IValueT Dd = encodeDRegister(OpDd, "Dd", Vabsd); 2326 const IValueT Dm = encodeDRegister(OpDm, "Dm", Vabsd); 2327 constexpr IValueT D0 = 0; 2328 constexpr IValueT VabsdOpcode = B23 | B21 | B20 | B7 | B6; 2329 emitVFPddd(Cond, VabsdOpcode, Dd, D0, Dm); 2330 } 2331 2332 void AssemblerARM32::vabsq(const Operand *OpQd, const Operand *OpQm) { 2333 // VABS - ARM section A8.8.280, encoding A1: 2334 // vabs.<dt> <Qd>, <Qm> 2335 // 2336 // 111100111D11ss01ddd0f1101M0mmm0 where Dddd=OpQd, Mddd=OpQm, and 2337 // <dt> in {s8, s16, s32, f32} and ss is the encoding of <dt>. 2338 const Type ElmtTy = typeElementType(OpQd->getType()); 2339 assert(ElmtTy != IceType_i64 && "vabsq doesn't allow i64!"); 2340 constexpr const char *Vabsq = "vabsq"; 2341 const IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Qd", Vabsq)); 2342 const IValueT Dm = mapQRegToDReg(encodeQRegister(OpQm, "Qm", Vabsq)); 2343 constexpr IValueT Dn = 0; 2344 const IValueT VabsqOpcode = 2345 B24 | B23 | B21 | B20 | B16 | B9 | B8 | (encodeElmtType(ElmtTy) << 18); 2346 constexpr bool UseQRegs = true; 2347 emitSIMDBase(VabsqOpcode, Dd, Dn, Dm, UseQRegs, isFloatingType(ElmtTy)); 2348 } 2349 2350 void AssemblerARM32::vadds(const Operand *OpSd, const Operand *OpSn, 2351 const Operand *OpSm, CondARM32::Cond Cond) { 2352 // VADD (floating-point) - ARM section A8.8.283, encoding A2: 2353 // vadd<c>.f32 <Sd>, <Sn>, <Sm> 2354 // 2355 // cccc11100D11nnnndddd101sN0M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn, 2356 // and mmmmM=Rm. 2357 constexpr const char *Vadds = "vadds"; 2358 constexpr IValueT VaddsOpcode = B21 | B20; 2359 emitVFPsss(Cond, VaddsOpcode, OpSd, OpSn, OpSm, Vadds); 2360 } 2361 2362 void AssemblerARM32::vaddqi(Type ElmtTy, const Operand *OpQd, 2363 const Operand *OpQm, const Operand *OpQn) { 2364 // VADD (integer) - ARM section A8.8.282, encoding A1: 2365 // vadd.<dt> <Qd>, <Qn>, <Qm> 2366 // 2367 // 111100100Dssnnn0ddd01000N1M0mmm0 where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm, 2368 // and dt in [i8, i16, i32, i64] where ss is the index. 2369 assert(isScalarIntegerType(ElmtTy) && 2370 "vaddqi expects vector with integer element type"); 2371 constexpr const char *Vaddqi = "vaddqi"; 2372 constexpr IValueT VaddqiOpcode = B11; 2373 emitSIMDqqq(VaddqiOpcode, ElmtTy, OpQd, OpQm, OpQn, Vaddqi); 2374 } 2375 2376 void AssemblerARM32::vaddqf(const Operand *OpQd, const Operand *OpQn, 2377 const Operand *OpQm) { 2378 // VADD (floating-point) - ARM section A8.8.283, Encoding A1: 2379 // vadd.f32 <Qd>, <Qn>, <Qm> 2380 // 2381 // 111100100D00nnn0ddd01101N1M0mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm. 2382 assert(OpQd->getType() == IceType_v4f32 && "vaddqf expects type <4 x float>"); 2383 constexpr const char *Vaddqf = "vaddqf"; 2384 constexpr IValueT VaddqfOpcode = B11 | B8; 2385 constexpr bool IsFloatTy = true; 2386 emitSIMDqqqBase(VaddqfOpcode, OpQd, OpQn, OpQm, IsFloatTy, Vaddqf); 2387 } 2388 2389 void AssemblerARM32::vaddd(const Operand *OpDd, const Operand *OpDn, 2390 const Operand *OpDm, CondARM32::Cond Cond) { 2391 // VADD (floating-point) - ARM section A8.8.283, encoding A2: 2392 // vadd<c>.f64 <Dd>, <Dn>, <Dm> 2393 // 2394 // cccc11100D11nnnndddd101sN0M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn, 2395 // and Mmmmm=Rm. 2396 constexpr const char *Vaddd = "vaddd"; 2397 constexpr IValueT VadddOpcode = B21 | B20; 2398 emitVFPddd(Cond, VadddOpcode, OpDd, OpDn, OpDm, Vaddd); 2399 } 2400 2401 void AssemblerARM32::vandq(const Operand *OpQd, const Operand *OpQm, 2402 const Operand *OpQn) { 2403 // VAND (register) - ARM section A8.8.287, encoding A1: 2404 // vand <Qd>, <Qn>, <Qm> 2405 // 2406 // 111100100D00nnn0ddd00001N1M1mmm0 where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm. 2407 constexpr const char *Vandq = "vandq"; 2408 constexpr IValueT VandqOpcode = B8 | B4; 2409 constexpr Type ElmtTy = IceType_i8; 2410 emitSIMDqqq(VandqOpcode, ElmtTy, OpQd, OpQm, OpQn, Vandq); 2411 } 2412 2413 void AssemblerARM32::vbslq(const Operand *OpQd, const Operand *OpQm, 2414 const Operand *OpQn) { 2415 // VBSL (register) - ARM section A8.8.290, encoding A1: 2416 // vbsl <Qd>, <Qn>, <Qm> 2417 // 2418 // 111100110D01nnn0ddd00001N1M1mmm0 where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm. 2419 constexpr const char *Vbslq = "vbslq"; 2420 constexpr IValueT VbslqOpcode = B24 | B20 | B8 | B4; 2421 constexpr Type ElmtTy = IceType_i8; // emits sz=0 2422 emitSIMDqqq(VbslqOpcode, ElmtTy, OpQd, OpQm, OpQn, Vbslq); 2423 } 2424 2425 void AssemblerARM32::vceqqi(const Type ElmtTy, const Operand *OpQd, 2426 const Operand *OpQm, const Operand *OpQn) { 2427 // vceq (register) - ARM section A8.8.291, encoding A1: 2428 // vceq.<st> <Qd>, <Qn>, <Qm> 2429 // 2430 // 111100110Dssnnnndddd1000NQM1mmmm where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm, and 2431 // st in [i8, i16, i32] where ss is the index. 2432 constexpr const char *Vceq = "vceq"; 2433 constexpr IValueT VceqOpcode = B24 | B11 | B4; 2434 emitSIMDqqq(VceqOpcode, ElmtTy, OpQd, OpQm, OpQn, Vceq); 2435 } 2436 2437 void AssemblerARM32::vceqqs(const Operand *OpQd, const Operand *OpQm, 2438 const Operand *OpQn) { 2439 // vceq (register) - ARM section A8.8.291, encoding A2: 2440 // vceq.f32 <Qd>, <Qn>, <Qm> 2441 // 2442 // 111100100D00nnnndddd1110NQM0mmmm where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm. 2443 constexpr const char *Vceq = "vceq"; 2444 constexpr IValueT VceqOpcode = B11 | B10 | B9; 2445 constexpr Type ElmtTy = IceType_i8; // encoded as 0b00 2446 emitSIMDqqq(VceqOpcode, ElmtTy, OpQd, OpQm, OpQn, Vceq); 2447 } 2448 2449 void AssemblerARM32::vcgeqi(const Type ElmtTy, const Operand *OpQd, 2450 const Operand *OpQm, const Operand *OpQn) { 2451 // vcge (register) - ARM section A8.8.293, encoding A1: 2452 // vcge.<st> <Qd>, <Qn>, <Qm> 2453 // 2454 // 1111001U0Dssnnnndddd0011NQM1mmmm where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm, 2455 // 0=U, and st in [s8, s16, s32] where ss is the index. 2456 constexpr const char *Vcge = "vcge"; 2457 constexpr IValueT VcgeOpcode = B9 | B8 | B4; 2458 emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge); 2459 } 2460 2461 void AssemblerARM32::vcugeqi(const Type ElmtTy, const Operand *OpQd, 2462 const Operand *OpQm, const Operand *OpQn) { 2463 // vcge (register) - ARM section A8.8.293, encoding A1: 2464 // vcge.<st> <Qd>, <Qn>, <Qm> 2465 // 2466 // 1111001U0Dssnnnndddd0011NQM1mmmm where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm, 2467 // 1=U, and st in [u8, u16, u32] where ss is the index. 2468 constexpr const char *Vcge = "vcge"; 2469 constexpr IValueT VcgeOpcode = B24 | B9 | B8 | B4; 2470 emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge); 2471 } 2472 2473 void AssemblerARM32::vcgeqs(const Operand *OpQd, const Operand *OpQm, 2474 const Operand *OpQn) { 2475 // vcge (register) - ARM section A8.8.293, encoding A2: 2476 // vcge.f32 <Qd>, <Qn>, <Qm> 2477 // 2478 // 111100110D00nnnndddd1110NQM0mmmm where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm. 2479 constexpr const char *Vcge = "vcge"; 2480 constexpr IValueT VcgeOpcode = B24 | B11 | B10 | B9; 2481 constexpr Type ElmtTy = IceType_i8; // encoded as 0b00. 2482 emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge); 2483 } 2484 2485 void AssemblerARM32::vcgtqi(const Type ElmtTy, const Operand *OpQd, 2486 const Operand *OpQm, const Operand *OpQn) { 2487 // vcgt (register) - ARM section A8.8.295, encoding A1: 2488 // vcgt.<st> <Qd>, <Qn>, <Qm> 2489 // 2490 // 1111001U0Dssnnnndddd0011NQM0mmmm where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm, 2491 // 0=U, and st in [s8, s16, s32] where ss is the index. 2492 constexpr const char *Vcge = "vcgt"; 2493 constexpr IValueT VcgeOpcode = B9 | B8; 2494 emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge); 2495 } 2496 2497 void AssemblerARM32::vcugtqi(const Type ElmtTy, const Operand *OpQd, 2498 const Operand *OpQm, const Operand *OpQn) { 2499 // vcgt (register) - ARM section A8.8.295, encoding A1: 2500 // vcgt.<st> <Qd>, <Qn>, <Qm> 2501 // 2502 // 111100110Dssnnnndddd0011NQM0mmmm where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm, 2503 // 1=U, and st in [u8, u16, u32] where ss is the index. 2504 constexpr const char *Vcge = "vcgt"; 2505 constexpr IValueT VcgeOpcode = B24 | B9 | B8; 2506 emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge); 2507 } 2508 2509 void AssemblerARM32::vcgtqs(const Operand *OpQd, const Operand *OpQm, 2510 const Operand *OpQn) { 2511 // vcgt (register) - ARM section A8.8.295, encoding A2: 2512 // vcgt.f32 <Qd>, <Qn>, <Qm> 2513 // 2514 // 111100110D10nnnndddd1110NQM0mmmm where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm. 2515 constexpr const char *Vcge = "vcgt"; 2516 constexpr IValueT VcgeOpcode = B24 | B21 | B11 | B10 | B9; 2517 constexpr Type ElmtTy = IceType_i8; // encoded as 0b00. 2518 emitSIMDqqq(VcgeOpcode, ElmtTy, OpQd, OpQm, OpQn, Vcge); 2519 } 2520 2521 void AssemblerARM32::vcmpd(const Operand *OpDd, const Operand *OpDm, 2522 CondARM32::Cond Cond) { 2523 constexpr const char *Vcmpd = "vcmpd"; 2524 IValueT Dd = encodeDRegister(OpDd, "Dd", Vcmpd); 2525 IValueT Dm = encodeDRegister(OpDm, "Dm", Vcmpd); 2526 constexpr IValueT VcmpdOpcode = B23 | B21 | B20 | B18 | B6; 2527 constexpr IValueT Dn = 0; 2528 emitVFPddd(Cond, VcmpdOpcode, Dd, Dn, Dm); 2529 } 2530 2531 void AssemblerARM32::vcmpdz(const Operand *OpDd, CondARM32::Cond Cond) { 2532 constexpr const char *Vcmpdz = "vcmpdz"; 2533 IValueT Dd = encodeDRegister(OpDd, "Dd", Vcmpdz); 2534 constexpr IValueT VcmpdzOpcode = B23 | B21 | B20 | B18 | B16 | B6; 2535 constexpr IValueT Dn = 0; 2536 constexpr IValueT Dm = 0; 2537 emitVFPddd(Cond, VcmpdzOpcode, Dd, Dn, Dm); 2538 } 2539 2540 void AssemblerARM32::vcmps(const Operand *OpSd, const Operand *OpSm, 2541 CondARM32::Cond Cond) { 2542 constexpr const char *Vcmps = "vcmps"; 2543 IValueT Sd = encodeSRegister(OpSd, "Sd", Vcmps); 2544 IValueT Sm = encodeSRegister(OpSm, "Sm", Vcmps); 2545 constexpr IValueT VcmpsOpcode = B23 | B21 | B20 | B18 | B6; 2546 constexpr IValueT Sn = 0; 2547 emitVFPsss(Cond, VcmpsOpcode, Sd, Sn, Sm); 2548 } 2549 2550 void AssemblerARM32::vcmpsz(const Operand *OpSd, CondARM32::Cond Cond) { 2551 constexpr const char *Vcmpsz = "vcmps"; 2552 IValueT Sd = encodeSRegister(OpSd, "Sd", Vcmpsz); 2553 constexpr IValueT VcmpszOpcode = B23 | B21 | B20 | B18 | B16 | B6; 2554 constexpr IValueT Sn = 0; 2555 constexpr IValueT Sm = 0; 2556 emitVFPsss(Cond, VcmpszOpcode, Sd, Sn, Sm); 2557 } 2558 2559 void AssemblerARM32::emitVFPsd(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd, 2560 IValueT Dm) { 2561 assert(Sd < RegARM32::getNumSRegs()); 2562 assert(Dm < RegARM32::getNumDRegs()); 2563 assert(CondARM32::isDefined(Cond)); 2564 constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9; 2565 const IValueT Encoding = 2566 Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) | 2567 (getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sd) << 12) | 2568 (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm); 2569 emitInst(Encoding); 2570 } 2571 2572 void AssemblerARM32::vcvtdi(const Operand *OpDd, const Operand *OpSm, 2573 CondARM32::Cond Cond) { 2574 // VCVT (between floating-point and integer, Floating-point) 2575 // - ARM Section A8.8.306, encoding A1: 2576 // vcvt<c>.f64.s32 <Dd>, <Sm> 2577 // 2578 // cccc11101D111000dddd10111M0mmmm where cccc=Cond, Ddddd=Dd, and mmmmM=Sm. 2579 constexpr const char *Vcvtdi = "vcvtdi"; 2580 IValueT Dd = encodeDRegister(OpDd, "Dd", Vcvtdi); 2581 IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtdi); 2582 constexpr IValueT VcvtdiOpcode = B23 | B21 | B20 | B19 | B8 | B7 | B6; 2583 emitVFPds(Cond, VcvtdiOpcode, Dd, Sm); 2584 } 2585 2586 void AssemblerARM32::vcvtdu(const Operand *OpDd, const Operand *OpSm, 2587 CondARM32::Cond Cond) { 2588 // VCVT (between floating-point and integer, Floating-point) 2589 // - ARM Section A8.8.306, encoding A1: 2590 // vcvt<c>.f64.u32 <Dd>, <Sm> 2591 // 2592 // cccc11101D111000dddd10101M0mmmm where cccc=Cond, Ddddd=Dd, and mmmmM=Sm. 2593 constexpr const char *Vcvtdu = "vcvtdu"; 2594 IValueT Dd = encodeDRegister(OpDd, "Dd", Vcvtdu); 2595 IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtdu); 2596 constexpr IValueT VcvtduOpcode = B23 | B21 | B20 | B19 | B8 | B6; 2597 emitVFPds(Cond, VcvtduOpcode, Dd, Sm); 2598 } 2599 2600 void AssemblerARM32::vcvtsd(const Operand *OpSd, const Operand *OpDm, 2601 CondARM32::Cond Cond) { 2602 constexpr const char *Vcvtsd = "vcvtsd"; 2603 IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtsd); 2604 IValueT Dm = encodeDRegister(OpDm, "Dm", Vcvtsd); 2605 constexpr IValueT VcvtsdOpcode = 2606 B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6; 2607 emitVFPsd(Cond, VcvtsdOpcode, Sd, Dm); 2608 } 2609 2610 void AssemblerARM32::vcvtis(const Operand *OpSd, const Operand *OpSm, 2611 CondARM32::Cond Cond) { 2612 // VCVT (between floating-point and integer, Floating-point) 2613 // - ARM Section A8.8.306, encoding A1: 2614 // vcvt<c>.s32.f32 <Sd>, <Sm> 2615 // 2616 // cccc11101D111101dddd10011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm. 2617 constexpr const char *Vcvtis = "vcvtis"; 2618 IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtis); 2619 IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtis); 2620 constexpr IValueT VcvtisOpcode = B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6; 2621 constexpr IValueT S0 = 0; 2622 emitVFPsss(Cond, VcvtisOpcode, Sd, S0, Sm); 2623 } 2624 2625 void AssemblerARM32::vcvtid(const Operand *OpSd, const Operand *OpDm, 2626 CondARM32::Cond Cond) { 2627 // VCVT (between floating-point and integer, Floating-point) 2628 // - ARM Section A8.8.306, encoding A1: 2629 // vcvt<c>.s32.f64 <Sd>, <Dm> 2630 // 2631 // cccc11101D111101dddd10111M0mmmm where cccc=Cond, ddddD=Sd, and Mmmmm=Dm. 2632 constexpr const char *Vcvtid = "vcvtid"; 2633 IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtid); 2634 IValueT Dm = encodeDRegister(OpDm, "Dm", Vcvtid); 2635 constexpr IValueT VcvtidOpcode = 2636 B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6; 2637 emitVFPsd(Cond, VcvtidOpcode, Sd, Dm); 2638 } 2639 2640 void AssemblerARM32::vcvtsi(const Operand *OpSd, const Operand *OpSm, 2641 CondARM32::Cond Cond) { 2642 // VCVT (between floating-point and integer, Floating-point) 2643 // - ARM Section A8.8.306, encoding A1: 2644 // vcvt<c>.f32.s32 <Sd>, <Sm> 2645 // 2646 // cccc11101D111000dddd10011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm. 2647 constexpr const char *Vcvtsi = "vcvtsi"; 2648 IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtsi); 2649 IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtsi); 2650 constexpr IValueT VcvtsiOpcode = B23 | B21 | B20 | B19 | B7 | B6; 2651 constexpr IValueT S0 = 0; 2652 emitVFPsss(Cond, VcvtsiOpcode, Sd, S0, Sm); 2653 } 2654 2655 void AssemblerARM32::vcvtsu(const Operand *OpSd, const Operand *OpSm, 2656 CondARM32::Cond Cond) { 2657 // VCVT (between floating-point and integer, Floating-point) 2658 // - ARM Section A8.8.306, encoding A1: 2659 // vcvt<c>.f32.u32 <Sd>, <Sm> 2660 // 2661 // cccc11101D111000dddd10001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm. 2662 constexpr const char *Vcvtsu = "vcvtsu"; 2663 IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtsu); 2664 IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtsu); 2665 constexpr IValueT VcvtsuOpcode = B23 | B21 | B20 | B19 | B6; 2666 constexpr IValueT S0 = 0; 2667 emitVFPsss(Cond, VcvtsuOpcode, Sd, S0, Sm); 2668 } 2669 2670 void AssemblerARM32::vcvtud(const Operand *OpSd, const Operand *OpDm, 2671 CondARM32::Cond Cond) { 2672 // VCVT (between floating-point and integer, Floating-point) 2673 // - ARM Section A8.8.306, encoding A1: 2674 // vcvt<c>.u32.f64 <Sd>, <Dm> 2675 // 2676 // cccc11101D111100dddd10111M0mmmm where cccc=Cond, ddddD=Sd, and Mmmmm=Dm. 2677 constexpr const char *Vcvtud = "vcvtud"; 2678 IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtud); 2679 IValueT Dm = encodeDRegister(OpDm, "Dm", Vcvtud); 2680 constexpr IValueT VcvtudOpcode = B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6; 2681 emitVFPsd(Cond, VcvtudOpcode, Sd, Dm); 2682 } 2683 2684 void AssemblerARM32::vcvtus(const Operand *OpSd, const Operand *OpSm, 2685 CondARM32::Cond Cond) { 2686 // VCVT (between floating-point and integer, Floating-point) 2687 // - ARM Section A8.8.306, encoding A1: 2688 // vcvt<c>.u32.f32 <Sd>, <Sm> 2689 // 2690 // cccc11101D111100dddd10011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm. 2691 constexpr const char *Vcvtus = "vcvtus"; 2692 IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtus); 2693 IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtus); 2694 constexpr IValueT VcvtsiOpcode = B23 | B21 | B20 | B19 | B18 | B7 | B6; 2695 constexpr IValueT S0 = 0; 2696 emitVFPsss(Cond, VcvtsiOpcode, Sd, S0, Sm); 2697 } 2698 2699 void AssemblerARM32::vcvtqsi(const Operand *OpQd, const Operand *OpQm) { 2700 // VCVT (between floating-point and integer, Advanced SIMD) 2701 // - ARM Section A8.8.305, encoding A1: 2702 // vcvt<c>.f32.s32 <Qd>, <Qm> 2703 // 2704 // 111100111D11ss11dddd011ooQM0mmmm where Ddddd=Qd, Mmmmm=Qm, and 10=op. 2705 constexpr const char *Vcvtqsi = "vcvt.s32.f32"; 2706 constexpr IValueT VcvtqsiOpcode = B8; 2707 emitSIMDCvtqq(VcvtqsiOpcode, OpQd, OpQm, Vcvtqsi); 2708 } 2709 2710 void AssemblerARM32::vcvtqsu(const Operand *OpQd, const Operand *OpQm) { 2711 // VCVT (between floating-point and integer, Advanced SIMD) 2712 // - ARM Section A8.8.305, encoding A1: 2713 // vcvt<c>.f32.u32 <Qd>, <Qm> 2714 // 2715 // 111100111D11ss11dddd011ooQM0mmmm where Ddddd=Qd, Mmmmm=Qm, and 11=op. 2716 constexpr const char *Vcvtqsu = "vcvt.u32.f32"; 2717 constexpr IValueT VcvtqsuOpcode = B8 | B7; 2718 emitSIMDCvtqq(VcvtqsuOpcode, OpQd, OpQm, Vcvtqsu); 2719 } 2720 2721 void AssemblerARM32::vcvtqis(const Operand *OpQd, const Operand *OpQm) { 2722 // VCVT (between floating-point and integer, Advanced SIMD) 2723 // - ARM Section A8.8.305, encoding A1: 2724 // vcvt<c>.f32.s32 <Qd>, <Qm> 2725 // 2726 // 111100111D11ss11dddd011ooQM0mmmm where Ddddd=Qd, Mmmmm=Qm, and 01=op. 2727 constexpr const char *Vcvtqis = "vcvt.f32.s32"; 2728 constexpr IValueT VcvtqisOpcode = 0; 2729 emitSIMDCvtqq(VcvtqisOpcode, OpQd, OpQm, Vcvtqis); 2730 } 2731 2732 void AssemblerARM32::vcvtqus(const Operand *OpQd, const Operand *OpQm) { 2733 // VCVT (between floating-point and integer, Advanced SIMD) 2734 // - ARM Section A8.8.305, encoding A1: 2735 // vcvt<c>.f32.u32 <Qd>, <Qm> 2736 // 2737 // 111100111D11ss11dddd011ooQM0mmmm where Ddddd=Qd, Mmmmm=Qm, and 01=op. 2738 constexpr const char *Vcvtqus = "vcvt.f32.u32"; 2739 constexpr IValueT VcvtqusOpcode = B7; 2740 emitSIMDCvtqq(VcvtqusOpcode, OpQd, OpQm, Vcvtqus); 2741 } 2742 2743 void AssemblerARM32::emitVFPds(CondARM32::Cond Cond, IValueT Opcode, IValueT Dd, 2744 IValueT Sm) { 2745 assert(Dd < RegARM32::getNumDRegs()); 2746 assert(Sm < RegARM32::getNumSRegs()); 2747 assert(CondARM32::isDefined(Cond)); 2748 constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9; 2749 const IValueT Encoding = 2750 Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) | 2751 (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dd) << 12) | 2752 (getYInRegXXXXY(Sm) << 5) | getXXXXInRegXXXXY(Sm); 2753 emitInst(Encoding); 2754 } 2755 2756 void AssemblerARM32::vcvtds(const Operand *OpDd, const Operand *OpSm, 2757 CondARM32::Cond Cond) { 2758 constexpr const char *Vcvtds = "Vctds"; 2759 IValueT Dd = encodeDRegister(OpDd, "Dd", Vcvtds); 2760 IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtds); 2761 constexpr IValueT VcvtdsOpcode = B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6; 2762 emitVFPds(Cond, VcvtdsOpcode, Dd, Sm); 2763 } 2764 2765 void AssemblerARM32::vdivs(const Operand *OpSd, const Operand *OpSn, 2766 const Operand *OpSm, CondARM32::Cond Cond) { 2767 // VDIV (floating-point) - ARM section A8.8.283, encoding A2: 2768 // vdiv<c>.f32 <Sd>, <Sn>, <Sm> 2769 // 2770 // cccc11101D00nnnndddd101sN0M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn, 2771 // and mmmmM=Rm. 2772 constexpr const char *Vdivs = "vdivs"; 2773 constexpr IValueT VdivsOpcode = B23; 2774 emitVFPsss(Cond, VdivsOpcode, OpSd, OpSn, OpSm, Vdivs); 2775 } 2776 2777 void AssemblerARM32::vdivd(const Operand *OpDd, const Operand *OpDn, 2778 const Operand *OpDm, CondARM32::Cond Cond) { 2779 // VDIV (floating-point) - ARM section A8.8.283, encoding A2: 2780 // vdiv<c>.f64 <Dd>, <Dn>, <Dm> 2781 // 2782 // cccc11101D00nnnndddd101sN0M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn, 2783 // and Mmmmm=Rm. 2784 constexpr const char *Vdivd = "vdivd"; 2785 constexpr IValueT VdivdOpcode = B23; 2786 emitVFPddd(Cond, VdivdOpcode, OpDd, OpDn, OpDm, Vdivd); 2787 } 2788 2789 void AssemblerARM32::veord(const Operand *OpDd, const Operand *OpDn, 2790 const Operand *OpDm) { 2791 // VEOR - ARM secdtion A8.8.315, encoding A1: 2792 // veor<c> <Dd>, <Dn>, <Dm> 2793 // 2794 // 111100110D00nnnndddd0001N0M1mmmm where Ddddd=Dd, Nnnnn=Dn, and Mmmmm=Dm. 2795 constexpr const char *Veord = "veord"; 2796 IValueT Dd = encodeDRegister(OpDd, "Dd", Veord); 2797 IValueT Dn = encodeDRegister(OpDn, "Dn", Veord); 2798 IValueT Dm = encodeDRegister(OpDm, "Dm", Veord); 2799 const IValueT Encoding = 2800 B25 | B24 | B8 | B4 | 2801 (encodeCondition(CondARM32::Cond::kNone) << kConditionShift) | 2802 (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) | 2803 (getXXXXInRegYXXXX(Dd) << 12) | (getYInRegYXXXX(Dn) << 7) | 2804 (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm); 2805 emitInst(Encoding); 2806 } 2807 2808 void AssemblerARM32::veorq(const Operand *OpQd, const Operand *OpQn, 2809 const Operand *OpQm) { 2810 // VEOR - ARM section A8.8.316, encoding A1: 2811 // veor <Qd>, <Qn>, <Qm> 2812 // 2813 // 111100110D00nnn0ddd00001N1M1mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm. 2814 constexpr const char *Veorq = "veorq"; 2815 constexpr IValueT VeorqOpcode = B24 | B8 | B4; 2816 emitSIMDqqq(VeorqOpcode, IceType_i8, OpQd, OpQn, OpQm, Veorq); 2817 } 2818 2819 void AssemblerARM32::vldrd(const Operand *OpDd, const Operand *OpAddress, 2820 CondARM32::Cond Cond, const TargetInfo &TInfo) { 2821 // VLDR - ARM section A8.8.333, encoding A1. 2822 // vldr<c> <Dd>, [<Rn>{, #+/-<imm>}] 2823 // 2824 // cccc1101UD01nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd, 2825 // iiiiiiii=abs(Imm >> 2), and U=1 if Opcode>=0. 2826 constexpr const char *Vldrd = "vldrd"; 2827 IValueT Dd = encodeDRegister(OpDd, "Dd", Vldrd); 2828 assert(CondARM32::isDefined(Cond)); 2829 IValueT Address; 2830 EncodedOperand AddressEncoding = 2831 encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address); 2832 (void)AddressEncoding; 2833 assert(AddressEncoding == EncodedAsImmRegOffset); 2834 IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | B8 | 2835 (encodeCondition(Cond) << kConditionShift) | 2836 (getYInRegYXXXX(Dd) << 22) | 2837 (getXXXXInRegYXXXX(Dd) << 12) | Address; 2838 emitInst(Encoding); 2839 } 2840 2841 void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress, 2842 CondARM32::Cond Cond, const TargetInfo &TInfo) { 2843 // VDLR - ARM section A8.8.333, encoding A2. 2844 // vldr<c> <Sd>, [<Rn>{, #+/-<imm>]] 2845 // 2846 // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd, 2847 // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0; 2848 constexpr const char *Vldrs = "vldrs"; 2849 IValueT Sd = encodeSRegister(OpSd, "Sd", Vldrs); 2850 assert(CondARM32::isDefined(Cond)); 2851 IValueT Address; 2852 EncodedOperand AddressEncoding = 2853 encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address); 2854 (void)AddressEncoding; 2855 assert(AddressEncoding == EncodedAsImmRegOffset); 2856 IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | 2857 (encodeCondition(Cond) << kConditionShift) | 2858 (getYInRegXXXXY(Sd) << 22) | 2859 (getXXXXInRegXXXXY(Sd) << 12) | Address; 2860 emitInst(Encoding); 2861 } 2862 2863 void AssemblerARM32::emitVMem1Op(IValueT Opcode, IValueT Dd, IValueT Rn, 2864 IValueT Rm, DRegListSize NumDRegs, 2865 size_t ElmtSize, IValueT Align, 2866 const char *InstName) { 2867 assert(Utils::IsAbsoluteUint(2, Align)); 2868 IValueT EncodedElmtSize; 2869 switch (ElmtSize) { 2870 default: { 2871 std::string Buffer; 2872 llvm::raw_string_ostream StrBuf(Buffer); 2873 StrBuf << InstName << ": found invalid vector element size " << ElmtSize; 2874 llvm::report_fatal_error(StrBuf.str()); 2875 } 2876 case 8: 2877 EncodedElmtSize = 0; 2878 break; 2879 case 16: 2880 EncodedElmtSize = 1; 2881 break; 2882 case 32: 2883 EncodedElmtSize = 2; 2884 break; 2885 case 64: 2886 EncodedElmtSize = 3; 2887 } 2888 const IValueT Encoding = 2889 Opcode | (encodeCondition(CondARM32::kNone) << kConditionShift) | 2890 (getYInRegYXXXX(Dd) << 22) | (Rn << kRnShift) | 2891 (getXXXXInRegYXXXX(Dd) << kRdShift) | (NumDRegs << 8) | 2892 (EncodedElmtSize << 6) | (Align << 4) | Rm; 2893 emitInst(Encoding); 2894 } 2895 2896 void AssemblerARM32::vld1qr(size_t ElmtSize, const Operand *OpQd, 2897 const Operand *OpAddress, const TargetInfo &TInfo) { 2898 // VLD1 (multiple single elements) - ARM section A8.8.320, encoding A1: 2899 // vld1.<size> <Qd>, [<Rn>] 2900 // 2901 // 111101000D10nnnnddd0ttttssaammmm where tttt=DRegListSize2, Dddd=Qd, 2902 // nnnn=Rn, aa=0 (use default alignment), size=ElmtSize, and ss is the 2903 // encoding of ElmtSize. 2904 constexpr const char *Vld1qr = "vld1qr"; 2905 const IValueT Qd = encodeQRegister(OpQd, "Qd", Vld1qr); 2906 const IValueT Dd = mapQRegToDReg(Qd); 2907 IValueT Address; 2908 if (encodeAddress(OpAddress, Address, TInfo, NoImmOffsetAddress) != 2909 EncodedAsImmRegOffset) 2910 llvm::report_fatal_error(std::string(Vld1qr) + ": malform memory address"); 2911 const IValueT Rn = mask(Address, kRnShift, 4); 2912 constexpr IValueT Rm = RegARM32::Reg_pc; 2913 constexpr IValueT Opcode = B26 | B21; 2914 constexpr IValueT Align = 0; // use default alignment. 2915 emitVMem1Op(Opcode, Dd, Rn, Rm, DRegListSize2, ElmtSize, Align, Vld1qr); 2916 } 2917 2918 bool AssemblerARM32::vmovqc(const Operand *OpQd, const ConstantInteger32 *Imm) { 2919 // VMOV (immediate) - ARM section A8.8.320, encoding A1: 2920 // VMOV.<dt> <Qd>, #<Imm> 2921 // 1111001x1D000yyyddddcccc01p1zzzz where Qd=Ddddd, Imm=xyyyzzzz, cmode=cccc, 2922 // and Op=p. 2923 constexpr const char *Vmovc = "vmovc"; 2924 const IValueT Dd = mapQRegToDReg(encodeQRegister(OpQd, "Qd", Vmovc)); 2925 IValueT Value = Imm->getValue(); 2926 const Type VecTy = OpQd->getType(); 2927 if (!isVectorType(VecTy)) 2928 return false; 2929 2930 IValueT Op; 2931 IValueT Cmode; 2932 IValueT Imm8; 2933 if (!encodeAdvSIMDExpandImm(Value, typeElementType(VecTy), Op, Cmode, Imm8)) 2934 return false; 2935 if (Op == 0 && mask(Cmode, 0, 1) == 1) 2936 return false; 2937 if (Op == 1 && Cmode != 13) 2938 return false; 2939 const IValueT Encoding = 2940 (0xF << kConditionShift) | B25 | B23 | B6 | B4 | 2941 (mask(Imm8, 7, 1) << 24) | (getYInRegYXXXX(Dd) << 22) | 2942 (mask(Imm8, 4, 3) << 16) | (getXXXXInRegYXXXX(Dd) << 12) | (Cmode << 8) | 2943 (Op << 5) | mask(Imm8, 0, 4); 2944 emitInst(Encoding); 2945 return true; 2946 } 2947 2948 void AssemblerARM32::vmovd(const Operand *OpDd, 2949 const OperandARM32FlexFpImm *OpFpImm, 2950 CondARM32::Cond Cond) { 2951 // VMOV (immediate) - ARM section A8.8.339, encoding A2: 2952 // vmov<c>.f64 <Dd>, #<imm> 2953 // 2954 // cccc11101D11xxxxdddd10110000yyyy where cccc=Cond, ddddD=Sn, xxxxyyyy=imm. 2955 constexpr const char *Vmovd = "vmovd"; 2956 IValueT Dd = encodeSRegister(OpDd, "Dd", Vmovd); 2957 IValueT Imm8 = OpFpImm->getModifiedImm(); 2958 assert(Imm8 < (1 << 8)); 2959 constexpr IValueT VmovsOpcode = B23 | B21 | B20 | B8; 2960 IValueT OpcodePlusImm8 = VmovsOpcode | ((Imm8 >> 4) << 16) | (Imm8 & 0xf); 2961 constexpr IValueT D0 = 0; 2962 emitVFPddd(Cond, OpcodePlusImm8, Dd, D0, D0); 2963 } 2964 2965 void AssemblerARM32::vmovdd(const Operand *OpDd, const Variable *OpDm, 2966 CondARM32::Cond Cond) { 2967 // VMOV (register) - ARM section A8.8.340, encoding A2: 2968 // vmov<c>.f64 <Dd>, <Sm> 2969 // 2970 // cccc11101D110000dddd101101M0mmmm where cccc=Cond, Ddddd=Sd, and Mmmmm=Sm. 2971 constexpr const char *Vmovdd = "Vmovdd"; 2972 IValueT Dd = encodeSRegister(OpDd, "Dd", Vmovdd); 2973 IValueT Dm = encodeSRegister(OpDm, "Dm", Vmovdd); 2974 constexpr IValueT VmovddOpcode = B23 | B21 | B20 | B6; 2975 constexpr IValueT D0 = 0; 2976 emitVFPddd(Cond, VmovddOpcode, Dd, D0, Dm); 2977 } 2978 2979 void AssemblerARM32::vmovdrr(const Operand *OpDm, const Operand *OpRt, 2980 const Operand *OpRt2, CondARM32::Cond Cond) { 2981 // VMOV (between two ARM core registers and a doubleword extension register). 2982 // ARM section A8.8.345, encoding A1: 2983 // vmov<c> <Dm>, <Rt>, <Rt2> 2984 // 2985 // cccc11000100xxxxyyyy101100M1mmmm where cccc=Cond, xxxx=Rt, yyyy=Rt2, and 2986 // Mmmmm=Dm. 2987 constexpr const char *Vmovdrr = "vmovdrr"; 2988 IValueT Dm = encodeDRegister(OpDm, "Dm", Vmovdrr); 2989 IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovdrr); 2990 IValueT Rt2 = encodeGPRegister(OpRt2, "Rt", Vmovdrr); 2991 assert(Rt != RegARM32::Encoded_Reg_sp); 2992 assert(Rt != RegARM32::Encoded_Reg_pc); 2993 assert(Rt2 != RegARM32::Encoded_Reg_sp); 2994 assert(Rt2 != RegARM32::Encoded_Reg_pc); 2995 assert(Rt != Rt2); 2996 assert(CondARM32::isDefined(Cond)); 2997 IValueT Encoding = B27 | B26 | B22 | B11 | B9 | B8 | B4 | 2998 (encodeCondition(Cond) << kConditionShift) | (Rt2 << 16) | 2999 (Rt << 12) | (getYInRegYXXXX(Dm) << 5) | 3000 getXXXXInRegYXXXX(Dm); 3001 emitInst(Encoding); 3002 } 3003 3004 void AssemblerARM32::vmovqir(const Operand *OpQn, uint32_t Index, 3005 const Operand *OpRt, CondARM32::Cond Cond) { 3006 // VMOV (ARM core register to scalar) - ARM section A8.8.341, encoding A1: 3007 // vmov<c>.<size> <Dn[x]>, <Rt> 3008 constexpr const char *Vmovdr = "vmovdr"; 3009 constexpr bool IsExtract = true; 3010 emitInsertExtractInt(Cond, OpQn, Index, OpRt, !IsExtract, Vmovdr); 3011 } 3012 3013 void AssemblerARM32::vmovqis(const Operand *OpQd, uint32_t Index, 3014 const Operand *OpSm, CondARM32::Cond Cond) { 3015 constexpr const char *Vmovqis = "vmovqis"; 3016 assert(Index < 4); 3017 IValueT Sd = mapQRegToSReg(encodeQRegister(OpQd, "Qd", Vmovqis)) + Index; 3018 IValueT Sm = encodeSRegister(OpSm, "Sm", Vmovqis); 3019 emitMoveSS(Cond, Sd, Sm); 3020 } 3021 3022 void AssemblerARM32::vmovrqi(const Operand *OpRt, const Operand *OpQn, 3023 uint32_t Index, CondARM32::Cond Cond) { 3024 // VMOV (scalar to ARM core register) - ARM section A8.8.342, encoding A1: 3025 // vmov<c>.<dt> <Rt>, <Dn[x]> 3026 constexpr const char *Vmovrd = "vmovrd"; 3027 constexpr bool IsExtract = true; 3028 emitInsertExtractInt(Cond, OpQn, Index, OpRt, IsExtract, Vmovrd); 3029 } 3030 3031 void AssemblerARM32::vmovrrd(const Operand *OpRt, const Operand *OpRt2, 3032 const Operand *OpDm, CondARM32::Cond Cond) { 3033 // VMOV (between two ARM core registers and a doubleword extension register). 3034 // ARM section A8.8.345, encoding A1: 3035 // vmov<c> <Rt>, <Rt2>, <Dm> 3036 // 3037 // cccc11000101xxxxyyyy101100M1mmmm where cccc=Cond, xxxx=Rt, yyyy=Rt2, and 3038 // Mmmmm=Dm. 3039 constexpr const char *Vmovrrd = "vmovrrd"; 3040 IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovrrd); 3041 IValueT Rt2 = encodeGPRegister(OpRt2, "Rt", Vmovrrd); 3042 IValueT Dm = encodeDRegister(OpDm, "Dm", Vmovrrd); 3043 assert(Rt != RegARM32::Encoded_Reg_sp); 3044 assert(Rt != RegARM32::Encoded_Reg_pc); 3045 assert(Rt2 != RegARM32::Encoded_Reg_sp); 3046 assert(Rt2 != RegARM32::Encoded_Reg_pc); 3047 assert(Rt != Rt2); 3048 assert(CondARM32::isDefined(Cond)); 3049 IValueT Encoding = B27 | B26 | B22 | B20 | B11 | B9 | B8 | B4 | 3050 (encodeCondition(Cond) << kConditionShift) | (Rt2 << 16) | 3051 (Rt << 12) | (getYInRegYXXXX(Dm) << 5) | 3052 getXXXXInRegYXXXX(Dm); 3053 emitInst(Encoding); 3054 } 3055 3056 void AssemblerARM32::vmovrs(const Operand *OpRt, const Operand *OpSn, 3057 CondARM32::Cond Cond) { 3058 // VMOV (between ARM core register and single-precision register) 3059 // ARM section A8.8.343, encoding A1. 3060 // 3061 // vmov<c> <Rt>, <Sn> 3062 // 3063 // cccc11100001nnnntttt1010N0010000 where cccc=Cond, nnnnN = Sn, and tttt=Rt. 3064 constexpr const char *Vmovrs = "vmovrs"; 3065 IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovrs); 3066 IValueT Sn = encodeSRegister(OpSn, "Sn", Vmovrs); 3067 assert(CondARM32::isDefined(Cond)); 3068 IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B27 | B26 | 3069 B25 | B20 | B11 | B9 | B4 | (getXXXXInRegXXXXY(Sn) << 16) | 3070 (Rt << kRdShift) | (getYInRegXXXXY(Sn) << 7); 3071 emitInst(Encoding); 3072 } 3073 3074 void AssemblerARM32::vmovs(const Operand *OpSd, 3075 const OperandARM32FlexFpImm *OpFpImm, 3076 CondARM32::Cond Cond) { 3077 // VMOV (immediate) - ARM section A8.8.339, encoding A2: 3078 // vmov<c>.f32 <Sd>, #<imm> 3079 // 3080 // cccc11101D11xxxxdddd10100000yyyy where cccc=Cond, ddddD=Sn, xxxxyyyy=imm. 3081 constexpr const char *Vmovs = "vmovs"; 3082 IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovs); 3083 IValueT Imm8 = OpFpImm->getModifiedImm(); 3084 assert(Imm8 < (1 << 8)); 3085 constexpr IValueT VmovsOpcode = B23 | B21 | B20; 3086 IValueT OpcodePlusImm8 = VmovsOpcode | ((Imm8 >> 4) << 16) | (Imm8 & 0xf); 3087 constexpr IValueT S0 = 0; 3088 emitVFPsss(Cond, OpcodePlusImm8, Sd, S0, S0); 3089 } 3090 3091 void AssemblerARM32::vmovss(const Operand *OpSd, const Variable *OpSm, 3092 CondARM32::Cond Cond) { 3093 constexpr const char *Vmovss = "Vmovss"; 3094 IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovss); 3095 IValueT Sm = encodeSRegister(OpSm, "Sm", Vmovss); 3096 emitMoveSS(Cond, Sd, Sm); 3097 } 3098 3099 void AssemblerARM32::vmovsqi(const Operand *OpSd, const Operand *OpQm, 3100 uint32_t Index, CondARM32::Cond Cond) { 3101 constexpr const char *Vmovsqi = "vmovsqi"; 3102 const IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovsqi); 3103 assert(Index < 4); 3104 const IValueT Sm = 3105 mapQRegToSReg(encodeQRegister(OpQm, "Qm", Vmovsqi)) + Index; 3106 emitMoveSS(Cond, Sd, Sm); 3107 } 3108 3109 void AssemblerARM32::vmovsr(const Operand *OpSn, const Operand *OpRt, 3110 CondARM32::Cond Cond) { 3111 // VMOV (between ARM core register and single-precision register) 3112 // ARM section A8.8.343, encoding A1. 3113 // 3114 // vmov<c> <Sn>, <Rt> 3115 // 3116 // cccc11100000nnnntttt1010N0010000 where cccc=Cond, nnnnN = Sn, and tttt=Rt. 3117 constexpr const char *Vmovsr = "vmovsr"; 3118 IValueT Sn = encodeSRegister(OpSn, "Sn", Vmovsr); 3119 IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovsr); 3120 assert(Sn < RegARM32::getNumSRegs()); 3121 assert(Rt < RegARM32::getNumGPRegs()); 3122 assert(CondARM32::isDefined(Cond)); 3123 IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B27 | B26 | 3124 B25 | B11 | B9 | B4 | (getXXXXInRegXXXXY(Sn) << 16) | 3125 (Rt << kRdShift) | (getYInRegXXXXY(Sn) << 7); 3126 emitInst(Encoding); 3127 } 3128 3129 void AssemblerARM32::vmlad(const Operand *OpDd, const Operand *OpDn, 3130 const Operand *OpDm, CondARM32::Cond Cond) { 3131 // VMLA, VMLS (floating-point), ARM section A8.8.337, encoding A2: 3132 // vmla<c>.f64 <Dd>, <Dn>, <Dm> 3133 // 3134 // cccc11100d00nnnndddd1011n0M0mmmm where cccc=Cond, Ddddd=Dd, Nnnnn=Dn, and 3135 // Mmmmm=Dm 3136 constexpr const char *Vmlad = "vmlad"; 3137 constexpr IValueT VmladOpcode = 0; 3138 emitVFPddd(Cond, VmladOpcode, OpDd, OpDn, OpDm, Vmlad); 3139 } 3140 3141 void AssemblerARM32::vmlas(const Operand *OpSd, const Operand *OpSn, 3142 const Operand *OpSm, CondARM32::Cond Cond) { 3143 // VMLA, VMLS (floating-point), ARM section A8.8.337, encoding A2: 3144 // vmla<c>.f32 <Sd>, <Sn>, <Sm> 3145 // 3146 // cccc11100d00nnnndddd1010n0M0mmmm where cccc=Cond, ddddD=Sd, nnnnN=Sn, and 3147 // mmmmM=Sm 3148 constexpr const char *Vmlas = "vmlas"; 3149 constexpr IValueT VmlasOpcode = 0; 3150 emitVFPsss(Cond, VmlasOpcode, OpSd, OpSn, OpSm, Vmlas); 3151 } 3152 3153 void AssemblerARM32::vmlsd(const Operand *OpDd, const Operand *OpDn, 3154 const Operand *OpDm, CondARM32::Cond Cond) { 3155 // VMLA, VMLS (floating-point), ARM section A8.8.337, encoding A2: 3156 // vmls<c>.f64 <Dd>, <Dn>, <Dm> 3157 // 3158 // cccc11100d00nnnndddd1011n1M0mmmm where cccc=Cond, Ddddd=Dd, Nnnnn=Dn, and 3159 // Mmmmm=Dm 3160 constexpr const char *Vmlad = "vmlad"; 3161 constexpr IValueT VmladOpcode = B6; 3162 emitVFPddd(Cond, VmladOpcode, OpDd, OpDn, OpDm, Vmlad); 3163 } 3164 3165 void AssemblerARM32::vmlss(const Operand *OpSd, const Operand *OpSn, 3166 const Operand *OpSm, CondARM32::Cond Cond) { 3167 // VMLA, VMLS (floating-point), ARM section A8.8.337, encoding A2: 3168 // vmls<c>.f32 <Sd>, <Sn>, <Sm> 3169 // 3170 // cccc11100d00nnnndddd1010n1M0mmmm where cccc=Cond, ddddD=Sd, nnnnN=Sn, and 3171 // mmmmM=Sm 3172 constexpr const char *Vmlas = "vmlas"; 3173 constexpr IValueT VmlasOpcode = B6; 3174 emitVFPsss(Cond, VmlasOpcode, OpSd, OpSn, OpSm, Vmlas); 3175 } 3176 3177 void AssemblerARM32::vmrsAPSR_nzcv(CondARM32::Cond Cond) { 3178 // MVRS - ARM section A*.8.348, encoding A1: 3179 // vmrs<c> APSR_nzcv, FPSCR 3180 // 3181 // cccc111011110001tttt101000010000 where tttt=0x15 (i.e. when Rt=pc, use 3182 // APSR_nzcv instead). 3183 assert(CondARM32::isDefined(Cond)); 3184 IValueT Encoding = B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 | B15 | B14 | 3185 B13 | B12 | B11 | B9 | B4 | 3186 (encodeCondition(Cond) << kConditionShift); 3187 emitInst(Encoding); 3188 } 3189 3190 void AssemblerARM32::vmuls(const Operand *OpSd, const Operand *OpSn, 3191 const Operand *OpSm, CondARM32::Cond Cond) { 3192 // VMUL (floating-point) - ARM section A8.8.351, encoding A2: 3193 // vmul<c>.f32 <Sd>, <Sn>, <Sm> 3194 // 3195 // cccc11100D10nnnndddd101sN0M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn, 3196 // and mmmmM=Rm. 3197 constexpr const char *Vmuls = "vmuls"; 3198 constexpr IValueT VmulsOpcode = B21; 3199 emitVFPsss(Cond, VmulsOpcode, OpSd, OpSn, OpSm, Vmuls); 3200 } 3201 3202 void AssemblerARM32::vmuld(const Operand *OpDd, const Operand *OpDn, 3203 const Operand *OpDm, CondARM32::Cond Cond) { 3204 // VMUL (floating-point) - ARM section A8.8.351, encoding A2: 3205 // vmul<c>.f64 <Dd>, <Dn>, <Dm> 3206 // 3207 // cccc11100D10nnnndddd101sN0M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn, 3208 // and Mmmmm=Rm. 3209 constexpr const char *Vmuld = "vmuld"; 3210 constexpr IValueT VmuldOpcode = B21; 3211 emitVFPddd(Cond, VmuldOpcode, OpDd, OpDn, OpDm, Vmuld); 3212 } 3213 3214 void AssemblerARM32::vmulqi(Type ElmtTy, const Operand *OpQd, 3215 const Operand *OpQn, const Operand *OpQm) { 3216 // VMUL, VMULL (integer and polynomial) - ARM section A8.8.350, encoding A1: 3217 // vmul<c>.<dt> <Qd>, <Qn>, <Qm> 3218 // 3219 // 111100100Dssnnn0ddd01001NqM1mmm0 where Dddd=Qd, Nnnn=Qn, Mmmm=Qm, and 3220 // dt in [i8, i16, i32] where ss is the index. 3221 assert(isScalarIntegerType(ElmtTy) && 3222 "vmulqi expects vector with integer element type"); 3223 assert(ElmtTy != IceType_i64 && "vmulqi on i64 vector not allowed"); 3224 constexpr const char *Vmulqi = "vmulqi"; 3225 constexpr IValueT VmulqiOpcode = B11 | B8 | B4; 3226 emitSIMDqqq(VmulqiOpcode, ElmtTy, OpQd, OpQn, OpQm, Vmulqi); 3227 } 3228 3229 void AssemblerARM32::vmulqf(const Operand *OpQd, const Operand *OpQn, 3230 const Operand *OpQm) { 3231 // VMUL (floating-point) - ARM section A8.8.351, encoding A1: 3232 // vmul.f32 <Qd>, <Qn>, <Qm> 3233 // 3234 // 111100110D00nnn0ddd01101MqM1mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm. 3235 assert(OpQd->getType() == IceType_v4f32 && "vmulqf expects type <4 x float>"); 3236 constexpr const char *Vmulqf = "vmulqf"; 3237 constexpr IValueT VmulqfOpcode = B24 | B11 | B8 | B4; 3238 constexpr bool IsFloatTy = true; 3239 emitSIMDqqqBase(VmulqfOpcode, OpQd, OpQn, OpQm, IsFloatTy, Vmulqf); 3240 } 3241 3242 void AssemblerARM32::vmvnq(const Operand *OpQd, const Operand *OpQm) { 3243 // VMVN (integer) - ARM section A8.8.354, encoding A1: 3244 // vmvn <Qd>, <Qm> 3245 // 3246 // 111100111D110000dddd01011QM0mmmm where Dddd=Qd, Mmmm=Qm, and 1=Q. 3247 // TODO(jpp) xxx: unify 3248 constexpr const char *Vmvn = "vmvn"; 3249 constexpr IValueT VmvnOpcode = B24 | B23 | B21 | B20 | B10 | B8 | B7; 3250 const IValueT Qd = encodeQRegister(OpQd, "Qd", Vmvn); 3251 constexpr IValueT Qn = 0; 3252 const IValueT Qm = encodeQRegister(OpQm, "Qm", Vmvn); 3253 constexpr bool UseQRegs = true; 3254 constexpr bool IsFloat = false; 3255 emitSIMDBase(VmvnOpcode, mapQRegToDReg(Qd), mapQRegToDReg(Qn), 3256 mapQRegToDReg(Qm), UseQRegs, IsFloat); 3257 } 3258 3259 void AssemblerARM32::vnegqs(Type ElmtTy, const Operand *OpQd, 3260 const Operand *OpQm) { 3261 // VNEG - ARM section A8.8.355, encoding A1: 3262 // vneg.<dt> <Qd>, <Qm> 3263 // 3264 // 111111111D11ss01dddd0F111QM0mmmm where Dddd=Qd, and Mmmm=Qm, and: 3265 // * dt=s8 -> 00=ss, 0=F 3266 // * dt=s16 -> 01=ss, 0=F 3267 // * dt=s32 -> 10=ss, 0=F 3268 // * dt=s32 -> 10=ss, 1=F 3269 constexpr const char *Vneg = "vneg"; 3270 constexpr IValueT VnegOpcode = B24 | B23 | B21 | B20 | B16 | B9 | B8 | B7; 3271 const IValueT Qd = encodeQRegister(OpQd, "Qd", Vneg); 3272 constexpr IValueT Qn = 0; 3273 const IValueT Qm = encodeQRegister(OpQm, "Qm", Vneg); 3274 constexpr bool UseQRegs = true; 3275 constexpr IValueT ElmtShift = 18; 3276 const IValueT ElmtSize = encodeElmtType(ElmtTy); 3277 assert(Utils::IsUint(2, ElmtSize)); 3278 emitSIMDBase(VnegOpcode | (ElmtSize << ElmtShift), mapQRegToDReg(Qd), 3279 mapQRegToDReg(Qn), mapQRegToDReg(Qm), UseQRegs, 3280 isFloatingType(ElmtTy)); 3281 } 3282 3283 void AssemblerARM32::vorrq(const Operand *OpQd, const Operand *OpQm, 3284 const Operand *OpQn) { 3285 // VORR (register) - ARM section A8.8.360, encoding A1: 3286 // vorr <Qd>, <Qn>, <Qm> 3287 // 3288 // 111100100D10nnn0ddd00001N1M1mmm0 where Dddd=OpQd, Nnnn=OpQm, and Mmmm=OpQm. 3289 constexpr const char *Vorrq = "vorrq"; 3290 constexpr IValueT VorrqOpcode = B21 | B8 | B4; 3291 constexpr Type ElmtTy = IceType_i8; 3292 emitSIMDqqq(VorrqOpcode, ElmtTy, OpQd, OpQm, OpQn, Vorrq); 3293 } 3294 3295 void AssemblerARM32::vstrd(const Operand *OpDd, const Operand *OpAddress, 3296 CondARM32::Cond Cond, const TargetInfo &TInfo) { 3297 // VSTR - ARM section A8.8.413, encoding A1: 3298 // vstr<c> <Dd>, [<Rn>{, #+/-<Imm>}] 3299 // 3300 // cccc1101UD00nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd, 3301 // iiiiiiii=abs(Imm >> 2), and U=1 if Imm>=0. 3302 constexpr const char *Vstrd = "vstrd"; 3303 IValueT Dd = encodeDRegister(OpDd, "Dd", Vstrd); 3304 assert(CondARM32::isDefined(Cond)); 3305 IValueT Address; 3306 IValueT AddressEncoding = 3307 encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address); 3308 (void)AddressEncoding; 3309 assert(AddressEncoding == EncodedAsImmRegOffset); 3310 IValueT Encoding = B27 | B26 | B24 | B11 | B9 | B8 | 3311 (encodeCondition(Cond) << kConditionShift) | 3312 (getYInRegYXXXX(Dd) << 22) | 3313 (getXXXXInRegYXXXX(Dd) << 12) | Address; 3314 emitInst(Encoding); 3315 } 3316 3317 void AssemblerARM32::vstrs(const Operand *OpSd, const Operand *OpAddress, 3318 CondARM32::Cond Cond, const TargetInfo &TInfo) { 3319 // VSTR - ARM section A8.8.413, encoding A2: 3320 // vstr<c> <Sd>, [<Rn>{, #+/-<imm>]] 3321 // 3322 // cccc1101UD01nnnndddd1010iiiiiiii where cccc=Cond, nnnn=Rn, ddddD=Sd, 3323 // iiiiiiii=abs(Opcode), and U=1 if Opcode >= 0; 3324 constexpr const char *Vstrs = "vstrs"; 3325 IValueT Sd = encodeSRegister(OpSd, "Sd", Vstrs); 3326 assert(CondARM32::isDefined(Cond)); 3327 IValueT Address; 3328 IValueT AddressEncoding = 3329 encodeAddress(OpAddress, Address, TInfo, RotatedImm8Div4Address); 3330 (void)AddressEncoding; 3331 assert(AddressEncoding == EncodedAsImmRegOffset); 3332 IValueT Encoding = 3333 B27 | B26 | B24 | B11 | B9 | (encodeCondition(Cond) << kConditionShift) | 3334 (getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sd) << 12) | Address; 3335 emitInst(Encoding); 3336 } 3337 3338 void AssemblerARM32::vst1qr(size_t ElmtSize, const Operand *OpQd, 3339 const Operand *OpAddress, const TargetInfo &TInfo) { 3340 // VST1 (multiple single elements) - ARM section A8.8.404, encoding A1: 3341 // vst1.<size> <Qd>, [<Rn>] 3342 // 3343 // 111101000D00nnnnddd0ttttssaammmm where tttt=DRegListSize2, Dddd=Qd, 3344 // nnnn=Rn, aa=0 (use default alignment), size=ElmtSize, and ss is the 3345 // encoding of ElmtSize. 3346 constexpr const char *Vst1qr = "vst1qr"; 3347 const IValueT Qd = encodeQRegister(OpQd, "Qd", Vst1qr); 3348 const IValueT Dd = mapQRegToDReg(Qd); 3349 IValueT Address; 3350 if (encodeAddress(OpAddress, Address, TInfo, NoImmOffsetAddress) != 3351 EncodedAsImmRegOffset) 3352 llvm::report_fatal_error(std::string(Vst1qr) + ": malform memory address"); 3353 const IValueT Rn = mask(Address, kRnShift, 4); 3354 constexpr IValueT Rm = RegARM32::Reg_pc; 3355 constexpr IValueT Opcode = B26; 3356 constexpr IValueT Align = 0; // use default alignment. 3357 emitVMem1Op(Opcode, Dd, Rn, Rm, DRegListSize2, ElmtSize, Align, Vst1qr); 3358 } 3359 3360 void AssemblerARM32::vsubs(const Operand *OpSd, const Operand *OpSn, 3361 const Operand *OpSm, CondARM32::Cond Cond) { 3362 // VSUB (floating-point) - ARM section A8.8.415, encoding A2: 3363 // vsub<c>.f32 <Sd>, <Sn>, <Sm> 3364 // 3365 // cccc11100D11nnnndddd101sN1M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn, 3366 // and mmmmM=Rm. 3367 constexpr const char *Vsubs = "vsubs"; 3368 constexpr IValueT VsubsOpcode = B21 | B20 | B6; 3369 emitVFPsss(Cond, VsubsOpcode, OpSd, OpSn, OpSm, Vsubs); 3370 } 3371 3372 void AssemblerARM32::vsubd(const Operand *OpDd, const Operand *OpDn, 3373 const Operand *OpDm, CondARM32::Cond Cond) { 3374 // VSUB (floating-point) - ARM section A8.8.415, encoding A2: 3375 // vsub<c>.f64 <Dd>, <Dn>, <Dm> 3376 // 3377 // cccc11100D11nnnndddd101sN1M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn, 3378 // and Mmmmm=Rm. 3379 constexpr const char *Vsubd = "vsubd"; 3380 constexpr IValueT VsubdOpcode = B21 | B20 | B6; 3381 emitVFPddd(Cond, VsubdOpcode, OpDd, OpDn, OpDm, Vsubd); 3382 } 3383 3384 void AssemblerARM32::vsubqi(Type ElmtTy, const Operand *OpQd, 3385 const Operand *OpQm, const Operand *OpQn) { 3386 // VSUB (integer) - ARM section A8.8.414, encoding A1: 3387 // vsub.<dt> <Qd>, <Qn>, <Qm> 3388 // 3389 // 111100110Dssnnn0ddd01000N1M0mmm0 where Dddd=OpQd, Nnnn=OpQm, Mmmm=OpQm, 3390 // and dt in [i8, i16, i32, i64] where ss is the index. 3391 assert(isScalarIntegerType(ElmtTy) && 3392 "vsubqi expects vector with integer element type"); 3393 constexpr const char *Vsubqi = "vsubqi"; 3394 constexpr IValueT VsubqiOpcode = B24 | B11; 3395 emitSIMDqqq(VsubqiOpcode, ElmtTy, OpQd, OpQm, OpQn, Vsubqi); 3396 } 3397 3398 void AssemblerARM32::vsubqf(const Operand *OpQd, const Operand *OpQn, 3399 const Operand *OpQm) { 3400 // VSUB (floating-point) - ARM section A8.8.415, Encoding A1: 3401 // vsub.f32 <Qd>, <Qn>, <Qm> 3402 // 3403 // 111100100D10nnn0ddd01101N1M0mmm0 where Dddd=Qd, Nnnn=Qn, and Mmmm=Qm. 3404 assert(OpQd->getType() == IceType_v4f32 && "vsubqf expects type <4 x float>"); 3405 constexpr const char *Vsubqf = "vsubqf"; 3406 constexpr IValueT VsubqfOpcode = B21 | B11 | B8; 3407 emitSIMDqqq(VsubqfOpcode, IceType_f32, OpQd, OpQn, OpQm, Vsubqf); 3408 } 3409 3410 void AssemblerARM32::emitVStackOp(CondARM32::Cond Cond, IValueT Opcode, 3411 const Variable *OpBaseReg, 3412 SizeT NumConsecRegs) { 3413 const IValueT BaseReg = getEncodedSRegNum(OpBaseReg); 3414 const IValueT DLastBit = mask(BaseReg, 0, 1); // Last bit of base register. 3415 const IValueT Rd = mask(BaseReg, 1, 4); // Top 4 bits of base register. 3416 assert(0 < NumConsecRegs); 3417 (void)VpushVpopMaxConsecRegs; 3418 assert(NumConsecRegs <= VpushVpopMaxConsecRegs); 3419 assert((BaseReg + NumConsecRegs) <= RegARM32::getNumSRegs()); 3420 assert(CondARM32::isDefined(Cond)); 3421 const IValueT Encoding = Opcode | (Cond << kConditionShift) | DLastBit | 3422 (Rd << kRdShift) | NumConsecRegs; 3423 emitInst(Encoding); 3424 } 3425 3426 void AssemblerARM32::vpop(const Variable *OpBaseReg, SizeT NumConsecRegs, 3427 CondARM32::Cond Cond) { 3428 // Note: Current implementation assumes that OpBaseReg is defined using S 3429 // registers. It doesn't implement the D register form. 3430 // 3431 // VPOP - ARM section A8.8.367, encoding A2: 3432 // vpop<c> <RegList> 3433 // 3434 // cccc11001D111101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and 3435 // iiiiiiii=NumConsecRegs. 3436 constexpr IValueT VpopOpcode = 3437 B27 | B26 | B23 | B21 | B20 | B19 | B18 | B16 | B11 | B9; 3438 emitVStackOp(Cond, VpopOpcode, OpBaseReg, NumConsecRegs); 3439 } 3440 3441 void AssemblerARM32::vpush(const Variable *OpBaseReg, SizeT NumConsecRegs, 3442 CondARM32::Cond Cond) { 3443 // Note: Current implementation assumes that OpBaseReg is defined using S 3444 // registers. It doesn't implement the D register form. 3445 // 3446 // VPUSH - ARM section A8.8.368, encoding A2: 3447 // vpush<c> <RegList> 3448 // 3449 // cccc11010D101101dddd1010iiiiiiii where cccc=Cond, ddddD=BaseReg, and 3450 // iiiiiiii=NumConsecRegs. 3451 constexpr IValueT VpushOpcode = 3452 B27 | B26 | B24 | B21 | B19 | B18 | B16 | B11 | B9; 3453 emitVStackOp(Cond, VpushOpcode, OpBaseReg, NumConsecRegs); 3454 } 3455 3456 void AssemblerARM32::vshlqi(Type ElmtTy, const Operand *OpQd, 3457 const Operand *OpQm, const Operand *OpQn) { 3458 // VSHL - ARM section A8.8.396, encoding A1: 3459 // vshl Qd, Qm, Qn 3460 // 3461 // 1111001U0Dssnnnndddd0100NQM0mmmm where Ddddd=Qd, Mmmmm=Qm, Nnnnn=Qn, 0=U, 3462 // 1=Q 3463 assert(isScalarIntegerType(ElmtTy) && 3464 "vshl expects vector with integer element type"); 3465 constexpr const char *Vshl = "vshl"; 3466 constexpr IValueT VshlOpcode = B10 | B6; 3467 emitSIMDqqq(VshlOpcode, ElmtTy, OpQd, OpQn, OpQm, Vshl); 3468 } 3469 3470 namespace { 3471 enum SIMDShiftType { ST_Vshl, ST_Vshr }; 3472 IValueT encodeSIMDShiftImm6(SIMDShiftType Shift, Type ElmtTy, 3473 const ConstantInteger32 *Imm6) { 3474 const IValueT Imm = Imm6->getValue(); 3475 assert(Imm > 0); 3476 const SizeT MaxShift = getScalarIntBitWidth(ElmtTy); 3477 assert(Imm < MaxShift); 3478 assert(ElmtTy == IceType_i8 || ElmtTy == IceType_i16 || 3479 ElmtTy == IceType_i32); 3480 const IValueT VshlImm = Imm - MaxShift; 3481 const IValueT VshrImm = 2 * MaxShift - Imm; 3482 return ((Shift == ST_Vshl) ? VshlImm : VshrImm) & (2 * MaxShift - 1); 3483 } 3484 } // end of anonymous namespace 3485 3486 void AssemblerARM32::vshlqc(Type ElmtTy, const Operand *OpQd, 3487 const Operand *OpQm, 3488 const ConstantInteger32 *Imm6) { 3489 // VSHL - ARM section A8.8.395, encoding A1: 3490 // vshl Qd, Qm, #Imm 3491 // 3492 // 1111001U1Diiiiiidddd0101LQM1mmmm where Ddddd=Qd, Mmmmm=Qm, iiiiii=Imm6, 3493 // 0=U, 1=Q, 0=L. 3494 assert(isScalarIntegerType(ElmtTy) && 3495 "vshl expects vector with integer element type"); 3496 constexpr const char *Vshl = "vshl"; 3497 constexpr IValueT VshlOpcode = B23 | B10 | B8 | B4; 3498 emitSIMDShiftqqc(VshlOpcode, OpQd, OpQm, 3499 encodeSIMDShiftImm6(ST_Vshl, ElmtTy, Imm6), Vshl); 3500 } 3501 3502 void AssemblerARM32::vshrqic(Type ElmtTy, const Operand *OpQd, 3503 const Operand *OpQm, 3504 const ConstantInteger32 *Imm6) { 3505 // VSHR - ARM section A8.8.398, encoding A1: 3506 // vshr Qd, Qm, #Imm 3507 // 3508 // 1111001U1Diiiiiidddd0101LQM1mmmm where Ddddd=Qd, Mmmmm=Qm, iiiiii=Imm6, 3509 // 0=U, 1=Q, 0=L. 3510 assert(isScalarIntegerType(ElmtTy) && 3511 "vshr expects vector with integer element type"); 3512 constexpr const char *Vshr = "vshr"; 3513 constexpr IValueT VshrOpcode = B23 | B4; 3514 emitSIMDShiftqqc(VshrOpcode, OpQd, OpQm, 3515 encodeSIMDShiftImm6(ST_Vshr, ElmtTy, Imm6), Vshr); 3516 } 3517 3518 void AssemblerARM32::vshrquc(Type ElmtTy, const Operand *OpQd, 3519 const Operand *OpQm, 3520 const ConstantInteger32 *Imm6) { 3521 // VSHR - ARM section A8.8.398, encoding A1: 3522 // vshr Qd, Qm, #Imm 3523 // 3524 // 1111001U1Diiiiiidddd0101LQM1mmmm where Ddddd=Qd, Mmmmm=Qm, iiiiii=Imm6, 3525 // 0=U, 1=Q, 0=L. 3526 assert(isScalarIntegerType(ElmtTy) && 3527 "vshr expects vector with integer element type"); 3528 constexpr const char *Vshr = "vshr"; 3529 constexpr IValueT VshrOpcode = B23 | B4; 3530 emitSIMDShiftqqc(VshrOpcode, OpQd, OpQm, 3531 encodeSIMDShiftImm6(ST_Vshr, ElmtTy, Imm6), Vshr); 3532 } 3533 3534 void AssemblerARM32::vshlqu(Type ElmtTy, const Operand *OpQd, 3535 const Operand *OpQm, const Operand *OpQn) { 3536 // VSHL - ARM section A8.8.396, encoding A1: 3537 // vshl Qd, Qm, Qn 3538 // 3539 // 1111001U0Dssnnnndddd0100NQM0mmmm where Ddddd=Qd, Mmmmm=Qm, Nnnnn=Qn, 1=U, 3540 // 1=Q 3541 assert(isScalarIntegerType(ElmtTy) && 3542 "vshl expects vector with integer element type"); 3543 constexpr const char *Vshl = "vshl"; 3544 constexpr IValueT VshlOpcode = B24 | B10 | B6; 3545 emitSIMDqqq(VshlOpcode, ElmtTy, OpQd, OpQn, OpQm, Vshl); 3546 } 3547 3548 void AssemblerARM32::vsqrtd(const Operand *OpDd, const Operand *OpDm, 3549 CondARM32::Cond Cond) { 3550 // VSQRT - ARM section A8.8.401, encoding A1: 3551 // vsqrt<c>.f64 <Dd>, <Dm> 3552 // 3553 // cccc11101D110001dddd101111M0mmmm where cccc=Cond, Ddddd=Sd, and Mmmmm=Sm. 3554 constexpr const char *Vsqrtd = "vsqrtd"; 3555 IValueT Dd = encodeDRegister(OpDd, "Dd", Vsqrtd); 3556 IValueT Dm = encodeDRegister(OpDm, "Dm", Vsqrtd); 3557 constexpr IValueT VsqrtdOpcode = B23 | B21 | B20 | B16 | B7 | B6; 3558 constexpr IValueT D0 = 0; 3559 emitVFPddd(Cond, VsqrtdOpcode, Dd, D0, Dm); 3560 } 3561 3562 void AssemblerARM32::vsqrts(const Operand *OpSd, const Operand *OpSm, 3563 CondARM32::Cond Cond) { 3564 // VSQRT - ARM section A8.8.401, encoding A1: 3565 // vsqrt<c>.f32 <Sd>, <Sm> 3566 // 3567 // cccc11101D110001dddd101011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm. 3568 constexpr const char *Vsqrts = "vsqrts"; 3569 IValueT Sd = encodeSRegister(OpSd, "Sd", Vsqrts); 3570 IValueT Sm = encodeSRegister(OpSm, "Sm", Vsqrts); 3571 constexpr IValueT VsqrtsOpcode = B23 | B21 | B20 | B16 | B7 | B6; 3572 constexpr IValueT S0 = 0; 3573 emitVFPsss(Cond, VsqrtsOpcode, Sd, S0, Sm); 3574 } 3575 3576 } // end of namespace ARM32 3577 } // end of namespace Ice 3578