1 //===- HexagonMCInstrInfo.cpp - Hexagon sub-class of MCInst ---------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This class extends MCInstrInfo to allow Hexagon specific MCInstr queries 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "MCTargetDesc/HexagonMCInstrInfo.h" 14 #include "MCTargetDesc/HexagonBaseInfo.h" 15 #include "MCTargetDesc/HexagonMCChecker.h" 16 #include "MCTargetDesc/HexagonMCExpr.h" 17 #include "MCTargetDesc/HexagonMCShuffler.h" 18 #include "MCTargetDesc/HexagonMCTargetDesc.h" 19 #include "llvm/ADT/SmallVector.h" 20 #include "llvm/ADT/StringSwitch.h" 21 #include "llvm/MC/MCContext.h" 22 #include "llvm/MC/MCExpr.h" 23 #include "llvm/MC/MCInst.h" 24 #include "llvm/MC/MCInstrInfo.h" 25 #include "llvm/MC/MCInstrItineraries.h" 26 #include "llvm/MC/MCSubtargetInfo.h" 27 #include "llvm/Support/Casting.h" 28 #include "llvm/Support/ErrorHandling.h" 29 #include <cassert> 30 #include <cstdint> 31 #include <limits> 32 33 using namespace llvm; 34 35 bool HexagonMCInstrInfo::PredicateInfo::isPredicated() const { 36 return Register != Hexagon::NoRegister; 37 } 38 39 Hexagon::PacketIterator::PacketIterator(MCInstrInfo const &MCII, 40 MCInst const &Inst) 41 : MCII(MCII), BundleCurrent(Inst.begin() + 42 HexagonMCInstrInfo::bundleInstructionsOffset), 43 BundleEnd(Inst.end()), DuplexCurrent(Inst.end()), DuplexEnd(Inst.end()) {} 44 45 Hexagon::PacketIterator::PacketIterator(MCInstrInfo const &MCII, 46 MCInst const &Inst, std::nullptr_t) 47 : MCII(MCII), BundleCurrent(Inst.end()), BundleEnd(Inst.end()), 48 DuplexCurrent(Inst.end()), DuplexEnd(Inst.end()) {} 49 50 Hexagon::PacketIterator &Hexagon::PacketIterator::operator++() { 51 if (DuplexCurrent != DuplexEnd) { 52 ++DuplexCurrent; 53 if (DuplexCurrent == DuplexEnd) { 54 DuplexCurrent = BundleEnd; 55 DuplexEnd = BundleEnd; 56 ++BundleCurrent; 57 } 58 return *this; 59 } 60 ++BundleCurrent; 61 if (BundleCurrent != BundleEnd) { 62 MCInst const &Inst = *BundleCurrent->getInst(); 63 if (HexagonMCInstrInfo::isDuplex(MCII, Inst)) { 64 DuplexCurrent = Inst.begin(); 65 DuplexEnd = Inst.end(); 66 } 67 } 68 return *this; 69 } 70 71 MCInst const &Hexagon::PacketIterator::operator*() const { 72 if (DuplexCurrent != DuplexEnd) 73 return *DuplexCurrent->getInst(); 74 return *BundleCurrent->getInst(); 75 } 76 77 bool Hexagon::PacketIterator::operator==(PacketIterator const &Other) const { 78 return BundleCurrent == Other.BundleCurrent && BundleEnd == Other.BundleEnd && 79 DuplexCurrent == Other.DuplexCurrent && DuplexEnd == Other.DuplexEnd; 80 } 81 82 void HexagonMCInstrInfo::addConstant(MCInst &MI, uint64_t Value, 83 MCContext &Context) { 84 MI.addOperand(MCOperand::createExpr(MCConstantExpr::create(Value, Context))); 85 } 86 87 void HexagonMCInstrInfo::addConstExtender(MCContext &Context, 88 MCInstrInfo const &MCII, MCInst &MCB, 89 MCInst const &MCI) { 90 assert(HexagonMCInstrInfo::isBundle(MCB)); 91 MCOperand const &exOp = 92 MCI.getOperand(HexagonMCInstrInfo::getExtendableOp(MCII, MCI)); 93 94 // Create the extender. 95 MCInst *XMCI = 96 new (Context) MCInst(HexagonMCInstrInfo::deriveExtender(MCII, MCI, exOp)); 97 XMCI->setLoc(MCI.getLoc()); 98 99 MCB.addOperand(MCOperand::createInst(XMCI)); 100 } 101 102 iterator_range<Hexagon::PacketIterator> 103 HexagonMCInstrInfo::bundleInstructions(MCInstrInfo const &MCII, 104 MCInst const &MCI) { 105 assert(isBundle(MCI)); 106 return make_range(Hexagon::PacketIterator(MCII, MCI), 107 Hexagon::PacketIterator(MCII, MCI, nullptr)); 108 } 109 110 iterator_range<MCInst::const_iterator> 111 HexagonMCInstrInfo::bundleInstructions(MCInst const &MCI) { 112 assert(isBundle(MCI)); 113 return make_range(MCI.begin() + bundleInstructionsOffset, MCI.end()); 114 } 115 116 size_t HexagonMCInstrInfo::bundleSize(MCInst const &MCI) { 117 if (HexagonMCInstrInfo::isBundle(MCI)) 118 return (MCI.size() - bundleInstructionsOffset); 119 else 120 return (1); 121 } 122 123 namespace { 124 bool canonicalizePacketImpl(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, 125 MCContext &Context, MCInst &MCB, 126 HexagonMCChecker *Check) { 127 // Check the bundle for errors. 128 bool CheckOk = Check ? Check->check(false) : true; 129 if (!CheckOk) 130 return false; 131 // Examine the packet and convert pairs of instructions to compound 132 // instructions when possible. 133 if (!HexagonDisableCompound) 134 HexagonMCInstrInfo::tryCompound(MCII, STI, Context, MCB); 135 HexagonMCShuffle(Context, false, MCII, STI, MCB); 136 137 // Examine the packet and convert pairs of instructions to duplex 138 // instructions when possible. 139 if (STI.getFeatureBits() [Hexagon::FeatureDuplex]) { 140 SmallVector<DuplexCandidate, 8> possibleDuplexes; 141 possibleDuplexes = 142 HexagonMCInstrInfo::getDuplexPossibilties(MCII, STI, MCB); 143 HexagonMCShuffle(Context, MCII, STI, MCB, possibleDuplexes); 144 } 145 // Examines packet and pad the packet, if needed, when an 146 // end-loop is in the bundle. 147 HexagonMCInstrInfo::padEndloop(MCB, Context); 148 // If compounding and duplexing didn't reduce the size below 149 // 4 or less we have a packet that is too big. 150 if (HexagonMCInstrInfo::bundleSize(MCB) > HEXAGON_PACKET_SIZE) { 151 if (Check) 152 Check->reportError("invalid instruction packet: out of slots"); 153 return false; 154 } 155 // Check the bundle for errors. 156 CheckOk = Check ? Check->check(true) : true; 157 if (!CheckOk) 158 return false; 159 HexagonMCShuffle(Context, true, MCII, STI, MCB); 160 return true; 161 } 162 } // namespace 163 164 bool HexagonMCInstrInfo::canonicalizePacket(MCInstrInfo const &MCII, 165 MCSubtargetInfo const &STI, 166 MCContext &Context, MCInst &MCB, 167 HexagonMCChecker *Check, 168 bool AttemptCompatibility) { 169 auto ArchSTI = Hexagon_MC::getArchSubtarget(&STI); 170 if (!AttemptCompatibility || ArchSTI == nullptr) 171 return canonicalizePacketImpl(MCII, STI, Context, MCB, Check); 172 173 const MCRegisterInfo *RI = Context.getRegisterInfo(); 174 HexagonMCChecker DefaultCheck(Context, MCII, STI, MCB, *RI, false); 175 HexagonMCChecker *BaseCheck = (Check == nullptr) ? &DefaultCheck : Check; 176 HexagonMCChecker PerfCheck(*BaseCheck, STI, false); 177 if (canonicalizePacketImpl(MCII, STI, Context, MCB, &PerfCheck)) 178 return true; 179 180 HexagonMCChecker ArchCheck(*BaseCheck, *ArchSTI, true); 181 return canonicalizePacketImpl(MCII, *ArchSTI, Context, MCB, &ArchCheck); 182 } 183 184 MCInst HexagonMCInstrInfo::deriveExtender(MCInstrInfo const &MCII, 185 MCInst const &Inst, 186 MCOperand const &MO) { 187 assert(HexagonMCInstrInfo::isExtendable(MCII, Inst) || 188 HexagonMCInstrInfo::isExtended(MCII, Inst)); 189 190 MCInst XMI; 191 XMI.setOpcode(Hexagon::A4_ext); 192 if (MO.isImm()) 193 XMI.addOperand(MCOperand::createImm(MO.getImm() & (~0x3f))); 194 else if (MO.isExpr()) 195 XMI.addOperand(MCOperand::createExpr(MO.getExpr())); 196 else 197 llvm_unreachable("invalid extendable operand"); 198 return XMI; 199 } 200 201 MCInst *HexagonMCInstrInfo::deriveDuplex(MCContext &Context, unsigned iClass, 202 MCInst const &inst0, 203 MCInst const &inst1) { 204 assert((iClass <= 0xf) && "iClass must have range of 0 to 0xf"); 205 MCInst *duplexInst = new (Context) MCInst; 206 duplexInst->setOpcode(Hexagon::DuplexIClass0 + iClass); 207 208 MCInst *SubInst0 = new (Context) MCInst(deriveSubInst(inst0)); 209 MCInst *SubInst1 = new (Context) MCInst(deriveSubInst(inst1)); 210 duplexInst->addOperand(MCOperand::createInst(SubInst0)); 211 duplexInst->addOperand(MCOperand::createInst(SubInst1)); 212 return duplexInst; 213 } 214 215 MCInst const *HexagonMCInstrInfo::extenderForIndex(MCInst const &MCB, 216 size_t Index) { 217 assert(Index <= bundleSize(MCB)); 218 if (Index == 0) 219 return nullptr; 220 MCInst const *Inst = 221 MCB.getOperand(Index + bundleInstructionsOffset - 1).getInst(); 222 if (isImmext(*Inst)) 223 return Inst; 224 return nullptr; 225 } 226 227 void HexagonMCInstrInfo::extendIfNeeded(MCContext &Context, 228 MCInstrInfo const &MCII, MCInst &MCB, 229 MCInst const &MCI) { 230 if (isConstExtended(MCII, MCI)) 231 addConstExtender(Context, MCII, MCB, MCI); 232 } 233 234 unsigned HexagonMCInstrInfo::getMemAccessSize(MCInstrInfo const &MCII, 235 MCInst const &MCI) { 236 uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 237 unsigned S = (F >> HexagonII::MemAccessSizePos) & HexagonII::MemAccesSizeMask; 238 return HexagonII::getMemAccessSizeInBytes(HexagonII::MemAccessSize(S)); 239 } 240 241 unsigned HexagonMCInstrInfo::getAddrMode(MCInstrInfo const &MCII, 242 MCInst const &MCI) { 243 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 244 return static_cast<unsigned>((F >> HexagonII::AddrModePos) & 245 HexagonII::AddrModeMask); 246 } 247 248 MCInstrDesc const &HexagonMCInstrInfo::getDesc(MCInstrInfo const &MCII, 249 MCInst const &MCI) { 250 return MCII.get(MCI.getOpcode()); 251 } 252 253 unsigned HexagonMCInstrInfo::getDuplexRegisterNumbering(unsigned Reg) { 254 using namespace Hexagon; 255 256 switch (Reg) { 257 default: 258 llvm_unreachable("unknown duplex register"); 259 // Rs Rss 260 case R0: 261 case D0: 262 return 0; 263 case R1: 264 case D1: 265 return 1; 266 case R2: 267 case D2: 268 return 2; 269 case R3: 270 case D3: 271 return 3; 272 case R4: 273 case D8: 274 return 4; 275 case R5: 276 case D9: 277 return 5; 278 case R6: 279 case D10: 280 return 6; 281 case R7: 282 case D11: 283 return 7; 284 case R16: 285 return 8; 286 case R17: 287 return 9; 288 case R18: 289 return 10; 290 case R19: 291 return 11; 292 case R20: 293 return 12; 294 case R21: 295 return 13; 296 case R22: 297 return 14; 298 case R23: 299 return 15; 300 } 301 } 302 303 MCExpr const &HexagonMCInstrInfo::getExpr(MCExpr const &Expr) { 304 const auto &HExpr = cast<HexagonMCExpr>(Expr); 305 assert(HExpr.getExpr()); 306 return *HExpr.getExpr(); 307 } 308 309 unsigned short HexagonMCInstrInfo::getExtendableOp(MCInstrInfo const &MCII, 310 MCInst const &MCI) { 311 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 312 return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask); 313 } 314 315 MCOperand const & 316 HexagonMCInstrInfo::getExtendableOperand(MCInstrInfo const &MCII, 317 MCInst const &MCI) { 318 unsigned O = HexagonMCInstrInfo::getExtendableOp(MCII, MCI); 319 MCOperand const &MO = MCI.getOperand(O); 320 321 assert((HexagonMCInstrInfo::isExtendable(MCII, MCI) || 322 HexagonMCInstrInfo::isExtended(MCII, MCI)) && 323 (MO.isImm() || MO.isExpr())); 324 return (MO); 325 } 326 327 unsigned HexagonMCInstrInfo::getExtentAlignment(MCInstrInfo const &MCII, 328 MCInst const &MCI) { 329 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 330 return ((F >> HexagonII::ExtentAlignPos) & HexagonII::ExtentAlignMask); 331 } 332 333 unsigned HexagonMCInstrInfo::getExtentBits(MCInstrInfo const &MCII, 334 MCInst const &MCI) { 335 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 336 return ((F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask); 337 } 338 339 bool HexagonMCInstrInfo::isExtentSigned(MCInstrInfo const &MCII, 340 MCInst const &MCI) { 341 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 342 return (F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask; 343 } 344 345 /// Return the maximum value of an extendable operand. 346 int HexagonMCInstrInfo::getMaxValue(MCInstrInfo const &MCII, 347 MCInst const &MCI) { 348 assert(HexagonMCInstrInfo::isExtendable(MCII, MCI) || 349 HexagonMCInstrInfo::isExtended(MCII, MCI)); 350 351 if (HexagonMCInstrInfo::isExtentSigned(MCII, MCI)) // if value is signed 352 return (1 << (HexagonMCInstrInfo::getExtentBits(MCII, MCI) - 1)) - 1; 353 return (1 << HexagonMCInstrInfo::getExtentBits(MCII, MCI)) - 1; 354 } 355 356 /// Return the minimum value of an extendable operand. 357 int HexagonMCInstrInfo::getMinValue(MCInstrInfo const &MCII, 358 MCInst const &MCI) { 359 assert(HexagonMCInstrInfo::isExtendable(MCII, MCI) || 360 HexagonMCInstrInfo::isExtended(MCII, MCI)); 361 362 if (HexagonMCInstrInfo::isExtentSigned(MCII, MCI)) // if value is signed 363 return -(1 << (HexagonMCInstrInfo::getExtentBits(MCII, MCI) - 1)); 364 return 0; 365 } 366 367 StringRef HexagonMCInstrInfo::getName(MCInstrInfo const &MCII, 368 MCInst const &MCI) { 369 return MCII.getName(MCI.getOpcode()); 370 } 371 372 unsigned short HexagonMCInstrInfo::getNewValueOp(MCInstrInfo const &MCII, 373 MCInst const &MCI) { 374 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 375 return ((F >> HexagonII::NewValueOpPos) & HexagonII::NewValueOpMask); 376 } 377 378 MCOperand const &HexagonMCInstrInfo::getNewValueOperand(MCInstrInfo const &MCII, 379 MCInst const &MCI) { 380 if (HexagonMCInstrInfo::hasTmpDst(MCII, MCI)) { 381 // VTMP doesn't actually exist in the encodings for these 184 382 // 3 instructions so go ahead and create it here. 383 static MCOperand MCO = MCOperand::createReg(Hexagon::VTMP); 384 return (MCO); 385 } else { 386 unsigned O = HexagonMCInstrInfo::getNewValueOp(MCII, MCI); 387 MCOperand const &MCO = MCI.getOperand(O); 388 389 assert((HexagonMCInstrInfo::isNewValue(MCII, MCI) || 390 HexagonMCInstrInfo::hasNewValue(MCII, MCI)) && 391 MCO.isReg()); 392 return (MCO); 393 } 394 } 395 396 /// Return the new value or the newly produced value. 397 unsigned short HexagonMCInstrInfo::getNewValueOp2(MCInstrInfo const &MCII, 398 MCInst const &MCI) { 399 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 400 return ((F >> HexagonII::NewValueOpPos2) & HexagonII::NewValueOpMask2); 401 } 402 403 MCOperand const & 404 HexagonMCInstrInfo::getNewValueOperand2(MCInstrInfo const &MCII, 405 MCInst const &MCI) { 406 unsigned O = HexagonMCInstrInfo::getNewValueOp2(MCII, MCI); 407 MCOperand const &MCO = MCI.getOperand(O); 408 409 assert((HexagonMCInstrInfo::isNewValue(MCII, MCI) || 410 HexagonMCInstrInfo::hasNewValue2(MCII, MCI)) && 411 MCO.isReg()); 412 return (MCO); 413 } 414 415 /// Return the Hexagon ISA class for the insn. 416 unsigned HexagonMCInstrInfo::getType(MCInstrInfo const &MCII, 417 MCInst const &MCI) { 418 const uint64_t F = MCII.get(MCI.getOpcode()).TSFlags; 419 return ((F >> HexagonII::TypePos) & HexagonII::TypeMask); 420 } 421 422 /// Return the resources used by this instruction 423 unsigned HexagonMCInstrInfo::getCVIResources(MCInstrInfo const &MCII, 424 MCSubtargetInfo const &STI, 425 MCInst const &MCI) { 426 427 const InstrItinerary *II = STI.getSchedModel().InstrItineraries; 428 int SchedClass = HexagonMCInstrInfo::getDesc(MCII, MCI).getSchedClass(); 429 int Size = II[SchedClass].LastStage - II[SchedClass].FirstStage; 430 431 // HVX resources used are currenty located at the second to last stage. 432 // This could also be done with a linear search of the stages looking for: 433 // CVI_ALL, CVI_MPY01, CVI_XLSHF, CVI_MPY0, CVI_MPY1, CVI_SHIFT, CVI_XLANE, 434 // CVI_ZW 435 unsigned Stage = II[SchedClass].LastStage - 1; 436 437 if (Size < 2) 438 return 0; 439 return ((Stage + HexagonStages)->getUnits()); 440 } 441 442 /// Return the slots this instruction can execute out of 443 unsigned HexagonMCInstrInfo::getUnits(MCInstrInfo const &MCII, 444 MCSubtargetInfo const &STI, 445 MCInst const &MCI) { 446 const InstrItinerary *II = STI.getSchedModel().InstrItineraries; 447 int SchedClass = HexagonMCInstrInfo::getDesc(MCII, MCI).getSchedClass(); 448 return ((II[SchedClass].FirstStage + HexagonStages)->getUnits()); 449 } 450 451 /// Return the slots this instruction consumes in addition to 452 /// the slot(s) it can execute out of 453 454 unsigned HexagonMCInstrInfo::getOtherReservedSlots(MCInstrInfo const &MCII, 455 MCSubtargetInfo const &STI, 456 MCInst const &MCI) { 457 const InstrItinerary *II = STI.getSchedModel().InstrItineraries; 458 int SchedClass = HexagonMCInstrInfo::getDesc(MCII, MCI).getSchedClass(); 459 unsigned Slots = 0; 460 461 // FirstStage are slots that this instruction can execute in. 462 // FirstStage+1 are slots that are also consumed by this instruction. 463 // For example: vmemu can only execute in slot 0 but also consumes slot 1. 464 for (unsigned Stage = II[SchedClass].FirstStage + 1; 465 Stage < II[SchedClass].LastStage; ++Stage) { 466 unsigned Units = (Stage + HexagonStages)->getUnits(); 467 if (Units > HexagonGetLastSlot()) 468 break; 469 // fyi: getUnits() will return 0x1, 0x2, 0x4 or 0x8 470 Slots |= Units; 471 } 472 473 // if 0 is returned, then no additional slots are consumed by this inst. 474 return Slots; 475 } 476 477 bool HexagonMCInstrInfo::hasDuplex(MCInstrInfo const &MCII, MCInst const &MCI) { 478 if (!HexagonMCInstrInfo::isBundle(MCI)) 479 return false; 480 481 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCI)) { 482 if (HexagonMCInstrInfo::isDuplex(MCII, *I.getInst())) 483 return true; 484 } 485 486 return false; 487 } 488 489 bool HexagonMCInstrInfo::hasExtenderForIndex(MCInst const &MCB, size_t Index) { 490 return extenderForIndex(MCB, Index) != nullptr; 491 } 492 493 bool HexagonMCInstrInfo::hasImmExt(MCInst const &MCI) { 494 if (!HexagonMCInstrInfo::isBundle(MCI)) 495 return false; 496 497 for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCI)) { 498 if (isImmext(*I.getInst())) 499 return true; 500 } 501 502 return false; 503 } 504 505 /// Return whether the insn produces a value. 506 bool HexagonMCInstrInfo::hasNewValue(MCInstrInfo const &MCII, 507 MCInst const &MCI) { 508 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 509 return ((F >> HexagonII::hasNewValuePos) & HexagonII::hasNewValueMask); 510 } 511 512 /// Return whether the insn produces a second value. 513 bool HexagonMCInstrInfo::hasNewValue2(MCInstrInfo const &MCII, 514 MCInst const &MCI) { 515 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 516 return ((F >> HexagonII::hasNewValuePos2) & HexagonII::hasNewValueMask2); 517 } 518 519 MCInst const &HexagonMCInstrInfo::instruction(MCInst const &MCB, size_t Index) { 520 assert(isBundle(MCB)); 521 assert(Index < HEXAGON_PRESHUFFLE_PACKET_SIZE); 522 return *MCB.getOperand(bundleInstructionsOffset + Index).getInst(); 523 } 524 525 /// Return where the instruction is an accumulator. 526 bool HexagonMCInstrInfo::isAccumulator(MCInstrInfo const &MCII, 527 MCInst const &MCI) { 528 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 529 return ((F >> HexagonII::AccumulatorPos) & HexagonII::AccumulatorMask); 530 } 531 532 bool HexagonMCInstrInfo::isBundle(MCInst const &MCI) { 533 auto Result = Hexagon::BUNDLE == MCI.getOpcode(); 534 assert(!Result || (MCI.size() > 0 && MCI.getOperand(0).isImm())); 535 return Result; 536 } 537 538 bool HexagonMCInstrInfo::isConstExtended(MCInstrInfo const &MCII, 539 MCInst const &MCI) { 540 if (HexagonMCInstrInfo::isExtended(MCII, MCI)) 541 return true; 542 if (!HexagonMCInstrInfo::isExtendable(MCII, MCI)) 543 return false; 544 MCOperand const &MO = HexagonMCInstrInfo::getExtendableOperand(MCII, MCI); 545 if (isa<HexagonMCExpr>(MO.getExpr()) && 546 HexagonMCInstrInfo::mustExtend(*MO.getExpr())) 547 return true; 548 // Branch insns are handled as necessary by relaxation. 549 if ((HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeJ) || 550 (HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeCJ && 551 HexagonMCInstrInfo::getDesc(MCII, MCI).isBranch()) || 552 (HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeNCJ && 553 HexagonMCInstrInfo::getDesc(MCII, MCI).isBranch())) 554 return false; 555 // Otherwise loop instructions and other CR insts are handled by relaxation 556 else if ((HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeCR) && 557 (MCI.getOpcode() != Hexagon::C4_addipc)) 558 return false; 559 560 assert(!MO.isImm()); 561 if (isa<HexagonMCExpr>(MO.getExpr()) && 562 HexagonMCInstrInfo::mustNotExtend(*MO.getExpr())) 563 return false; 564 int64_t Value; 565 if (!MO.getExpr()->evaluateAsAbsolute(Value)) 566 return true; 567 int MinValue = HexagonMCInstrInfo::getMinValue(MCII, MCI); 568 int MaxValue = HexagonMCInstrInfo::getMaxValue(MCII, MCI); 569 return (MinValue > Value || Value > MaxValue); 570 } 571 572 bool HexagonMCInstrInfo::isCanon(MCInstrInfo const &MCII, MCInst const &MCI) { 573 return !HexagonMCInstrInfo::getDesc(MCII, MCI).isPseudo() && 574 !HexagonMCInstrInfo::isPrefix(MCII, MCI); 575 } 576 577 bool HexagonMCInstrInfo::isCofMax1(MCInstrInfo const &MCII, MCInst const &MCI) { 578 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 579 return ((F >> HexagonII::CofMax1Pos) & HexagonII::CofMax1Mask); 580 } 581 582 bool HexagonMCInstrInfo::isCofRelax1(MCInstrInfo const &MCII, 583 MCInst const &MCI) { 584 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 585 return ((F >> HexagonII::CofRelax1Pos) & HexagonII::CofRelax1Mask); 586 } 587 588 bool HexagonMCInstrInfo::isCofRelax2(MCInstrInfo const &MCII, 589 MCInst const &MCI) { 590 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 591 return ((F >> HexagonII::CofRelax2Pos) & HexagonII::CofRelax2Mask); 592 } 593 594 bool HexagonMCInstrInfo::isCompound(MCInstrInfo const &MCII, 595 MCInst const &MCI) { 596 return (getType(MCII, MCI) == HexagonII::TypeCJ); 597 } 598 599 bool HexagonMCInstrInfo::isCVINew(MCInstrInfo const &MCII, MCInst const &MCI) { 600 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 601 return ((F >> HexagonII::CVINewPos) & HexagonII::CVINewMask); 602 } 603 604 bool HexagonMCInstrInfo::isDblRegForSubInst(unsigned Reg) { 605 return ((Reg >= Hexagon::D0 && Reg <= Hexagon::D3) || 606 (Reg >= Hexagon::D8 && Reg <= Hexagon::D11)); 607 } 608 609 bool HexagonMCInstrInfo::isDuplex(MCInstrInfo const &MCII, MCInst const &MCI) { 610 return HexagonII::TypeDUPLEX == HexagonMCInstrInfo::getType(MCII, MCI); 611 } 612 613 bool HexagonMCInstrInfo::isExtendable(MCInstrInfo const &MCII, 614 MCInst const &MCI) { 615 uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 616 return (F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask; 617 } 618 619 bool HexagonMCInstrInfo::isExtended(MCInstrInfo const &MCII, 620 MCInst const &MCI) { 621 uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 622 return (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask; 623 } 624 625 bool HexagonMCInstrInfo::isFloat(MCInstrInfo const &MCII, MCInst const &MCI) { 626 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 627 return ((F >> HexagonII::FPPos) & HexagonII::FPMask); 628 } 629 630 bool HexagonMCInstrInfo::isHVX(MCInstrInfo const &MCII, MCInst const &MCI) { 631 const uint64_t V = getType(MCII, MCI); 632 return HexagonII::TypeCVI_FIRST <= V && V <= HexagonII::TypeCVI_LAST; 633 } 634 635 bool HexagonMCInstrInfo::isImmext(MCInst const &MCI) { 636 return MCI.getOpcode() == Hexagon::A4_ext; 637 } 638 639 bool HexagonMCInstrInfo::isInnerLoop(MCInst const &MCI) { 640 assert(isBundle(MCI)); 641 int64_t Flags = MCI.getOperand(0).getImm(); 642 return (Flags & innerLoopMask) != 0; 643 } 644 645 bool HexagonMCInstrInfo::isIntReg(unsigned Reg) { 646 return (Reg >= Hexagon::R0 && Reg <= Hexagon::R31); 647 } 648 649 bool HexagonMCInstrInfo::isIntRegForSubInst(unsigned Reg) { 650 return ((Reg >= Hexagon::R0 && Reg <= Hexagon::R7) || 651 (Reg >= Hexagon::R16 && Reg <= Hexagon::R23)); 652 } 653 654 /// Return whether the insn expects newly produced value. 655 bool HexagonMCInstrInfo::isNewValue(MCInstrInfo const &MCII, 656 MCInst const &MCI) { 657 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 658 return ((F >> HexagonII::NewValuePos) & HexagonII::NewValueMask); 659 } 660 661 bool HexagonMCInstrInfo::isNewValueStore(MCInstrInfo const &MCII, 662 MCInst const &MCI) { 663 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 664 return (F >> HexagonII::NVStorePos) & HexagonII::NVStoreMask; 665 } 666 667 /// Return whether the operand is extendable. 668 bool HexagonMCInstrInfo::isOpExtendable(MCInstrInfo const &MCII, 669 MCInst const &MCI, unsigned short O) { 670 return (O == HexagonMCInstrInfo::getExtendableOp(MCII, MCI)); 671 } 672 673 bool HexagonMCInstrInfo::isOuterLoop(MCInst const &MCI) { 674 assert(isBundle(MCI)); 675 int64_t Flags = MCI.getOperand(0).getImm(); 676 return (Flags & outerLoopMask) != 0; 677 } 678 679 bool HexagonMCInstrInfo::IsVecRegPair(unsigned VecReg) { 680 return (VecReg >= Hexagon::W0 && VecReg <= Hexagon::W15) || 681 (VecReg >= Hexagon::WR0 && VecReg <= Hexagon::WR15); 682 } 683 684 bool HexagonMCInstrInfo::IsReverseVecRegPair(unsigned VecReg) { 685 return (VecReg >= Hexagon::WR0 && VecReg <= Hexagon::WR15); 686 } 687 688 bool HexagonMCInstrInfo::IsVecRegSingle(unsigned VecReg) { 689 return (VecReg >= Hexagon::V0 && VecReg <= Hexagon::V31); 690 } 691 692 std::pair<unsigned, unsigned> 693 HexagonMCInstrInfo::GetVecRegPairIndices(unsigned VecRegPair) { 694 assert(IsVecRegPair(VecRegPair) && 695 "VecRegPair must be a vector register pair"); 696 697 const bool IsRev = IsReverseVecRegPair(VecRegPair); 698 const unsigned PairIndex = 699 2 * (IsRev ? VecRegPair - Hexagon::WR0 : VecRegPair - Hexagon::W0); 700 701 return IsRev ? std::make_pair(PairIndex, PairIndex + 1) 702 : std::make_pair(PairIndex + 1, PairIndex); 703 } 704 705 bool HexagonMCInstrInfo::IsSingleConsumerRefPairProducer(unsigned Producer, 706 unsigned Consumer) { 707 if (IsVecRegPair(Producer) && IsVecRegSingle(Consumer)) { 708 const unsigned ProdPairIndex = IsReverseVecRegPair(Producer) 709 ? Producer - Hexagon::WR0 710 : Producer - Hexagon::W0; 711 const unsigned ConsumerSingleIndex = (Consumer - Hexagon::V0) >> 1; 712 713 return ConsumerSingleIndex == ProdPairIndex; 714 } 715 return false; 716 } 717 718 bool HexagonMCInstrInfo::isPredicated(MCInstrInfo const &MCII, 719 MCInst const &MCI) { 720 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 721 return ((F >> HexagonII::PredicatedPos) & HexagonII::PredicatedMask); 722 } 723 724 bool HexagonMCInstrInfo::isPrefix(MCInstrInfo const &MCII, MCInst const &MCI) { 725 return HexagonII::TypeEXTENDER == HexagonMCInstrInfo::getType(MCII, MCI); 726 } 727 728 bool HexagonMCInstrInfo::isPredicateLate(MCInstrInfo const &MCII, 729 MCInst const &MCI) { 730 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 731 return (F >> HexagonII::PredicateLatePos & HexagonII::PredicateLateMask); 732 } 733 734 /// Return whether the insn is newly predicated. 735 bool HexagonMCInstrInfo::isPredicatedNew(MCInstrInfo const &MCII, 736 MCInst const &MCI) { 737 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 738 return ((F >> HexagonII::PredicatedNewPos) & HexagonII::PredicatedNewMask); 739 } 740 741 bool HexagonMCInstrInfo::isPredicatedTrue(MCInstrInfo const &MCII, 742 MCInst const &MCI) { 743 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 744 return ( 745 !((F >> HexagonII::PredicatedFalsePos) & HexagonII::PredicatedFalseMask)); 746 } 747 748 bool HexagonMCInstrInfo::isPredReg(MCRegisterInfo const &MRI, unsigned Reg) { 749 auto &PredRegClass = MRI.getRegClass(Hexagon::PredRegsRegClassID); 750 return PredRegClass.contains(Reg); 751 } 752 753 bool HexagonMCInstrInfo::isPredRegister(MCInstrInfo const &MCII, 754 MCInst const &Inst, unsigned I) { 755 MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, Inst); 756 757 return Inst.getOperand(I).isReg() && 758 Desc.OpInfo[I].RegClass == Hexagon::PredRegsRegClassID; 759 } 760 761 /// Return whether the insn can be packaged only with A and X-type insns. 762 bool HexagonMCInstrInfo::isSoloAX(MCInstrInfo const &MCII, MCInst const &MCI) { 763 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 764 return ((F >> HexagonII::SoloAXPos) & HexagonII::SoloAXMask); 765 } 766 767 /// Return whether the insn can be packaged only with an A-type insn in slot #1. 768 bool HexagonMCInstrInfo::isRestrictSlot1AOK(MCInstrInfo const &MCII, 769 MCInst const &MCI) { 770 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 771 return ((F >> HexagonII::RestrictSlot1AOKPos) & 772 HexagonII::RestrictSlot1AOKMask); 773 } 774 775 bool HexagonMCInstrInfo::isRestrictNoSlot1Store(MCInstrInfo const &MCII, 776 MCInst const &MCI) { 777 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 778 return ((F >> HexagonII::RestrictNoSlot1StorePos) & 779 HexagonII::RestrictNoSlot1StoreMask); 780 } 781 782 /// Return whether the insn is solo, i.e., cannot be in a packet. 783 bool HexagonMCInstrInfo::isSolo(MCInstrInfo const &MCII, MCInst const &MCI) { 784 const uint64_t F = MCII.get(MCI.getOpcode()).TSFlags; 785 return ((F >> HexagonII::SoloPos) & HexagonII::SoloMask); 786 } 787 788 bool HexagonMCInstrInfo::isMemReorderDisabled(MCInst const &MCI) { 789 assert(isBundle(MCI)); 790 auto Flags = MCI.getOperand(0).getImm(); 791 return (Flags & memReorderDisabledMask) != 0; 792 } 793 794 bool HexagonMCInstrInfo::isSubInstruction(MCInst const &MCI) { 795 switch (MCI.getOpcode()) { 796 default: 797 return false; 798 case Hexagon::SA1_addi: 799 case Hexagon::SA1_addrx: 800 case Hexagon::SA1_addsp: 801 case Hexagon::SA1_and1: 802 case Hexagon::SA1_clrf: 803 case Hexagon::SA1_clrfnew: 804 case Hexagon::SA1_clrt: 805 case Hexagon::SA1_clrtnew: 806 case Hexagon::SA1_cmpeqi: 807 case Hexagon::SA1_combine0i: 808 case Hexagon::SA1_combine1i: 809 case Hexagon::SA1_combine2i: 810 case Hexagon::SA1_combine3i: 811 case Hexagon::SA1_combinerz: 812 case Hexagon::SA1_combinezr: 813 case Hexagon::SA1_dec: 814 case Hexagon::SA1_inc: 815 case Hexagon::SA1_seti: 816 case Hexagon::SA1_setin1: 817 case Hexagon::SA1_sxtb: 818 case Hexagon::SA1_sxth: 819 case Hexagon::SA1_tfr: 820 case Hexagon::SA1_zxtb: 821 case Hexagon::SA1_zxth: 822 case Hexagon::SL1_loadri_io: 823 case Hexagon::SL1_loadrub_io: 824 case Hexagon::SL2_deallocframe: 825 case Hexagon::SL2_jumpr31: 826 case Hexagon::SL2_jumpr31_f: 827 case Hexagon::SL2_jumpr31_fnew: 828 case Hexagon::SL2_jumpr31_t: 829 case Hexagon::SL2_jumpr31_tnew: 830 case Hexagon::SL2_loadrb_io: 831 case Hexagon::SL2_loadrd_sp: 832 case Hexagon::SL2_loadrh_io: 833 case Hexagon::SL2_loadri_sp: 834 case Hexagon::SL2_loadruh_io: 835 case Hexagon::SL2_return: 836 case Hexagon::SL2_return_f: 837 case Hexagon::SL2_return_fnew: 838 case Hexagon::SL2_return_t: 839 case Hexagon::SL2_return_tnew: 840 case Hexagon::SS1_storeb_io: 841 case Hexagon::SS1_storew_io: 842 case Hexagon::SS2_allocframe: 843 case Hexagon::SS2_storebi0: 844 case Hexagon::SS2_storebi1: 845 case Hexagon::SS2_stored_sp: 846 case Hexagon::SS2_storeh_io: 847 case Hexagon::SS2_storew_sp: 848 case Hexagon::SS2_storewi0: 849 case Hexagon::SS2_storewi1: 850 return true; 851 } 852 } 853 854 bool HexagonMCInstrInfo::isVector(MCInstrInfo const &MCII, MCInst const &MCI) { 855 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 856 return (F >> HexagonII::isCVIPos) & HexagonII::isCVIMask; 857 } 858 859 int64_t HexagonMCInstrInfo::minConstant(MCInst const &MCI, size_t Index) { 860 auto Sentinal = static_cast<int64_t>(std::numeric_limits<uint32_t>::max()) 861 << 8; 862 if (MCI.size() <= Index) 863 return Sentinal; 864 MCOperand const &MCO = MCI.getOperand(Index); 865 if (!MCO.isExpr()) 866 return Sentinal; 867 int64_t Value; 868 if (!MCO.getExpr()->evaluateAsAbsolute(Value)) 869 return Sentinal; 870 return Value; 871 } 872 873 void HexagonMCInstrInfo::setMustExtend(MCExpr const &Expr, bool Val) { 874 HexagonMCExpr &HExpr = const_cast<HexagonMCExpr &>(cast<HexagonMCExpr>(Expr)); 875 HExpr.setMustExtend(Val); 876 } 877 878 bool HexagonMCInstrInfo::mustExtend(MCExpr const &Expr) { 879 HexagonMCExpr const &HExpr = cast<HexagonMCExpr>(Expr); 880 return HExpr.mustExtend(); 881 } 882 void HexagonMCInstrInfo::setMustNotExtend(MCExpr const &Expr, bool Val) { 883 HexagonMCExpr &HExpr = const_cast<HexagonMCExpr &>(cast<HexagonMCExpr>(Expr)); 884 HExpr.setMustNotExtend(Val); 885 } 886 bool HexagonMCInstrInfo::mustNotExtend(MCExpr const &Expr) { 887 HexagonMCExpr const &HExpr = cast<HexagonMCExpr>(Expr); 888 return HExpr.mustNotExtend(); 889 } 890 void HexagonMCInstrInfo::setS27_2_reloc(MCExpr const &Expr, bool Val) { 891 HexagonMCExpr &HExpr = 892 const_cast<HexagonMCExpr &>(*cast<HexagonMCExpr>(&Expr)); 893 HExpr.setS27_2_reloc(Val); 894 } 895 bool HexagonMCInstrInfo::s27_2_reloc(MCExpr const &Expr) { 896 HexagonMCExpr const *HExpr = dyn_cast<HexagonMCExpr>(&Expr); 897 if (!HExpr) 898 return false; 899 return HExpr->s27_2_reloc(); 900 } 901 902 unsigned HexagonMCInstrInfo::packetSizeSlots(MCSubtargetInfo const &STI) { 903 const bool IsTiny = STI.getFeatureBits()[Hexagon::ProcTinyCore]; 904 905 return IsTiny ? (HEXAGON_PACKET_SIZE - 1) : HEXAGON_PACKET_SIZE; 906 } 907 908 unsigned HexagonMCInstrInfo::packetSize(StringRef CPU) { 909 return llvm::StringSwitch<unsigned>(CPU) 910 .Case("hexagonv67t", 3) 911 .Default(4); 912 } 913 914 void HexagonMCInstrInfo::padEndloop(MCInst &MCB, MCContext &Context) { 915 MCInst Nop; 916 Nop.setOpcode(Hexagon::A2_nop); 917 assert(isBundle(MCB)); 918 while ((HexagonMCInstrInfo::isInnerLoop(MCB) && 919 (HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_INNER_SIZE)) || 920 ((HexagonMCInstrInfo::isOuterLoop(MCB) && 921 (HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_OUTER_SIZE)))) 922 MCB.addOperand(MCOperand::createInst(new (Context) MCInst(Nop))); 923 } 924 925 HexagonMCInstrInfo::PredicateInfo 926 HexagonMCInstrInfo::predicateInfo(MCInstrInfo const &MCII, MCInst const &MCI) { 927 if (!isPredicated(MCII, MCI)) 928 return {0, 0, false}; 929 MCInstrDesc const &Desc = getDesc(MCII, MCI); 930 for (auto I = Desc.getNumDefs(), N = Desc.getNumOperands(); I != N; ++I) 931 if (Desc.OpInfo[I].RegClass == Hexagon::PredRegsRegClassID) 932 return {MCI.getOperand(I).getReg(), I, isPredicatedTrue(MCII, MCI)}; 933 return {0, 0, false}; 934 } 935 936 bool HexagonMCInstrInfo::prefersSlot3(MCInstrInfo const &MCII, 937 MCInst const &MCI) { 938 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 939 return (F >> HexagonII::PrefersSlot3Pos) & HexagonII::PrefersSlot3Mask; 940 } 941 942 /// return true if instruction has hasTmpDst attribute. 943 bool HexagonMCInstrInfo::hasTmpDst(MCInstrInfo const &MCII, MCInst const &MCI) { 944 const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; 945 return (F >> HexagonII::HasTmpDstPos) & HexagonII::HasTmpDstMask; 946 } 947 948 bool HexagonMCInstrInfo::requiresSlot(MCSubtargetInfo const &STI, 949 MCInst const &MCI) { 950 const unsigned OpCode = MCI.getOpcode(); 951 const bool IsTiny = STI.getFeatureBits() [Hexagon::ProcTinyCore]; 952 const bool NoSlotReqd = Hexagon::A4_ext == OpCode || 953 (IsTiny && Hexagon::A2_nop == OpCode) || 954 (IsTiny && Hexagon::J4_hintjumpr == OpCode); 955 956 return !NoSlotReqd; 957 } 958 959 unsigned HexagonMCInstrInfo::slotsConsumed(MCInstrInfo const &MCII, 960 MCSubtargetInfo const &STI, 961 MCInst const &MCI) { 962 unsigned slotsUsed = 0; 963 for (auto HMI : bundleInstructions(MCI)) { 964 MCInst const &MCI = *HMI.getInst(); 965 if (!requiresSlot(STI, MCI)) 966 continue; 967 if (isDuplex(MCII, MCI)) 968 slotsUsed += 2; 969 else 970 ++slotsUsed; 971 } 972 return slotsUsed; 973 } 974 975 void HexagonMCInstrInfo::replaceDuplex(MCContext &Context, MCInst &MCB, 976 DuplexCandidate Candidate) { 977 assert(Candidate.packetIndexI < MCB.size()); 978 assert(Candidate.packetIndexJ < MCB.size()); 979 assert(isBundle(MCB)); 980 MCInst *Duplex = 981 deriveDuplex(Context, Candidate.iClass, 982 *MCB.getOperand(Candidate.packetIndexJ).getInst(), 983 *MCB.getOperand(Candidate.packetIndexI).getInst()); 984 assert(Duplex != nullptr); 985 MCB.getOperand(Candidate.packetIndexI).setInst(Duplex); 986 MCB.erase(MCB.begin() + Candidate.packetIndexJ); 987 } 988 989 void HexagonMCInstrInfo::setInnerLoop(MCInst &MCI) { 990 assert(isBundle(MCI)); 991 MCOperand &Operand = MCI.getOperand(0); 992 Operand.setImm(Operand.getImm() | innerLoopMask); 993 } 994 995 void HexagonMCInstrInfo::setMemReorderDisabled(MCInst &MCI) { 996 assert(isBundle(MCI)); 997 MCOperand &Operand = MCI.getOperand(0); 998 Operand.setImm(Operand.getImm() | memReorderDisabledMask); 999 assert(isMemReorderDisabled(MCI)); 1000 } 1001 1002 void HexagonMCInstrInfo::setOuterLoop(MCInst &MCI) { 1003 assert(isBundle(MCI)); 1004 MCOperand &Operand = MCI.getOperand(0); 1005 Operand.setImm(Operand.getImm() | outerLoopMask); 1006 } 1007 1008 unsigned HexagonMCInstrInfo::SubregisterBit(unsigned Consumer, 1009 unsigned Producer, 1010 unsigned Producer2) { 1011 // If we're a single vector consumer of a double producer, set subreg bit 1012 // based on if we're accessing the lower or upper register component 1013 if (IsVecRegPair(Producer) && IsVecRegSingle(Consumer)) 1014 return (Consumer - Hexagon::V0) & 0x1; 1015 if (Producer2 != Hexagon::NoRegister) 1016 return Consumer == Producer; 1017 return 0; 1018 } 1019