Checking in conditionals, function call, arrays and libcalls implementation.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@62174 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sanjiv Gupta 2009-01-13 19:18:47 +00:00
parent a1f50e2c2c
commit 1b04694116
12 changed files with 1154 additions and 280 deletions

View File

@ -1,10 +1,10 @@
##===- lib/Target/PIC16/Makefile ---------------------------*- Makefile -*-===##
#
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
#
##===----------------------------------------------------------------------===##
LEVEL = ../../..
LIBRARYNAME = LLVMPIC16

View File

@ -15,12 +15,39 @@
#ifndef LLVM_TARGET_PIC16_H
#define LLVM_TARGET_PIC16_H
#include <iosfwd>
#include <cassert>
namespace llvm {
class PIC16TargetMachine;
class FunctionPass;
class MachineCodeEmitter;
class raw_ostream;
namespace PIC16CC {
enum CondCodes {
EQ,
NE,
LT,
LE,
GT,
GE
};
}
inline static const char *PIC16CondCodeToString(PIC16CC::CondCodes CC) {
switch (CC) {
default: assert(0 && "Unknown condition code");
case PIC16CC::NE: return "ne";
case PIC16CC::EQ: return "eq";
case PIC16CC::LT: return "lt";
case PIC16CC::LE: return "le";
case PIC16CC::GT: return "gt";
case PIC16CC::GE: return "ge";
}
}
FunctionPass *createPIC16ISelDag(PIC16TargetMachine &TM);
FunctionPass *createPIC16CodePrinterPass(raw_ostream &OS,
PIC16TargetMachine &TM);

View File

@ -24,6 +24,33 @@
using namespace llvm;
#include "PIC16GenAsmWriter.inc"
bool PIC16AsmPrinter::inSameBank (char *s1, char *s2){
assert (s1 && s2 && "Null pointer assignment");
if ((*s1 == '.') && (*s2 == '.')) { //skip if they both start with '.'
s1++;
s2++;
}
while (*s1 && *s2) {
if (*s1 != *s2)
goto _NotInSameBank;
if ((*s1 == '.') && (*s2 == '.')) //both symbols in same function
goto _InSameBank; //in the same bank
s1++;
s2++;
}
if (*s1 && *s1) {
_InSameBank:
return true;
}
_NotInSameBank:
return false;
}
bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
std::string NewBankselLabel;
@ -45,8 +72,8 @@ bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
// generate banksel.
const MachineOperand &BS = MI->getOperand(Operands-1);
if (((int)BS.getImm() == 1) &&
(strcmp (CurrentBankselLabelInBasicBlock.c_str(),
NewBankselLabel.c_str()))) {
(!inSameBank ((char *)CurrentBankselLabelInBasicBlock.c_str(),
(char *)NewBankselLabel.c_str()))) {
CurrentBankselLabelInBasicBlock = NewBankselLabel;
O << "\tbanksel ";
printOperand(MI, Operands-2);
@ -73,9 +100,11 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
// Emit the function variables.
emitFunctionData(MF);
std::string codeSection;
codeSection = "code." + CurrentFnName + ".#";
codeSection = "code." + CurrentFnName + ".# " + "CODE";
const Section *fCodeSection = TAI->getNamedSection(codeSection.c_str(),
SectionFlags::Code);
O << "\n";
SwitchToTextSection (codeSection.c_str(),F);
SwitchToSection (fCodeSection);
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
@ -130,11 +159,21 @@ void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
O << MO.getSymbolName();
break;
case MachineOperand::MO_MachineBasicBlock:
printBasicBlockLabel(MO.getMBB());
return;
default:
assert(0 && " Operand type not supported.");
}
}
void PIC16AsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
int CC = (int)MI->getOperand(opNum).getImm();
O << PIC16CondCodeToString((PIC16CC::CondCodes)CC);
}
bool PIC16AsmPrinter::doInitialization (Module &M) {
bool Result = AsmPrinter::doInitialization(M);
// FIXME:: This is temporary solution to generate the include file.
@ -166,6 +205,10 @@ void PIC16AsmPrinter::EmitExternsAndGlobals (Module &M) {
O << "\tglobal " << Name << ".args\n";
}
}
// Emit header file to include declaration of library functions
O << "\t#include C16IntrinsicCalls.INC\n";
// Emit declarations for external globals.
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; I++) {
@ -177,8 +220,7 @@ void PIC16AsmPrinter::EmitExternsAndGlobals (Module &M) {
}
}
void PIC16AsmPrinter::EmitInitData (Module &M) {
std::string iDataSection = "idata.#";
SwitchToDataSection(iDataSection.c_str());
SwitchToSection(TAI->getDataSection());
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
if (!I->hasInitializer()) // External global require no code.
@ -244,8 +286,7 @@ void PIC16AsmPrinter::EmitConstantValueOnly(const Constant* CV) {
void PIC16AsmPrinter::EmitRomData (Module &M)
{
std::string romDataSection = "romdata.#";
SwitchToRomDataSection(romDataSection.c_str());
SwitchToSection(TAI->getReadOnlySection());
IsRomData = true;
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
@ -274,11 +315,9 @@ void PIC16AsmPrinter::EmitRomData (Module &M)
IsRomData = false;
}
void PIC16AsmPrinter::EmitUnInitData (Module &M)
{
std::string uDataSection = "udata.#";
SwitchToUDataSection(uDataSection.c_str());
SwitchToSection(TAI->getBSSSection_());
const TargetData *TD = TM.getTargetData();
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
@ -300,6 +339,7 @@ void PIC16AsmPrinter::EmitUnInitData (Module &M)
const Type *Ty = C->getType();
unsigned Size = TD->getTypePaddedSize(Ty);
O << name << " " <<"RES"<< " " << Size ;
O << "\n";
}
@ -317,29 +357,24 @@ void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
std::string FuncName = Mang->getValueName(F);
const Module *M = F->getParent();
const TargetData *TD = TM.getTargetData();
unsigned FrameSize = 0;
// Emit the data section name.
O << "\n";
std::string fDataSection = "fdata." + CurrentFnName + ".#";
SwitchToUDataSection(fDataSection.c_str(), F);
std::string SectionName = "fdata." + CurrentFnName + ".# " + "UDATA";
const Section *fDataSection = TAI->getNamedSection(SectionName.c_str(),
SectionFlags::Writeable);
SwitchToSection(fDataSection);
//Emit function return value.
O << CurrentFnName << ".retval:\n";
const Type *RetType = F->getReturnType();
if (RetType->getTypeID() != Type::VoidTyID) {
unsigned RetSize = TD->getTypePaddedSize(RetType);
if (RetSize > 0)
O << CurrentFnName << ".retval" << " RES " << RetSize;
}
unsigned RetSize = 0;
if (RetType->getTypeID() != Type::VoidTyID)
RetSize = TD->getTypePaddedSize(RetType);
// Emit function arguments.
O << CurrentFnName << ".args:\n";
for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
AI != AE; ++AI) {
std::string ArgName = Mang->getValueName(AI);
const Type *ArgTy = AI->getType();
unsigned ArgSize = TD->getTypePaddedSize(ArgTy);
O << CurrentFnName << ".args." << ArgName << " RES " << ArgSize;
}
// Emit the function variables.
// In PIC16 all the function arguments and local variables are global.
@ -358,22 +393,28 @@ void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
Constant *C = I->getInitializer();
const Type *Ty = C->getType();
unsigned Size = TD->getTypePaddedSize(Ty);
FrameSize += Size;
// Emit memory reserve directive.
O << VarName << " RES " << Size << "\n";
}
emitFunctionTempData(MF);
emitFunctionTempData(MF, FrameSize);
if (RetSize > FrameSize)
O << CurrentFnName << ".dummy" << "RES" << (RetSize - FrameSize);
}
void PIC16AsmPrinter::emitFunctionTempData(MachineFunction &MF) {
void PIC16AsmPrinter::emitFunctionTempData(MachineFunction &MF,
unsigned &FrameSize) {
// Emit temporary variables.
MachineFrameInfo *FrameInfo = MF.getFrameInfo();
if (FrameInfo->hasStackObjects()) {
int indexBegin = FrameInfo->getObjectIndexBegin();
int indexEnd = FrameInfo->getObjectIndexEnd();
if (indexBegin < indexEnd)
if (indexBegin < indexEnd) {
FrameSize += indexEnd - indexBegin;
O << CurrentFnName << ".tmp RES"<< " "
<<indexEnd - indexBegin <<"\n";
}
/*
while (indexBegin < indexEnd) {
O << CurrentFnName << "_tmp_" << indexBegin << " " << "RES"<< " "
@ -383,56 +424,3 @@ void PIC16AsmPrinter::emitFunctionTempData(MachineFunction &MF) {
*/
}
}
/// The function is same as AsmPrinter::SwitchtoDataSection except the call
/// to getUDataSectionStartSuffix.
void PIC16AsmPrinter::SwitchToUDataSection(const char *NewSection,
const GlobalValue *GV) {
std::string NS;
if (GV && GV->hasSection())
NS = TAI->getSwitchToSectionDirective() + GV->getSection();
else
NS = NewSection;
// If we're already in this section, we're done.
if (CurrentSection == NS) return;
// Close the current section, if applicable.
if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
CurrentSection = NS;
if (!CurrentSection.empty()){}
O << CurrentSection << (static_cast<const PIC16TargetAsmInfo *>(TAI))->
getUDataSectionStartSuffix() << '\n';
IsInTextSection = false;
}
/// The function is same as AsmPrinter::SwitchtoDataSection except the call
/// to getRomDataSectionStartSuffix.
void PIC16AsmPrinter::SwitchToRomDataSection(const char *NewSection,
const GlobalValue *GV) {
std::string NS;
if (GV && GV->hasSection())
NS = TAI->getSwitchToSectionDirective() + GV->getSection();
else
NS = NewSection;
// If we're already in this section, we're done.
if (CurrentSection == NS) return;
// Close the current section, if applicable.
if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
CurrentSection = NS;
if (!CurrentSection.empty()) {}
O << CurrentSection << (static_cast< const PIC16TargetAsmInfo *>(TAI))->
getRomDataSectionStartSuffix() << '\n';
IsInTextSection = false;
}

View File

@ -36,10 +36,7 @@ namespace llvm {
bool runOnMachineFunction(MachineFunction &F);
void printOperand(const MachineInstr *MI, int opNum);
void SwitchToUDataSection(const char *NewSection,
const GlobalValue *GV = NULL);
void SwitchToRomDataSection(const char *NewSection,
const GlobalValue *GV = NULL);
void printCCOperand(const MachineInstr *MI, int opNum);
bool printInstruction(const MachineInstr *MI); // definition autogenerated.
bool printMachineInstruction(const MachineInstr *MI);
void EmitExternsAndGlobals (Module &M);
@ -48,11 +45,12 @@ namespace llvm {
void EmitRomData (Module &M);
virtual void EmitConstantValueOnly(const Constant *CV);
void emitFunctionData(MachineFunction &MF);
void emitFunctionTempData(MachineFunction &MF);
void emitFunctionTempData(MachineFunction &MF, unsigned &FrameSize);
protected:
bool doInitialization(Module &M);
bool doFinalization(Module &M);
bool inSameBank(char *s1, char *s2);
private:
std::string CurrentBankselLabelInBasicBlock;

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,9 @@ namespace llvm {
Lo, // Low 8-bits of GlobalAddress.
Hi, // High 8-bits of GlobalAddress.
PIC16Load,
PIC16LdWF,
PIC16Store,
PIC16StWF,
Banksel,
MTLO,
MTHI,
@ -38,6 +40,10 @@ namespace llvm {
LRLF, // PIC16 Logical shift right
RLF, // Rotate left through carry
RRF, // Rotate right through carry
CALL, // PIC16 Call instruction
SUBCC, // Compare for equality or inequality.
SELECT_ICC, // Psuedo to be caught in schedular and expanded to brcond.
BRCOND, // Conditional branch.
Dummy
};
@ -46,8 +52,21 @@ namespace llvm {
RAM_SPACE = 0, // RAM address space
ROM_SPACE = 1 // ROM address space number is 1
};
enum PIC16LibCall {
SRA_I8,
SLL_I8,
SRL_I8,
SRA_I16,
SLL_I16,
SRL_I16,
SRA_I32,
SLL_I32,
SRL_I32,
PIC16UnknownCall
};
}
//===--------------------------------------------------------------------===//
// TargetLowering Implementation
//===--------------------------------------------------------------------===//
@ -58,25 +77,37 @@ namespace llvm {
/// getTargetNodeName - This method returns the name of a target specific
/// DAG node.
virtual const char *getTargetNodeName(unsigned Opcode) const;
/// getSetCCResultType - Return the ISD::SETCC ValueType
virtual MVT getSetCCResultType(MVT ValType) const;
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
SDValue LowerADDE(SDValue Op, SelectionDAG &DAG);
SDValue LowerADDC(SDValue Op, SelectionDAG &DAG);
SDValue LowerSUBE(SDValue Op, SelectionDAG &DAG);
SDValue LowerSUBC(SDValue Op, SelectionDAG &DAG);
SDValue LowerADD(SDValue Op, SelectionDAG &DAG);
SDValue LowerSUB(SDValue Op, SelectionDAG &DAG);
SDValue LowerBinOp(SDValue Op, SelectionDAG &DAG);
SDValue LowerCALL(SDValue Op, SelectionDAG &DAG);
SDValue LowerRET(SDValue Op, SelectionDAG &DAG);
SDValue LowerCallReturn(SDValue Op, SDValue Chain, SDValue FrameAddress,
SDValue InFlag, SelectionDAG &DAG);
SDValue LowerCallArguments(SDValue Op, SDValue Chain, SDValue FrameAddress,
SDValue InFlag, SelectionDAG &DAG);
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG);
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG);
SDValue getPIC16Cmp(SDValue LHS, SDValue RHS, unsigned OrigCC, SDValue &CC,
SelectionDAG &DAG);
virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *MBB);
/// ReplaceNodeResults - Replace the results of node with an illegal result
/// type with new values built out of custom code.
///
virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results,
virtual void ReplaceNodeResults(SDNode *N,
SmallVectorImpl<SDValue> &Results,
SelectionDAG &DAG);
SDValue ExpandStore(SDNode *N, SelectionDAG &DAG);
SDValue ExpandLoad(SDNode *N, SelectionDAG &DAG);
// SDNode *ExpandAdd(SDNode *N, SelectionDAG &DAG);
//SDValue ExpandAdd(SDNode *N, SelectionDAG &DAG);
SDValue ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG);
SDValue ExpandExternalSymbol(SDNode *N, SelectionDAG &DAG);
SDValue ExpandShift(SDNode *N, SelectionDAG &DAG);
SDValue ExpandFrameIndex(SDNode *N, SelectionDAG &DAG);
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
SDValue PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const;
@ -95,6 +126,8 @@ namespace llvm {
// code at one place. In case of any change in future it will
// help maintain the code
SDValue getChain(SDValue &Op);
SDValue getOutFlag(SDValue &Op);
// Extract the Lo and Hi component of Op.
@ -108,13 +141,44 @@ namespace llvm {
void LegalizeAddress(SDValue Ptr, SelectionDAG &DAG, SDValue &Chain,
SDValue &NewPtr, unsigned &Offset);
// FrameIndex should be broken down into ExternalSymbol and FrameOffset.
void LegalizeFrameIndex(SDValue Op, SelectionDAG &DAG, SDValue &ES,
int &Offset);
// We can not have both operands of a binary operation in W.
// This function is used to put one operand on stack and generate a load.
SDValue ConvertToMemOperand(SDValue Op, SelectionDAG &DAG);
// 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);
/// Subtarget - Keep a pointer to the PIC16Subtarget around so that we can
/// make the right decision when generating code for different targets.
const PIC16Subtarget *Subtarget;
// Extending the LIB Call framework of LLVM
// To hold the names of PIC16LibCalls
const char *PIC16LibCallNames[PIC16ISD::PIC16UnknownCall];
// To set and retrieve the lib call names
void setPIC16LibCallName(PIC16ISD::PIC16LibCall Call, const char *Name);
const char *getPIC16LibCallName(PIC16ISD::PIC16LibCall Call);
// Make PIC16 LibCall
SDValue MakePIC16LibCall(PIC16ISD::PIC16LibCall Call, MVT RetVT,
const SDValue *Ops, unsigned NumOps, bool isSigned,
SelectionDAG &DAG);
// Check if operation has a direct load operand.
inline bool isDirectLoad(const SDValue Op);
// Create the symbol and index for function frame
void getCurrentFrameIndex(SelectionDAG &DAG, SDValue &ES,
unsigned SlotSize, int &FI);
SDValue getCurrentFrame(SelectionDAG &DAG);
};
} // namespace llvm

