1 //===-- M68kISelDAGToDAG.cpp - M68k Dag to Dag Inst Selector ----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file defines an instruction selector for the M68K target. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "M68k.h" 15 16 #include "M68kMachineFunction.h" 17 #include "M68kRegisterInfo.h" 18 #include "M68kTargetMachine.h" 19 20 #include "llvm/CodeGen/MachineConstantPool.h" 21 #include "llvm/CodeGen/MachineFrameInfo.h" 22 #include "llvm/CodeGen/MachineFunction.h" 23 #include "llvm/CodeGen/MachineInstrBuilder.h" 24 #include "llvm/CodeGen/MachineRegisterInfo.h" 25 #include "llvm/CodeGen/SelectionDAGISel.h" 26 #include "llvm/CodeGen/SelectionDAGNodes.h" 27 #include "llvm/IR/CFG.h" 28 #include "llvm/IR/GlobalValue.h" 29 #include "llvm/IR/Instructions.h" 30 #include "llvm/IR/Intrinsics.h" 31 #include "llvm/IR/Type.h" 32 #include "llvm/Support/Alignment.h" 33 #include "llvm/Support/Debug.h" 34 #include "llvm/Support/ErrorHandling.h" 35 #include "llvm/Support/MathExtras.h" 36 #include "llvm/Support/raw_ostream.h" 37 #include "llvm/Target/TargetMachine.h" 38 39 using namespace llvm; 40 41 #define DEBUG_TYPE "m68k-isel" 42 43 namespace { 44 45 // For reference, the full order of operands for memory references is: 46 // (Operand), Displacement, Base, Index, Scale 47 struct M68kISelAddressMode { 48 enum class AddrType { 49 ARI, // Address Register Indirect 50 ARIPI, // Address Register Indirect with Postincrement 51 ARIPD, // Address Register Indirect with Postdecrement 52 ARID, // Address Register Indirect with Displacement 53 ARII, // Address Register Indirect with Index 54 PCD, // Program Counter Indirect with Displacement 55 PCI, // Program Counter Indirect with Index 56 AL, // Absolute 57 }; 58 AddrType AM; 59 60 enum class Base { RegBase, FrameIndexBase }; 61 Base BaseType; 62 63 int64_t Disp; 64 65 // This is really a union, discriminated by BaseType! 66 SDValue BaseReg; 67 int BaseFrameIndex; 68 69 SDValue IndexReg; 70 unsigned Scale; 71 72 const GlobalValue *GV; 73 const Constant *CP; 74 const BlockAddress *BlockAddr; 75 const char *ES; 76 MCSymbol *MCSym; 77 int JT; 78 Align Alignment; // CP alignment. 79 80 unsigned char SymbolFlags; // M68kII::MO_* 81 82 M68kISelAddressMode(AddrType AT) 83 : AM(AT), BaseType(Base::RegBase), Disp(0), BaseFrameIndex(0), IndexReg(), 84 Scale(1), GV(nullptr), CP(nullptr), BlockAddr(nullptr), ES(nullptr), 85 MCSym(nullptr), JT(-1), Alignment(), SymbolFlags(M68kII::MO_NO_FLAG) {} 86 87 bool hasSymbolicDisplacement() const { 88 return GV != nullptr || CP != nullptr || ES != nullptr || 89 MCSym != nullptr || JT != -1 || BlockAddr != nullptr; 90 } 91 92 bool hasBase() const { 93 return BaseType == Base::FrameIndexBase || BaseReg.getNode() != nullptr; 94 } 95 96 bool hasFrameIndex() const { return BaseType == Base::FrameIndexBase; } 97 98 bool hasBaseReg() const { 99 return BaseType == Base::RegBase && BaseReg.getNode() != nullptr; 100 } 101 102 bool hasIndexReg() const { 103 return BaseType == Base::RegBase && IndexReg.getNode() != nullptr; 104 } 105 106 /// True if address mode type supports displacement 107 bool isDispAddrType() const { 108 return AM == AddrType::ARII || AM == AddrType::PCI || 109 AM == AddrType::ARID || AM == AddrType::PCD || AM == AddrType::AL; 110 } 111 112 unsigned getDispSize() const { 113 switch (AM) { 114 default: 115 return 0; 116 case AddrType::ARII: 117 case AddrType::PCI: 118 return 8; 119 // These two in the next chip generations can hold upto 32 bit 120 case AddrType::ARID: 121 case AddrType::PCD: 122 return 16; 123 case AddrType::AL: 124 return 32; 125 } 126 } 127 128 bool hasDisp() const { return getDispSize() != 0; } 129 bool isDisp8() const { return getDispSize() == 8; } 130 bool isDisp16() const { return getDispSize() == 16; } 131 bool isDisp32() const { return getDispSize() == 32; } 132 133 /// Return true if this addressing mode is already PC-relative. 134 bool isPCRelative() const { 135 if (BaseType != Base::RegBase) 136 return false; 137 if (auto *RegNode = dyn_cast_or_null<RegisterSDNode>(BaseReg.getNode())) 138 return RegNode->getReg() == M68k::PC; 139 return false; 140 } 141 142 void setBaseReg(SDValue Reg) { 143 BaseType = Base::RegBase; 144 BaseReg = Reg; 145 } 146 147 void setIndexReg(SDValue Reg) { IndexReg = Reg; } 148 149 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 150 void dump() { 151 dbgs() << "M68kISelAddressMode " << this; 152 dbgs() << "\nDisp: " << Disp; 153 dbgs() << ", BaseReg: "; 154 if (BaseReg.getNode()) 155 BaseReg.getNode()->dump(); 156 else 157 dbgs() << "null"; 158 dbgs() << ", BaseFI: " << BaseFrameIndex; 159 dbgs() << ", IndexReg: "; 160 if (IndexReg.getNode()) { 161 IndexReg.getNode()->dump(); 162 } else { 163 dbgs() << "null"; 164 dbgs() << ", Scale: " << Scale; 165 } 166 dbgs() << '\n'; 167 } 168 #endif 169 }; 170 } // end anonymous namespace 171 172 namespace { 173 174 class M68kDAGToDAGISel : public SelectionDAGISel { 175 public: 176 explicit M68kDAGToDAGISel(M68kTargetMachine &TM) 177 : SelectionDAGISel(TM), Subtarget(nullptr) {} 178 179 StringRef getPassName() const override { 180 return "M68k DAG->DAG Pattern Instruction Selection"; 181 } 182 183 bool runOnMachineFunction(MachineFunction &MF) override; 184 185 private: 186 /// Keep a pointer to the M68kSubtarget around so that we can 187 /// make the right decision when generating code for different targets. 188 const M68kSubtarget *Subtarget; 189 190 // Include the pieces autogenerated from the target description. 191 #include "M68kGenDAGISel.inc" 192 193 /// getTargetMachine - Return a reference to the TargetMachine, casted 194 /// to the target-specific type. 195 const M68kTargetMachine &getTargetMachine() { 196 return static_cast<const M68kTargetMachine &>(TM); 197 } 198 199 void Select(SDNode *N) override; 200 201 // Insert instructions to initialize the global base register in the 202 // first MBB of the function. 203 // HMM... do i need this? 204 void initGlobalBaseReg(MachineFunction &MF); 205 206 bool foldOffsetIntoAddress(uint64_t Offset, M68kISelAddressMode &AM); 207 208 bool matchLoadInAddress(LoadSDNode *N, M68kISelAddressMode &AM); 209 bool matchAddress(SDValue N, M68kISelAddressMode &AM); 210 bool matchAddressBase(SDValue N, M68kISelAddressMode &AM); 211 bool matchAddressRecursively(SDValue N, M68kISelAddressMode &AM, 212 unsigned Depth); 213 bool matchADD(SDValue &N, M68kISelAddressMode &AM, unsigned Depth); 214 bool matchWrapper(SDValue N, M68kISelAddressMode &AM); 215 216 std::pair<bool, SDNode *> selectNode(SDNode *Node); 217 218 bool SelectARI(SDNode *Parent, SDValue N, SDValue &Base); 219 bool SelectARIPI(SDNode *Parent, SDValue N, SDValue &Base); 220 bool SelectARIPD(SDNode *Parent, SDValue N, SDValue &Base); 221 bool SelectARID(SDNode *Parent, SDValue N, SDValue &Imm, SDValue &Base); 222 bool SelectARII(SDNode *Parent, SDValue N, SDValue &Imm, SDValue &Base, 223 SDValue &Index); 224 bool SelectAL(SDNode *Parent, SDValue N, SDValue &Sym); 225 bool SelectPCD(SDNode *Parent, SDValue N, SDValue &Imm); 226 bool SelectPCI(SDNode *Parent, SDValue N, SDValue &Imm, SDValue &Index); 227 228 // If Address Mode represents Frame Index store FI in Disp and 229 // Displacement bit size in Base. These values are read symmetrically by 230 // M68kRegisterInfo::eliminateFrameIndex method 231 inline bool getFrameIndexAddress(M68kISelAddressMode &AM, const SDLoc &DL, 232 SDValue &Disp, SDValue &Base) { 233 if (AM.BaseType == M68kISelAddressMode::Base::FrameIndexBase) { 234 Disp = getI32Imm(AM.Disp, DL); 235 Base = CurDAG->getTargetFrameIndex( 236 AM.BaseFrameIndex, TLI->getPointerTy(CurDAG->getDataLayout())); 237 return true; 238 } 239 240 return false; 241 } 242 243 // Gets a symbol plus optional displacement 244 inline bool getSymbolicDisplacement(M68kISelAddressMode &AM, const SDLoc &DL, 245 SDValue &Sym) { 246 if (AM.GV) { 247 Sym = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(), MVT::i32, AM.Disp, 248 AM.SymbolFlags); 249 return true; 250 } 251 252 if (AM.CP) { 253 Sym = CurDAG->getTargetConstantPool(AM.CP, MVT::i32, AM.Alignment, 254 AM.Disp, AM.SymbolFlags); 255 return true; 256 } 257 258 if (AM.ES) { 259 assert(!AM.Disp && "Non-zero displacement is ignored with ES."); 260 Sym = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32, AM.SymbolFlags); 261 return true; 262 } 263 264 if (AM.MCSym) { 265 assert(!AM.Disp && "Non-zero displacement is ignored with MCSym."); 266 assert(AM.SymbolFlags == 0 && "oo"); 267 Sym = CurDAG->getMCSymbol(AM.MCSym, MVT::i32); 268 return true; 269 } 270 271 if (AM.JT != -1) { 272 assert(!AM.Disp && "Non-zero displacement is ignored with JT."); 273 Sym = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags); 274 return true; 275 } 276 277 if (AM.BlockAddr) { 278 Sym = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, AM.Disp, 279 AM.SymbolFlags); 280 return true; 281 } 282 283 return false; 284 } 285 286 /// Return a target constant with the specified value of type i8. 287 inline SDValue getI8Imm(int64_t Imm, const SDLoc &DL) { 288 return CurDAG->getTargetConstant(Imm, DL, MVT::i8); 289 } 290 291 /// Return a target constant with the specified value of type i8. 292 inline SDValue getI16Imm(int64_t Imm, const SDLoc &DL) { 293 return CurDAG->getTargetConstant(Imm, DL, MVT::i16); 294 } 295 296 /// Return a target constant with the specified value, of type i32. 297 inline SDValue getI32Imm(int64_t Imm, const SDLoc &DL) { 298 return CurDAG->getTargetConstant(Imm, DL, MVT::i32); 299 } 300 301 /// Return a reference to the TargetInstrInfo, casted to the target-specific 302 /// type. 303 const M68kInstrInfo *getInstrInfo() const { 304 return Subtarget->getInstrInfo(); 305 } 306 307 /// Return an SDNode that returns the value of the global base register. 308 /// Output instructions required to initialize the global base register, 309 /// if necessary. 310 SDNode *getGlobalBaseReg(); 311 }; 312 } // namespace 313 314 bool M68kDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { 315 Subtarget = &static_cast<const M68kSubtarget &>(MF.getSubtarget()); 316 return SelectionDAGISel::runOnMachineFunction(MF); 317 } 318 319 /// This pass converts a legalized DAG into a M68k-specific DAG, 320 /// ready for instruction scheduling. 321 FunctionPass *llvm::createM68kISelDag(M68kTargetMachine &TM) { 322 return new M68kDAGToDAGISel(TM); 323 } 324 325 static bool doesDispFitFI(M68kISelAddressMode &AM) { 326 if (!AM.isDispAddrType()) 327 return false; 328 // -1 to make sure that resolved FI will fit into Disp field 329 return isIntN(AM.getDispSize() - 1, AM.Disp); 330 } 331 332 static bool doesDispFit(M68kISelAddressMode &AM, int64_t Val) { 333 if (!AM.isDispAddrType()) 334 return false; 335 return isIntN(AM.getDispSize(), Val); 336 } 337 338 /// Return an SDNode that returns the value of the global base register. 339 /// Output instructions required to initialize the global base register, 340 /// if necessary. 341 SDNode *M68kDAGToDAGISel::getGlobalBaseReg() { 342 unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF); 343 auto &DL = MF->getDataLayout(); 344 return CurDAG->getRegister(GlobalBaseReg, TLI->getPointerTy(DL)).getNode(); 345 } 346 347 bool M68kDAGToDAGISel::foldOffsetIntoAddress(uint64_t Offset, 348 M68kISelAddressMode &AM) { 349 // Cannot combine ExternalSymbol displacements with integer offsets. 350 if (Offset != 0 && (AM.ES || AM.MCSym)) 351 return false; 352 353 int64_t Val = AM.Disp + Offset; 354 355 if (doesDispFit(AM, Val)) { 356 AM.Disp = Val; 357 return true; 358 } 359 360 return false; 361 } 362 363 //===----------------------------------------------------------------------===// 364 // Matchers 365 //===----------------------------------------------------------------------===// 366 367 /// Helper for MatchAddress. Add the specified node to the 368 /// specified addressing mode without any further recursion. 369 bool M68kDAGToDAGISel::matchAddressBase(SDValue N, M68kISelAddressMode &AM) { 370 // Is the base register already occupied? 371 if (AM.hasBase()) { 372 // If so, check to see if the scale index register is set. 373 if (!AM.hasIndexReg()) { 374 AM.IndexReg = N; 375 AM.Scale = 1; 376 return true; 377 } 378 379 // Otherwise, we cannot select it. 380 return false; 381 } 382 383 // Default, generate it as a register. 384 AM.BaseType = M68kISelAddressMode::Base::RegBase; 385 AM.BaseReg = N; 386 return true; 387 } 388 389 /// TODO Add TLS support 390 bool M68kDAGToDAGISel::matchLoadInAddress(LoadSDNode *N, 391 M68kISelAddressMode &AM) { 392 return false; 393 } 394 395 bool M68kDAGToDAGISel::matchAddressRecursively(SDValue N, 396 M68kISelAddressMode &AM, 397 unsigned Depth) { 398 SDLoc DL(N); 399 400 // Limit recursion. 401 if (Depth > 5) 402 return matchAddressBase(N, AM); 403 404 // If this is already a %PC relative address, we can only merge immediates 405 // into it. Instead of handling this in every case, we handle it here. 406 // PC relative addressing: %PC + 16-bit displacement! 407 if (AM.isPCRelative()) { 408 // FIXME JumpTable and ExternalSymbol address currently don't like 409 // displacements. It isn't very important, but should be fixed for 410 // consistency. 411 412 if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(N)) 413 if (foldOffsetIntoAddress(Cst->getSExtValue(), AM)) 414 return true; 415 return false; 416 } 417 418 switch (N.getOpcode()) { 419 default: 420 break; 421 422 case ISD::Constant: { 423 uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue(); 424 if (foldOffsetIntoAddress(Val, AM)) 425 return true; 426 break; 427 } 428 429 case M68kISD::Wrapper: 430 case M68kISD::WrapperPC: 431 if (matchWrapper(N, AM)) 432 return true; 433 break; 434 435 case ISD::LOAD: 436 if (matchLoadInAddress(cast<LoadSDNode>(N), AM)) 437 return true; 438 break; 439 440 case ISD::OR: 441 // We want to look through a transform in InstCombine and DAGCombiner that 442 // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'. 443 // Example: (or (and x, 1), (shl y, 3)) --> (add (and x, 1), (shl y, 3)) 444 // An 'lea' can then be used to match the shift (multiply) and add: 445 // and $1, %esi 446 // lea (%rsi, %rdi, 8), %rax 447 if (CurDAG->haveNoCommonBitsSet(N.getOperand(0), N.getOperand(1)) && 448 matchADD(N, AM, Depth)) 449 return true; 450 break; 451 452 case ISD::ADD: 453 if (matchADD(N, AM, Depth)) 454 return true; 455 break; 456 457 case ISD::FrameIndex: 458 if (AM.isDispAddrType() && 459 AM.BaseType == M68kISelAddressMode::Base::RegBase && 460 AM.BaseReg.getNode() == nullptr && doesDispFitFI(AM)) { 461 AM.BaseType = M68kISelAddressMode::Base::FrameIndexBase; 462 AM.BaseFrameIndex = cast<FrameIndexSDNode>(N)->getIndex(); 463 return true; 464 } 465 break; 466 } 467 468 return matchAddressBase(N, AM); 469 } 470 471 /// Add the specified node to the specified addressing mode, returning true if 472 /// it cannot be done. This just pattern matches for the addressing mode. 473 bool M68kDAGToDAGISel::matchAddress(SDValue N, M68kISelAddressMode &AM) { 474 // TODO: Post-processing: Convert lea(,%reg,2) to lea(%reg,%reg), which has 475 // a smaller encoding and avoids a scaled-index. 476 // And make sure it is an indexed mode 477 478 // TODO: Post-processing: Convert foo to foo(%pc), even in non-PIC mode, 479 // because it has a smaller encoding. 480 // Make sure this must be done only if PC* modes are currently being matched 481 return matchAddressRecursively(N, AM, 0); 482 } 483 484 bool M68kDAGToDAGISel::matchADD(SDValue &N, M68kISelAddressMode &AM, 485 unsigned Depth) { 486 // Add an artificial use to this node so that we can keep track of 487 // it if it gets CSE'd with a different node. 488 HandleSDNode Handle(N); 489 490 M68kISelAddressMode Backup = AM; 491 if (matchAddressRecursively(N.getOperand(0), AM, Depth + 1) && 492 matchAddressRecursively(Handle.getValue().getOperand(1), AM, Depth + 1)) { 493 return true; 494 } 495 AM = Backup; 496 497 // Try again after commuting the operands. 498 if (matchAddressRecursively(Handle.getValue().getOperand(1), AM, Depth + 1) && 499 matchAddressRecursively(Handle.getValue().getOperand(0), AM, Depth + 1)) { 500 return true; 501 } 502 AM = Backup; 503 504 // If we couldn't fold both operands into the address at the same time, 505 // see if we can just put each operand into a register and fold at least 506 // the add. 507 if (!AM.hasBase() && !AM.hasIndexReg()) { 508 N = Handle.getValue(); 509 AM.BaseReg = N.getOperand(0); 510 AM.IndexReg = N.getOperand(1); 511 AM.Scale = 1; 512 return true; 513 } 514 515 N = Handle.getValue(); 516 return false; 517 } 518 519 /// Try to match M68kISD::Wrapper and M68kISD::WrapperPC nodes into an 520 /// addressing mode. These wrap things that will resolve down into a symbol 521 /// reference. If no match is possible, this returns true, otherwise it returns 522 /// false. 523 bool M68kDAGToDAGISel::matchWrapper(SDValue N, M68kISelAddressMode &AM) { 524 // If the addressing mode already has a symbol as the displacement, we can 525 // never match another symbol. 526 if (AM.hasSymbolicDisplacement()) 527 return false; 528 529 SDValue N0 = N.getOperand(0); 530 531 if (N.getOpcode() == M68kISD::WrapperPC) { 532 533 // If cannot match here just restore the old version 534 M68kISelAddressMode Backup = AM; 535 536 if (AM.hasBase()) { 537 return false; 538 } 539 540 if (auto *G = dyn_cast<GlobalAddressSDNode>(N0)) { 541 AM.GV = G->getGlobal(); 542 AM.SymbolFlags = G->getTargetFlags(); 543 if (!foldOffsetIntoAddress(G->getOffset(), AM)) { 544 AM = Backup; 545 return false; 546 } 547 } else if (auto *CP = dyn_cast<ConstantPoolSDNode>(N0)) { 548 AM.CP = CP->getConstVal(); 549 AM.Alignment = CP->getAlign(); 550 AM.SymbolFlags = CP->getTargetFlags(); 551 if (!foldOffsetIntoAddress(CP->getOffset(), AM)) { 552 AM = Backup; 553 return false; 554 } 555 } else if (auto *S = dyn_cast<ExternalSymbolSDNode>(N0)) { 556 AM.ES = S->getSymbol(); 557 AM.SymbolFlags = S->getTargetFlags(); 558 } else if (auto *S = dyn_cast<MCSymbolSDNode>(N0)) { 559 AM.MCSym = S->getMCSymbol(); 560 } else if (auto *J = dyn_cast<JumpTableSDNode>(N0)) { 561 AM.JT = J->getIndex(); 562 AM.SymbolFlags = J->getTargetFlags(); 563 } else if (auto *BA = dyn_cast<BlockAddressSDNode>(N0)) { 564 AM.BlockAddr = BA->getBlockAddress(); 565 AM.SymbolFlags = BA->getTargetFlags(); 566 if (!foldOffsetIntoAddress(BA->getOffset(), AM)) { 567 AM = Backup; 568 return false; 569 } 570 } else 571 llvm_unreachable("Unhandled symbol reference node."); 572 573 AM.setBaseReg(CurDAG->getRegister(M68k::PC, MVT::i32)); 574 return true; 575 } 576 577 // This wrapper requires 32bit disp/imm field for Medium CM 578 if (!AM.isDisp32()) { 579 return false; 580 } 581 582 if (N.getOpcode() == M68kISD::Wrapper) { 583 if (auto *G = dyn_cast<GlobalAddressSDNode>(N0)) { 584 AM.GV = G->getGlobal(); 585 AM.Disp += G->getOffset(); 586 AM.SymbolFlags = G->getTargetFlags(); 587 } else if (auto *CP = dyn_cast<ConstantPoolSDNode>(N0)) { 588 AM.CP = CP->getConstVal(); 589 AM.Alignment = CP->getAlign(); 590 AM.Disp += CP->getOffset(); 591 AM.SymbolFlags = CP->getTargetFlags(); 592 } else if (auto *S = dyn_cast<ExternalSymbolSDNode>(N0)) { 593 AM.ES = S->getSymbol(); 594 AM.SymbolFlags = S->getTargetFlags(); 595 } else if (auto *S = dyn_cast<MCSymbolSDNode>(N0)) { 596 AM.MCSym = S->getMCSymbol(); 597 } else if (auto *J = dyn_cast<JumpTableSDNode>(N0)) { 598 AM.JT = J->getIndex(); 599 AM.SymbolFlags = J->getTargetFlags(); 600 } else if (auto *BA = dyn_cast<BlockAddressSDNode>(N0)) { 601 AM.BlockAddr = BA->getBlockAddress(); 602 AM.Disp += BA->getOffset(); 603 AM.SymbolFlags = BA->getTargetFlags(); 604 } else 605 llvm_unreachable("Unhandled symbol reference node."); 606 return true; 607 } 608 609 return false; 610 } 611 612 //===----------------------------------------------------------------------===// 613 // Selectors 614 //===----------------------------------------------------------------------===// 615 616 void M68kDAGToDAGISel::Select(SDNode *Node) { 617 unsigned Opcode = Node->getOpcode(); 618 SDLoc DL(Node); 619 620 LLVM_DEBUG(dbgs() << "Selecting: "; Node->dump(CurDAG); dbgs() << '\n'); 621 622 if (Node->isMachineOpcode()) { 623 LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << '\n'); 624 Node->setNodeId(-1); 625 return; // Already selected. 626 } 627 628 switch (Opcode) { 629 default: 630 break; 631 632 case M68kISD::GLOBAL_BASE_REG: 633 ReplaceNode(Node, getGlobalBaseReg()); 634 return; 635 } 636 637 SelectCode(Node); 638 } 639 640 bool M68kDAGToDAGISel::SelectARIPI(SDNode *Parent, SDValue N, SDValue &Base) { 641 LLVM_DEBUG(dbgs() << "Selecting AddrType::ARIPI: "); 642 LLVM_DEBUG(dbgs() << "NOT IMPLEMENTED\n"); 643 return false; 644 } 645 646 bool M68kDAGToDAGISel::SelectARIPD(SDNode *Parent, SDValue N, SDValue &Base) { 647 LLVM_DEBUG(dbgs() << "Selecting AddrType::ARIPD: "); 648 LLVM_DEBUG(dbgs() << "NOT IMPLEMENTED\n"); 649 return false; 650 } 651 652 bool M68kDAGToDAGISel::SelectARID(SDNode *Parent, SDValue N, SDValue &Disp, 653 SDValue &Base) { 654 LLVM_DEBUG(dbgs() << "Selecting AddrType::ARID: "); 655 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARID); 656 657 if (!matchAddress(N, AM)) 658 return false; 659 660 if (AM.isPCRelative()) { 661 LLVM_DEBUG(dbgs() << "REJECT: Cannot match PC relative address\n"); 662 return false; 663 } 664 665 // If this is a frame index, grab it 666 if (getFrameIndexAddress(AM, SDLoc(N), Disp, Base)) { 667 LLVM_DEBUG(dbgs() << "SUCCESS matched FI\n"); 668 return true; 669 } 670 671 if (AM.hasIndexReg()) { 672 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Index\n"); 673 return false; 674 } 675 676 if (!AM.hasBaseReg()) { 677 LLVM_DEBUG(dbgs() << "REJECT: No Base reg\n"); 678 return false; 679 } 680 681 if (getSymbolicDisplacement(AM, SDLoc(N), Disp)) { 682 assert(!AM.Disp && "Should not be any displacement"); 683 LLVM_DEBUG(dbgs() << "SUCCESS, matched Symbol\n"); 684 return true; 685 } 686 687 // Give a chance to AddrType::ARI 688 if (AM.Disp == 0) { 689 LLVM_DEBUG(dbgs() << "REJECT: No displacement\n"); 690 return false; 691 } 692 693 Base = AM.BaseReg; 694 Disp = getI16Imm(AM.Disp, SDLoc(N)); 695 696 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 697 return true; 698 } 699 700 static bool isAddressBase(const SDValue &N) { 701 switch (N.getOpcode()) { 702 case ISD::ADD: 703 case ISD::ADDC: 704 return llvm::any_of(N.getNode()->ops(), 705 [](const SDUse &U) { return isAddressBase(U.get()); }); 706 case M68kISD::Wrapper: 707 case M68kISD::WrapperPC: 708 case M68kISD::GLOBAL_BASE_REG: 709 return true; 710 default: 711 return false; 712 } 713 } 714 715 bool M68kDAGToDAGISel::SelectARII(SDNode *Parent, SDValue N, SDValue &Disp, 716 SDValue &Base, SDValue &Index) { 717 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARII); 718 LLVM_DEBUG(dbgs() << "Selecting AddrType::ARII: "); 719 720 if (!matchAddress(N, AM)) 721 return false; 722 723 if (AM.isPCRelative()) { 724 LLVM_DEBUG(dbgs() << "REJECT: PC relative\n"); 725 return false; 726 } 727 728 if (!AM.hasIndexReg()) { 729 LLVM_DEBUG(dbgs() << "REJECT: No Index\n"); 730 return false; 731 } 732 733 if (!AM.hasBaseReg()) { 734 LLVM_DEBUG(dbgs() << "REJECT: No Base\n"); 735 return false; 736 } 737 738 if (!isAddressBase(AM.BaseReg) && isAddressBase(AM.IndexReg)) { 739 Base = AM.IndexReg; 740 Index = AM.BaseReg; 741 } else { 742 Base = AM.BaseReg; 743 Index = AM.IndexReg; 744 } 745 746 if (AM.hasSymbolicDisplacement()) { 747 LLVM_DEBUG(dbgs() << "REJECT, Cannot match symbolic displacement\n"); 748 return false; 749 } 750 751 // The idea here is that we want to use AddrType::ARII without displacement 752 // only if necessary like memory operations, otherwise this must be lowered 753 // into addition 754 if (AM.Disp == 0 && (!Parent || (Parent->getOpcode() != ISD::LOAD && 755 Parent->getOpcode() != ISD::STORE))) { 756 LLVM_DEBUG(dbgs() << "REJECT: Displacement is Zero\n"); 757 return false; 758 } 759 760 Disp = getI8Imm(AM.Disp, SDLoc(N)); 761 762 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 763 return true; 764 } 765 766 bool M68kDAGToDAGISel::SelectAL(SDNode *Parent, SDValue N, SDValue &Sym) { 767 LLVM_DEBUG(dbgs() << "Selecting AddrType::AL: "); 768 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::AL); 769 770 if (!matchAddress(N, AM)) { 771 LLVM_DEBUG(dbgs() << "REJECT: Match failed\n"); 772 return false; 773 } 774 775 if (AM.isPCRelative()) { 776 LLVM_DEBUG(dbgs() << "REJECT: Cannot match PC relative address\n"); 777 return false; 778 } 779 780 if (AM.hasBase()) { 781 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Base\n"); 782 return false; 783 } 784 785 if (AM.hasIndexReg()) { 786 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Index\n"); 787 return false; 788 } 789 790 if (getSymbolicDisplacement(AM, SDLoc(N), Sym)) { 791 LLVM_DEBUG(dbgs() << "SUCCESS: Matched symbol\n"); 792 return true; 793 } 794 795 if (AM.Disp) { 796 Sym = getI32Imm(AM.Disp, SDLoc(N)); 797 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 798 return true; 799 } 800 801 LLVM_DEBUG(dbgs() << "REJECT: Not Symbol or Disp\n"); 802 return false; 803 ; 804 } 805 806 bool M68kDAGToDAGISel::SelectPCD(SDNode *Parent, SDValue N, SDValue &Disp) { 807 LLVM_DEBUG(dbgs() << "Selecting AddrType::PCD: "); 808 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::PCD); 809 810 if (!matchAddress(N, AM)) 811 return false; 812 813 if (!AM.isPCRelative()) { 814 LLVM_DEBUG(dbgs() << "REJECT: Not PC relative\n"); 815 return false; 816 } 817 818 if (AM.hasIndexReg()) { 819 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Index\n"); 820 return false; 821 } 822 823 if (getSymbolicDisplacement(AM, SDLoc(N), Disp)) { 824 LLVM_DEBUG(dbgs() << "SUCCESS, matched Symbol\n"); 825 return true; 826 } 827 828 Disp = getI16Imm(AM.Disp, SDLoc(N)); 829 830 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 831 return true; 832 } 833 834 bool M68kDAGToDAGISel::SelectPCI(SDNode *Parent, SDValue N, SDValue &Disp, 835 SDValue &Index) { 836 LLVM_DEBUG(dbgs() << "Selecting AddrType::PCI: "); 837 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::PCI); 838 839 if (!matchAddress(N, AM)) 840 return false; 841 842 if (!AM.isPCRelative()) { 843 LLVM_DEBUG(dbgs() << "REJECT: Not PC relative\n"); 844 return false; 845 } 846 847 if (!AM.hasIndexReg()) { 848 LLVM_DEBUG(dbgs() << "REJECT: No Index\n"); 849 return false; 850 } 851 852 Index = AM.IndexReg; 853 854 if (getSymbolicDisplacement(AM, SDLoc(N), Disp)) { 855 assert(!AM.Disp && "Should not be any displacement"); 856 LLVM_DEBUG(dbgs() << "SUCCESS, matched Symbol\n"); 857 return true; 858 } 859 860 Disp = getI8Imm(AM.Disp, SDLoc(N)); 861 862 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 863 return true; 864 } 865 866 bool M68kDAGToDAGISel::SelectARI(SDNode *Parent, SDValue N, SDValue &Base) { 867 LLVM_DEBUG(dbgs() << "Selecting AddrType::ARI: "); 868 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARI); 869 870 if (!matchAddress(N, AM)) { 871 LLVM_DEBUG(dbgs() << "REJECT: Match failed\n"); 872 return false; 873 } 874 875 if (AM.isPCRelative()) { 876 LLVM_DEBUG(dbgs() << "REJECT: Cannot match PC relative address\n"); 877 return false; 878 } 879 880 // AddrType::ARI does not use these 881 if (AM.hasIndexReg() || AM.Disp != 0) { 882 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Index or Disp\n"); 883 return false; 884 } 885 886 // Must be matched by AddrType::AL 887 if (AM.hasSymbolicDisplacement()) { 888 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Symbolic Disp\n"); 889 return false; 890 } 891 892 if (AM.hasBaseReg()) { 893 Base = AM.BaseReg; 894 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 895 return true; 896 } 897 898 return false; 899 } 900