371 lines
11 KiB
C++
371 lines
11 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 SelectFrameIndex(SDNode *N, SDLoc &Loc);
|
|
void SelectCall(SDNode *N, SDLoc &Loc);
|
|
void SelectBr(SDNode *N, SDLoc &Loc);
|
|
void SelectCmp(SDNode *N, SDLoc &Loc);
|
|
void SelectBrL(SDNode *N, SDLoc &Loc);
|
|
void SelectBrLE(SDNode *N, SDLoc &Loc);
|
|
void SelectBrE(SDNode *N, SDLoc &Loc);
|
|
void SelectBrGE(SDNode *N, SDLoc &Loc);
|
|
void SelectBrG(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();
|
|
|
|
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
|
|
|
|
if (GlobalAddressSDNode *GAN = dyn_cast<GlobalAddressSDNode>(Addr.getNode())) {
|
|
Addr = CurDAG->getTargetGlobalAddress(GAN->getGlobal(), 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();
|
|
|
|
SDNode *Store;
|
|
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode())) {
|
|
Val = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
|
|
SDValue Ops[] = { Addr, Val, Chain };
|
|
Store = CurDAG->getMachineNode(Foot::CNST_STR_I_A, Loc, MVT::Other, Ops);
|
|
}
|
|
else {
|
|
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
|
|
|
|
SDValue Ops[] = { Addr, Val, Zero, Chain };
|
|
Store = CurDAG->getMachineNode(Foot::BWOR_STR_I_D_M_A, Loc, MVT::Other, Ops);
|
|
}
|
|
|
|
ReplaceNode(N, Store);
|
|
}
|
|
|
|
void FootDAGToDAGISel::SelectAdd(SDNode *N, SDLoc &Loc) {
|
|
SDValue LHS = N->getOperand(0);
|
|
SDValue RHS = N->getOperand(1);
|
|
|
|
int LHS_AddrMode = FOOT_ADDRMODE_D;
|
|
|
|
if (isa<FrameIndexSDNode>(LHS.getNode())) {
|
|
LHS_AddrMode = FOOT_ADDRMODE_I;
|
|
}
|
|
else if (isa<GlobalAddressSDNode>(LHS.getNode())) {
|
|
LHS_AddrMode = FOOT_ADDRMODE_I;
|
|
}
|
|
else if (isa<ConstantSDNode>(LHS.getNode())) {
|
|
LHS_AddrMode = FOOT_ADDRMODE_M;
|
|
}
|
|
|
|
int RHS_AddrMode = FOOT_ADDRMODE_D;
|
|
|
|
if (isa<FrameIndexSDNode>(RHS.getNode())) {
|
|
RHS_AddrMode = FOOT_ADDRMODE_I;
|
|
}
|
|
else if (isa<GlobalAddressSDNode>(RHS.getNode())) {
|
|
RHS_AddrMode = FOOT_ADDRMODE_I;
|
|
}
|
|
else if (isa<ConstantSDNode>(RHS.getNode())) {
|
|
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);
|
|
|
|
SDNode *NewNode;
|
|
if (CN->getSExtValue() > 0xFFFF) {
|
|
SDValue Val = CurDAG->getTargetConstantPool(CN->getConstantIntValue(), MVT::i32);
|
|
SDNode *Addr = CurDAG->getMachineNode(Foot::CNST_D_A, Loc, MVT::i32, Val);
|
|
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
|
|
NewNode = CurDAG->getMachineNode(Foot::BWOR_D_I_M_A, Loc, MVT::i32, {SDValue(Addr, 0), Zero});
|
|
}
|
|
else {
|
|
SDValue Val = CurDAG->getTargetConstant(CN->getSExtValue(), Loc, MVT::i32);
|
|
NewNode = CurDAG->getMachineNode(Foot::CNST_D_A, Loc, MVT::i32, Val);
|
|
}
|
|
|
|
ReplaceNode(N, NewNode);
|
|
}
|
|
|
|
void FootDAGToDAGISel::SelectFrameIndex(SDNode *N, SDLoc &Loc) {
|
|
assert(N->getOpcode() == ISD::FrameIndex && "expected frame index");
|
|
|
|
FrameIndexSDNode *FN = cast<FrameIndexSDNode>(N);
|
|
SDValue TFN = CurDAG->getTargetFrameIndex(FN->getIndex(), MVT::i32);
|
|
|
|
ReplaceUses(SDValue(N, 0), TFN);
|
|
CurDAG->RemoveDeadNode(N);
|
|
}
|
|
|
|
void FootDAGToDAGISel::SelectCall(SDNode *N, SDLoc &Loc) {
|
|
SDValue Chain = N->getOperand(0);
|
|
SDValue Callee = N->getOperand(1);
|
|
SDValue RPC = CurDAG->getRegister(Foot::RPC, MVT::i32);
|
|
|
|
SDValue Ops[] = { RPC, Callee, Chain };
|
|
SDNode *Jump = CurDAG->getMachineNode(Foot::CNST_JMP_D_A, Loc, {MVT::Other, MVT::Glue}, Ops);
|
|
|
|
ReplaceNode(N, Jump);
|
|
}
|
|
|
|
void FootDAGToDAGISel::SelectBr(SDNode *N, SDLoc &Loc) {
|
|
SDValue PC = CurDAG->getRegister(Foot::RPC, MVT::i32);
|
|
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
|
|
SDValue Chain = N->getOperand(0);
|
|
SDValue Target = N->getOperand(1);
|
|
|
|
SDNode *NewNode;
|
|
if (isa<BasicBlockSDNode>(Target.getNode()) || isa<GlobalAddressSDNode>(Target.getNode())) {
|
|
NewNode = CurDAG->getMachineNode(Foot::CNST_JMP_D_A, Loc, MVT::Other, {PC, Target, Chain});
|
|
}
|
|
else {
|
|
NewNode = CurDAG->getMachineNode(Foot::BWOR_JMP_D_D_M_A, Loc, MVT::Other, {PC, Target, Zero, Chain});
|
|
}
|
|
|
|
ReplaceNode(N, NewNode);
|
|
}
|
|
|
|
void FootDAGToDAGISel::SelectBrL(SDNode *N, SDLoc &Loc) {
|
|
SDValue PC = CurDAG->getRegister(Foot::RPC, MVT::i32);
|
|
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
|
|
SDValue Chain = N->getOperand(0);
|
|
SDValue Target = N->getOperand(1);
|
|
|
|
SDNode *NewNode;
|
|
if (isa<BasicBlockSDNode>(Target.getNode()) || isa<GlobalAddressSDNode>(Target.getNode())) {
|
|
NewNode = CurDAG->getMachineNode(Foot::CNST_JMP_D_L, Loc, MVT::Other, {PC, Target, Chain});
|
|
}
|
|
else {
|
|
NewNode = CurDAG->getMachineNode(Foot::BWOR_JMP_D_D_M_L, Loc, MVT::Other, {PC, Target, Zero, Chain});
|
|
}
|
|
|
|
ReplaceNode(N, NewNode);
|
|
}
|
|
|
|
void FootDAGToDAGISel::SelectBrLE(SDNode *N, SDLoc &Loc) {
|
|
SDValue PC = CurDAG->getRegister(Foot::RPC, MVT::i32);
|
|
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
|
|
SDValue Chain = N->getOperand(0);
|
|
SDValue Target = N->getOperand(1);
|
|
|
|
SDNode *NewNode;
|
|
if (isa<BasicBlockSDNode>(Target.getNode()) || isa<GlobalAddressSDNode>(Target.getNode())) {
|
|
NewNode = CurDAG->getMachineNode(Foot::CNST_JMP_D_LE, Loc, MVT::Other, {PC, Target, Chain});
|
|
}
|
|
else {
|
|
NewNode = CurDAG->getMachineNode(Foot::BWOR_JMP_D_D_M_LE, Loc, MVT::Other, {PC, Target, Zero, Chain});
|
|
}
|
|
|
|
ReplaceNode(N, NewNode);
|
|
}
|
|
|
|
void FootDAGToDAGISel::SelectBrE(SDNode *N, SDLoc &Loc) {
|
|
SDValue PC = CurDAG->getRegister(Foot::RPC, MVT::i32);
|
|
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
|
|
SDValue Chain = N->getOperand(0);
|
|
SDValue Target = N->getOperand(1);
|
|
|
|
SDNode *NewNode;
|
|
if (isa<BasicBlockSDNode>(Target.getNode()) || isa<GlobalAddressSDNode>(Target.getNode())) {
|
|
NewNode = CurDAG->getMachineNode(Foot::CNST_JMP_D_E, Loc, MVT::Other, {PC, Target, Chain});
|
|
}
|
|
else {
|
|
NewNode = CurDAG->getMachineNode(Foot::BWOR_JMP_D_D_M_E, Loc, MVT::Other, {PC, Target, Zero, Chain});
|
|
}
|
|
|
|
ReplaceNode(N, NewNode);
|
|
}
|
|
|
|
void FootDAGToDAGISel::SelectBrGE(SDNode *N, SDLoc &Loc) {
|
|
SDValue PC = CurDAG->getRegister(Foot::RPC, MVT::i32);
|
|
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
|
|
SDValue Chain = N->getOperand(0);
|
|
SDValue Target = N->getOperand(1);
|
|
|
|
SDNode *NewNode;
|
|
if (isa<BasicBlockSDNode>(Target.getNode()) || isa<GlobalAddressSDNode>(Target.getNode())) {
|
|
NewNode = CurDAG->getMachineNode(Foot::CNST_JMP_D_GE, Loc, MVT::Other, {PC, Target, Chain});
|
|
}
|
|
else {
|
|
NewNode = CurDAG->getMachineNode(Foot::BWOR_JMP_D_D_M_GE, Loc, MVT::Other, {PC, Target, Zero, Chain});
|
|
}
|
|
|
|
ReplaceNode(N, NewNode);
|
|
}
|
|
|
|
void FootDAGToDAGISel::SelectBrG(SDNode *N, SDLoc &Loc) {
|
|
SDValue PC = CurDAG->getRegister(Foot::RPC, MVT::i32);
|
|
SDValue Zero = CurDAG->getTargetConstant(0, Loc, MVT::i32);
|
|
SDValue Chain = N->getOperand(0);
|
|
SDValue Target = N->getOperand(1);
|
|
|
|
SDNode *NewNode;
|
|
if (isa<BasicBlockSDNode>(Target.getNode()) || isa<GlobalAddressSDNode>(Target.getNode())) {
|
|
NewNode = CurDAG->getMachineNode(Foot::CNST_JMP_D_G, Loc, MVT::Other, {PC, Target, Chain});
|
|
}
|
|
else {
|
|
NewNode = CurDAG->getMachineNode(Foot::BWOR_JMP_D_D_M_G, Loc, MVT::Other, {PC, Target, Zero, Chain});
|
|
}
|
|
|
|
ReplaceNode(N, NewNode);
|
|
}
|
|
|
|
void FootDAGToDAGISel::SelectCmp(SDNode *N, SDLoc &Loc) {
|
|
SDValue Chain = N->getOperand(0);
|
|
SDValue LHS = N->getOperand(1);
|
|
SDValue RHS = N->getOperand(2);
|
|
|
|
SDNode *NewNode = CurDAG->getMachineNode(Foot::CMPR_D_D_A, Loc, MVT::Other, {LHS, RHS, Chain});
|
|
|
|
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 ISD::FrameIndex:
|
|
SelectFrameIndex(N, DL);
|
|
break;
|
|
case ISD::BR:
|
|
SelectBr(N, DL);
|
|
break;
|
|
case FootISD::CALL:
|
|
SelectCall(N, DL);
|
|
break;
|
|
case FootISD::BR_L:
|
|
SelectBrL(N, DL);
|
|
break;
|
|
case FootISD::BR_LE:
|
|
SelectBrLE(N, DL);
|
|
break;
|
|
case FootISD::BR_E:
|
|
SelectBrE(N, DL);
|
|
break;
|
|
case FootISD::BR_GE:
|
|
SelectBrGE(N, DL);
|
|
break;
|
|
case FootISD::BR_G:
|
|
SelectBrG(N, DL);
|
|
break;
|
|
case FootISD::CMP:
|
|
SelectCmp(N, DL);
|
|
break;
|
|
default:
|
|
SelectCode(N);
|
|
break;
|
|
}
|
|
}
|
|
|
|
char FootDAGToDAGISelLegacy::ID = 0;
|
|
|
|
Pass *llvm::createFootISelDAG(FootTargetMachine &TM) {
|
|
return new FootDAGToDAGISelLegacy(TM);
|
|
}
|