View File

@ -125,20 +125,29 @@ bool PIC16InstrInfo::copyRegToReg (MachineBasicBlock &MBB,
const TargetRegisterClass *SrcRC) const {
if (DestRC == PIC16::FSR16RegisterClass) {
BuildMI(MBB, I, get(PIC16::copy_fsr), DestReg).addReg(SrcReg);
return true;
}
return true;
if (DestRC == PIC16::GPRRegisterClass) {
BuildMI(MBB, I, get(PIC16::copy_w), DestReg).addReg(SrcReg);
return true;
}
// Not yet supported.
return false;
}
bool PIC16InstrInfo::isMoveInstr(const MachineInstr &MI,
unsigned &SrcReg,
unsigned &DestReg) const {
if (MI.getOpcode() == PIC16::copy_fsr) {
if (MI.getOpcode() == PIC16::copy_fsr
|| MI.getOpcode() == PIC16::copy_w) {
DestReg = MI.getOperand(0).getReg();
SrcReg = MI.getOperand(1).getReg();
return true;
}
return false;
}

View File

@ -38,9 +38,22 @@ def SDTI16BinOp : SDTypeProfile<1, 2, [SDTCisI16<0>, SDTCisI16<1>,
// Node specific type profiles.
def SDT_PIC16Load : SDTypeProfile<1, 3, [SDTCisI8<0>, SDTCisI8<1>,
SDTCisI8<2>, SDTCisI8<3>]>;
def SDT_PIC16Store : SDTypeProfile<0, 4, [SDTCisI8<0>, SDTCisI8<1>,
SDTCisI8<2>, SDTCisI8<3>]>;
// PIC16ISD::CALL type prorile
def SDT_PIC16call : SDTypeProfile<0, -1, [SDTCisInt<0>]>;
// PIC16ISD::BRCOND
def SDT_PIC16Brcond: SDTypeProfile<0, 2,
[SDTCisVT<0, OtherVT>, SDTCisI8<1>]>;
// PIC16ISD::BRCOND
def SDT_PIC16Selecticc: SDTypeProfile<1, 3,
[SDTCisI8<0>, SDTCisI8<1>, SDTCisI8<2>,
SDTCisI8<3>]>;
//===----------------------------------------------------------------------===//
// PIC16 addressing modes matching via DAG.
//===----------------------------------------------------------------------===//
@ -52,7 +65,7 @@ def diraddr : ComplexPattern<i8, 1, "SelectDirectAddr", [], []>;
def PIC16callseq_start : SDNode<"ISD::CALLSEQ_START", SDTI8VoidOp,
[SDNPHasChain, SDNPOutFlag]>;
def PIC16callseq_end : SDNode<"ISD::CALLSEQ_END", SDTI8VoidOp,
[SDNPHasChain, SDNPOutFlag]>;
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
// Low 8-bits of GlobalAddress.
def PIC16Lo : SDNode<"PIC16ISD::Lo", SDTI8UnaryOp>;
@ -71,18 +84,37 @@ def Banksel : SDNode<"PIC16ISD::Banksel", SDTI8UnaryOp>;
// Node to match a direct store operation.
def PIC16Store : SDNode<"PIC16ISD::PIC16Store", SDT_PIC16Store, [SDNPHasChain]>;
def PIC16StWF : SDNode<"PIC16ISD::PIC16StWF", SDT_PIC16Store,
[SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
// Node to match a direct load operation.
def PIC16Load : SDNode<"PIC16ISD::PIC16Load", SDT_PIC16Load, [SDNPHasChain]>;
def PIC16LdWF : SDNode<"PIC16ISD::PIC16LdWF", SDT_PIC16Load,
[SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
// Node to match PIC16 call
def PIC16call : SDNode<"PIC16ISD::CALL", SDT_PIC16call,
[SDNPHasChain , SDNPOptInFlag, SDNPOutFlag]>;
// Node to match a comparison instruction.
def PIC16Subcc : SDNode<"PIC16ISD::SUBCC", SDTI8BinOp, [SDNPOutFlag]>;
// Node to match a conditional branch.
def PIC16Brcond : SDNode<"PIC16ISD::BRCOND", SDT_PIC16Brcond,
[SDNPHasChain, SDNPInFlag]>;
def PIC16Selecticc : SDNode<"PIC16ISD::SELECT_ICC", SDT_PIC16Selecticc,
[SDNPInFlag]>;
// Nodes to match bitwise operatios.
def OR : SDNode<"ISD::OR", SDTI8BinOp>;
def XOR : SDNode<"ISD::XOR", SDTI8BinOp>;
def AND : SDNode<"ISD::AND", SDTI8BinOp>;
//===----------------------------------------------------------------------===//
// PIC16 Operand Definitions.
//===----------------------------------------------------------------------===//
def i8mem : Operand<i8>;
def brtarget: Operand<OtherVT>;
// Operand for printing out a condition code.
let PrintMethod = "printCCOperand" in
def CCOp : Operand<i8>;
include "PIC16InstrFormats.td"
@ -90,7 +122,7 @@ include "PIC16InstrFormats.td"
// PIC16 Common Classes.
//===----------------------------------------------------------------------===//
// W = W Op F : Load the value from F and do Op to W
// W = W Op F : Load the value from F and do Op to W.
class BinOpFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
ByteFormat<OpCode, (outs GPR:$dst),
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
@ -98,7 +130,8 @@ class BinOpFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
[(set GPR:$dst, (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
(i8 imm:$ptrhi),
(i8 imm:$offset))))]>;
// F = F Op W : Load the value from F, do op with W and store in F
// F = F Op W : Load the value from F, do op with W and store in F.
class BinOpWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
ByteFormat<OpCode, (outs),
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
@ -110,6 +143,13 @@ class BinOpWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
(i8 imm:$ptrhi), (i8 imm:$offset)
)]>;
// W = W Op L : Do Op of L with W and place result in W.
class BinOpLW<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)))]>;
//===----------------------------------------------------------------------===//
// PIC16 Instructions.
//===----------------------------------------------------------------------===//
@ -163,6 +203,9 @@ def set_fsrhi:
def copy_fsr:
Pseudo<(outs FSR16:$dst), (ins FSR16:$src), "copy_fsr $dst, $src", []>;
def copy_w:
Pseudo<(outs GPR:$dst), (ins GPR:$src), "copy_w $dst, $src", []>;
//--------------------------
// Store to memory
//-------------------------
@ -181,6 +224,14 @@ def movwf_1 :
[(PIC16Store GPR:$val, texternalsym:$ptrlo, (i8 imm:$ptrhi),
(i8 imm:$offset))]>;
// Store with InFlag and OutFlag
def movwf_2 :
ByteFormat<0, (outs),
(ins GPR:$val, i8mem:$ptrlo, i8imm:$ptrhi, i8imm:$offset),
"movwf ${ptrlo} + ${offset}",
[(PIC16StWF GPR:$val, texternalsym:$ptrlo, (i8 imm:$ptrhi),
(i8 imm:$offset))]>;
// Indirect store. Matched via a DAG replacement pattern.
def store_indirect :
ByteFormat<0, (outs),
@ -208,6 +259,16 @@ def movf_1 :
(PIC16Load texternalsym:$ptrlo, (i8 imm:$ptrhi),
(i8 imm:$offset)))]>;
// Load with InFlag and OutFlag
def movf_2 :
ByteFormat<0, (outs GPR:$dst),
(ins i8mem:$ptrlo, i8imm:$ptrhi, i8imm:$offset),
"movf ${ptrlo} + ${offset}, W",
[(set GPR:$dst,
(PIC16LdWF texternalsym:$ptrlo, (i8 imm:$ptrhi),
(i8 imm:$offset)))]>;
// Indirect load. Matched via a DAG replacement pattern.
def load_indirect :
ByteFormat<0, (outs GPR:$dst),
@ -218,23 +279,25 @@ def load_indirect :
//-------------------------
// Bitwise operations patterns
//--------------------------
def OrFW : BinOpFW<0, "iorwf", OR>;
def XOrFW : BinOpFW<0, "xorwf", XOR>;
def AndFW : BinOpFW<0, "andwf", AND>;
let isTwoAddress = 1 in {
def OrFW : BinOpFW<0, "iorwf", or>;
def XOrFW : BinOpFW<0, "xorwf", xor>;
def AndFW : BinOpFW<0, "andwf", and>;
}
def OrWF : BinOpWF<0, "iorwf", OR>;
def XOrWF : BinOpWF<0, "xorwf", XOR>;
def AndWF : BinOpWF<0, "andwf", AND>;
def OrWF : BinOpWF<0, "iorwf", or>;
def XOrWF : BinOpWF<0, "xorwf", xor>;
def AndWF : BinOpWF<0, "andwf", and>;
//-------------------------
// Various add/sub patterns.
//-------------------------
// let isTwoAddress = 1 in {
let isTwoAddress = 1 in {
def addfw_1: BinOpFW<0, "addwf", add>;
def addfw_2: BinOpFW<0, "addwf", addc>;
def addfwc: BinOpFW<0, "addwfc", adde>; // With Carry.
// }
}
def addwf_1: BinOpWF<0, "addwf", add>;
def addwf_2: BinOpWF<0, "addwf", addc>;
@ -248,11 +311,12 @@ class SUBFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
[(set GPR:$dst, (OpNode (PIC16Load diraddr:$ptrlo,
(i8 imm:$ptrhi), (i8 imm:$offset)),
GPR:$src))]>;
//let isTwoAddress = 1 in {
let isTwoAddress = 1 in {
def subfw_1: SUBFW<0, "subwf", sub>;
def subfw_2: SUBFW<0, "subwf", subc>;
def subfwb: SUBFW<0, "subwfb", sube>; // With Borrow.
//}
def subfw_cc: SUBFW<0, "subwf", PIC16Subcc>;
}
// [F] -= W ;
class SUBWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
@ -267,33 +331,62 @@ class SUBWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
def subwf_1: SUBWF<0, "subwf", sub>;
def subwf_2: SUBWF<0, "subwf", subc>;
def subwfb: SUBWF<0, "subwfb", sube>; // With Borrow.
def subwf_cc: SUBWF<0, "subwf", PIC16Subcc>;
// addlw
// W += C ; add literal to W. (Without carry). May Produce a carry.
class ADDLW<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 isTwoAddress = 1 in {
def addlw_1 : BinOpLW<0, "addlw", add>;
def addlw_2 : BinOpLW<0, "addlw", addc>;
def addlwc : BinOpLW<0, "addlwc", adde>; // With Carry. (Assembler macro).
}
// let isTwoAddress = 1 in {
def addlw_1 : ADDLW<0, "addlw", add>;
def addlw_2 : ADDLW<0, "addlw", addc>;
def addlwc : ADDLW<0, "addlwc", adde>; // With Carry. (Assembler macro).
//}
// bitwise operations involving a literal and w.
let isTwoAddress = 1 in {
def andlw : BinOpLW<0, "andlw", and>;
def xorlw : BinOpLW<0, "xorlw", xor>;
def orlw : BinOpLW<0, "iorlw", or>;
}
// sublw
// W = C - W ; sub W from literal. (Without borrow).
class SUBLW<bits<6> opcode, SDNode OpNode> :
LiteralFormat<opcode, (outs GPR:$dst),
(ins GPR:$src, i8imm:$literal),
"addlw $literal",
"sublw $literal",
[(set GPR:$dst, (OpNode (i8 imm:$literal), GPR:$src))]>;
//let isTwoAddress = 1 in {
let isTwoAddress = 1 in {
def sublw_1 : SUBLW<0, sub>;
def sublw_2 : SUBLW<0, subc>;
//}
def sublw_cc : SUBLW<0, PIC16Subcc>;
}
// Call instruction.
let isCall = 1 in {
def CALL: LiteralFormat<0x1, (outs), (ins i8imm:$func),
"call ${func}",
[(PIC16call diraddr:$func)]>;
}
def pic16brcond: ControlFormat<0x0, (outs), (ins brtarget:$dst, CCOp:$cc),
"b$cc $dst",
[(PIC16Brcond bb:$dst, imm:$cc)]>;
// Unconditional branch.
def br_uncond: ControlFormat<0x0, (outs), (ins brtarget:$dst),
"goto $dst",
[(br bb:$dst)]>;
// SELECT_CC_* - Used to implement the SELECT_CC DAG operation. Expanded by the
// scheduler into a branch sequence.
let usesCustomDAGSchedInserter = 1 in { // Expanded by the scheduler.
def SELECT_CC_Int_ICC
: Pseudo<(outs GPR:$dst), (ins GPR:$T, GPR:$F, i8imm:$Cond),
"; SELECT_CC_Int_ICC PSEUDO!",
[(set GPR:$dst, (PIC16Selecticc GPR:$T, GPR:$F,
imm:$Cond))]>;
}
// Banksel.
let isReMaterializable = 1 in {

View File

@ -79,4 +79,13 @@ unsigned PIC16RegisterInfo::getRARegister() const {
return 0;
}
// This function eliminates ADJCALLSTACKDOWN,
// ADJCALLSTACKUP pseudo instructions
void PIC16RegisterInfo::
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
// Simply discard ADJCALLSTACKDOWN,
// ADJCALLSTACKUP instructions.
MBB.erase(I);
}

