mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-07 11:33:44 +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 -*-===##
|
##===- lib/Target/PIC16/Makefile ---------------------------*- Makefile -*-===##
|
||||||
#
|
#
|
||||||
# The LLVM Compiler Infrastructure
|
# 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.
|
# License. See LICENSE.TXT for details.
|
||||||
#
|
#
|
||||||
##===----------------------------------------------------------------------===##
|
##===----------------------------------------------------------------------===##
|
||||||
LEVEL = ../../..
|
LEVEL = ../../..
|
||||||
LIBRARYNAME = LLVMPIC16
|
LIBRARYNAME = LLVMPIC16
|
||||||
|
@ -15,12 +15,39 @@
|
|||||||
#ifndef LLVM_TARGET_PIC16_H
|
#ifndef LLVM_TARGET_PIC16_H
|
||||||
#define LLVM_TARGET_PIC16_H
|
#define LLVM_TARGET_PIC16_H
|
||||||
|
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class PIC16TargetMachine;
|
class PIC16TargetMachine;
|
||||||
class FunctionPass;
|
class FunctionPass;
|
||||||
class MachineCodeEmitter;
|
class MachineCodeEmitter;
|
||||||
class raw_ostream;
|
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 *createPIC16ISelDag(PIC16TargetMachine &TM);
|
||||||
FunctionPass *createPIC16CodePrinterPass(raw_ostream &OS,
|
FunctionPass *createPIC16CodePrinterPass(raw_ostream &OS,
|
||||||
PIC16TargetMachine &TM);
|
PIC16TargetMachine &TM);
|
||||||
|
@ -24,6 +24,33 @@
|
|||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
#include "PIC16GenAsmWriter.inc"
|
#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) {
|
bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
|
||||||
std::string NewBankselLabel;
|
std::string NewBankselLabel;
|
||||||
@ -45,8 +72,8 @@ bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
|
|||||||
// generate banksel.
|
// generate banksel.
|
||||||
const MachineOperand &BS = MI->getOperand(Operands-1);
|
const MachineOperand &BS = MI->getOperand(Operands-1);
|
||||||
if (((int)BS.getImm() == 1) &&
|
if (((int)BS.getImm() == 1) &&
|
||||||
(strcmp (CurrentBankselLabelInBasicBlock.c_str(),
|
(!inSameBank ((char *)CurrentBankselLabelInBasicBlock.c_str(),
|
||||||
NewBankselLabel.c_str()))) {
|
(char *)NewBankselLabel.c_str()))) {
|
||||||
CurrentBankselLabelInBasicBlock = NewBankselLabel;
|
CurrentBankselLabelInBasicBlock = NewBankselLabel;
|
||||||
O << "\tbanksel ";
|
O << "\tbanksel ";
|
||||||
printOperand(MI, Operands-2);
|
printOperand(MI, Operands-2);
|
||||||
@ -73,9 +100,11 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
|||||||
// Emit the function variables.
|
// Emit the function variables.
|
||||||
emitFunctionData(MF);
|
emitFunctionData(MF);
|
||||||
std::string codeSection;
|
std::string codeSection;
|
||||||
codeSection = "code." + CurrentFnName + ".#";
|
codeSection = "code." + CurrentFnName + ".# " + "CODE";
|
||||||
|
const Section *fCodeSection = TAI->getNamedSection(codeSection.c_str(),
|
||||||
|
SectionFlags::Code);
|
||||||
O << "\n";
|
O << "\n";
|
||||||
SwitchToTextSection (codeSection.c_str(),F);
|
SwitchToSection (fCodeSection);
|
||||||
|
|
||||||
// Print out code for the function.
|
// Print out code for the function.
|
||||||
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
|
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();
|
O << MO.getSymbolName();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MachineOperand::MO_MachineBasicBlock:
|
||||||
|
printBasicBlockLabel(MO.getMBB());
|
||||||
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(0 && " Operand type not supported.");
|
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 PIC16AsmPrinter::doInitialization (Module &M) {
|
||||||
bool Result = AsmPrinter::doInitialization(M);
|
bool Result = AsmPrinter::doInitialization(M);
|
||||||
// FIXME:: This is temporary solution to generate the include file.
|
// FIXME:: This is temporary solution to generate the include file.
|
||||||
@ -166,6 +205,10 @@ void PIC16AsmPrinter::EmitExternsAndGlobals (Module &M) {
|
|||||||
O << "\tglobal " << Name << ".args\n";
|
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.
|
// Emit declarations for external globals.
|
||||||
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
|
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
|
||||||
I != E; I++) {
|
I != E; I++) {
|
||||||
@ -177,8 +220,7 @@ void PIC16AsmPrinter::EmitExternsAndGlobals (Module &M) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void PIC16AsmPrinter::EmitInitData (Module &M) {
|
void PIC16AsmPrinter::EmitInitData (Module &M) {
|
||||||
std::string iDataSection = "idata.#";
|
SwitchToSection(TAI->getDataSection());
|
||||||
SwitchToDataSection(iDataSection.c_str());
|
|
||||||
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
|
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
if (!I->hasInitializer()) // External global require no code.
|
if (!I->hasInitializer()) // External global require no code.
|
||||||
@ -244,8 +286,7 @@ void PIC16AsmPrinter::EmitConstantValueOnly(const Constant* CV) {
|
|||||||
|
|
||||||
void PIC16AsmPrinter::EmitRomData (Module &M)
|
void PIC16AsmPrinter::EmitRomData (Module &M)
|
||||||
{
|
{
|
||||||
std::string romDataSection = "romdata.#";
|
SwitchToSection(TAI->getReadOnlySection());
|
||||||
SwitchToRomDataSection(romDataSection.c_str());
|
|
||||||
IsRomData = true;
|
IsRomData = true;
|
||||||
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
|
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
@ -274,11 +315,9 @@ void PIC16AsmPrinter::EmitRomData (Module &M)
|
|||||||
IsRomData = false;
|
IsRomData = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIC16AsmPrinter::EmitUnInitData (Module &M)
|
void PIC16AsmPrinter::EmitUnInitData (Module &M)
|
||||||
{
|
{
|
||||||
std::string uDataSection = "udata.#";
|
SwitchToSection(TAI->getBSSSection_());
|
||||||
SwitchToUDataSection(uDataSection.c_str());
|
|
||||||
const TargetData *TD = TM.getTargetData();
|
const TargetData *TD = TM.getTargetData();
|
||||||
|
|
||||||
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
|
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();
|
const Type *Ty = C->getType();
|
||||||
unsigned Size = TD->getTypePaddedSize(Ty);
|
unsigned Size = TD->getTypePaddedSize(Ty);
|
||||||
|
|
||||||
O << name << " " <<"RES"<< " " << Size ;
|
O << name << " " <<"RES"<< " " << Size ;
|
||||||
O << "\n";
|
O << "\n";
|
||||||
}
|
}
|
||||||
@ -317,29 +357,24 @@ void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
|
|||||||
std::string FuncName = Mang->getValueName(F);
|
std::string FuncName = Mang->getValueName(F);
|
||||||
const Module *M = F->getParent();
|
const Module *M = F->getParent();
|
||||||
const TargetData *TD = TM.getTargetData();
|
const TargetData *TD = TM.getTargetData();
|
||||||
|
unsigned FrameSize = 0;
|
||||||
// Emit the data section name.
|
// Emit the data section name.
|
||||||
O << "\n";
|
O << "\n";
|
||||||
std::string fDataSection = "fdata." + CurrentFnName + ".#";
|
std::string SectionName = "fdata." + CurrentFnName + ".# " + "UDATA";
|
||||||
SwitchToUDataSection(fDataSection.c_str(), F);
|
|
||||||
|
const Section *fDataSection = TAI->getNamedSection(SectionName.c_str(),
|
||||||
|
SectionFlags::Writeable);
|
||||||
|
SwitchToSection(fDataSection);
|
||||||
|
|
||||||
//Emit function return value.
|
//Emit function return value.
|
||||||
O << CurrentFnName << ".retval:\n";
|
O << CurrentFnName << ".retval:\n";
|
||||||
const Type *RetType = F->getReturnType();
|
const Type *RetType = F->getReturnType();
|
||||||
if (RetType->getTypeID() != Type::VoidTyID) {
|
unsigned RetSize = 0;
|
||||||
unsigned RetSize = TD->getTypePaddedSize(RetType);
|
if (RetType->getTypeID() != Type::VoidTyID)
|
||||||
if (RetSize > 0)
|
RetSize = TD->getTypePaddedSize(RetType);
|
||||||
O << CurrentFnName << ".retval" << " RES " << RetSize;
|
|
||||||
}
|
|
||||||
// Emit function arguments.
|
// Emit function arguments.
|
||||||
O << CurrentFnName << ".args:\n";
|
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.
|
// Emit the function variables.
|
||||||
|
|
||||||
// In PIC16 all the function arguments and local variables are global.
|
// In PIC16 all the function arguments and local variables are global.
|
||||||
@ -358,22 +393,28 @@ void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
|
|||||||
Constant *C = I->getInitializer();
|
Constant *C = I->getInitializer();
|
||||||
const Type *Ty = C->getType();
|
const Type *Ty = C->getType();
|
||||||
unsigned Size = TD->getTypePaddedSize(Ty);
|
unsigned Size = TD->getTypePaddedSize(Ty);
|
||||||
|
FrameSize += Size;
|
||||||
// Emit memory reserve directive.
|
// Emit memory reserve directive.
|
||||||
O << VarName << " RES " << Size << "\n";
|
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.
|
// Emit temporary variables.
|
||||||
MachineFrameInfo *FrameInfo = MF.getFrameInfo();
|
MachineFrameInfo *FrameInfo = MF.getFrameInfo();
|
||||||
if (FrameInfo->hasStackObjects()) {
|
if (FrameInfo->hasStackObjects()) {
|
||||||
int indexBegin = FrameInfo->getObjectIndexBegin();
|
int indexBegin = FrameInfo->getObjectIndexBegin();
|
||||||
int indexEnd = FrameInfo->getObjectIndexEnd();
|
int indexEnd = FrameInfo->getObjectIndexEnd();
|
||||||
|
|
||||||
if (indexBegin < indexEnd)
|
if (indexBegin < indexEnd) {
|
||||||
|
FrameSize += indexEnd - indexBegin;
|
||||||
O << CurrentFnName << ".tmp RES"<< " "
|
O << CurrentFnName << ".tmp RES"<< " "
|
||||||
<<indexEnd - indexBegin <<"\n";
|
<<indexEnd - indexBegin <<"\n";
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
while (indexBegin < indexEnd) {
|
while (indexBegin < indexEnd) {
|
||||||
O << CurrentFnName << "_tmp_" << indexBegin << " " << "RES"<< " "
|
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);
|
bool runOnMachineFunction(MachineFunction &F);
|
||||||
void printOperand(const MachineInstr *MI, int opNum);
|
void printOperand(const MachineInstr *MI, int opNum);
|
||||||
void SwitchToUDataSection(const char *NewSection,
|
void printCCOperand(const MachineInstr *MI, int opNum);
|
||||||
const GlobalValue *GV = NULL);
|
|
||||||
void SwitchToRomDataSection(const char *NewSection,
|
|
||||||
const GlobalValue *GV = NULL);
|
|
||||||
bool printInstruction(const MachineInstr *MI); // definition autogenerated.
|
bool printInstruction(const MachineInstr *MI); // definition autogenerated.
|
||||||
bool printMachineInstruction(const MachineInstr *MI);
|
bool printMachineInstruction(const MachineInstr *MI);
|
||||||
void EmitExternsAndGlobals (Module &M);
|
void EmitExternsAndGlobals (Module &M);
|
||||||
@ -48,11 +45,12 @@ namespace llvm {
|
|||||||
void EmitRomData (Module &M);
|
void EmitRomData (Module &M);
|
||||||
virtual void EmitConstantValueOnly(const Constant *CV);
|
virtual void EmitConstantValueOnly(const Constant *CV);
|
||||||
void emitFunctionData(MachineFunction &MF);
|
void emitFunctionData(MachineFunction &MF);
|
||||||
void emitFunctionTempData(MachineFunction &MF);
|
void emitFunctionTempData(MachineFunction &MF, unsigned &FrameSize);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool doInitialization(Module &M);
|
bool doInitialization(Module &M);
|
||||||
bool doFinalization(Module &M);
|
bool doFinalization(Module &M);
|
||||||
|
bool inSameBank(char *s1, char *s2);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string CurrentBankselLabelInBasicBlock;
|
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.
|
Lo, // Low 8-bits of GlobalAddress.
|
||||||
Hi, // High 8-bits of GlobalAddress.
|
Hi, // High 8-bits of GlobalAddress.
|
||||||
PIC16Load,
|
PIC16Load,
|
||||||
|
PIC16LdWF,
|
||||||
PIC16Store,
|
PIC16Store,
|
||||||
|
PIC16StWF,
|
||||||
Banksel,
|
Banksel,
|
||||||
MTLO,
|
MTLO,
|
||||||
MTHI,
|
MTHI,
|
||||||
@ -38,6 +40,10 @@ namespace llvm {
|
|||||||
LRLF, // PIC16 Logical shift right
|
LRLF, // PIC16 Logical shift right
|
||||||
RLF, // Rotate left through carry
|
RLF, // Rotate left through carry
|
||||||
RRF, // Rotate right 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
|
Dummy
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -46,8 +52,21 @@ namespace llvm {
|
|||||||
RAM_SPACE = 0, // RAM address space
|
RAM_SPACE = 0, // RAM address space
|
||||||
ROM_SPACE = 1 // ROM address space number is 1
|
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
|
// TargetLowering Implementation
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
@ -58,25 +77,37 @@ namespace llvm {
|
|||||||
/// getTargetNodeName - This method returns the name of a target specific
|
/// getTargetNodeName - This method returns the name of a target specific
|
||||||
/// DAG node.
|
/// DAG node.
|
||||||
virtual const char *getTargetNodeName(unsigned Opcode) const;
|
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 LowerOperation(SDValue Op, SelectionDAG &DAG);
|
||||||
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
|
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
|
||||||
SDValue LowerADDE(SDValue Op, SelectionDAG &DAG);
|
SDValue LowerADD(SDValue Op, SelectionDAG &DAG);
|
||||||
SDValue LowerADDC(SDValue Op, SelectionDAG &DAG);
|
SDValue LowerSUB(SDValue Op, SelectionDAG &DAG);
|
||||||
SDValue LowerSUBE(SDValue Op, SelectionDAG &DAG);
|
|
||||||
SDValue LowerSUBC(SDValue Op, SelectionDAG &DAG);
|
|
||||||
SDValue LowerBinOp(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);
|
SelectionDAG &DAG);
|
||||||
|
|
||||||
SDValue ExpandStore(SDNode *N, SelectionDAG &DAG);
|
SDValue ExpandStore(SDNode *N, SelectionDAG &DAG);
|
||||||
SDValue ExpandLoad(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 ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG);
|
||||||
|
SDValue ExpandExternalSymbol(SDNode *N, SelectionDAG &DAG);
|
||||||
SDValue ExpandShift(SDNode *N, SelectionDAG &DAG);
|
SDValue ExpandShift(SDNode *N, SelectionDAG &DAG);
|
||||||
|
SDValue ExpandFrameIndex(SDNode *N, SelectionDAG &DAG);
|
||||||
|
|
||||||
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||||
SDValue PerformPIC16LoadCombine(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
|
// code at one place. In case of any change in future it will
|
||||||
// help maintain the code
|
// help maintain the code
|
||||||
SDValue getChain(SDValue &Op);
|
SDValue getChain(SDValue &Op);
|
||||||
|
|
||||||
|
SDValue getOutFlag(SDValue &Op);
|
||||||
|
|
||||||
|
|
||||||
// Extract the Lo and Hi component of Op.
|
// Extract the Lo and Hi component of Op.
|
||||||
@ -108,13 +141,44 @@ namespace llvm {
|
|||||||
void LegalizeAddress(SDValue Ptr, SelectionDAG &DAG, SDValue &Chain,
|
void LegalizeAddress(SDValue Ptr, SelectionDAG &DAG, SDValue &Chain,
|
||||||
SDValue &NewPtr, unsigned &Offset);
|
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.
|
// 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.
|
// This function is used to put one operand on stack and generate a load.
|
||||||
SDValue ConvertToMemOperand(SDValue Op, SelectionDAG &DAG);
|
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
|
/// Subtarget - Keep a pointer to the PIC16Subtarget around so that we can
|
||||||
/// make the right decision when generating code for different targets.
|
/// make the right decision when generating code for different targets.
|
||||||
const PIC16Subtarget *Subtarget;
|
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
|
} // namespace llvm
|
||||||
|
|
||||||
|
@ -125,20 +125,29 @@ bool PIC16InstrInfo::copyRegToReg (MachineBasicBlock &MBB,
|
|||||||
const TargetRegisterClass *SrcRC) const {
|
const TargetRegisterClass *SrcRC) const {
|
||||||
if (DestRC == PIC16::FSR16RegisterClass) {
|
if (DestRC == PIC16::FSR16RegisterClass) {
|
||||||
BuildMI(MBB, I, get(PIC16::copy_fsr), DestReg).addReg(SrcReg);
|
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,
|
bool PIC16InstrInfo::isMoveInstr(const MachineInstr &MI,
|
||||||
unsigned &SrcReg,
|
unsigned &SrcReg,
|
||||||
unsigned &DestReg) const {
|
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();
|
DestReg = MI.getOperand(0).getReg();
|
||||||
SrcReg = MI.getOperand(1).getReg();
|
SrcReg = MI.getOperand(1).getReg();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,9 +38,22 @@ def SDTI16BinOp : SDTypeProfile<1, 2, [SDTCisI16<0>, SDTCisI16<1>,
|
|||||||
// Node specific type profiles.
|
// Node specific type profiles.
|
||||||
def SDT_PIC16Load : SDTypeProfile<1, 3, [SDTCisI8<0>, SDTCisI8<1>,
|
def SDT_PIC16Load : SDTypeProfile<1, 3, [SDTCisI8<0>, SDTCisI8<1>,
|
||||||
SDTCisI8<2>, SDTCisI8<3>]>;
|
SDTCisI8<2>, SDTCisI8<3>]>;
|
||||||
|
|
||||||
def SDT_PIC16Store : SDTypeProfile<0, 4, [SDTCisI8<0>, SDTCisI8<1>,
|
def SDT_PIC16Store : SDTypeProfile<0, 4, [SDTCisI8<0>, SDTCisI8<1>,
|
||||||
SDTCisI8<2>, SDTCisI8<3>]>;
|
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.
|
// PIC16 addressing modes matching via DAG.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -52,7 +65,7 @@ def diraddr : ComplexPattern<i8, 1, "SelectDirectAddr", [], []>;
|
|||||||
def PIC16callseq_start : SDNode<"ISD::CALLSEQ_START", SDTI8VoidOp,
|
def PIC16callseq_start : SDNode<"ISD::CALLSEQ_START", SDTI8VoidOp,
|
||||||
[SDNPHasChain, SDNPOutFlag]>;
|
[SDNPHasChain, SDNPOutFlag]>;
|
||||||
def PIC16callseq_end : SDNode<"ISD::CALLSEQ_END", SDTI8VoidOp,
|
def PIC16callseq_end : SDNode<"ISD::CALLSEQ_END", SDTI8VoidOp,
|
||||||
[SDNPHasChain, SDNPOutFlag]>;
|
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
||||||
|
|
||||||
// Low 8-bits of GlobalAddress.
|
// Low 8-bits of GlobalAddress.
|
||||||
def PIC16Lo : SDNode<"PIC16ISD::Lo", SDTI8UnaryOp>;
|
def PIC16Lo : SDNode<"PIC16ISD::Lo", SDTI8UnaryOp>;
|
||||||
@ -71,18 +84,37 @@ def Banksel : SDNode<"PIC16ISD::Banksel", SDTI8UnaryOp>;
|
|||||||
|
|
||||||
// Node to match a direct store operation.
|
// Node to match a direct store operation.
|
||||||
def PIC16Store : SDNode<"PIC16ISD::PIC16Store", SDT_PIC16Store, [SDNPHasChain]>;
|
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.
|
// Node to match a direct load operation.
|
||||||
def PIC16Load : SDNode<"PIC16ISD::PIC16Load", SDT_PIC16Load, [SDNPHasChain]>;
|
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.
|
// PIC16 Operand Definitions.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
def i8mem : Operand<i8>;
|
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"
|
include "PIC16InstrFormats.td"
|
||||||
|
|
||||||
@ -90,7 +122,7 @@ include "PIC16InstrFormats.td"
|
|||||||
// PIC16 Common Classes.
|
// 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>:
|
class BinOpFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
|
||||||
ByteFormat<OpCode, (outs GPR:$dst),
|
ByteFormat<OpCode, (outs GPR:$dst),
|
||||||
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
|
(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,
|
[(set GPR:$dst, (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
|
||||||
(i8 imm:$ptrhi),
|
(i8 imm:$ptrhi),
|
||||||
(i8 imm:$offset))))]>;
|
(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>:
|
class BinOpWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
|
||||||
ByteFormat<OpCode, (outs),
|
ByteFormat<OpCode, (outs),
|
||||||
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
|
(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)
|
(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.
|
// PIC16 Instructions.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -163,6 +203,9 @@ def set_fsrhi:
|
|||||||
def copy_fsr:
|
def copy_fsr:
|
||||||
Pseudo<(outs FSR16:$dst), (ins FSR16:$src), "copy_fsr $dst, $src", []>;
|
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
|
// Store to memory
|
||||||
//-------------------------
|
//-------------------------
|
||||||
@ -181,6 +224,14 @@ def movwf_1 :
|
|||||||
[(PIC16Store GPR:$val, texternalsym:$ptrlo, (i8 imm:$ptrhi),
|
[(PIC16Store GPR:$val, texternalsym:$ptrlo, (i8 imm:$ptrhi),
|
||||||
(i8 imm:$offset))]>;
|
(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.
|
// Indirect store. Matched via a DAG replacement pattern.
|
||||||
def store_indirect :
|
def store_indirect :
|
||||||
ByteFormat<0, (outs),
|
ByteFormat<0, (outs),
|
||||||
@ -208,6 +259,16 @@ def movf_1 :
|
|||||||
(PIC16Load texternalsym:$ptrlo, (i8 imm:$ptrhi),
|
(PIC16Load texternalsym:$ptrlo, (i8 imm:$ptrhi),
|
||||||
(i8 imm:$offset)))]>;
|
(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.
|
// Indirect load. Matched via a DAG replacement pattern.
|
||||||
def load_indirect :
|
def load_indirect :
|
||||||
ByteFormat<0, (outs GPR:$dst),
|
ByteFormat<0, (outs GPR:$dst),
|
||||||
@ -218,23 +279,25 @@ def load_indirect :
|
|||||||
//-------------------------
|
//-------------------------
|
||||||
// Bitwise operations patterns
|
// Bitwise operations patterns
|
||||||
//--------------------------
|
//--------------------------
|
||||||
def OrFW : BinOpFW<0, "iorwf", OR>;
|
let isTwoAddress = 1 in {
|
||||||
def XOrFW : BinOpFW<0, "xorwf", XOR>;
|
def OrFW : BinOpFW<0, "iorwf", or>;
|
||||||
def AndFW : BinOpFW<0, "andwf", AND>;
|
def XOrFW : BinOpFW<0, "xorwf", xor>;
|
||||||
|
def AndFW : BinOpFW<0, "andwf", and>;
|
||||||
|
}
|
||||||
|
|
||||||
def OrWF : BinOpWF<0, "iorwf", OR>;
|
def OrWF : BinOpWF<0, "iorwf", or>;
|
||||||
def XOrWF : BinOpWF<0, "xorwf", XOR>;
|
def XOrWF : BinOpWF<0, "xorwf", xor>;
|
||||||
def AndWF : BinOpWF<0, "andwf", AND>;
|
def AndWF : BinOpWF<0, "andwf", and>;
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
// Various add/sub patterns.
|
// Various add/sub patterns.
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
// let isTwoAddress = 1 in {
|
let isTwoAddress = 1 in {
|
||||||
def addfw_1: BinOpFW<0, "addwf", add>;
|
def addfw_1: BinOpFW<0, "addwf", add>;
|
||||||
def addfw_2: BinOpFW<0, "addwf", addc>;
|
def addfw_2: BinOpFW<0, "addwf", addc>;
|
||||||
def addfwc: BinOpFW<0, "addwfc", adde>; // With Carry.
|
def addfwc: BinOpFW<0, "addwfc", adde>; // With Carry.
|
||||||
// }
|
}
|
||||||
|
|
||||||
def addwf_1: BinOpWF<0, "addwf", add>;
|
def addwf_1: BinOpWF<0, "addwf", add>;
|
||||||
def addwf_2: BinOpWF<0, "addwf", addc>;
|
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,
|
[(set GPR:$dst, (OpNode (PIC16Load diraddr:$ptrlo,
|
||||||
(i8 imm:$ptrhi), (i8 imm:$offset)),
|
(i8 imm:$ptrhi), (i8 imm:$offset)),
|
||||||
GPR:$src))]>;
|
GPR:$src))]>;
|
||||||
//let isTwoAddress = 1 in {
|
let isTwoAddress = 1 in {
|
||||||
def subfw_1: SUBFW<0, "subwf", sub>;
|
def subfw_1: SUBFW<0, "subwf", sub>;
|
||||||
def subfw_2: SUBFW<0, "subwf", subc>;
|
def subfw_2: SUBFW<0, "subwf", subc>;
|
||||||
def subfwb: SUBFW<0, "subwfb", sube>; // With Borrow.
|
def subfwb: SUBFW<0, "subwfb", sube>; // With Borrow.
|
||||||
//}
|
def subfw_cc: SUBFW<0, "subwf", PIC16Subcc>;
|
||||||
|
}
|
||||||
|
|
||||||
// [F] -= W ;
|
// [F] -= W ;
|
||||||
class SUBWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
|
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_1: SUBWF<0, "subwf", sub>;
|
||||||
def subwf_2: SUBWF<0, "subwf", subc>;
|
def subwf_2: SUBWF<0, "subwf", subc>;
|
||||||
def subwfb: SUBWF<0, "subwfb", sube>; // With Borrow.
|
def subwfb: SUBWF<0, "subwfb", sube>; // With Borrow.
|
||||||
|
def subwf_cc: SUBWF<0, "subwf", PIC16Subcc>;
|
||||||
|
|
||||||
// addlw
|
// addlw
|
||||||
// W += C ; add literal to W. (Without carry). May Produce a carry.
|
let isTwoAddress = 1 in {
|
||||||
class ADDLW<bits<6> opcode, string OpcStr, SDNode OpNode> :
|
def addlw_1 : BinOpLW<0, "addlw", add>;
|
||||||
LiteralFormat<opcode, (outs GPR:$dst),
|
def addlw_2 : BinOpLW<0, "addlw", addc>;
|
||||||
(ins GPR:$src, i8imm:$literal),
|
def addlwc : BinOpLW<0, "addlwc", adde>; // With Carry. (Assembler macro).
|
||||||
!strconcat(OpcStr, " $literal"),
|
}
|
||||||
[(set GPR:$dst, (OpNode GPR:$src, (i8 imm:$literal)))]>;
|
|
||||||
|
|
||||||
// let isTwoAddress = 1 in {
|
// bitwise operations involving a literal and w.
|
||||||
def addlw_1 : ADDLW<0, "addlw", add>;
|
let isTwoAddress = 1 in {
|
||||||
def addlw_2 : ADDLW<0, "addlw", addc>;
|
def andlw : BinOpLW<0, "andlw", and>;
|
||||||
def addlwc : ADDLW<0, "addlwc", adde>; // With Carry. (Assembler macro).
|
def xorlw : BinOpLW<0, "xorlw", xor>;
|
||||||
//}
|
def orlw : BinOpLW<0, "iorlw", or>;
|
||||||
|
}
|
||||||
|
|
||||||
// sublw
|
// sublw
|
||||||
// W = C - W ; sub W from literal. (Without borrow).
|
// W = C - W ; sub W from literal. (Without borrow).
|
||||||
class SUBLW<bits<6> opcode, SDNode OpNode> :
|
class SUBLW<bits<6> opcode, SDNode OpNode> :
|
||||||
LiteralFormat<opcode, (outs GPR:$dst),
|
LiteralFormat<opcode, (outs GPR:$dst),
|
||||||
(ins GPR:$src, i8imm:$literal),
|
(ins GPR:$src, i8imm:$literal),
|
||||||
"addlw $literal",
|
"sublw $literal",
|
||||||
[(set GPR:$dst, (OpNode (i8 imm:$literal), GPR:$src))]>;
|
[(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_1 : SUBLW<0, sub>;
|
||||||
def sublw_2 : SUBLW<0, subc>;
|
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.
|
// Banksel.
|
||||||
let isReMaterializable = 1 in {
|
let isReMaterializable = 1 in {
|
||||||
|
@ -79,4 +79,13 @@ unsigned PIC16RegisterInfo::getRARegister() const {
|
|||||||
return 0;
|
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,
|
virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI,
|
||||||
int SPAdj, RegScavenger *RS=NULL) const;
|
int SPAdj, RegScavenger *RS=NULL) const;
|
||||||
|
|
||||||
|
void eliminateCallFramePseudoInstr(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator I) const;
|
||||||
|
|
||||||
virtual void emitPrologue(MachineFunction &MF) const;
|
virtual void emitPrologue(MachineFunction &MF) const;
|
||||||
virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const;
|
virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const;
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "PIC16TargetAsmInfo.h"
|
#include "PIC16TargetAsmInfo.h"
|
||||||
#include "PIC16TargetMachine.h"
|
#include "PIC16TargetMachine.h"
|
||||||
|
#include "llvm/GlobalValue.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
@ -23,9 +24,12 @@ PIC16TargetAsmInfo(const PIC16TargetMachine &TM)
|
|||||||
Data8bitsDirective = " db ";
|
Data8bitsDirective = " db ";
|
||||||
Data16bitsDirective = " db ";
|
Data16bitsDirective = " db ";
|
||||||
Data32bitsDirective = " db ";
|
Data32bitsDirective = " db ";
|
||||||
DataSectionStartSuffix = " IDATA ";
|
|
||||||
UDataSectionStartSuffix = " UDATA ";
|
|
||||||
TextSectionStartSuffix = " CODE ";
|
|
||||||
RomDataSectionStartSuffix = " ROMDATA ";
|
|
||||||
ZeroDirective = NULL;
|
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 {
|
struct PIC16TargetAsmInfo : public TargetAsmInfo {
|
||||||
PIC16TargetAsmInfo(const PIC16TargetMachine &TM);
|
PIC16TargetAsmInfo(const PIC16TargetMachine &TM);
|
||||||
const char *UDataSectionStartSuffix;
|
|
||||||
const char *RomDataSectionStartSuffix;
|
|
||||||
public :
|
public :
|
||||||
const char *getUDataSectionStartSuffix() const {
|
|
||||||
return UDataSectionStartSuffix;
|
|
||||||
}
|
|
||||||
const char *getRomDataSectionStartSuffix() const {
|
|
||||||
return RomDataSectionStartSuffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
Loading…
Reference in New Issue
Block a user