summaryrefslogtreecommitdiff
path: root/lib/Target/PIC16
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2010-01-01 10:31:22 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2010-01-01 10:31:22 +0000
commit1e7804dbd25b8dbf534c850355d70ad215206f4b (patch)
treedba00119388b84f9f44e6ec5e9129f807fd79ca3 /lib/Target/PIC16
parent571945e6affd20b19264ec22495da418d0fbdbb4 (diff)
Notes
Diffstat (limited to 'lib/Target/PIC16')
-rw-r--r--lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp18
-rw-r--r--lib/Target/PIC16/PIC16ISelDAGToDAG.h5
-rw-r--r--lib/Target/PIC16/PIC16ISelLowering.cpp112
-rw-r--r--lib/Target/PIC16/PIC16ISelLowering.h11
-rw-r--r--lib/Target/PIC16/PIC16InstrInfo.td39
5 files changed, 132 insertions, 53 deletions
diff --git a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp
index e1f2587658ee2..87f5aad02a63c 100644
--- a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp
+++ b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp
@@ -170,7 +170,16 @@ void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
switch (MO.getType()) {
case MachineOperand::MO_Register:
- O << getRegisterName(MO.getReg());
+ {
+ // For indirect load/store insns, the fsr name is printed as INDF.
+ std::string RegName = getRegisterName(MO.getReg());
+ if ((MI->getOpcode() == PIC16::load_indirect) ||
+ (MI->getOpcode() == PIC16::store_indirect))
+ {
+ RegName.replace (0, 3, "INDF");
+ }
+ O << RegName;
+ }
return;
case MachineOperand::MO_Immediate:
@@ -263,10 +272,9 @@ void PIC16AsmPrinter::printLibcallDecls() {
bool PIC16AsmPrinter::doInitialization(Module &M) {
bool Result = AsmPrinter::doInitialization(M);
- // FIXME:: This is temporary solution to generate the include file.
- // The processor should be passed to llc as in input and the header file
- // should be generated accordingly.
- O << "\n\t#include P16F1937.INC\n";
+ // Every asmbly contains these std headers.
+ O << "\n#include p16f1xxx.inc";
+ O << "\n#include stdmacros.inc";
// Set the section names for all globals.
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
diff --git a/lib/Target/PIC16/PIC16ISelDAGToDAG.h b/lib/Target/PIC16/PIC16ISelDAGToDAG.h
index 3a2f6b47b37e1..d9172f2b3622b 100644
--- a/lib/Target/PIC16/PIC16ISelDAGToDAG.h
+++ b/lib/Target/PIC16/PIC16ISelDAGToDAG.h
@@ -36,7 +36,10 @@ class VISIBILITY_HIDDEN PIC16DAGToDAGISel : public SelectionDAGISel {
public:
explicit PIC16DAGToDAGISel(PIC16TargetMachine &tm) :
SelectionDAGISel(tm),
- TM(tm), PIC16Lowering(*TM.getTargetLowering()) {}
+ TM(tm), PIC16Lowering(*TM.getTargetLowering()) {
+ // Keep PIC16 specific DAGISel to use during the lowering
+ PIC16Lowering.ISel = this;
+ }
// Pass Name
virtual const char *getPassName() const {
diff --git a/lib/Target/PIC16/PIC16ISelLowering.cpp b/lib/Target/PIC16/PIC16ISelLowering.cpp
index 71c3d37341096..9f093e817df64 100644
--- a/lib/Target/PIC16/PIC16ISelLowering.cpp
+++ b/lib/Target/PIC16/PIC16ISelLowering.cpp
@@ -226,6 +226,7 @@ PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM)
setLibcallName(RTLIB::DIV_F32, getIntrinsicName(RTLIB::DIV_F32));
// Floationg point comparison
+ setLibcallName(RTLIB::O_F32, getIntrinsicName(RTLIB::O_F32));
setLibcallName(RTLIB::UO_F32, getIntrinsicName(RTLIB::UO_F32));
setLibcallName(RTLIB::OLE_F32, getIntrinsicName(RTLIB::OLE_F32));
setLibcallName(RTLIB::OGE_F32, getIntrinsicName(RTLIB::OGE_F32));
@@ -371,6 +372,11 @@ PIC16TargetLowering::getSetCCResultType(EVT ValType) const {
return MVT::i8;
}
+MVT::SimpleValueType
+PIC16TargetLowering::getCmpLibcallReturnType() const {
+ return MVT::i8;
+}
+
/// The type legalizer framework of generating legalizer can generate libcalls
/// only when the operand/result types are illegal.
/// PIC16 needs to generate libcalls even for the legal types (i8) for some ops.
@@ -413,7 +419,8 @@ PIC16TargetLowering::MakePIC16Libcall(PIC16ISD::PIC16Libcall Call,
LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false,
false, 0, CallingConv::C, false,
/*isReturnValueUsed=*/true,
- Callee, Args, DAG, dl);
+ Callee, Args, DAG, dl,
+ DAG.GetOrdering(DAG.getEntryNode().getNode()));
return CallInfo.first;
}
@@ -924,7 +931,7 @@ SDValue PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) {
}
else if (VT == MVT::i16) {
BP = DAG.getNode(ISD::BUILD_PAIR, dl, VT, PICLoads[0], PICLoads[1]);
- if (MemVT == MVT::i8)
+ if ((MemVT == MVT::i8) || (MemVT == MVT::i1))
Chain = getChain(PICLoads[0]);
else
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
@@ -936,7 +943,7 @@ SDValue PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) {
BPs[1] = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i16,
PICLoads[2], PICLoads[3]);
BP = DAG.getNode(ISD::BUILD_PAIR, dl, VT, BPs[0], BPs[1]);
- if (MemVT == MVT::i8)
+ if ((MemVT == MVT::i8) || (MemVT == MVT::i1))
Chain = getChain(PICLoads[0]);
else if (MemVT == MVT::i16)
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
@@ -1270,7 +1277,6 @@ PIC16TargetLowering::LowerReturn(SDValue Chain,
std::string FuncName = F->getName();
const char *tmpName = createESName(PAN::getFrameLabel(FuncName));
- SDVTList VTs = DAG.getVTList (MVT::i8, MVT::Other);
SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
SDValue BS = DAG.getConstant(1, MVT::i8);
SDValue RetVal;
@@ -1482,7 +1488,8 @@ bool PIC16TargetLowering::isDirectLoad(const SDValue Op) {
// operand no. of the operand to be converted in 'MemOp'. Remember, PIC16 has
// no instruction that can operation on two registers. Most insns take
// one register and one memory operand (addwf) / Constant (addlw).
-bool PIC16TargetLowering::NeedToConvertToMemOp(SDValue Op, unsigned &MemOp) {
+bool PIC16TargetLowering::NeedToConvertToMemOp(SDValue Op, unsigned &MemOp,
+ SelectionDAG &DAG) {
// If one of the operand is a constant, return false.
if (Op.getOperand(0).getOpcode() == ISD::Constant ||
Op.getOperand(1).getOpcode() == ISD::Constant)
@@ -1491,11 +1498,33 @@ bool PIC16TargetLowering::NeedToConvertToMemOp(SDValue Op, unsigned &MemOp) {
// Return false if one of the operands is already a direct
// load and that operand has only one use.
if (isDirectLoad(Op.getOperand(0))) {
- if (Op.getOperand(0).hasOneUse())
- return false;
- else
- MemOp = 0;
+ if (Op.getOperand(0).hasOneUse()) {
+ // Legal and profitable folding check uses the NodeId of DAG nodes.
+ // This NodeId is assigned by topological order. Therefore first
+ // assign topological order then perform legal and profitable check.
+ // Note:- Though this ordering is done before begining with legalization,
+ // newly added node during legalization process have NodeId=-1 (NewNode)
+ // therefore before performing any check proper ordering of the node is
+ // required.
+ DAG.AssignTopologicalOrder();
+
+ // Direct load operands are folded in binary operations. But before folding
+ // verify if this folding is legal. Fold only if it is legal otherwise
+ // convert this direct load to a separate memory operation.
+ if(ISel->IsLegalAndProfitableToFold(Op.getOperand(0).getNode(),
+ Op.getNode(), Op.getNode()))
+ return false;
+ else
+ MemOp = 0;
+ }
}
+
+ // For operations that are non-cummutative there is no need to check
+ // for right operand because folding right operand may result in
+ // incorrect operation.
+ if (! SelectionDAG::isCommutativeBinOp(Op.getOpcode()))
+ return true;
+
if (isDirectLoad(Op.getOperand(1))) {
if (Op.getOperand(1).hasOneUse())
return false;
@@ -1514,7 +1543,7 @@ SDValue PIC16TargetLowering::LowerBinOp(SDValue Op, SelectionDAG &DAG) {
assert (Op.getValueType() == MVT::i8 && "illegal Op to lower");
unsigned MemOp = 1;
- if (NeedToConvertToMemOp(Op, MemOp)) {
+ if (NeedToConvertToMemOp(Op, MemOp, DAG)) {
// Put one value on stack.
SDValue NewVal = ConvertToMemOperand (Op.getOperand(MemOp), DAG, dl);
@@ -1533,7 +1562,7 @@ SDValue PIC16TargetLowering::LowerADD(SDValue Op, SelectionDAG &DAG) {
assert (Op.getValueType() == MVT::i8 && "illegal add to lower");
DebugLoc dl = Op.getDebugLoc();
unsigned MemOp = 1;
- if (NeedToConvertToMemOp(Op, MemOp)) {
+ if (NeedToConvertToMemOp(Op, MemOp, DAG)) {
// Put one value on stack.
SDValue NewVal = ConvertToMemOperand (Op.getOperand(MemOp), DAG, dl);
@@ -1561,30 +1590,47 @@ SDValue PIC16TargetLowering::LowerSUB(SDValue Op, SelectionDAG &DAG) {
DebugLoc dl = Op.getDebugLoc();
// We should have handled larger operands in type legalizer itself.
assert (Op.getValueType() == MVT::i8 && "illegal sub to lower");
+ unsigned MemOp = 1;
+ SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag);
- // Nothing to do if the first operand is already a direct load and it has
- // only one use.
- if (isDirectLoad(Op.getOperand(0)) && Op.getOperand(0).hasOneUse())
- return Op;
-
- // Put first operand on stack.
- SDValue NewVal = ConvertToMemOperand (Op.getOperand(0), DAG, dl);
+ // Since we don't have an instruction for X - c ,
+ // we can change it to X + (-c)
+ ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
+ if (C && (Op.getOpcode() == ISD::SUB))
+ {
+ return DAG.getNode(ISD::ADD,
+ dl, MVT::i8, Op.getOperand(0),
+ DAG.getConstant(0-(C->getZExtValue()), MVT::i8));
+ }
- SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag);
- switch (Op.getOpcode()) {
- default:
- assert (0 && "Opcode unknown.");
- case ISD::SUBE:
- return DAG.getNode(Op.getOpcode(), dl, Tys, NewVal, Op.getOperand(1),
- Op.getOperand(2));
- break;
- case ISD::SUBC:
- return DAG.getNode(Op.getOpcode(), dl, Tys, NewVal, Op.getOperand(1));
- break;
- case ISD::SUB:
- return DAG.getNode(Op.getOpcode(), dl, MVT::i8, NewVal, Op.getOperand(1));
- break;
- }
+ if (NeedToConvertToMemOp(Op, MemOp, DAG) ||
+ (isDirectLoad(Op.getOperand(1)) &&
+ (!isDirectLoad(Op.getOperand(0))) &&
+ (Op.getOperand(0).getOpcode() != ISD::Constant)))
+ {
+ // Put first operand on stack.
+ SDValue NewVal = ConvertToMemOperand (Op.getOperand(0), DAG, dl);
+
+ switch (Op.getOpcode()) {
+ default:
+ assert (0 && "Opcode unknown.");
+ case ISD::SUBE:
+ return DAG.getNode(Op.getOpcode(),
+ dl, Tys, NewVal, Op.getOperand(1),
+ Op.getOperand(2));
+ break;
+ case ISD::SUBC:
+ return DAG.getNode(Op.getOpcode(),
+ dl, Tys, NewVal, Op.getOperand(1));
+ break;
+ case ISD::SUB:
+ return DAG.getNode(Op.getOpcode(),
+ dl, MVT::i8, NewVal, Op.getOperand(1));
+ break;
+ }
+ }
+ else
+ return Op;
}
void PIC16TargetLowering::InitReservedFrameCount(const Function *F) {
diff --git a/lib/Target/PIC16/PIC16ISelLowering.h b/lib/Target/PIC16/PIC16ISelLowering.h
index 286ed2411ef89..afdd4b4364170 100644
--- a/lib/Target/PIC16/PIC16ISelLowering.h
+++ b/lib/Target/PIC16/PIC16ISelLowering.h
@@ -18,6 +18,7 @@
#include "PIC16.h"
#include "PIC16Subtarget.h"
#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetLowering.h"
#include <map>
@@ -83,6 +84,7 @@ namespace llvm {
virtual const char *getTargetNodeName(unsigned Opcode) const;
/// getSetCCResultType - Return the ISD::SETCC ValueType
virtual MVT::SimpleValueType getSetCCResultType(EVT ValType) const;
+ virtual MVT::SimpleValueType getCmpLibcallReturnType() const;
SDValue LowerShift(SDValue Op, SelectionDAG &DAG);
SDValue LowerMUL(SDValue Op, SelectionDAG &DAG);
SDValue LowerADD(SDValue Op, SelectionDAG &DAG);
@@ -216,7 +218,9 @@ namespace llvm {
// This function checks if we need to put an operand of an operation on
// stack and generate a load or not.
- bool NeedToConvertToMemOp(SDValue Op, unsigned &MemOp);
+ // DAG parameter is required to access DAG information during
+ // analysis.
+ bool NeedToConvertToMemOp(SDValue Op, unsigned &MemOp, SelectionDAG &DAG);
/// Subtarget - Keep a pointer to the PIC16Subtarget around so that we can
/// make the right decision when generating code for different targets.
@@ -239,6 +243,11 @@ namespace llvm {
// Check if operation has a direct load operand.
inline bool isDirectLoad(const SDValue Op);
+ public:
+ // Keep a pointer to SelectionDAGISel to access its public
+ // interface (It is required during legalization)
+ SelectionDAGISel *ISel;
+
private:
// The frameindexes generated for spill/reload are stack based.
// This maps maintain zero based indexes for these FIs.
diff --git a/lib/Target/PIC16/PIC16InstrInfo.td b/lib/Target/PIC16/PIC16InstrInfo.td
index 5eec6c4e66b5c..24df251b50887 100644
--- a/lib/Target/PIC16/PIC16InstrInfo.td
+++ b/lib/Target/PIC16/PIC16InstrInfo.td
@@ -151,7 +151,7 @@ let mayStore = 1 in
class BinOpWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
ByteFormat<OpCode, (outs),
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
- !strconcat(OpcStr, " $ptrlo + $offset"),
+ !strconcat(OpcStr, " $ptrlo + $offset, F"),
[(PIC16Store (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
(i8 imm:$ptrhi),
(i8 imm:$offset))),
@@ -161,7 +161,7 @@ class BinOpWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
// W = W Op L : Do Op of L with W and place result in W.
let isTwoAddress = 1 in
-class BinOpLW<bits<6> opcode, string OpcStr, SDNode OpNode> :
+class BinOpWL<bits<6> opcode, string OpcStr, SDNode OpNode> :
LiteralFormat<opcode, (outs GPR:$dst),
(ins GPR:$src, i8imm:$literal),
!strconcat(OpcStr, " $literal"),
@@ -404,33 +404,46 @@ def subwf_cc: SUBWF<0, "subwf", PIC16Subcc>;
// addlw
let Defs = [STATUS] in {
-def addlw_1 : BinOpLW<0, "addlw", add>;
-def addlw_2 : BinOpLW<0, "addlw", addc>;
+def addlw_1 : BinOpWL<0, "addlw", add>;
+def addlw_2 : BinOpWL<0, "addlw", addc>;
let Uses = [STATUS] in
-def addlwc : BinOpLW<0, "addlwc", adde>; // With Carry. (Assembler macro).
+def addlwc : BinOpWL<0, "addlwc", adde>; // With Carry. (Assembler macro).
// bitwise operations involving a literal and w.
-def andlw : BinOpLW<0, "andlw", and>;
-def xorlw : BinOpLW<0, "xorlw", xor>;
-def orlw : BinOpLW<0, "iorlw", or>;
+def andlw : BinOpWL<0, "andlw", and>;
+def xorlw : BinOpWL<0, "xorlw", xor>;
+def orlw : BinOpWL<0, "iorlw", or>;
}
// sublw
// W = C - W ; sub W from literal. (Without borrow).
let isTwoAddress = 1 in
-class SUBLW<bits<6> opcode, SDNode OpNode> :
+class SUBLW<bits<6> opcode, string OpcStr, SDNode OpNode> :
LiteralFormat<opcode, (outs GPR:$dst),
(ins GPR:$src, i8imm:$literal),
- "sublw $literal",
+ !strconcat(OpcStr, " $literal"),
[(set GPR:$dst, (OpNode (i8 imm:$literal), GPR:$src))]>;
+// subwl
+// W = W - C ; sub literal from W (Without borrow).
+let isTwoAddress = 1 in
+class SUBWL<bits<6> opcode, string OpcStr, SDNode OpNode> :
+ LiteralFormat<opcode, (outs GPR:$dst),
+ (ins GPR:$src, i8imm:$literal),
+ !strconcat(OpcStr, " $literal"),
+ [(set GPR:$dst, (OpNode GPR:$src, (i8 imm:$literal)))]>;
let Defs = [STATUS] in {
-def sublw_1 : SUBLW<0, sub>;
-def sublw_2 : SUBLW<0, subc>;
+def sublw_1 : SUBLW<0, "sublw", sub>;
+def sublw_2 : SUBLW<0, "sublw", subc>;
+def sublw_3 : SUBLW<0, "sublwb", sube>; // With borrow (Assembler macro).
+
+def sublw_4 : SUBWL<0, "subwl", sub>; // Assembler macro replace with addlw
+def sublw_5 : SUBWL<0, "subwl", subc>; // Assembler macro replace with addlw
+def sublw_6 : SUBWL<0, "subwlb", sube>; // With borrow (Assembler macro).
}
let Defs = [STATUS], isTerminator = 1 in
-def sublw_cc : SUBLW<0, PIC16Subcc>;
+def sublw_cc : SUBLW<0, "sublw", PIC16Subcc>;
// Call instruction.
let isCall = 1,