llvm-project/llvm/lib/Target/Foot/FootDAGToDAGISel.cpp
2025-10-21 18:25:06 -04:00

242 lines
6.9 KiB
C++

#include "FootISelLowering.h"
#include "Foot.h"
#include "FootTargetMachine.h"
#include "MCTargetDesc/FootMCTargetDesc.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
using namespace llvm;
namespace {
enum FootAddrModes {
FOOT_ADDRMODE_M = 0,
FOOT_ADDRMODE_D = 1,
FOOT_ADDRMODE_I = 2,
FOOT_ADDRMODE_A = 3,
FOOT_ADDRMODE_COUNT = 4
};
} // namespace
class FootDAGToDAGISel : public SelectionDAGISel {
public:
explicit FootDAGToDAGISel(TargetMachine &TM) : SelectionDAGISel(TM) {}
private:
void SelectLoad(SDNode *N, SDLoc &Loc);
void SelectStore(SDNode *N, SDLoc &Loc);
void SelectAdd(SDNode *N, SDLoc &Loc);
void SelectSub(SDNode *N, SDLoc &Loc);
void SelectConstant(SDNode *N, SDLoc &Loc);
void SelectCall(SDNode *N, SDLoc &Loc);
void Select(SDNode *N) override;
#include "FootGenDAGISel.inc"
};
class FootDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
public:
static char ID;
FootDAGToDAGISelLegacy(FootTargetMachine &TM)
: SelectionDAGISelLegacy(ID, std::make_unique<FootDAGToDAGISel>(TM)) {}
StringRef getPassName() const override { return "FootDAGToDAGISelLegacy"; }
};
void FootDAGToDAGISel::SelectLoad(SDNode *N, SDLoc &Loc) {
LoadSDNode *LN = cast<LoadSDNode>(N);
SDValue Addr = LN->getBasePtr();
SDValue Chain = LN->getChain();
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
Addr = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
}
else if (GlobalAddressSDNode *GAN = dyn_cast<GlobalAddressSDNode>(Addr)) {
Addr = CurDAG->getTargetGlobalAddress(GAN->getGlobal(), Loc, MVT::i32);
}
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
SDValue Ops[] = { Addr, Zero, Chain };
SDNode *NewNode = CurDAG->getMachineNode(Foot::BWOR_D_I_M_A, Loc, {MVT::i32, MVT::Other}, Ops);
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectStore(SDNode *N, SDLoc &Loc) {
StoreSDNode *SN = cast<StoreSDNode>(N);
SDValue Val = SN->getValue();
SDValue Addr = SN->getBasePtr();
SDValue Chain = SN->getChain();
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
Addr = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
}
else if (GlobalAddressSDNode *GAN = dyn_cast<GlobalAddressSDNode>(Addr)) {
Addr = CurDAG->getTargetGlobalAddress(GAN->getGlobal(), Loc, MVT::i32);
}
SDValue RegOp = CurDAG->getRegister(Foot::R27, MVT::i32);
SDValue CopyOps[] = { Addr, Chain };
SDNode* CopyNode = CurDAG->getMachineNode(Foot::CNST_D_A_R, Loc, MVT::i32, CopyOps);
SDNode *Store;
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val)) {
SDValue Imm = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
SDValue Ops[] = { Imm };
Store = CurDAG->getMachineNode(Foot::CNST_I_A, Loc, MVT::i32, Ops);
}
else {
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
SDValue Ops[] = { Val, Zero };
Store = CurDAG->getMachineNode(Foot::BWOR_I_D_M_A, Loc, MVT::i32, Ops);
}
SDValue FakeStoreOps[] = { SDValue(Store, 0) };
SDNode* FakeStore = CurDAG->getMachineNode(Foot::PSEUDO_STORE, Loc, MVT::Other, FakeStoreOps);
ReplaceNode(N, FakeStore);
}
void FootDAGToDAGISel::SelectAdd(SDNode *N, SDLoc &Loc) {
SDValue LHS = N->getOperand(0);
SDValue RHS = N->getOperand(1);
int LHS_AddrMode = FOOT_ADDRMODE_D;
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(LHS)) {
LHS = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
LHS_AddrMode = FOOT_ADDRMODE_I;
}
else if (GlobalAddressSDNode *GAN = dyn_cast<GlobalAddressSDNode>(LHS)) {
LHS = CurDAG->getTargetGlobalAddress(GAN->getGlobal(), Loc, MVT::i32);
LHS_AddrMode = FOOT_ADDRMODE_I;
}
else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(LHS)) {
LHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
LHS_AddrMode = FOOT_ADDRMODE_M;
}
int RHS_AddrMode = FOOT_ADDRMODE_D;
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(RHS)) {
RHS = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
RHS_AddrMode = FOOT_ADDRMODE_I;
}
else if (GlobalAddressSDNode *GAN = dyn_cast<GlobalAddressSDNode>(RHS)) {
RHS = CurDAG->getTargetGlobalAddress(GAN->getGlobal(), Loc, MVT::i32);
RHS_AddrMode = FOOT_ADDRMODE_I;
}
else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(RHS)) {
RHS = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
RHS_AddrMode = FOOT_ADDRMODE_M;
}
unsigned Opc = Foot::ADDI_D_D_D_A;
switch (LHS_AddrMode + FOOT_ADDRMODE_COUNT * RHS_AddrMode) {
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT * FOOT_ADDRMODE_M:
Opc = Foot::ADDI_D_D_M_A;
break;
case FOOT_ADDRMODE_D + FOOT_ADDRMODE_COUNT * FOOT_ADDRMODE_I:
Opc = Foot::ADDI_D_D_I_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT * FOOT_ADDRMODE_D:
Opc = Foot::ADDI_D_M_D_A;
break;
case FOOT_ADDRMODE_M + FOOT_ADDRMODE_COUNT * FOOT_ADDRMODE_I:
Opc = Foot::ADDI_D_M_I_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT * FOOT_ADDRMODE_D:
Opc = Foot::ADDI_D_I_D_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT * FOOT_ADDRMODE_M:
Opc = Foot::ADDI_D_I_M_A;
break;
case FOOT_ADDRMODE_I + FOOT_ADDRMODE_COUNT * FOOT_ADDRMODE_I:
Opc = Foot::ADDI_D_I_I_A;
break;
}
SDValue Ops[] = { LHS, RHS };
SDNode *NewNode = CurDAG->getMachineNode(Opc, Loc, MVT::i32, Ops);
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectSub(SDNode *N, SDLoc &Loc) {
llvm_unreachable("not yet implemented");
}
void FootDAGToDAGISel::SelectConstant(SDNode *N, SDLoc &Loc) {
ConstantSDNode *CN = cast<ConstantSDNode>(N);
if (CN->getSExtValue() > 0xFFFF) {
report_fatal_error(">16-bit constants not yet supported");
}
SDValue Val = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
SDNode *NewNode = CurDAG->getMachineNode(Foot::CNST_D_A, Loc, MVT::i32, Val);
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::SelectCall(SDNode *N, SDLoc &Loc) {
SDValue Chain = N->getOperand(0);
SDValue RRA = CurDAG->getRegister(Foot::RRA, MVT::i32);
SDValue RPC = CurDAG->getRegister(Foot::RPC, MVT::i32);
SDValue Zero = CurDAG->getTargetConstant(1, Loc, MVT::i32);
SDValue Ops[] = { RPC, Zero, Chain };
SDNode *Jump = CurDAG->getMachineNode(Foot::ADDI_D_D_M_A, Loc, MVT::i32, Ops);
SDNode *NewNode = CurDAG->getMachineNode(Foot::PSEUDO_CALL, Loc, {MVT::Other, MVT::Glue}, SDValue(Jump, 0));
ReplaceNode(N, NewNode);
}
void FootDAGToDAGISel::Select(SDNode *N) {
if (N->isMachineOpcode()) {
return;
}
SDLoc DL(N);
switch (N->getOpcode()) {
case ISD::LOAD:
SelectLoad(N, DL);
break;
case ISD::STORE:
SelectStore(N, DL);
break;
case ISD::ADD:
SelectAdd(N, DL);
break;
case ISD::SUB:
SelectSub(N, DL);
break;
case ISD::Constant:
SelectConstant(N, DL);
break;
case FootISD::CALL:
SelectCall(N, DL);
break;
default:
SelectCode(N);
break;
}
}
char FootDAGToDAGISelLegacy::ID = 0;
Pass *llvm::createFootISelDAG(FootTargetMachine &TM) {
return new FootDAGToDAGISelLegacy(TM);
}