mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
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:
parent
a1f50e2c2c
commit
1b04694116
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 = "";
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user