#include "M68k.h"
#include "M68kMachineFunction.h"
#include "M68kRegisterInfo.h"
#include "M68kTargetMachine.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/Alignment.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
#define DEBUG_TYPE "m68k-isel"
namespace {
struct M68kISelAddressMode {
enum class AddrType {
ARI, ARIPI, ARIPD, ARID, ARII, PCD, PCI, AL, };
AddrType AM;
enum class Base { RegBase, FrameIndexBase };
Base BaseType;
int64_t Disp;
SDValue BaseReg;
int BaseFrameIndex;
SDValue IndexReg;
unsigned Scale;
const GlobalValue *GV;
const Constant *CP;
const BlockAddress *BlockAddr;
const char *ES;
MCSymbol *MCSym;
int JT;
Align Alignment;
unsigned char SymbolFlags;
M68kISelAddressMode(AddrType AT)
: AM(AT), BaseType(Base::RegBase), Disp(0), BaseFrameIndex(0), IndexReg(),
Scale(1), GV(nullptr), CP(nullptr), BlockAddr(nullptr), ES(nullptr),
MCSym(nullptr), JT(-1), Alignment(), SymbolFlags(M68kII::MO_NO_FLAG) {}
bool hasSymbolicDisplacement() const {
return GV != nullptr || CP != nullptr || ES != nullptr ||
MCSym != nullptr || JT != -1 || BlockAddr != nullptr;
}
bool hasBase() const {
return BaseType == Base::FrameIndexBase || BaseReg.getNode() != nullptr;
}
bool hasFrameIndex() const { return BaseType == Base::FrameIndexBase; }
bool hasBaseReg() const {
return BaseType == Base::RegBase && BaseReg.getNode() != nullptr;
}
bool hasIndexReg() const {
return BaseType == Base::RegBase && IndexReg.getNode() != nullptr;
}
bool isDispAddrType() const {
return AM == AddrType::ARII || AM == AddrType::PCI ||
AM == AddrType::ARID || AM == AddrType::PCD || AM == AddrType::AL;
}
unsigned getDispSize() const {
switch (AM) {
default:
return 0;
case AddrType::ARII:
case AddrType::PCI:
return 8;
case AddrType::ARID:
case AddrType::PCD:
return 16;
case AddrType::AL:
return 32;
}
}
bool hasDisp() const { return getDispSize() != 0; }
bool isDisp8() const { return getDispSize() == 8; }
bool isDisp16() const { return getDispSize() == 16; }
bool isDisp32() const { return getDispSize() == 32; }
bool isPCRelative() const {
if (BaseType != Base::RegBase)
return false;
if (auto *RegNode = dyn_cast_or_null<RegisterSDNode>(BaseReg.getNode()))
return RegNode->getReg() == M68k::PC;
return false;
}
void setBaseReg(SDValue Reg) {
BaseType = Base::RegBase;
BaseReg = Reg;
}
void setIndexReg(SDValue Reg) { IndexReg = Reg; }
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void dump() {
dbgs() << "M68kISelAddressMode " << this;
dbgs() << "\nDisp: " << Disp;
dbgs() << ", BaseReg: ";
if (BaseReg.getNode())
BaseReg.getNode()->dump();
else
dbgs() << "null";
dbgs() << ", BaseFI: " << BaseFrameIndex;
dbgs() << ", IndexReg: ";
if (IndexReg.getNode()) {
IndexReg.getNode()->dump();
} else {
dbgs() << "null";
dbgs() << ", Scale: " << Scale;
}
dbgs() << '\n';
}
#endif
};
}
namespace {
class M68kDAGToDAGISel : public SelectionDAGISel {
public:
explicit M68kDAGToDAGISel(M68kTargetMachine &TM)
: SelectionDAGISel(TM), Subtarget(nullptr) {}
StringRef getPassName() const override {
return "M68k DAG->DAG Pattern Instruction Selection";
}
bool runOnMachineFunction(MachineFunction &MF) override;
bool IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const override;
private:
const M68kSubtarget *Subtarget;
#include "M68kGenDAGISel.inc"
const M68kTargetMachine &getTargetMachine() {
return static_cast<const M68kTargetMachine &>(TM);
}
void Select(SDNode *N) override;
void initGlobalBaseReg(MachineFunction &MF);
bool foldOffsetIntoAddress(uint64_t Offset, M68kISelAddressMode &AM);
bool matchLoadInAddress(LoadSDNode *N, M68kISelAddressMode &AM);
bool matchAddress(SDValue N, M68kISelAddressMode &AM);
bool matchAddressBase(SDValue N, M68kISelAddressMode &AM);
bool matchAddressRecursively(SDValue N, M68kISelAddressMode &AM,
unsigned Depth);
bool matchADD(SDValue &N, M68kISelAddressMode &AM, unsigned Depth);
bool matchWrapper(SDValue N, M68kISelAddressMode &AM);
std::pair<bool, SDNode *> selectNode(SDNode *Node);
bool SelectARI(SDNode *Parent, SDValue N, SDValue &Base);
bool SelectARIPI(SDNode *Parent, SDValue N, SDValue &Base);
bool SelectARIPD(SDNode *Parent, SDValue N, SDValue &Base);
bool SelectARID(SDNode *Parent, SDValue N, SDValue &Imm, SDValue &Base);
bool SelectARII(SDNode *Parent, SDValue N, SDValue &Imm, SDValue &Base,
SDValue &Index);
bool SelectAL(SDNode *Parent, SDValue N, SDValue &Sym);
bool SelectPCD(SDNode *Parent, SDValue N, SDValue &Imm);
bool SelectPCI(SDNode *Parent, SDValue N, SDValue &Imm, SDValue &Index);
inline bool getFrameIndexAddress(M68kISelAddressMode &AM, const SDLoc &DL,
SDValue &Disp, SDValue &Base) {
if (AM.BaseType == M68kISelAddressMode::Base::FrameIndexBase) {
Disp = getI32Imm(AM.Disp, DL);
Base = CurDAG->getTargetFrameIndex(
AM.BaseFrameIndex, TLI->getPointerTy(CurDAG->getDataLayout()));
return true;
}
return false;
}
inline bool getSymbolicDisplacement(M68kISelAddressMode &AM, const SDLoc &DL,
SDValue &Sym) {
if (AM.GV) {
Sym = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(), MVT::i32, AM.Disp,
AM.SymbolFlags);
return true;
}
if (AM.CP) {
Sym = CurDAG->getTargetConstantPool(AM.CP, MVT::i32, AM.Alignment,
AM.Disp, AM.SymbolFlags);
return true;
}
if (AM.ES) {
assert(!AM.Disp && "Non-zero displacement is ignored with ES.");
Sym = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32, AM.SymbolFlags);
return true;
}
if (AM.MCSym) {
assert(!AM.Disp && "Non-zero displacement is ignored with MCSym.");
assert(AM.SymbolFlags == 0 && "oo");
Sym = CurDAG->getMCSymbol(AM.MCSym, MVT::i32);
return true;
}
if (AM.JT != -1) {
assert(!AM.Disp && "Non-zero displacement is ignored with JT.");
Sym = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags);
return true;
}
if (AM.BlockAddr) {
Sym = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, AM.Disp,
AM.SymbolFlags);
return true;
}
return false;
}
inline SDValue getI8Imm(int64_t Imm, const SDLoc &DL) {
return CurDAG->getTargetConstant(Imm, DL, MVT::i8);
}
inline SDValue getI16Imm(int64_t Imm, const SDLoc &DL) {
return CurDAG->getTargetConstant(Imm, DL, MVT::i16);
}
inline SDValue getI32Imm(int64_t Imm, const SDLoc &DL) {
return CurDAG->getTargetConstant(Imm, DL, MVT::i32);
}
const M68kInstrInfo *getInstrInfo() const {
return Subtarget->getInstrInfo();
}
SDNode *getGlobalBaseReg();
};
}
bool M68kDAGToDAGISel::IsProfitableToFold(SDValue N, SDNode *U,
SDNode *Root) const {
if (OptLevel == CodeGenOpt::None)
return false;
if (U == Root) {
switch (U->getOpcode()) {
default:
return true;
case M68kISD::SUB:
case ISD::SUB:
if (llvm::isNullConstant(U->getOperand(0)))
return false;
break;
}
}
return true;
}
bool M68kDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
Subtarget = &MF.getSubtarget<M68kSubtarget>();
return SelectionDAGISel::runOnMachineFunction(MF);
}
FunctionPass *llvm::createM68kISelDag(M68kTargetMachine &TM) {
return new M68kDAGToDAGISel(TM);
}
static bool doesDispFitFI(M68kISelAddressMode &AM) {
if (!AM.isDispAddrType())
return false;
return isIntN(AM.getDispSize() - 1, AM.Disp);
}
static bool doesDispFit(M68kISelAddressMode &AM, int64_t Val) {
if (!AM.isDispAddrType())
return false;
return isIntN(AM.getDispSize(), Val);
}
SDNode *M68kDAGToDAGISel::getGlobalBaseReg() {
unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF);
auto &DL = MF->getDataLayout();
return CurDAG->getRegister(GlobalBaseReg, TLI->getPointerTy(DL)).getNode();
}
bool M68kDAGToDAGISel::foldOffsetIntoAddress(uint64_t Offset,
M68kISelAddressMode &AM) {
if (Offset != 0 && (AM.ES || AM.MCSym))
return false;
int64_t Val = AM.Disp + Offset;
if (doesDispFit(AM, Val)) {
AM.Disp = Val;
return true;
}
return false;
}
bool M68kDAGToDAGISel::matchAddressBase(SDValue N, M68kISelAddressMode &AM) {
if (AM.hasBase()) {
if (!AM.hasIndexReg()) {
AM.IndexReg = N;
AM.Scale = 1;
return true;
}
return false;
}
AM.BaseType = M68kISelAddressMode::Base::RegBase;
AM.BaseReg = N;
return true;
}
bool M68kDAGToDAGISel::matchLoadInAddress(LoadSDNode *N,
M68kISelAddressMode &AM) {
return false;
}
bool M68kDAGToDAGISel::matchAddressRecursively(SDValue N,
M68kISelAddressMode &AM,
unsigned Depth) {
SDLoc DL(N);
if (Depth > 5)
return matchAddressBase(N, AM);
if (AM.isPCRelative()) {
if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(N))
if (foldOffsetIntoAddress(Cst->getSExtValue(), AM))
return true;
return false;
}
switch (N.getOpcode()) {
default:
break;
case ISD::Constant: {
uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
if (foldOffsetIntoAddress(Val, AM))
return true;
break;
}
case M68kISD::Wrapper:
case M68kISD::WrapperPC:
if (matchWrapper(N, AM))
return true;
break;
case ISD::LOAD:
if (matchLoadInAddress(cast<LoadSDNode>(N), AM))
return true;
break;
case ISD::OR:
if (CurDAG->haveNoCommonBitsSet(N.getOperand(0), N.getOperand(1)) &&
matchADD(N, AM, Depth))
return true;
break;
case ISD::ADD:
if (matchADD(N, AM, Depth))
return true;
break;
case ISD::FrameIndex:
if (AM.isDispAddrType() &&
AM.BaseType == M68kISelAddressMode::Base::RegBase &&
AM.BaseReg.getNode() == nullptr && doesDispFitFI(AM)) {
AM.BaseType = M68kISelAddressMode::Base::FrameIndexBase;
AM.BaseFrameIndex = cast<FrameIndexSDNode>(N)->getIndex();
return true;
}
break;
}
return matchAddressBase(N, AM);
}
bool M68kDAGToDAGISel::matchAddress(SDValue N, M68kISelAddressMode &AM) {
return matchAddressRecursively(N, AM, 0);
}
bool M68kDAGToDAGISel::matchADD(SDValue &N, M68kISelAddressMode &AM,
unsigned Depth) {
HandleSDNode Handle(N);
M68kISelAddressMode Backup = AM;
if (matchAddressRecursively(N.getOperand(0), AM, Depth + 1) &&
matchAddressRecursively(Handle.getValue().getOperand(1), AM, Depth + 1)) {
return true;
}
AM = Backup;
if (matchAddressRecursively(Handle.getValue().getOperand(1), AM, Depth + 1) &&
matchAddressRecursively(Handle.getValue().getOperand(0), AM, Depth + 1)) {
return true;
}
AM = Backup;
if (!AM.hasBase() && !AM.hasIndexReg()) {
N = Handle.getValue();
AM.BaseReg = N.getOperand(0);
AM.IndexReg = N.getOperand(1);
AM.Scale = 1;
return true;
}
N = Handle.getValue();
return false;
}
bool M68kDAGToDAGISel::matchWrapper(SDValue N, M68kISelAddressMode &AM) {
if (AM.hasSymbolicDisplacement())
return false;
SDValue N0 = N.getOperand(0);
if (N.getOpcode() == M68kISD::WrapperPC) {
M68kISelAddressMode Backup = AM;
if (AM.hasBase()) {
return false;
}
if (auto *G = dyn_cast<GlobalAddressSDNode>(N0)) {
AM.GV = G->getGlobal();
AM.SymbolFlags = G->getTargetFlags();
if (!foldOffsetIntoAddress(G->getOffset(), AM)) {
AM = Backup;
return false;
}
} else if (auto *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
AM.CP = CP->getConstVal();
AM.Alignment = CP->getAlign();
AM.SymbolFlags = CP->getTargetFlags();
if (!foldOffsetIntoAddress(CP->getOffset(), AM)) {
AM = Backup;
return false;
}
} else if (auto *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
AM.ES = S->getSymbol();
AM.SymbolFlags = S->getTargetFlags();
} else if (auto *S = dyn_cast<MCSymbolSDNode>(N0)) {
AM.MCSym = S->getMCSymbol();
} else if (auto *J = dyn_cast<JumpTableSDNode>(N0)) {
AM.JT = J->getIndex();
AM.SymbolFlags = J->getTargetFlags();
} else if (auto *BA = dyn_cast<BlockAddressSDNode>(N0)) {
AM.BlockAddr = BA->getBlockAddress();
AM.SymbolFlags = BA->getTargetFlags();
if (!foldOffsetIntoAddress(BA->getOffset(), AM)) {
AM = Backup;
return false;
}
} else
llvm_unreachable("Unhandled symbol reference node.");
AM.setBaseReg(CurDAG->getRegister(M68k::PC, MVT::i32));
return true;
}
if (!AM.isDisp32()) {
return false;
}
if (N.getOpcode() == M68kISD::Wrapper) {
if (auto *G = dyn_cast<GlobalAddressSDNode>(N0)) {
AM.GV = G->getGlobal();
AM.Disp += G->getOffset();
AM.SymbolFlags = G->getTargetFlags();
} else if (auto *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
AM.CP = CP->getConstVal();
AM.Alignment = CP->getAlign();
AM.Disp += CP->getOffset();
AM.SymbolFlags = CP->getTargetFlags();
} else if (auto *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
AM.ES = S->getSymbol();
AM.SymbolFlags = S->getTargetFlags();
} else if (auto *S = dyn_cast<MCSymbolSDNode>(N0)) {
AM.MCSym = S->getMCSymbol();
} else if (auto *J = dyn_cast<JumpTableSDNode>(N0)) {
AM.JT = J->getIndex();
AM.SymbolFlags = J->getTargetFlags();
} else if (auto *BA = dyn_cast<BlockAddressSDNode>(N0)) {
AM.BlockAddr = BA->getBlockAddress();
AM.Disp += BA->getOffset();
AM.SymbolFlags = BA->getTargetFlags();
} else
llvm_unreachable("Unhandled symbol reference node.");
return true;
}
return false;
}
void M68kDAGToDAGISel::Select(SDNode *Node) {
unsigned Opcode = Node->getOpcode();
SDLoc DL(Node);
LLVM_DEBUG(dbgs() << "Selecting: "; Node->dump(CurDAG); dbgs() << '\n');
if (Node->isMachineOpcode()) {
LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << '\n');
Node->setNodeId(-1);
return; }
switch (Opcode) {
default:
break;
case M68kISD::GLOBAL_BASE_REG:
ReplaceNode(Node, getGlobalBaseReg());
return;
}
SelectCode(Node);
}
bool M68kDAGToDAGISel::SelectARIPI(SDNode *Parent, SDValue N, SDValue &Base) {
LLVM_DEBUG(dbgs() << "Selecting AddrType::ARIPI: ");
LLVM_DEBUG(dbgs() << "NOT IMPLEMENTED\n");
return false;
}
bool M68kDAGToDAGISel::SelectARIPD(SDNode *Parent, SDValue N, SDValue &Base) {
LLVM_DEBUG(dbgs() << "Selecting AddrType::ARIPD: ");
LLVM_DEBUG(dbgs() << "NOT IMPLEMENTED\n");
return false;
}
bool M68kDAGToDAGISel::SelectARID(SDNode *Parent, SDValue N, SDValue &Disp,
SDValue &Base) {
LLVM_DEBUG(dbgs() << "Selecting AddrType::ARID: ");
M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARID);
if (!matchAddress(N, AM))
return false;
if (AM.isPCRelative()) {
LLVM_DEBUG(dbgs() << "REJECT: Cannot match PC relative address\n");
return false;
}
if (getFrameIndexAddress(AM, SDLoc(N), Disp, Base)) {
LLVM_DEBUG(dbgs() << "SUCCESS matched FI\n");
return true;
}
if (AM.hasIndexReg()) {
LLVM_DEBUG(dbgs() << "REJECT: Cannot match Index\n");
return false;
}
if (!AM.hasBaseReg()) {
LLVM_DEBUG(dbgs() << "REJECT: No Base reg\n");
return false;
}
if (getSymbolicDisplacement(AM, SDLoc(N), Disp)) {
assert(!AM.Disp && "Should not be any displacement");
LLVM_DEBUG(dbgs() << "SUCCESS, matched Symbol\n");
return true;
}
if (AM.Disp == 0) {
LLVM_DEBUG(dbgs() << "REJECT: No displacement\n");
return false;
}
Base = AM.BaseReg;
Disp = getI16Imm(AM.Disp, SDLoc(N));
LLVM_DEBUG(dbgs() << "SUCCESS\n");
return true;
}
static bool isAddressBase(const SDValue &N) {
switch (N.getOpcode()) {
case ISD::ADD:
case ISD::ADDC:
return llvm::any_of(N.getNode()->ops(),
[](const SDUse &U) { return isAddressBase(U.get()); });
case M68kISD::Wrapper:
case M68kISD::WrapperPC:
case M68kISD::GLOBAL_BASE_REG:
return true;
default:
return false;
}
}
bool M68kDAGToDAGISel::SelectARII(SDNode *Parent, SDValue N, SDValue &Disp,
SDValue &Base, SDValue &Index) {
M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARII);
LLVM_DEBUG(dbgs() << "Selecting AddrType::ARII: ");
if (!matchAddress(N, AM))
return false;
if (AM.isPCRelative()) {
LLVM_DEBUG(dbgs() << "REJECT: PC relative\n");
return false;
}
if (!AM.hasIndexReg()) {
LLVM_DEBUG(dbgs() << "REJECT: No Index\n");
return false;
}
if (!AM.hasBaseReg()) {
LLVM_DEBUG(dbgs() << "REJECT: No Base\n");
return false;
}
if (!isAddressBase(AM.BaseReg) && isAddressBase(AM.IndexReg)) {
Base = AM.IndexReg;
Index = AM.BaseReg;
} else {
Base = AM.BaseReg;
Index = AM.IndexReg;
}
if (AM.hasSymbolicDisplacement()) {
LLVM_DEBUG(dbgs() << "REJECT, Cannot match symbolic displacement\n");
return false;
}
if (AM.Disp == 0 && (!Parent || (Parent->getOpcode() != ISD::LOAD &&
Parent->getOpcode() != ISD::STORE))) {
LLVM_DEBUG(dbgs() << "REJECT: Displacement is Zero\n");
return false;
}
Disp = getI8Imm(AM.Disp, SDLoc(N));
LLVM_DEBUG(dbgs() << "SUCCESS\n");
return true;
}
bool M68kDAGToDAGISel::SelectAL(SDNode *Parent, SDValue N, SDValue &Sym) {
LLVM_DEBUG(dbgs() << "Selecting AddrType::AL: ");
M68kISelAddressMode AM(M68kISelAddressMode::AddrType::AL);
if (!matchAddress(N, AM)) {
LLVM_DEBUG(dbgs() << "REJECT: Match failed\n");
return false;
}
if (AM.isPCRelative()) {
LLVM_DEBUG(dbgs() << "REJECT: Cannot match PC relative address\n");
return false;
}
if (AM.hasBase()) {
LLVM_DEBUG(dbgs() << "REJECT: Cannot match Base\n");
return false;
}
if (AM.hasIndexReg()) {
LLVM_DEBUG(dbgs() << "REJECT: Cannot match Index\n");
return false;
}
if (getSymbolicDisplacement(AM, SDLoc(N), Sym)) {
LLVM_DEBUG(dbgs() << "SUCCESS: Matched symbol\n");
return true;
}
if (AM.Disp) {
Sym = getI32Imm(AM.Disp, SDLoc(N));
LLVM_DEBUG(dbgs() << "SUCCESS\n");
return true;
}
LLVM_DEBUG(dbgs() << "REJECT: Not Symbol or Disp\n");
return false;
;
}
bool M68kDAGToDAGISel::SelectPCD(SDNode *Parent, SDValue N, SDValue &Disp) {
LLVM_DEBUG(dbgs() << "Selecting AddrType::PCD: ");
M68kISelAddressMode AM(M68kISelAddressMode::AddrType::PCD);
if (!matchAddress(N, AM))
return false;
if (!AM.isPCRelative()) {
LLVM_DEBUG(dbgs() << "REJECT: Not PC relative\n");
return false;
}
if (AM.hasIndexReg()) {
LLVM_DEBUG(dbgs() << "REJECT: Cannot match Index\n");
return false;
}
if (getSymbolicDisplacement(AM, SDLoc(N), Disp)) {
LLVM_DEBUG(dbgs() << "SUCCESS, matched Symbol\n");
return true;
}
Disp = getI16Imm(AM.Disp, SDLoc(N));
LLVM_DEBUG(dbgs() << "SUCCESS\n");
return true;
}
bool M68kDAGToDAGISel::SelectPCI(SDNode *Parent, SDValue N, SDValue &Disp,
SDValue &Index) {
LLVM_DEBUG(dbgs() << "Selecting AddrType::PCI: ");
M68kISelAddressMode AM(M68kISelAddressMode::AddrType::PCI);
if (!matchAddress(N, AM))
return false;
if (!AM.isPCRelative()) {
LLVM_DEBUG(dbgs() << "REJECT: Not PC relative\n");
return false;
}
if (!AM.hasIndexReg()) {
LLVM_DEBUG(dbgs() << "REJECT: No Index\n");
return false;
}
Index = AM.IndexReg;
if (getSymbolicDisplacement(AM, SDLoc(N), Disp)) {
assert(!AM.Disp && "Should not be any displacement");
LLVM_DEBUG(dbgs() << "SUCCESS, matched Symbol\n");
return true;
}
Disp = getI8Imm(AM.Disp, SDLoc(N));
LLVM_DEBUG(dbgs() << "SUCCESS\n");
return true;
}
bool M68kDAGToDAGISel::SelectARI(SDNode *Parent, SDValue N, SDValue &Base) {
LLVM_DEBUG(dbgs() << "Selecting AddrType::ARI: ");
M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARI);
if (!matchAddress(N, AM)) {
LLVM_DEBUG(dbgs() << "REJECT: Match failed\n");
return false;
}
if (AM.isPCRelative()) {
LLVM_DEBUG(dbgs() << "REJECT: Cannot match PC relative address\n");
return false;
}
if (AM.hasIndexReg() || AM.Disp != 0) {
LLVM_DEBUG(dbgs() << "REJECT: Cannot match Index or Disp\n");
return false;
}
if (AM.hasSymbolicDisplacement()) {
LLVM_DEBUG(dbgs() << "REJECT: Cannot match Symbolic Disp\n");
return false;
}
if (AM.hasBaseReg()) {
Base = AM.BaseReg;
LLVM_DEBUG(dbgs() << "SUCCESS\n");
return true;
}
return false;
}