View File

@ -51,6 +51,10 @@ class PIC16RegisterInfo : public PIC16GenRegisterInfo {
virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI,
int SPAdj, RegScavenger *RS=NULL) const;
void eliminateCallFramePseudoInstr(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const;
virtual void emitPrologue(MachineFunction &MF) const;
virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const;

View File

@ -13,6 +13,7 @@
#include "PIC16TargetAsmInfo.h"
#include "PIC16TargetMachine.h"
#include "llvm/GlobalValue.h"
using namespace llvm;
@ -23,9 +24,12 @@ PIC16TargetAsmInfo(const PIC16TargetMachine &TM)
Data8bitsDirective = " db ";
Data16bitsDirective = " db ";
Data32bitsDirective = " db ";
DataSectionStartSuffix = " IDATA ";
UDataSectionStartSuffix = " UDATA ";
TextSectionStartSuffix = " CODE ";
RomDataSectionStartSuffix = " ROMDATA ";
ZeroDirective = NULL;
AsciiDirective = " dt ";
AscizDirective = NULL;
BSSSection_ = getNamedSection("udata.# UDATA",
SectionFlags::Writeable | SectionFlags::BSS);
ReadOnlySection = getNamedSection("romdata.# ROMDATA", SectionFlags::None);
DataSection = getNamedSection("idata.# IDATA", SectionFlags::Writeable);
SwitchToSectionDirective = "";
}

View File

@ -23,17 +23,7 @@ namespace llvm {
struct PIC16TargetAsmInfo : public TargetAsmInfo {
PIC16TargetAsmInfo(const PIC16TargetMachine &TM);
const char *UDataSectionStartSuffix;
const char *RomDataSectionStartSuffix;
public :
const char *getUDataSectionStartSuffix() const {
return UDataSectionStartSuffix;
}
const char *getRomDataSectionStartSuffix() const {
return RomDataSectionStartSuffix;
}
};
} // namespace llvm