Added a more function PIC16 backend. However to get this working a patch in

ExpandIntegerOperand (LegalizeIntegerTypes.cpp) is needed which is yet to be reworked and submitted. 


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59617 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sanjiv Gupta 2008-11-19 11:00:54 +00:00
parent 2f45f9762d
commit b1b5ffd827
23 changed files with 1671 additions and 2399 deletions

View File

@ -12,14 +12,13 @@
//
//===----------------------------------------------------------------------===//
#ifndef TARGET_PIC16_H
#define TARGET_PIC16_H
#ifndef LLVM_TARGET_PIC16_H
#define LLVM_TARGET_PIC16_H
#include <iosfwd>
namespace llvm {
class PIC16TargetMachine;
class FunctionPassManager;
class FunctionPass;
class MachineCodeEmitter;
class raw_ostream;

View File

@ -15,30 +15,24 @@
include "../Target.td"
//===----------------------------------------------------------------------===//
// Descriptions
//===----------------------------------------------------------------------===//
include "PIC16RegisterInfo.td"
include "PIC16CallingConv.td"
include "PIC16InstrInfo.td"
def PIC16InstrInfo : InstrInfo {
let TSFlagsFields = [];
let TSFlagsShifts = [];
}
// Not currently supported, but work as SubtargetFeature placeholder.
def FeaturePIC16Old : SubtargetFeature<"pic16old", "IsPIC16Old", "true",
"PIC16 Old ISA Support">;
//===----------------------------------------------------------------------===//
// Subtarget Features.
//===----------------------------------------------------------------------===//
def FeatureCooper : SubtargetFeature<"cooper", "IsCooper", "true",
"PIC16 Cooper ISA Support">;
//===----------------------------------------------------------------------===//
// PIC16 processors supported.
// PIC16 supported processors.
//===----------------------------------------------------------------------===//
def : Processor<"generic", NoItineraries, []>;
def : Processor<"cooper", NoItineraries, [FeatureCooper]>;
def PIC16InstrInfo : InstrInfo {}
def PIC16 : Target {
let InstructionSet = PIC16InstrInfo;

View File

@ -12,99 +12,91 @@
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "asm-printer"
#include "PIC16.h"
#include "PIC16TargetMachine.h"
#include "PIC16ConstantPoolValue.h"
#include "PIC16InstrInfo.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include "PIC16AsmPrinter.h"
#include "PIC16TargetAsmInfo.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <cctype>
#include "llvm/Support/Mangler.h"
#include "llvm/Function.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/DerivedTypes.h"
using namespace llvm;
STATISTIC(EmittedInsts, "Number of machine instrs printed");
namespace {
struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter {
PIC16AsmPrinter(raw_ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
: AsmPrinter(O, TM, T) {
}
/// We name each basic block in a Function with a unique number, so
/// that we can consistently refer to them later. This is cleared
/// at the beginning of each call to runOnMachineFunction().
///
typedef std::map<const Value *, unsigned> ValueMapTy;
ValueMapTy NumberForBB;
/// Keeps the set of GlobalValues that require non-lazy-pointers for
/// indirect access.
std::set<std::string> GVNonLazyPtrs;
/// Keeps the set of external function GlobalAddresses that the asm
/// printer should generate stubs for.
std::set<std::string> FnStubs;
/// True if asm printer is printing a series of CONSTPOOL_ENTRY.
bool InCPMode;
virtual const char *getPassName() const {
return "PIC16 Assembly Printer";
}
void printOperand(const MachineInstr *MI, int opNum,
const char *Modifier = 0);
void printSOImmOperand(const MachineInstr *MI, int opNum);
void printAddrModeOperand(const MachineInstr *MI, int OpNo);
void printRegisterList(const MachineInstr *MI, int opNum);
void printCPInstOperand(const MachineInstr *MI, int opNum,
const char *Modifier);
bool printInstruction(const MachineInstr *MI); // autogenerated.
void emitFunctionStart(MachineFunction &F);
bool runOnMachineFunction(MachineFunction &F);
bool doInitialization(Module &M);
bool doFinalization(Module &M);
virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV);
void getAnalysisUsage(AnalysisUsage &AU) const;
public:
void SwitchToTextSection(const char *NewSection,
const GlobalValue *GV = NULL);
void SwitchToDataSection(const char *NewSection,
const GlobalValue *GV = NULL);
void SwitchToDataOvrSection(const char *NewSection,
const GlobalValue *GV = NULL);
};
} // end of anonymous namespace
#include "PIC16GenAsmWriter.inc"
bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
std::string NewBankselLabel;
unsigned Operands = MI->getNumOperands();
if (Operands > 1) {
// Global address or external symbol should be second operand from last
// if we want to print banksel for it.
const MachineOperand &Op = MI->getOperand(Operands-2);
unsigned OpType = Op.getType();
if (OpType == MachineOperand::MO_GlobalAddress ||
OpType == MachineOperand::MO_ExternalSymbol) {
if (OpType == MachineOperand::MO_GlobalAddress )
NewBankselLabel = Mang->getValueName(Op.getGlobal());
else
NewBankselLabel = Op.getSymbolName();
// Operand after global address or external symbol should be banksel.
// Value 1 for this operand means we need to generate banksel else do not
// generate banksel.
const MachineOperand &BS = MI->getOperand(Operands-1);
if (((int)BS.getImm() == 1) &&
(strcmp (CurrentBankselLabelInBasicBlock.c_str(),
NewBankselLabel.c_str()))) {
CurrentBankselLabelInBasicBlock = NewBankselLabel;
O << "\tbanksel ";
printOperand(MI, Operands-2);
O << "\n";
}
}
}
printInstruction(MI);
return true;
}
/// runOnMachineFunction - This uses the printInstruction()
/// method to print assembly for each instruction.
///
bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
// This calls the base class function required to be called at beginning
// of runOnMachineFunction.
SetupMachineFunction(MF);
// Get the mangled name.
const Function *F = MF.getFunction();
CurrentFnName = Mang->getValueName(F);
// Emit the function variables.
emitFunctionData(MF);
std::string codeSection;
codeSection = "code." + CurrentFnName + ".#";
O << "\n";
SwitchToTextSection (codeSection.c_str(),F);
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
// Print a label for the basic block.
if (I != MF.begin()) {
printBasicBlockLabel(I, true);
O << '\n';
}
else
O << "_" << CurrentFnName << ":\n";
CurrentBankselLabelInBasicBlock = "";
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
// Print the assembly for the instruction.
printMachineInstruction(II);
}
}
return false; // we didn't modify anything.
}
/// createPIC16CodePrinterPass - Returns a pass that prints the PIC16
/// assembly code for a MachineFunction to the given output stream,
/// using the given target machine description. This should work
@ -115,413 +107,295 @@ FunctionPass *llvm::createPIC16CodePrinterPass(raw_ostream &o,
return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo());
}
void PIC16AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const
{
// FIXME: Currently unimplemented.
}
void PIC16AsmPrinter ::
EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV)
{
printDataDirective(MCPV->getType());
PIC16ConstantPoolValue *ACPV = (PIC16ConstantPoolValue*)MCPV;
GlobalValue *GV = ACPV->getGV();
std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix();
if (!GV)
Name += ACPV->getSymbol();
if (ACPV->isNonLazyPointer()) {
GVNonLazyPtrs.insert(Name);
O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr";
} else if (ACPV->isStub()) {
FnStubs.insert(Name);
O << TAI->getPrivateGlobalPrefix() << Name << "$stub";
} else {
O << Name;
}
if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
if (ACPV->getPCAdjustment() != 0) {
O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
<< utostr(ACPV->getLabelId())
<< "+" << (unsigned)ACPV->getPCAdjustment();
if (ACPV->mustAddCurrentAddress())
O << "-.";
O << ")";
}
O << "\n";
// If the constant pool value is a extern weak symbol, remember to emit
// the weak reference.
if (GV && GV->hasExternalWeakLinkage())
ExtWeakSymbols.insert(GV);
}
/// emitFunctionStart - Emit the directives used by ASM on the start of
/// functions.
void PIC16AsmPrinter::emitFunctionStart(MachineFunction &MF)
{
// Print out the label for the function.
const Function *F = MF.getFunction();
MachineFrameInfo *FrameInfo = MF.getFrameInfo();
if (FrameInfo->hasStackObjects()) {
int indexBegin = FrameInfo->getObjectIndexBegin();
int indexEnd = FrameInfo->getObjectIndexEnd();
while (indexBegin < indexEnd) {
if (indexBegin == 0)
SwitchToDataOvrSection(F->getParent()->getModuleIdentifier().c_str(),
F);
O << "\t\t" << CurrentFnName << "_" << indexBegin << " " << "RES"
<< " " << FrameInfo->getObjectSize(indexBegin) << "\n" ;
indexBegin++;
}
}
SwitchToTextSection(CurrentFnName.c_str(), F);
O << "_" << CurrentFnName << ":" ;
O << "\n";
}
/// runOnMachineFunction - This uses the printInstruction()
/// method to print assembly for each instruction.
///
bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF)
{
SetupMachineFunction(MF);
O << "\n";
// What's my mangled name?
CurrentFnName = Mang->getValueName(MF.getFunction());
// Emit the function start directives
emitFunctionStart(MF);
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
// Print a label for the basic block.
if (I != MF.begin()) {
printBasicBlockLabel(I, true);
O << '\n';
}
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
// Print the assembly for the instruction.
O << '\t';
printInstruction(II);
++EmittedInsts;
}
}
// We didn't modify anything.
return false;
}
void PIC16AsmPrinter::
printOperand(const MachineInstr *MI, int opNum, const char *Modifier)
{
void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
const MachineOperand &MO = MI->getOperand(opNum);
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
switch (MO.getType()) {
case MachineOperand::MO_Register:
if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
O << RI.get(MO.getReg()).Name;
O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
else
assert(0 && "not implemented");
break;
return;
case MachineOperand::MO_Immediate:
if (!Modifier || strcmp(Modifier, "no_hash") != 0)
O << "#";
case MachineOperand::MO_Immediate:
O << (int)MO.getImm();
break;
case MachineOperand::MO_MachineBasicBlock:
printBasicBlockLabel(MO.getMBB());
return;
case MachineOperand::MO_GlobalAddress:
O << Mang->getValueName(MO.getGlobal())<<'+'<<MO.getOffset();
case MachineOperand::MO_GlobalAddress:
O << Mang->getValueName(MO.getGlobal());
break;
case MachineOperand::MO_ExternalSymbol:
case MachineOperand::MO_ExternalSymbol:
O << MO.getSymbolName();
break;
case MachineOperand::MO_ConstantPoolIndex:
O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
<< '_' << MO.getIndex();
break;
case MachineOperand::MO_FrameIndex:
O << "_" << CurrentFnName
<< '+' << MO.getIndex();
break;
case MachineOperand::MO_JumpTableIndex:
O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< '_' << MO.getIndex();
break;
default:
O << "<unknown operand type>"; abort ();
break;
} // end switch.
}
static void
printSOImm(raw_ostream &O, int64_t V, const TargetAsmInfo *TAI)
{
assert(V < (1 << 12) && "Not a valid so_imm value!");
O << (unsigned) V;
}
/// printSOImmOperand - SOImm is 4-bit rotated amount in bits 8-11 with 8-bit
/// immediate in bits 0-7.
void PIC16AsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum)
{
const MachineOperand &MO = MI->getOperand(OpNum);
assert(MO.isImm() && "Not a valid so_imm value!");
printSOImm(O, MO.getImm(), TAI);
}
void PIC16AsmPrinter::printAddrModeOperand(const MachineInstr *MI, int Op)
{
const MachineOperand &MO1 = MI->getOperand(Op);
const MachineOperand &MO2 = MI->getOperand(Op+1);
if (MO2.isFI()) {
printOperand(MI, Op+1);
return;
}
if (!MO1.isReg()) {
// FIXME: This is for CP entries, but isn't right.
printOperand(MI, Op);
return;
}
// If this is Stack Slot
if (MO1.isReg()) {
if (strcmp(TM.getRegisterInfo()->get(MO1.getReg()).Name, "SP") == 0) {
O << CurrentFnName <<"_"<< MO2.getImm();
return;
}
O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
O << "+";
O << MO2.getImm();
O << "]";
return;
}
O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
O << "]";
}
void PIC16AsmPrinter::printRegisterList(const MachineInstr *MI, int opNum)
{
O << "{";
for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) {
printOperand(MI, i);
if (i != e-1) O << ", ";
}
O << "}";
}
void PIC16AsmPrinter::
printCPInstOperand(const MachineInstr *MI, int OpNo, const char *Modifier)
{
assert(Modifier && "This operand only works with a modifier!");
// There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
// data itself.
if (!strcmp(Modifier, "label")) {
unsigned ID = MI->getOperand(OpNo).getImm();
O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
<< '_' << ID << ":\n";
} else {
assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
unsigned CPI = MI->getOperand(OpNo).getIndex();
const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun?
MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI];
if (MCPE.isMachineConstantPoolEntry())
EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
else {
EmitGlobalConstant(MCPE.Val.ConstVal);
// remember to emit the weak reference
if (const GlobalValue *GV = dyn_cast<GlobalValue>(MCPE.Val.ConstVal))
if (GV->hasExternalWeakLinkage())
ExtWeakSymbols.insert(GV);
}
assert(0 && " Operand type not supported.");
}
}
bool PIC16AsmPrinter::doInitialization(Module &M)
{
bool PIC16AsmPrinter::doInitialization (Module &M) {
bool Result = AsmPrinter::doInitialization(M);
// FIXME:: This is temporary solution to generate the include file.
// The processor should be passed to llc as in input and the header file
// should be generated accordingly.
O << "\t#include P16F1937.INC\n";
EmitInitData (M);
EmitUnInitData(M);
EmitRomData(M);
return Result;
}
bool PIC16AsmPrinter::doFinalization(Module &M)
void PIC16AsmPrinter::EmitInitData (Module &M)
{
std::string iDataSection = "idata.#";
SwitchToDataSection(iDataSection.c_str());
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
if (!I->hasInitializer()) // External global require no code.
continue;
Constant *C = I->getInitializer();
const PointerType *PtrTy = I->getType();
int AddrSpace = PtrTy->getAddressSpace();
if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::RAM_SPACE)) {
if (EmitSpecialLLVMGlobal(I))
continue;
// Any variables reaching here with "." in its name is a local scope
// variable and should not be printed in global data section.
std::string name = Mang->getValueName(I);
if (name.find(".") != std::string::npos)
continue;
O << name;
EmitGlobalConstant(C);
}
}
}
void PIC16AsmPrinter::EmitConstantValueOnly(const Constant* CV) {
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
unsigned BitWidth = CI->getBitWidth();
int Val = CI->getZExtValue();
if (BitWidth == 8) {
// Expecting db directive here. In case of romdata we need to pad the
// word with zeros.
if (IsRomData)
O << 0 <<", ";
O << Val;
}
else if (BitWidth == 16) {
unsigned Element1, Element2;
Element1 = 0x00ff & Val;
Element2 = 0x00ff & (Val >> 8);
if (IsRomData)
O << 0 <<", "<<Element1 <<", "<< 0 <<", "<< Element2;
else
O << Element1 <<", "<< Element2;
}
else if (BitWidth == 32) {
unsigned Element1, Element2, Element3, Element4;
Element1 = 0x00ff & Val;
Element2 = 0x00ff & (Val >> 8);
Element3 = 0x00ff & (Val >> 16);
Element4 = 0x00ff & (Val >> 24);
if (IsRomData)
O << 0 <<", "<< Element1 <<", "<< 0 <<", "<< Element2 <<", "<< 0
<<", "<< Element3 <<", "<< 0 <<", "<< Element4;
else
O << Element1 <<", "<< Element2 <<", "<< Element3 <<", "<< Element4;
}
return;
}
AsmPrinter::EmitConstantValueOnly(CV);
}
void PIC16AsmPrinter::EmitRomData (Module &M)
{
std::string romDataSection = "romdata.#";
SwitchToRomDataSection(romDataSection.c_str());
IsRomData = true;
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
if (!I->hasInitializer()) // External global require no code.
continue;
Constant *C = I->getInitializer();
const PointerType *PtrTy = I->getType();
int AddrSpace = PtrTy->getAddressSpace();
if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::ROM_SPACE)) {
if (EmitSpecialLLVMGlobal(I))
continue;
// Any variables reaching here with "." in its name is a local scope
// variable and should not be printed in global data section.
std::string name = Mang->getValueName(I);
if (name.find(".") != std::string::npos)
continue;
O << name;
EmitGlobalConstant(C);
O << "\n";
}
}
IsRomData = false;
}
void PIC16AsmPrinter::EmitUnInitData (Module &M)
{
std::string uDataSection = "udata.#";
SwitchToUDataSection(uDataSection.c_str());
const TargetData *TD = TM.getTargetData();
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
if (!I->hasInitializer()) // External global require no code
if (!I->hasInitializer()) // External global require no code.
continue;
if (EmitSpecialLLVMGlobal(I)) {
continue;
Constant *C = I->getInitializer();
if (C->isNullValue()) {
if (EmitSpecialLLVMGlobal(I))
continue;
// Any variables reaching here with "." in its name is a local scope
// variable and should not be printed in global data section.
std::string name = Mang->getValueName(I);
if (name.find(".") != std::string::npos)
continue;
const Type *Ty = C->getType();
unsigned Size = TD->getABITypeSize(Ty);
O << name << " " <<"RES"<< " " << Size ;
O << "\n";
}
}
}
std::string name = Mang->getValueName(I);
bool PIC16AsmPrinter::doFinalization(Module &M) {
O << "\t" << "END\n";
bool Result = AsmPrinter::doFinalization(M);
return Result;
}
void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
const Function *F = MF.getFunction();
std::string FuncName = Mang->getValueName(F);
const Module *M = F->getParent();
const TargetData *TD = TM.getTargetData();
// Emit the data section name.
O << "\n";
std::string fDataSection = "fdata." + CurrentFnName + ".#";
SwitchToUDataSection(fDataSection.c_str(), F);
// Emit the label for data section of current function.
O << "_frame_" << CurrentFnName << ":" ;
O << "\n";
// Emit the function variables.
if (F->hasExternalLinkage()) {
O << "\t" << "GLOBAL _frame_" << CurrentFnName << "\n";
O << "\t" << "GLOBAL _" << CurrentFnName << "\n";
}
// In PIC16 all the function arguments and local variables are global.
// Therefore to get the variable belonging to this function entire
// global list will be traversed and variables belonging to this function
// will be emitted in the current data section.
for (Module::const_global_iterator I = M->global_begin(), E = M->global_end();
I != E; ++I) {
std::string VarName = Mang->getValueName(I);
// The variables of a function are of form FuncName.* . If this variable
// does not belong to this function then continue.
if (!(VarName.find(FuncName + ".") == 0 ? true : false))
continue;
Constant *C = I->getInitializer();
const Type *Ty = C->getType();
unsigned Size = TD->getABITypeSize(Ty);
unsigned Align = TD->getPreferredAlignmentLog(I);
// Emit memory reserve directive.
O << VarName << " RES " << Size << "\n";
}
emitFunctionTempData(MF);
}
const char *VisibilityDirective = NULL;
if (I->hasHiddenVisibility())
VisibilityDirective = TAI->getHiddenDirective();
else if (I->hasProtectedVisibility())
VisibilityDirective = TAI->getProtectedDirective();
void PIC16AsmPrinter::emitFunctionTempData(MachineFunction &MF) {
// Emit temporary variables.
MachineFrameInfo *FrameInfo = MF.getFrameInfo();
if (FrameInfo->hasStackObjects()) {
int indexBegin = FrameInfo->getObjectIndexBegin();
int indexEnd = FrameInfo->getObjectIndexEnd();
if (VisibilityDirective)
O << VisibilityDirective << name << "\n";
if (C->isNullValue()) {
if (I->hasExternalLinkage()) {
if (const char *Directive = TAI->getZeroFillDirective()) {
O << "\t.globl\t" << name << "\n";
O << Directive << "__DATA__, __common, " << name << ", "
<< Size << ", " << Align << "\n";
continue;
}
}
if (!I->hasSection() &&
(I->hasInternalLinkage() || I->hasWeakLinkage() ||
I->hasLinkOnceLinkage() || I->hasCommonLinkage())) {
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
SwitchToDataSection(M.getModuleIdentifier().c_str(), I);
if (TAI->getLCOMMDirective() != NULL) {
if (I->hasInternalLinkage()) {
O << TAI->getLCOMMDirective() << name << "," << Size;
} else
O << TAI->getCOMMDirective() << name << "," << Size;
} else {
if (I->hasInternalLinkage())
O << "\t.local\t" << name << "\n";
O << TAI->getCOMMDirective() <<"\t" << name << " " <<"RES"<< " "
<< Size;
O << "\n\t\tGLOBAL" <<" "<< name;
if (TAI->getCOMMDirectiveTakesAlignment())
O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
}
continue;
}
if (indexBegin < indexEnd)
O << CurrentFnName << ".tmp RES"<< " "
<<indexEnd - indexBegin <<"\n";
/*
while (indexBegin < indexEnd) {
O << CurrentFnName << "_tmp_" << indexBegin << " " << "RES"<< " "
<< 1 << "\n" ;
indexBegin++;
}
switch (I->getLinkage()) {
case GlobalValue::AppendingLinkage:
// FIXME: appending linkage variables should go into a section of
// their name or something. For now, just emit them as external.
// FALL THROUGH
case GlobalValue::ExternalLinkage:
O << "\t.globl " << name << "\n";
// FALL THROUGH
case GlobalValue::InternalLinkage:
break;
default:
assert(0 && "Unknown linkage type!");
break;
} // end switch.
EmitAlignment(Align, I);
O << name << ":\t\t\t\t" << TAI->getCommentString() << " " << I->getName()
<< "\n";
// If the initializer is a extern weak symbol, remember to emit the weak
// reference!
if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
if (GV->hasExternalWeakLinkage())
ExtWeakSymbols.insert(GV);
EmitGlobalConstant(C);
O << '\n';
} // end for.
O << "\n "<< "END";
return AsmPrinter::doFinalization(M);
*/
}
}
void PIC16AsmPrinter::
SwitchToTextSection(const char *NewSection, const GlobalValue *GV)
{
O << "\n";
if (NewSection && *NewSection) {
std::string codeSection = "code_";
codeSection += NewSection;
codeSection += " ";
codeSection += "CODE";
AsmPrinter::SwitchToTextSection(codeSection.c_str(), GV);
}
else
AsmPrinter::SwitchToTextSection(NewSection, GV);
}
void PIC16AsmPrinter::
SwitchToDataSection(const char *NewSection, const GlobalValue *GV)
{
// Need to append index for page.
O << "\n";
if (NewSection && *NewSection) {
std::string dataSection = "udata_";
dataSection += NewSection;
if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) {
dataSection = dataSection.substr(0, dataSection.length() - 2);
}
dataSection += " ";
dataSection += "UDATA";
AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV);
}
/// 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
AsmPrinter::SwitchToDataSection(NewSection, GV);
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;
}
void PIC16AsmPrinter::
SwitchToDataOvrSection(const char *NewSection, const GlobalValue *GV)
{
O << "\n";
if (NewSection && *NewSection) {
std::string dataSection = "frame_";
dataSection += NewSection;
if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) {
dataSection = dataSection.substr(0, dataSection.length() - 2);
}
dataSection += "_";
dataSection += CurrentFnName;
dataSection += " ";
dataSection += "UDATA_OVR";
AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV);
}
/// 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
AsmPrinter::SwitchToDataSection(NewSection, GV);
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

@ -1,16 +0,0 @@
//===- PIC16CallingConv.td - Calling Conventions PIC16 -----*- tablegen -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This describes the calling conventions for the PIC16 architectures.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Return Value Calling Conventions
//===----------------------------------------------------------------------===//

View File

@ -1,89 +0,0 @@
//===- PIC16ConstantPoolValue.cpp - PIC16 constantpool value --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the PIC16 specific constantpool value class.
//
//===----------------------------------------------------------------------===//
#include "PIC16ConstantPoolValue.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/GlobalValue.h"
#include "llvm/Type.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
PIC16ConstantPoolValue::PIC16ConstantPoolValue(GlobalValue *gv, unsigned id,
PIC16CP::PIC16CPKind k,
unsigned char PCAdj,
const char *Modif, bool AddCA)
: MachineConstantPoolValue((const Type*)gv->getType()),
GV(gv), S(NULL), LabelId(id), Kind(k), PCAdjust(PCAdj),
Modifier(Modif), AddCurrentAddress(AddCA) {}
PIC16ConstantPoolValue::PIC16ConstantPoolValue(const char *s, unsigned id,
PIC16CP::PIC16CPKind k,
unsigned char PCAdj,
const char *Modif, bool AddCA)
: MachineConstantPoolValue((const Type*)Type::Int32Ty),
GV(NULL), S(s), LabelId(id), Kind(k), PCAdjust(PCAdj),
Modifier(Modif), AddCurrentAddress(AddCA) {}
PIC16ConstantPoolValue::PIC16ConstantPoolValue(GlobalValue *gv,
PIC16CP::PIC16CPKind k,
const char *Modif)
: MachineConstantPoolValue((const Type*)Type::Int32Ty),
GV(gv), S(NULL), LabelId(0), Kind(k), PCAdjust(0),
Modifier(Modif) {}
int PIC16ConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
unsigned Alignment) {
unsigned AlignMask = (1 << Alignment)-1;
const std::vector<MachineConstantPoolEntry> Constants = CP->getConstants();
for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
if (Constants[i].isMachineConstantPoolEntry() &&
(Constants[i].Offset & AlignMask) == 0) {
PIC16ConstantPoolValue *CPV =
(PIC16ConstantPoolValue *)Constants[i].Val.MachineCPVal;
if (CPV->GV == GV &&
CPV->S == S &&
CPV->LabelId == LabelId &&
CPV->Kind == Kind &&
CPV->PCAdjust == PCAdjust)
return i;
}
}
return -1;
}
void
PIC16ConstantPoolValue::AddSelectionDAGCSEId(FoldingSetNodeID &ID) {
ID.AddPointer(GV);
ID.AddPointer(S);
ID.AddInteger(LabelId);
ID.AddInteger((unsigned)Kind);
ID.AddInteger(PCAdjust);
}
void PIC16ConstantPoolValue::print(raw_ostream &O) const {
if (GV)
O << GV->getName();
else
O << S;
if (isNonLazyPointer()) O << "$non_lazy_ptr";
else if (isStub()) O << "$stub";
if (Modifier) O << "(" << Modifier << ")";
if (PCAdjust != 0) {
O << "-(LPIC" << LabelId << "+"
<< (unsigned)PCAdjust;
if (AddCurrentAddress)
O << "-.";
O << ")";
}
}

View File

@ -1,77 +0,0 @@
//===- PIC16ConstantPoolValue.h - PIC16 constantpool value ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the PIC16 specific constantpool value class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TARGET_PIC16_CONSTANTPOOLVALUE_H
#define LLVM_TARGET_PIC16_CONSTANTPOOLVALUE_H
#include "llvm/CodeGen/MachineConstantPool.h"
namespace llvm {
class GlobalValue;
namespace PIC16CP {
enum PIC16CPKind {
CPValue,
CPNonLazyPtr,
CPStub
};
}
/// PIC16ConstantPoolValue - PIC16 specific constantpool value. This is used to
/// represent PC relative displacement between the address of the load
/// instruction and the global value being loaded, i.e. (&GV-(LPIC+8)).
class PIC16ConstantPoolValue : public MachineConstantPoolValue {
GlobalValue *GV; // GlobalValue being loaded.
const char *S; // ExtSymbol being loaded.
unsigned LabelId; // Label id of the load.
PIC16CP::PIC16CPKind Kind; // non_lazy_ptr or stub?
unsigned char PCAdjust; // Extra adjustment if constantpool is pc relative.
// 8 for PIC16
const char *Modifier; // GV modifier i.e. (&GV(modifier)-(LPIC+8))
bool AddCurrentAddress;
public:
PIC16ConstantPoolValue(GlobalValue *gv, unsigned id,
PIC16CP::PIC16CPKind Kind = PIC16CP::CPValue,
unsigned char PCAdj = 0, const char *Modifier = NULL,
bool AddCurrentAddress = false);
PIC16ConstantPoolValue(const char *s, unsigned id,
PIC16CP::PIC16CPKind Kind = PIC16CP::CPValue,
unsigned char PCAdj = 0, const char *Modifier = NULL,
bool AddCurrentAddress = false);
PIC16ConstantPoolValue(GlobalValue *GV, PIC16CP::PIC16CPKind Kind,
const char *Modifier);
GlobalValue *getGV() const { return GV; }
const char *getSymbol() const { return S; }
const char *getModifier() const { return Modifier; }
bool hasModifier() const { return Modifier != NULL; }
bool mustAddCurrentAddress() const { return AddCurrentAddress; }
unsigned getLabelId() const { return LabelId; }
bool isNonLazyPointer() const { return Kind == PIC16CP::CPNonLazyPtr; }
bool isStub() const { return Kind == PIC16CP::CPStub; }
unsigned char getPCAdjustment() const { return PCAdjust; }
virtual int getExistingMachineCPValue(MachineConstantPool *CP,
unsigned Alignment);
virtual void AddSelectionDAGCSEId(FoldingSetNodeID &ID);
virtual void print(raw_ostream &O) const;
};
}
#endif

View File

@ -13,263 +13,47 @@
#define DEBUG_TYPE "pic16-isel"
#include "PIC16.h"
#include "PIC16ISelLowering.h"
#include "PIC16RegisterInfo.h"
#include "PIC16Subtarget.h"
#include "PIC16TargetMachine.h"
#include "llvm/GlobalValue.h"
#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
#include "llvm/Type.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/Compiler.h"
#include "PIC16ISelDAGToDAG.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
// Instruction Selector Implementation
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// PIC16DAGToDAGISel - PIC16 specific code to select PIC16 machine
// instructions for SelectionDAG operations.
//===----------------------------------------------------------------------===//
namespace {
class VISIBILITY_HIDDEN PIC16DAGToDAGISel : public SelectionDAGISel {
/// TM - Keep a reference to PIC16TargetMachine.
PIC16TargetMachine &TM;
public:
explicit PIC16DAGToDAGISel(PIC16TargetMachine &tm) :
SelectionDAGISel(*tm.getTargetLowering()),
TM(tm) {}
virtual void InstructionSelect();
// Pass Name
virtual const char *getPassName() const {
return "PIC16 DAG->DAG Pattern Instruction Selection";
}
private:
// Include the pieces autogenerated from the target description.
#include "PIC16GenDAGISel.inc"
SDNode *Select(SDValue N);
// Select addressing mode. currently assume base + offset addr mode.
bool SelectAM(SDValue Op, SDValue N, SDValue &Base, SDValue &Offset);
bool SelectDirectAM(SDValue Op, SDValue N, SDValue &Base,
SDValue &Offset);
bool StoreInDirectAM(SDValue Op, SDValue N, SDValue &fsr);
bool LoadFSR(SDValue Op, SDValue N, SDValue &Base, SDValue &Offset);
bool LoadNothing(SDValue Op, SDValue N, SDValue &Base,
SDValue &Offset);
// getI8Imm - Return a target constant with the specified
// value, of type i8.
inline SDValue getI8Imm(unsigned Imm) {
return CurDAG->getTargetConstant(Imm, MVT::i8);
}
#ifndef NDEBUG
unsigned Indent;
#endif
};
}
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void PIC16DAGToDAGISel::InstructionSelect()
{
DEBUG(BB->dump());
// Codegen the basic block.
DOUT << "===== Instruction selection begins:\n";
#ifndef NDEBUG
Indent = 0;
#endif
// Select target instructions for the DAG.
SelectRoot(*CurDAG);
DOUT << "===== Instruction selection ends:\n";
CurDAG->RemoveDeadNodes();
}
bool PIC16DAGToDAGISel::
SelectDirectAM (SDValue Op, SDValue N, SDValue &Base, SDValue &Offset)
{
GlobalAddressSDNode *GA;
ConstantSDNode *GC;
// if Address is FI, get the TargetFrameIndex.
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
DOUT << "--------- its frame Index\n";
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
Offset = CurDAG->getTargetConstant(0, MVT::i32);
return true;
}
if (N.getOpcode() == ISD::GlobalAddress) {
GA = dyn_cast<GlobalAddressSDNode>(N);
Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8);
Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
GA->getOffset());
return true;
}
if (N.getOpcode() == ISD::ADD) {
GC = dyn_cast<ConstantSDNode>(N.getOperand(1));
Offset = CurDAG->getTargetConstant((unsigned char)GC->getZExtValue(),
MVT::i8);
if ((GA = dyn_cast<GlobalAddressSDNode>(N.getOperand(0)))) {
Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
GC->getZExtValue());
return true;
}
else if (FrameIndexSDNode *FIN
= dyn_cast<FrameIndexSDNode>(N.getOperand(0))) {
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
return true;
}
}
return false;
}
// FIXME: must also account for preinc/predec/postinc/postdec.
bool PIC16DAGToDAGISel::
StoreInDirectAM (SDValue Op, SDValue N, SDValue &fsr)
{
RegisterSDNode *Reg;
if (N.getOpcode() == ISD::LOAD) {
LoadSDNode *LD = dyn_cast<LoadSDNode>(N);
if (LD) {
fsr = LD->getBasePtr();
}
else if (isa<RegisterSDNode>(N.getNode())) {
//FIXME an attempt to retrieve the register number
//but does not work
DOUT << "this is a register\n";
Reg = dyn_cast<RegisterSDNode>(N.getNode());
fsr = CurDAG->getRegister(Reg->getReg(),MVT::i16);
}
else {
DOUT << "this is not a register\n";
// FIXME must use whatever load is using
fsr = CurDAG->getRegister(1,MVT::i16);
}
return true;
}
return false;
}
bool PIC16DAGToDAGISel::
LoadFSR (SDValue Op, SDValue N, SDValue &Base, SDValue &Offset)
{
GlobalAddressSDNode *GA;
if (N.getOpcode() == ISD::GlobalAddress) {
GA = dyn_cast<GlobalAddressSDNode>(N);
Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8);
Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
GA->getOffset());
return true;
}
else if (N.getOpcode() == PIC16ISD::Package) {
CurDAG->setGraphColor(Op.getNode(), "blue");
CurDAG->viewGraph();
}
return false;
}
// LoadNothing - Don't thake this seriously, it will change.
bool PIC16DAGToDAGISel::
LoadNothing (SDValue Op, SDValue N, SDValue &Base, SDValue &Offset)
{
GlobalAddressSDNode *GA;
if (N.getOpcode() == ISD::GlobalAddress) {
GA = dyn_cast<GlobalAddressSDNode>(N);
DOUT << "==========" << GA->getOffset() << "\n";
Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8);
Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
GA->getOffset());
return true;
}
return false;
}
/// Select - Select instructions not customized! Used for
/// expanded, promoted and normal instructions.
SDNode* PIC16DAGToDAGISel::Select(SDValue N)
{
SDNode *Node = N.getNode();
unsigned Opcode = Node->getOpcode();
// Dump information about the Node being selected
#ifndef NDEBUG
DOUT << std::string(Indent, ' ') << "Selecting: ";
DEBUG(Node->dump(CurDAG));
DOUT << "\n";
Indent += 2;
#endif
// If we have a custom node, we already have selected!
if (Node->isMachineOpcode()) {
#ifndef NDEBUG
DOUT << std::string(Indent-2, ' ') << "== ";
DEBUG(Node->dump(CurDAG));
DOUT << "\n";
Indent -= 2;
#endif
return NULL;
}
///
// FIXME: Instruction Selection not handled by custom or by the
// auto-generated tablegen selection should be handled here.
///
switch(Opcode) {
default: break;
}
// Select the default instruction.
SDNode *ResNode = SelectCode(N);
#ifndef NDEBUG
DOUT << std::string(Indent-2, ' ') << "=> ";
if (ResNode == NULL || ResNode == N.getNode())
DEBUG(N.getNode()->dump(CurDAG));
else
DEBUG(ResNode->dump(CurDAG));
DOUT << "\n";
Indent -= 2;
#endif
return ResNode;
}
/// createPIC16ISelDag - This pass converts a legalized DAG into a
/// createPIC16ISelDag - This pass converts a legalized DAG into a
/// PIC16-specific DAG, ready for instruction scheduling.
FunctionPass *llvm::createPIC16ISelDag(PIC16TargetMachine &TM) {
return new PIC16DAGToDAGISel(TM);
}
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void PIC16DAGToDAGISel::InstructionSelect() {
DEBUG(BB->dump());
SelectRoot(*CurDAG);
CurDAG->RemoveDeadNodes();
}
/// Select - Select instructions not customized! Used for
/// expanded, promoted and normal instructions.
SDNode* PIC16DAGToDAGISel::Select(SDValue N) {
// Select the default instruction.
SDNode *ResNode = SelectCode(N);
return ResNode;
}
// SelectDirectAddr - Match a direct address for DAG.
// A direct address could be a globaladdress or externalsymbol.
bool PIC16DAGToDAGISel::SelectDirectAddr(SDValue Op, SDValue N,
SDValue &Address) {
// Return true if TGA or ES.
if (N.getOpcode() == ISD::TargetGlobalAddress
|| N.getOpcode() == ISD::TargetExternalSymbol) {
Address = N;
return true;
}
return false;
}

View File

@ -0,0 +1,60 @@
//===-- PIC16ISelDAGToDAG.cpp - A dag to dag inst selector for PIC16 ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines an instruction selector for the PIC16 target.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "pic16-isel"
#include "PIC16.h"
#include "PIC16ISelLowering.h"
#include "PIC16RegisterInfo.h"
#include "PIC16TargetMachine.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Intrinsics.h"
using namespace llvm;
namespace {
class VISIBILITY_HIDDEN PIC16DAGToDAGISel : public SelectionDAGISel {
/// TM - Keep a reference to PIC16TargetMachine.
PIC16TargetMachine &TM;
/// PIC16Lowering - This object fully describes how to lower LLVM code to an
/// PIC16-specific SelectionDAG.
PIC16TargetLowering PIC16Lowering;
public:
explicit PIC16DAGToDAGISel(PIC16TargetMachine &tm) :
SelectionDAGISel(PIC16Lowering),
TM(tm), PIC16Lowering(*TM.getTargetLowering()) {}
// Pass Name
virtual const char *getPassName() const {
return "PIC16 DAG->DAG Pattern Instruction Selection";
}
virtual void InstructionSelect();
private:
// Include the pieces autogenerated from the target description.
#include "PIC16GenDAGISel.inc"
SDNode *Select(SDValue N);
// Match direct address complex pattern.
bool SelectDirectAddr(SDValue Op, SDValue N, SDValue &Address);
};
}

File diff suppressed because it is too large Load Diff

View File

@ -26,66 +26,89 @@ namespace llvm {
// Start the numbering from where ISD NodeType finishes.
FIRST_NUMBER = ISD::BUILTIN_OP_END,
// used for encapsulating the expanded nodes into one node.
Package,
Lo, // Low 8-bits of GlobalAddress.
Hi, // High 8-bits of GlobalAddress.
PIC16Load,
PIC16Store,
Banksel,
MTLO,
MTHI,
BCF,
LSLF, // PIC16 Logical shift left
LRLF, // PIC16 Logical shift right
RLF, // Rotate left through carry
RRF, // Rotate right through carry
Dummy
};
// Get the Higher 16 bits from a 32-bit immediate
Hi,
// Get the Lower 16 bits from a 32-bit immediate
Lo,
Cmp, // PIC16 Generic Comparison instruction.
Branch, // PIC16 Generic Branch Instruction.
BTFSS, // PIC16 BitTest Instruction (Skip if set).
BTFSC, // PIC16 BitTest Instruction (Skip if clear).
// PIC16 comparison to be converted to either XOR or SUB
// Following instructions cater to those convertions.
XORCC,
SUBCC,
// Get the Global Address wrapped into a wrapper that also captures
// the bank or page.
Wrapper,
SetBank,
SetPage
// Keep track of different address spaces.
enum AddressSpace {
RAM_SPACE = 0, // RAM address space
ROM_SPACE = 1 // ROM address space number is 1
};
}
//===--------------------------------------------------------------------===//
// TargetLowering Implementation
//===--------------------------------------------------------------------===//
class PIC16TargetLowering : public TargetLowering
{
class PIC16TargetLowering : public TargetLowering {
public:
typedef std::map<SDNode *, SDNode *> NodeMap_t;
explicit PIC16TargetLowering(PIC16TargetMachine &TM);
/// LowerOperation - Provide custom lowering hooks for some operations.
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
SDValue LowerRET(SDValue Op, SelectionDAG &DAG);
SDValue LowerFrameIndex(SDValue Op, SelectionDAG &DAG);
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG);
SDValue RemoveHiLo(SDNode *, SelectionDAG &DAG,
DAGCombinerInfo &DCI) const;
SDValue LowerADDSUB(SDNode *, SelectionDAG &DAG,
DAGCombinerInfo &DCI) const;
SDValue LowerLOAD(SDNode *, SelectionDAG &DAG,
DAGCombinerInfo &DCI) const;
/// getTargetNodeName - This method returns the name of a target specific
// DAG node.
/// getTargetNodeName - This method returns the name of a target specific
/// DAG node.
virtual const char *getTargetNodeName(unsigned Opcode) const;
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) 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);
// utility function.
const SDValue *findLoadi8(const SDValue &Src, SelectionDAG &DAG) const;
SDNode *ReplaceNodeResults(SDNode *N, SelectionDAG &DAG);
SDNode *ExpandStore(SDNode *N, SelectionDAG &DAG);
SDNode *ExpandLoad(SDNode *N, SelectionDAG &DAG);
SDNode *ExpandAdd(SDNode *N, SelectionDAG &DAG);
SDNode *ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG);
SDNode *ExpandShift(SDNode *N, SelectionDAG &DAG);
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
SDValue PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const;
private:
// If the Node is a BUILD_PAIR representing representing an Address
// then this function will return true
bool isDirectAddress(const SDValue &Op);
// If the Node is a DirectAddress in ROM_SPACE then this
// function will return true
bool isRomAddress(const SDValue &Op);
// To extract chain value from the SDValue Nodes
// This function will help to maintain the chain extracting
// code at one place. In case of any change in future it will
// help maintain the code
SDValue getChain(SDValue &Op);
// Extract the Lo and Hi component of Op.
void GetExpandedParts(SDValue Op, SelectionDAG &DAG, SDValue &Lo,
SDValue &Hi);
// Load pointer can be a direct or indirect address. In PIC16 direct
// addresses need Banksel and Indirect addresses need to be loaded to
// FSR first. Handle address specific cases here.
void LegalizeAddress(SDValue Ptr, SelectionDAG &DAG, SDValue &Chain,
SDValue &NewPtr, unsigned &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);
/// 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;
};
} // namespace llvm

View File

@ -1,4 +1,4 @@
//===- PIC16RegisterInfo.td - PIC16 Register defs ------------*- tblgen -*-===//
//===- PIC16InstrFormats.td - PIC16 Instruction Formats-------*- tblgen -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -21,16 +21,17 @@
//===----------------------------------------------------------------------===//
// Generic PIC16 Format
// PIC16 Instructions are 14-bit wide.
// FIXME: Add Cooper Specific Formats if any.
class PIC16Inst<dag outs, dag ins, string asmstr, list<dag> pattern>
: Instruction
{
: Instruction {
field bits<14> Inst;
let Namespace = "PIC16";
dag OutOperandList = outs;
dag InOperandList = ins;
let AsmString = asmstr;
let Pattern = pattern;
}
@ -38,16 +39,18 @@ class PIC16Inst<dag outs, dag ins, string asmstr, list<dag> pattern>
//===----------------------------------------------------------------------===//
// Byte Oriented instruction class in PIC16 : <|opcode|d|f|>
// opcode = 6 bits.
// d = direction = 1 bit.
// f = file register address = 7 bits.
//===----------------------------------------------------------------------===//
class ByteFormat<bits<6> op, dag outs, dag ins, string asmstr,
list<dag> pattern>
:PIC16Inst<outs, ins, asmstr, pattern>
{
class ByteFormat<bits<6> opcode, dag outs, dag ins, string asmstr,
list<dag> pattern>
:PIC16Inst<outs, ins, asmstr, pattern> {
bits<1> d;
bits<7> f;
let Inst{13-8} = op;
let Inst{13-8} = opcode;
let Inst{7} = d;
let Inst{6-0} = f;
@ -55,15 +58,18 @@ class ByteFormat<bits<6> op, dag outs, dag ins, string asmstr,
//===----------------------------------------------------------------------===//
// Bit Oriented instruction class in PIC16 : <|opcode|b|f|>
// opcode = 4 bits.
// b = bit specifier = 3 bits.
// f = file register address = 7 bits.
//===----------------------------------------------------------------------===//
class BitFormat<bits<4> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: PIC16Inst<outs, ins, asmstr, pattern>
{
class BitFormat<bits<4> opcode, dag outs, dag ins, string asmstr,
list<dag> pattern>
: PIC16Inst<outs, ins, asmstr, pattern> {
bits<3> b;
bits<7> f;
let Inst{13-10} = op;
let Inst{13-10} = opcode;
let Inst{9-7} = b;
let Inst{6-0} = f;
@ -71,32 +77,32 @@ class BitFormat<bits<4> op, dag outs, dag ins, string asmstr, list<dag> pattern>
//===----------------------------------------------------------------------===//
// Literal Format instruction class in PIC16 : <|opcode|k|>
// opcode = 6 bits
// k = literal = 8 bits
//===----------------------------------------------------------------------===//
class LiteralFormat<bits<6> op, dag outs, dag ins, string asmstr,
class LiteralFormat<bits<6> opcode, dag outs, dag ins, string asmstr,
list<dag> pattern>
: PIC16Inst<outs, ins, asmstr, pattern>
{
: PIC16Inst<outs, ins, asmstr, pattern> {
bits<8> k;
let Inst{13-8} = op;
let Inst{13-8} = opcode;
let Inst{7-0} = k;
}
//===----------------------------------------------------------------------===//
// Control Format instruction class in PIC16 : <|opcode|k|>
// opcode = 3 bits.
// k = jump address = 11 bits.
//===----------------------------------------------------------------------===//
class ControlFormat<bits<3> op, dag outs, dag ins, string asmstr,
class ControlFormat<bits<3> opcode, dag outs, dag ins, string asmstr,
list<dag> pattern>
:PIC16Inst<outs, ins, asmstr, pattern>
{
: PIC16Inst<outs, ins, asmstr, pattern> {
bits<11> k;
let Inst{13-11} = op;
let Inst{13-11} = opcode;
let Inst{10-0} = k;
}
@ -105,8 +111,7 @@ class ControlFormat<bits<3> op, dag outs, dag ins, string asmstr,
// Pseudo instruction class in PIC16
//===----------------------------------------------------------------------===//
class Pseudo<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern>:
PIC16Inst<outs, ins, asmstr, pattern>
{
let Inst{13-6} = op;
class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
: PIC16Inst<outs, ins, asmstr, pattern> {
let Inst{13-6} = 0;
}

View File

@ -13,132 +13,131 @@
#include "PIC16.h"
#include "PIC16InstrInfo.h"
#include "PIC16TargetMachine.h"
#include "PIC16GenInstrInfo.inc"
#include "llvm/Function.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "PIC16GenInstrInfo.inc"
#include <cstdio>
#include "llvm/CodeGen/MachineRegisterInfo.h"
using namespace llvm;
// FIXME: Add the subtarget support on this constructor.
PIC16InstrInfo::PIC16InstrInfo(PIC16TargetMachine &tm)
: TargetInstrInfoImpl(PIC16Insts, array_lengthof(PIC16Insts)),
TM(tm), RI(*this) {}
TM(tm),
RegInfo(*this, *TM.getSubtargetImpl()) {}
static bool isZeroImm(const MachineOperand &op) {
return op.isImm() && op.getImm() == 0;
}
/// isLoadFromStackSlot - If the specified machine instruction is a direct
/// load from a stack slot, return the virtual or physical register number of
/// the destination along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than loading from the stack slot.
unsigned PIC16InstrInfo::
isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const
{
if (MI->getOpcode() == PIC16::MOVF) {
if ((MI->getOperand(2).isFI()) && // is a stack slot
(MI->getOperand(1).isImm()) && // the imm is zero
(isZeroImm(MI->getOperand(1)))) {
FrameIndex = MI->getOperand(2).getIndex();
return MI->getOperand(0).getReg();
}
}
return 0;
}
/// isStoreToStackSlot - If the specified machine instruction is a direct
/// store to a stack slot, return the virtual or physical register number of
/// the source reg along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// the source reg along with the FrameIndex of the loaded stack slot.
/// If not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than storing to the stack slot.
unsigned PIC16InstrInfo::
isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const
{
if (MI->getOpcode() == PIC16::MOVWF) {
if ((MI->getOperand(0).isFI()) && // is a stack slot
(MI->getOperand(1).isImm()) && // the imm is zero
(isZeroImm(MI->getOperand(1)))) {
FrameIndex = MI->getOperand(0).getIndex();
return MI->getOperand(2).getReg();
}
unsigned PIC16InstrInfo::isStoreToStackSlot(MachineInstr *MI,
int &FrameIndex) const {
if (MI->getOpcode() == PIC16::movwf
&& MI->getOperand(0).isReg()
&& MI->getOperand(1).isSymbol()) {
FrameIndex = MI->getOperand(1).getIndex();
return MI->getOperand(0).getReg();
}
return 0;
}
void PIC16InstrInfo::
storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned SrcReg, bool isKill, int FI,
const TargetRegisterClass *RC) const {
/// isLoadFromStackSlot - If the specified machine instruction is a direct
/// load from a stack slot, return the virtual or physical register number of
/// the dest reg along with the FrameIndex of the stack slot.
/// If not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than storing to the stack slot.
unsigned PIC16InstrInfo::isLoadFromStackSlot(MachineInstr *MI,
int &FrameIndex) const {
if (MI->getOpcode() == PIC16::movf
&& MI->getOperand(0).isReg()
&& MI->getOperand(1).isSymbol()) {
FrameIndex = MI->getOperand(1).getIndex();
return MI->getOperand(0).getReg();
}
return 0;
}
void PIC16InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned SrcReg, bool isKill, int FI,
const TargetRegisterClass *RC) const {
const Function *Func = MBB.getParent()->getFunction();
const std::string FuncName = Func->getName();
char *tmpName = new char [strlen(FuncName.c_str()) + 6];
sprintf(tmpName, "%s_tmp_%d",FuncName.c_str(),FI);
sprintf(tmpName, "%s.tmp", FuncName.c_str());
if (RC == PIC16::CPURegsRegisterClass) {
//src is always WREG.
BuildMI(MBB, I, this->get(PIC16::MOVWF))
.addReg(SrcReg,false,false,true,true)
.addExternalSymbol(tmpName) // the current printer expects 3 operands,
.addExternalSymbol(tmpName); // all we need is actually one,
// so we repeat.
// On the order of operands here: think "movwf SrcReg, tmp_slot, offset".
if (RC == PIC16::GPRRegisterClass) {
//MachineFunction &MF = *MBB.getParent();
//MachineRegisterInfo &RI = MF.getRegInfo();
BuildMI(MBB, I, get(PIC16::movwf))
.addReg(SrcReg, false, false, isKill)
.addImm(FI)
.addExternalSymbol(tmpName)
.addImm(1); // Emit banksel for it.
}
else if (RC == PIC16::FSR16RegisterClass)
assert(0 && "Don't know yet how to store a FSR16 to stack slot");
else
assert(0 && "Can't store this register to stack slot");
}
void PIC16InstrInfo::
loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
unsigned DestReg, int FI,
const TargetRegisterClass *RC) const
{
void PIC16InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned DestReg, int FI,
const TargetRegisterClass *RC) const {
const Function *Func = MBB.getParent()->getFunction();
const std::string FuncName = Func->getName();
char *tmpName = new char [strlen(FuncName.c_str()) + 6];
sprintf(tmpName, "%s_tmp_%d",FuncName.c_str(),FI);
sprintf(tmpName, "%s.tmp", FuncName.c_str());
if (RC == PIC16::CPURegsRegisterClass)
BuildMI(MBB, I, this->get(PIC16::MOVF), DestReg)
.addExternalSymbol(tmpName) // the current printer expects 3 operands,
.addExternalSymbol(tmpName); // all we need is actually one,so we repeat.
// On the order of operands here: think "movf FrameIndex, W".
if (RC == PIC16::GPRRegisterClass) {
//MachineFunction &MF = *MBB.getParent();
//MachineRegisterInfo &RI = MF.getRegInfo();
BuildMI(MBB, I, get(PIC16::movf), DestReg)
.addImm(FI)
.addExternalSymbol(tmpName)
.addImm(1); // Emit banksel for it.
}
else if (RC == PIC16::FSR16RegisterClass)
assert(0 && "Don't know yet how to load an FSR16 from stack slot");
else
assert(0 && "Can't load this register from stack slot");
}
/// InsertBranch - Insert a branch into the end of the specified
/// MachineBasicBlock. This operands to this method are the same as those
/// returned by AnalyzeBranch. This is invoked in cases where AnalyzeBranch
/// returns success and when an unconditional branch (TBB is non-null, FBB is
/// null, Cond is empty) needs to be inserted. It returns the number of
/// instructions inserted.
unsigned PIC16InstrInfo::
InsertBranch(MachineBasicBlock &MBB,
MachineBasicBlock *TBB, MachineBasicBlock *FBB,
const SmallVectorImpl<MachineOperand> &Cond) const
{
// Shouldn't be a fall through.
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
if (FBB == 0) { // One way branch.
if (Cond.empty()) {
// Unconditional branch?
BuildMI(&MBB, get(PIC16::GOTO)).addMBB(TBB);
}
return 1;
bool PIC16InstrInfo::copyRegToReg (MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned DestReg, unsigned SrcReg,
const TargetRegisterClass *DestRC,
const TargetRegisterClass *SrcRC) const {
if (DestRC == PIC16::FSR16RegisterClass) {
BuildMI(MBB, I, get(PIC16::copy_fsr), DestReg).addReg(SrcReg);
}
// FIXME: If the there are some conditions specified then conditional branch
// should be generated.
// For the time being no instruction is being generated therefore
// returning NULL.
return 0;
return true;
}
bool PIC16InstrInfo::isMoveInstr(const MachineInstr &MI,
unsigned &SrcReg,
unsigned &DestReg) const {
if (MI.getOpcode() == PIC16::copy_fsr) {
DestReg = MI.getOperand(0).getReg();
SrcReg = MI.getOperand(1).getReg();
return true;
}
return false;
}

View File

@ -24,54 +24,43 @@ namespace llvm {
class PIC16InstrInfo : public TargetInstrInfoImpl
{
PIC16TargetMachine &TM;
const PIC16RegisterInfo RI;
const PIC16RegisterInfo RegInfo;
public:
explicit PIC16InstrInfo(PIC16TargetMachine &TM);
/// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
/// such, whenever a client has an instance of instruction info, it should
/// always be able to get register info as well (through this method).
///
virtual const PIC16RegisterInfo &getRegisterInfo() const { return RI; }
virtual const PIC16RegisterInfo &getRegisterInfo() const { return RegInfo; }
/// isLoadFromStackSlot - If the specified machine instruction is a direct
/// load from a stack slot, return the virtual or physical register number of
/// the destination along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than loading from the stack slot.
virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
int &FrameIndex) const;
virtual unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const;
/// isStoreToStackSlot - If the specified machine instruction is a direct
/// store to a stack slot, return the virtual or physical register number of
/// the source reg along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than storing to the stack slot.
virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
int &FrameIndex) const;
/// Used for spilling a register
void storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned SrcReg, bool isKill, int FrameIndex,
const TargetRegisterClass *RC) const;
virtual unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const;
void loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned DestReg, int FrameIndex,
const TargetRegisterClass *RC) const;
/// InsertBranch - Insert a branch into the end of the specified
/// MachineBasicBlock. This operands to this method are the same as those
/// returned by AnalyzeBranch. This is invoked in cases where AnalyzeBranch
/// returns success and when an unconditional branch (TBB is non-null, FBB is
/// null, Cond is empty) needs to be inserted. It returns the number of
/// instructions inserted.
virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
MachineBasicBlock *FBB,
const SmallVectorImpl<MachineOperand> &Cond) const ;
virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned SrcReg, bool isKill, int FrameIndex,
const TargetRegisterClass *RC) const;
virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned DestReg, int FrameIndex,
const TargetRegisterClass *RC) const;
virtual bool copyRegToReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned DestReg, unsigned SrcReg,
const TargetRegisterClass *DestRC,
const TargetRegisterClass *SrcRC) const;
virtual bool isMoveInstr(const MachineInstr &MI,
unsigned &SrcReg,
unsigned &DestReg) const;
};

View File

@ -1,4 +1,4 @@
//===- PIC16InstrInfo.td - PIC16 Register defs ----------------*- tblgen-*-===//
//===- PIC16InstrInfo.td - PIC16 Instruction defs -------------*- tblgen-*-===//
//
// The LLVM Compiler Infrastructure
//
@ -6,297 +6,302 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Instruction format superclass
//
// This file describes the ARM instructions in TableGen format.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// PIC16 Specific Type Constraints.
//===----------------------------------------------------------------------===//
class SDTCisI8<int OpNum> : SDTCisVT<OpNum, i8>;
class SDTCisI16<int OpNum> : SDTCisVT<OpNum, i16>;
//===----------------------------------------------------------------------===//
// PIC16 Specific Type Profiles.
//===----------------------------------------------------------------------===//
// Generic type profiles for i8/i16 unary/binary operations.
// Taking one i8 or i16 and producing void.
def SDTI8VoidOp : SDTypeProfile<0, 1, [SDTCisI8<0>]>;
def SDTI16VoidOp : SDTypeProfile<0, 1, [SDTCisI16<0>]>;
// Taking one value and producing an output of same type.
def SDTI8UnaryOp : SDTypeProfile<1, 1, [SDTCisI8<0>, SDTCisI8<1>]>;
def SDTI16UnaryOp : SDTypeProfile<1, 1, [SDTCisI16<0>, SDTCisI16<1>]>;
// Taking two values and producing an output of same type.
def SDTI8BinOp : SDTypeProfile<1, 2, [SDTCisI8<0>, SDTCisI8<1>, SDTCisI8<2>]>;
def SDTI16BinOp : SDTypeProfile<1, 2, [SDTCisI16<0>, SDTCisI16<1>,
SDTCisI16<2>]>;
// 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>]>;
//===----------------------------------------------------------------------===//
// PIC16 addressing modes matching via DAG.
//===----------------------------------------------------------------------===//
def diraddr : ComplexPattern<i8, 1, "SelectDirectAddr", [], []>;
//===----------------------------------------------------------------------===//
// PIC16 Specific Node Definitions.
//===----------------------------------------------------------------------===//
def PIC16callseq_start : SDNode<"ISD::CALLSEQ_START", SDTI8VoidOp,
[SDNPHasChain, SDNPOutFlag]>;
def PIC16callseq_end : SDNode<"ISD::CALLSEQ_END", SDTI8VoidOp,
[SDNPHasChain, SDNPOutFlag]>;
// Low 8-bits of GlobalAddress.
def PIC16Lo : SDNode<"PIC16ISD::Lo", SDTI8UnaryOp>;
// High 8-bits of GlobalAddress.
def PIC16Hi : SDNode<"PIC16ISD::Hi", SDTI8UnaryOp>;
// The MTHI and MTLO nodes are used only to match them in the incoming
// DAG for replacement by corresponding set_fsrhi, set_fsrlo insntructions.
// These nodes are not used for defining any instructions.
def MTLO : SDNode<"PIC16ISD::MTLO", SDTI8UnaryOp>;
def MTHI : SDNode<"PIC16ISD::MTHI", SDTI8UnaryOp>;
// Node to generate Bank Select for a GlobalAddress.
def Banksel : SDNode<"PIC16ISD::Banksel", SDTI8UnaryOp>;
// Node to match a direct store operation.
def PIC16Store : SDNode<"PIC16ISD::PIC16Store", SDT_PIC16Store, [SDNPHasChain]>;
// Node to match a direct load operation.
def PIC16Load : SDNode<"PIC16ISD::PIC16Load", SDT_PIC16Load, [SDNPHasChain]>;
//===----------------------------------------------------------------------===//
// PIC16 Operand Definitions.
//===----------------------------------------------------------------------===//
def i8mem : Operand<i8>;
//===----------------------------------------------------------------------===//
// PIC16 Instructions.
//===----------------------------------------------------------------------===//
include "PIC16InstrFormats.td"
//===----------------------------------------------------------------------===//
// PIC16 profiles and nodes
//===----------------------------------------------------------------------===//
// Pseudo-instructions.
def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i8imm:$amt),
"!ADJCALLSTACKDOWN $amt",
[(PIC16callseq_start imm:$amt)]>;
//===----------------------------------------------------------------------===//
// PIC16 addressing mode.
//===----------------------------------------------------------------------===//
// It matches address of globals as well as the stack slots
// that are created for locals and temporaries. This addressing mode
// converts the GlobalAddress and FrameIndex nodes to TargetGlobalAddress
// and TargetFrameIndex nodes.
def diraddrmode : ComplexPattern<i16, 2, "SelectDirectAM", [frameindex], []>;
def dirloadmode : ComplexPattern<i16, 2, "LoadNothing", [frameindex], []>;
def indirloadmode : ComplexPattern<i16, 2, "LoadFSR", [frameindex], []>;
// Address operand.
def mem : Operand<i16> {
let PrintMethod = "printAddrModeOperand";
let MIOperandInfo = (ops i16imm, PTRRegs);
}
// Instruction operand types
def simm8 : Operand<i8>;
// These are target-independent nodes, but have target-specific formats.
def SDT_PIC16CallSeq : SDTypeProfile<0, 1, [ SDTCisVT<0, i8> ]>;
def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PIC16CallSeq,
[SDNPHasChain, SDNPOutFlag]>;
def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PIC16CallSeq,
[SDNPHasChain, SDNPOutFlag]>;
def PIC16Wrapper : SDNode<"PIC16ISD::Wrapper", SDTIntUnaryOp>;
// so_imm_XFORM - Return a so_imm value packed into the format described for
// so_imm def below.
def so_imm_XFORM : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant((int8_t)N->getZExtValue(), MVT::i32);
}]>;
def so_imm : Operand<i8>,
PatLeaf<(imm), [{}]> {
let PrintMethod = "printSOImmOperand";
}
// PIC16 Address Mode! SDNode frameindex could possibily be a match
// since load and store instructions from stack used it.
def addr : Operand<i16>;
// Arithmetic 2 register operands
class ArithI<bits<6> op, string instr_asm, SDNode OpNode,
Operand Od> :
LiteralFormat< op,
(outs CPURegs:$dst),
(ins CPURegs:$b, Od:$c),
!strconcat(instr_asm, " $c"),
[(set CPURegs:$dst, (OpNode CPURegs:$b, Od:$c))]>;
// Memory Load/Store.
class LoadDirect<bits<6> op, string instr_asm, PatFrag OpNode>:
ByteFormat< op,
(outs CPURegs:$dst),
(ins mem:$addr),
!strconcat(instr_asm, " $addr"),
[(set CPURegs:$dst, (OpNode diraddrmode:$addr))]>;
class LoadInDirect<bits<6> op, string instr_asm, PatFrag OpNode>:
ByteFormat< op,
(outs PTRRegs:$dst),
(ins mem:$addr),
!strconcat(instr_asm, " $addr, $dst"),
[(set PTRRegs:$dst, (OpNode indirloadmode:$addr))]>;
class StoreDirect<bits<6> op, string instr_asm, PatFrag OpNode>:
ByteFormat< op,
(outs),
(ins CPURegs:$src, mem:$addr),
!strconcat(instr_asm, " $addr"),
[(OpNode CPURegs:$src, diraddrmode:$addr)]>;
class StoreInDirect<bits<6> op, string instr_asm, PatFrag OpNode>:
ByteFormat< op,
(outs),
(ins CPURegs:$src, PTRRegs:$fsr),
!strconcat(instr_asm, " $fsr"),
[(OpNode CPURegs:$src, PTRRegs:$fsr)]>;
// Move.
class MovLit<bits<6> op, string instr_asm>:
LiteralFormat< op,
(outs CPURegs:$dst),
(ins i8imm:$src),
!strconcat(instr_asm, " $src"),
[(set CPURegs:$dst, imm:$src)]>;
// Arithmetic with memory store.
// Arithmetic instrunctions involving W and memory location.
// Since W is implicit, we only print the memory operand.
class Arith1M<bits<6> op, string instr_asm, SDNode OpNode>:
ByteFormat< op,
(outs),
(ins CPURegs:$b, mem:$dst),
!strconcat(instr_asm, " $dst"),
[(store (OpNode (load diraddrmode:$dst), CPURegs:$b), diraddrmode:$dst),
(store (OpNode CPURegs:$b, (load diraddrmode:$dst)), diraddrmode:$dst)]>;
// Arithmetic with memory load.
// Arithmetic instrunctions involving W and memory location.
// Since W is implicit, we only print the memory operand.
class Arith1R<bits<6> op, string instr_asm, SDNode OpNode>:
ByteFormat< op,
(outs CPURegs:$dst),
(ins mem:$src1, CPURegs:$src2),
!strconcat(instr_asm, " $src1"),
[(set CPURegs:$dst, (OpNode (load diraddrmode:$src1), CPURegs:$src2))]>;
// Arithmetic with memory load.
// Arithmetic instrunctions involving W and memory location.
// Since W is implicit, we only print the memory operand.
class Arith2R<bits<6> op, string instr_asm, SDNode OpNode>:
ByteFormat< op,
(outs CPURegs:$dst),
(ins mem:$src1, CPURegs:$src2),
!strconcat(instr_asm, " $src1"),
[(set CPURegs:$dst, (OpNode CPURegs:$src2, (load diraddrmode:$src1)))]>;
//===----------------------------------------------------------------------===//
// Instruction definition
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// PIC16I Instructions
//===----------------------------------------------------------------------===//
// Arithmetic
// ADDiu just accept 16-bit immediates but we handle this on Pat's.
// immZExt32 is used here so it can match GlobalAddress immediates.
// def ADDLW : ArithI<0x09, "addlw", add, so_imm>;
def ADJCALLSTACKUP : Pseudo<(outs), (ins i8imm:$amt),
"!ADJCALLSTACKUP $amt",
[(PIC16callseq_end imm:$amt)]>;
//-----------------------------------
// Vaious movlw insn patterns.
//-----------------------------------
let isReMaterializable = 1 in {
def MOVLW : MovLit<0x24, "movlw">;
// Move 8-bit literal to W.
def movlw : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
"movlw $src",
[(set GPR:$dst, (i8 imm:$src))]>;
// Move a Lo(TGA) to W.
def movlw_lo : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
"movlw LOW(${src})",
[(set GPR:$dst, (PIC16Lo tglobaladdr:$src))]>;
// Move a Hi(TGA) to W.
def movlw_hi : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
"movlw HIGH(${src})",
[(set GPR:$dst, (PIC16Hi tglobaladdr:$src))]>;
}
// Load/Store
def LFSR1 : LoadInDirect <0x4, "lfsr", load>;
//-------------------
// FSR setting insns.
//-------------------
// These insns are matched via a DAG replacement pattern.
def set_fsrlo:
ByteFormat<0, (outs FSR16:$fsr),
(ins GPR:$val),
"movwf ${fsr}L",
[]>;
let isTwoAddress = 1 in
def set_fsrhi:
ByteFormat<0, (outs FSR16:$dst),
(ins FSR16:$src, GPR:$val),
"movwf ${dst}H",
[]>;
def copy_fsr:
Pseudo<(outs FSR16:$dst), (ins FSR16:$src), "copy_fsr $dst, $src", []>;
//--------------------------
// Store to memory
//-------------------------
// Direct store.
def movwf :
ByteFormat<0, (outs),
(ins GPR:$val, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
"movwf ${ptrlo} + ${offset}",
[(PIC16Store GPR:$val, tglobaladdr:$ptrlo, (i8 imm:$ptrhi),
(i8 imm:$offset))]>;
def movwf_1 :
ByteFormat<0, (outs),
(ins GPR:$val, i8mem:$ptrlo, i8imm:$ptrhi, i8imm:$offset),
"movwf ${ptrlo} + ${offset}",
[(PIC16Store GPR:$val, texternalsym:$ptrlo, (i8 imm:$ptrhi),
(i8 imm:$offset))]>;
// Indirect store. Matched via a DAG replacement pattern.
def store_indirect :
ByteFormat<0, (outs),
(ins GPR:$val, FSR16:$fsr, i8imm:$offset),
"movwi $offset[$fsr]",
[]>;
//----------------------------
// Load from memory
//----------------------------
// Direct load.
def movf :
ByteFormat<0, (outs GPR:$dst),
(ins i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
"movf ${ptrlo} + ${offset}, W",
[(set GPR:$dst,
(PIC16Load tglobaladdr:$ptrlo, (i8 imm:$ptrhi),
(i8 imm:$offset)))]>;
def movf_1 :
ByteFormat<0, (outs GPR:$dst),
(ins i8mem:$ptrlo, i8imm:$ptrhi, i8imm:$offset),
"movf ${ptrlo} + ${offset}, W",
[(set GPR:$dst,
(PIC16Load texternalsym:$ptrlo, (i8 imm:$ptrhi),
(i8 imm:$offset)))]>;
// Indirect load. Matched via a DAG replacement pattern.
def load_indirect :
ByteFormat<0, (outs GPR:$dst),
(ins FSR16:$fsr, i8imm:$offset),
"moviw $offset[$fsr]",
[]>;
//-------------------------
// Various add/sub patterns.
//-------------------------
// W += [F] ; load from F and add the value to W.
class ADDFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
ByteFormat<OpCode, (outs GPR:$dst),
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
!strconcat(OpcStr, " $ptrlo + $offset, W"),
[(set GPR:$dst, (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
(i8 imm:$ptrhi),
(i8 imm:$offset))))]>;
// let isTwoAddress = 1 in {
def addfw_1: ADDFW<0, "addwf", add>;
def addfw_2: ADDFW<0, "addwf", addc>;
def addfwc: ADDFW<0, "addwfc", adde>; // With Carry.
// }
// [F] += W ; add the value of W to [F].
class ADDWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
ByteFormat<OpCode, (outs),
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
!strconcat(OpcStr, " $ptrlo + $offset"),
[(PIC16Store (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
(i8 imm:$ptrhi),
(i8 imm:$offset))),
diraddr:$ptrlo,
(i8 imm:$ptrhi), (i8 imm:$offset)
)]>;
def addwf_1: ADDWF<0, "addwf", add>;
def addwf_2: ADDWF<0, "addwf", addc>;
def addwfc: ADDWF<0, "addwfc", adde>; // With Carry.
// W -= [F] ; load from F and sub the value from W.
class SUBFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
ByteFormat<OpCode, (outs GPR:$dst),
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
!strconcat(OpcStr, " $ptrlo + $offset, W"),
[(set GPR:$dst, (OpNode (PIC16Load diraddr:$ptrlo,
(i8 imm:$ptrhi), (i8 imm:$offset)),
GPR:$src))]>;
//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.
//}
// [F] -= W ;
class SUBWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
ByteFormat<OpCode, (outs),
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
!strconcat(OpcStr, " $ptrlo + $offset"),
[(PIC16Store (OpNode (PIC16Load diraddr:$ptrlo,
(i8 imm:$ptrhi), (i8 imm:$offset)),
GPR:$src), diraddr:$ptrlo,
(i8 imm:$ptrhi), (i8 imm:$offset))]>;
def subwf_1: SUBWF<0, "subwf", sub>;
def subwf_2: SUBWF<0, "subwf", subc>;
def subwfb: SUBWF<0, "subwfb", sube>; // With Borrow.
// 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 : ADDLW<0, "addlw", add>;
def addlw_2 : ADDLW<0, "addlw", addc>;
def addlwc : ADDLW<0, "addlwc", adde>; // With Carry. (Assembler macro).
//}
// 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",
[(set GPR:$dst, (OpNode (i8 imm:$literal), GPR:$src))]>;
//let isTwoAddress = 1 in {
def sublw_1 : SUBLW<0, sub>;
def sublw_2 : SUBLW<0, subc>;
//}
// Banksel.
let isReMaterializable = 1 in {
def MOVF : LoadDirect <0x23, "movf", load>;
def banksel :
Pseudo<(outs BSR:$dst),
(ins i8mem:$ptr),
"banksel $ptr",
[(set BSR:$dst, (Banksel tglobaladdr:$ptr))]>;
}
def MOVWF : StoreDirect <0x2b, "movwf", store>;
def MOVFSRINC : StoreInDirect <0x5, "movfsrinc", store>;
def RETURN : ControlFormat<0x03, (outs), (ins), "return", []>;
def ADDWF : Arith1M<0x01, "addwf", add>;
def ADDFW : Arith1R<0x02, "addfw", add>;
def ADDWFE : Arith1M<0x03, "addwfe", adde>;
def ADDFWE : Arith1R<0x04, "addfwe", adde>;
def ADDWFC : Arith1M<0x05, "addwfc", addc>;
def ADDFWC : Arith1R<0x06, "addfwc", addc>;
def SUBWF : Arith1M<0x07, "subwf", sub>;
def SUBFW : Arith1R<0x08, "subfw", sub>;
def SUBWFE : Arith1M<0x09, "subwfe", sube>;
def SUBFWE : Arith1R<0x0a, "subfwe", sube>;
def SUBWFC : Arith1M<0x0b, "subwfc", subc>;
def SUBFWC : Arith1R<0x0d, "subfwc", subc>;
def SUBRFW : Arith2R<0x08, "subfw", sub>;
def SUBRFWE : Arith2R<0x0a, "subfwe", sube>;
def SUBRFWC : Arith2R<0x0d, "subfwc", subc>;
def brtarget : Operand<OtherVT>;
class UncondJump< bits<4> op, string instr_asm>:
BitFormat< op,
(outs),
(ins brtarget:$target),
!strconcat(instr_asm, " $target"),
[(br bb:$target)]>;
def GOTO : UncondJump<0x1, "goto">;
class LogicM<bits<6> op, string instr_asm, SDNode OpNode> :
ByteFormat< op,
(outs),
(ins CPURegs:$b, mem:$dst),
!strconcat(instr_asm, " $dst"),
[(store (OpNode (load diraddrmode:$dst), CPURegs:$b), diraddrmode:$dst)]>;
class LogicR<bits<6> op, string instr_asm, SDNode OpNode> :
ByteFormat< op,
(outs CPURegs:$dst),
(ins CPURegs:$b, mem:$c),
!strconcat(instr_asm, " $c"),
[(set CPURegs:$dst, (OpNode (load diraddrmode:$c), CPURegs:$b))]>;
class LogicI<bits<6> op, string instr_asm, SDNode OpNode, Operand Od> :
LiteralFormat< op,
(outs CPURegs:$dst),
(ins CPURegs:$b, Od:$c),
!strconcat(instr_asm, " $c"),
[(set CPURegs:$dst, (OpNode CPURegs:$b, Od:$c ))]>;
def XORWF : LogicM<0x1,"xorwf",xor>;
def XORFW : LogicR<0x1,"xorfw",xor>;
def XORLW : LogicI<0x1,"xorlw",xor, so_imm>;
def ANDWF : LogicM<0x1,"andwf",and>;
def ANDFW : LogicR<0x1,"andfw",and>;
def ANDLW : LogicI<0x1,"andlw",and, so_imm>;
def IORWF : LogicM<0x1,"iorwf",or>;
def IORFW : LogicR<0x1,"iorfw",or>;
def IORLW : LogicI<0x1,"iorlw",or, so_imm>;
/* For comparison before branch */
def SDT_PIC16Cmp : SDTypeProfile<1, 3, [SDTCisSameAs<0,1>]>;
def SDTIntBinOpPIC16 : SDTypeProfile<1, 2, [SDTCisSameAs<0,1>,
SDTCisSameAs<1,2>, SDTCisInt<1>]>;
def PIC16Cmp : SDNode<"PIC16ISD::Cmp",SDTIntBinOpPIC16, [SDNPOutFlag]>;
def PIC16XORCC : SDNode<"PIC16ISD::XORCC",SDTIntBinOpPIC16, [SDNPOutFlag]>;
def PIC16SUBCC : SDNode<"PIC16ISD::SUBCC",SDTIntBinOpPIC16, [SDNPOutFlag]>;
def XORFWCC : LogicR<0x1,"xorfw",PIC16XORCC>;
def XORLWCC : LogicI<0x1,"xorlw",PIC16XORCC, so_imm>;
def SUBFWCC : Arith1R<0x1,"subfw",PIC16SUBCC>;
def SUBLWCC : ArithI<0x1,"sublw",PIC16SUBCC, so_imm>;
/* For branch conditions */
def SDT_PIC16Branch : SDTypeProfile<0, 3, [SDTCisVT<0, OtherVT>,
SDTCisVT<1,i8>, SDTCisVT<2,i8>]>;
def PIC16Branch : SDNode<"PIC16ISD::Branch",SDT_PIC16Branch,
[SDNPHasChain, SDNPInFlag]>;
def PIC16BTFSS : SDNode<"PIC16ISD::BTFSS",SDT_PIC16Branch,
[SDNPHasChain, SDNPInFlag]>;
def PIC16BTFSC : SDNode<"PIC16ISD::BTFSC",SDT_PIC16Branch,
[SDNPHasChain, SDNPInFlag]>;
class InstrBitTestCC<bits<4> op, string instr_asm,SDNode OpNode>:
BitFormat< op,
(outs),
(ins brtarget:$target ,so_imm:$i, STATUSRegs:$s ),
!strconcat(instr_asm, " $s, $i, $target"),
[(OpNode bb:$target, so_imm:$i, STATUSRegs:$s )]>;
def BTFSS : InstrBitTestCC<0x1,"btfss",PIC16BTFSS>;
def BTFSC : InstrBitTestCC<0x1,"btfsc",PIC16BTFSC>;
// Return insn.
def Return :
ControlFormat<0, (outs), (ins), "return", [(ret)]>;
//===----------------------------------------------------------------------===//
// Pseudo instructions
// PIC16 Replacment Patterns.
//===----------------------------------------------------------------------===//
let Defs = [STKPTR], Uses = [STKPTR] in {
def ADJCALLSTACKDOWN : Pseudo<255, (outs), (ins i8imm:$amt),
"!ADJCALLSTACKDOWN $amt",
[(callseq_start imm:$amt)]>;
def ADJCALLSTACKUP : Pseudo<254, (outs), (ins i8imm:$amt),
"!ADJCALLSTACKUP $amt",
[(callseq_end imm:$amt)]>;
}
// Identify an indirect store and select insns for it.
def : Pat<(PIC16Store GPR:$val, (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
imm:$offset),
(store_indirect GPR:$val,
(set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
imm:$offset)>;
// Identify an indirect load and select insns for it.
def : Pat<(PIC16Load (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
imm:$offset),
(load_indirect (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
imm:$offset)>;
//===----------------------------------------------------------------------===//
// Arbitrary patterns that map to one or more instructions
//===----------------------------------------------------------------------===//
def : Pat<(ret), (RETURN)>;

View File

@ -15,206 +15,68 @@
#include "PIC16.h"
#include "PIC16RegisterInfo.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Type.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
// FIXME: add subtarget support.
PIC16RegisterInfo::PIC16RegisterInfo(const TargetInstrInfo &tii)
PIC16RegisterInfo::PIC16RegisterInfo(const TargetInstrInfo &tii,
const PIC16Subtarget &st)
: PIC16GenRegisterInfo(PIC16::ADJCALLSTACKDOWN, PIC16::ADJCALLSTACKUP),
TII(tii) {}
TII(tii),
ST(st) {}
/// getRegisterNumbering - Given the enum value for some register, e.g.
/// PIC16::RA, return the number that it corresponds to (e.g. 31).
unsigned PIC16RegisterInfo::
getRegisterNumbering(unsigned RegEnum)
{
assert (RegEnum <= 31 && "Unknown register number!");
return RegEnum;
}
void PIC16RegisterInfo::
copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
unsigned DestReg, unsigned SrcReg,
const TargetRegisterClass *RC) const
{
return;
}
void PIC16RegisterInfo::reMaterialize(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned DestReg,
const MachineInstr *Orig) const
{
MachineInstr *MI = MBB.getParent()->CloneMachineInstr(Orig);
MI->getOperand(0).setReg(DestReg);
MBB.insert(I, MI);
}
MachineInstr *PIC16RegisterInfo::
foldMemoryOperand(MachineInstr* MI, unsigned OpNum, int FI) const
{
MachineInstr *NewMI = NULL;
return NewMI;
}
//===----------------------------------------------------------------------===//
//
// Callee Saved Registers methods
//
//===----------------------------------------------------------------------===//
#include "PIC16GenRegisterInfo.inc"
/// PIC16 Callee Saved Registers
const unsigned* PIC16RegisterInfo::
getCalleeSavedRegs(const MachineFunction *MF) const
{
// PIC16 calle-save register range is $16-$26(s0-s7)
getCalleeSavedRegs(const MachineFunction *MF) const {
static const unsigned CalleeSavedRegs[] = { 0 };
return CalleeSavedRegs;
}
/// PIC16 Callee Saved Register Classes
const TargetRegisterClass* const*
PIC16RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const
{
// PIC16 Callee Saved Reg Classes
const TargetRegisterClass* const*
PIC16RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
static const TargetRegisterClass * const CalleeSavedRegClasses[] = { 0 };
return CalleeSavedRegClasses;
}
BitVector PIC16RegisterInfo::
getReservedRegs(const MachineFunction &MF) const
{
BitVector PIC16RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
BitVector Reserved(getNumRegs());
return Reserved;
}
//===----------------------------------------------------------------------===//
//
// Stack Frame Processing methods
// +----------------------------+
//
// FIXME: Add stack layout description here.
//
//
//===----------------------------------------------------------------------===//
// hasFP - Return true if the specified function should have a dedicated frame
// pointer register. This is true if the function has variable sized allocas or
// if frame pointer elimination is disabled.
bool PIC16RegisterInfo::
hasFP(const MachineFunction &MF) const {
bool PIC16RegisterInfo::hasFP(const MachineFunction &MF) const {
return false;
}
// This function eliminate ADJCALLSTACKDOWN,
// ADJCALLSTACKUP pseudo instructions
void PIC16RegisterInfo::
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
// Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions.
MBB.erase(I);
}
eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
RegScavenger *RS) const
{ /* NOT YET IMPLEMENTED */ }
// FrameIndex represent objects inside a abstract stack.
// We must replace FrameIndex with an stack/frame pointer
// direct reference.
void PIC16RegisterInfo::
eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
RegScavenger *RS) const
{
MachineInstr &MI = *II;
MachineFunction &MF = *MI.getParent()->getParent();
unsigned i = 0;
while (!MI.getOperand(i).isFI()) {
++i;
assert(i < MI.getNumOperands() &&
"Instr doesn't have FrameIndex operand!");
}
int FrameIndex = MI.getOperand(i).getIndex();
int stackSize = MF.getFrameInfo()->getStackSize();
int spOffset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
DOUT << "\nFunction : " << MF.getFunction()->getName() << "\n";
DOUT << "<--------->\n";
#ifndef NDEBUG
MI.print(DOUT);
#endif
DOUT << "FrameIndex : " << FrameIndex << "\n";
DOUT << "spOffset : " << spOffset << "\n";
DOUT << "stackSize : " << stackSize << "\n";
// As explained on LowerFORMAL_ARGUMENTS, detect negative offsets
// and adjust SPOffsets considering the final stack size.
int Offset = ((spOffset < 0) ? (stackSize + (-(spOffset+4))) : (spOffset));
DOUT << "Offset : " << Offset << "\n";
DOUT << "<--------->\n";
// MI.getOperand(i+1).ChangeToImmediate(Offset);
MI.getOperand(i).ChangeToRegister(getFrameRegister(MF), false);
}
void PIC16RegisterInfo::emitPrologue(MachineFunction &MF) const
{ /* NOT YET IMPLEMENTED */ }
void PIC16RegisterInfo::
emitPrologue(MachineFunction &MF) const
{
}
void PIC16RegisterInfo::
emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
{
}
void PIC16RegisterInfo::
processFunctionBeforeFrameFinalized(MachineFunction &MF) const
{
}
unsigned PIC16RegisterInfo::
getRARegister() const {
assert(0 && "What is the return address register");
return 0;
}
unsigned PIC16RegisterInfo::
getFrameRegister(MachineFunction &MF) const {
return PIC16::STKPTR;
}
unsigned PIC16RegisterInfo::
getEHExceptionRegister() const {
assert(0 && "What is the exception register");
return 0;
}
unsigned PIC16RegisterInfo::
getEHHandlerRegister() const {
assert(0 && "What is the exception handler register");
return 0;
}
emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
{ /* NOT YET IMPLEMENTED */ }
int PIC16RegisterInfo::
getDwarfRegNum(unsigned RegNum, bool isEH) const {
assert(0 && "What is the dwarf register number");
assert(0 && "Not keeping track of debug information yet!!");
return -1;
}
unsigned PIC16RegisterInfo::getFrameRegister(MachineFunction &MF) const {
assert(0 && "PIC16 Does not have any frame register");
return 0;
}
unsigned PIC16RegisterInfo::getRARegister() const {
assert(0 && "PIC16 Does not have any return address register");
return 0;
}
#include "PIC16GenRegisterInfo.inc"

View File

@ -20,65 +20,43 @@
namespace llvm {
// Forward Declarations.
class TargetInstrInfo;
class Type;
class PIC16Subtarget;
class TargetInstrInfo;
struct PIC16RegisterInfo : public PIC16GenRegisterInfo {
const TargetInstrInfo &TII;
class PIC16RegisterInfo : public PIC16GenRegisterInfo {
private:
const TargetInstrInfo &TII;
const PIC16Subtarget &ST;
explicit PIC16RegisterInfo(const TargetInstrInfo &tii);
public:
PIC16RegisterInfo(const TargetInstrInfo &tii,
const PIC16Subtarget &st);
/// getRegisterNumbering - Given the enum value for some register, e.g.
/// PIC16::RA, return the number that it corresponds to (e.g. 31).
static unsigned getRegisterNumbering(unsigned RegEnum);
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
unsigned DestReg, const MachineInstr *Orig) const;
//------------------------------------------------------
// Pure virtual functions from TargetRegisterInfo
//------------------------------------------------------
MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
int FrameIndex) const;
// PIC16 callee saved registers
virtual const unsigned*
getCalleeSavedRegs(const MachineFunction *MF = 0) const;
MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
MachineInstr* LoadMI) const {
return 0;
}
// PIC16 callee saved register classes
virtual const TargetRegisterClass* const *
getCalleeSavedRegClasses(const MachineFunction *MF) const;
void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
unsigned DestReg, unsigned SrcReg,
const TargetRegisterClass *RC) const;
virtual BitVector getReservedRegs(const MachineFunction &MF) const;
virtual bool hasFP(const MachineFunction &MF) const;
const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const;
virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI,
int SPAdj, RegScavenger *RS=NULL) const;
const TargetRegisterClass* const*
getCalleeSavedRegClasses(const MachineFunction* MF = 0) const;
virtual void emitPrologue(MachineFunction &MF) const;
virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const;
virtual unsigned getFrameRegister(MachineFunction &MF) const;
virtual unsigned getRARegister() const;
BitVector getReservedRegs(const MachineFunction &MF) const;
bool hasFP(const MachineFunction &MF) const;
void eliminateCallFramePseudoInstr(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const;
/// Stack Frame Processing Methods.
void eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, RegScavenger *RS = NULL) const;
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
void emitPrologue(MachineFunction &MF) const;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
/// Debug information queries.
unsigned getRARegister() const;
unsigned getFrameRegister(MachineFunction &MF) const;
/// Exception handling queries.
unsigned getEHExceptionRegister() const;
unsigned getEHHandlerRegister() const;
int getDwarfRegNum(unsigned RegNum, bool isEH) const;
};
} // end namespace llvm

View File

@ -11,74 +11,22 @@
// Declarations that describe the PIC16 register file
//===----------------------------------------------------------------------===//
// We have banks of 32 registers each.
class PIC16Reg<string n> : Register<n> {
field bits<5> Num;
let Namespace = "PIC16";
}
// PIC16 CPU Registers
class PIC16GPRReg<bits<5> num, string n> : PIC16Reg<n> {
let Num = num;
}
// PIC16 Registers.
def W : PIC16Reg<"W">;
def FSR0 : PIC16Reg<"FSR0">;
def FSR1 : PIC16Reg<"FSR1">;
def BS : PIC16Reg<"BS">;
// CPU GPR Registers
def FSR0 : PIC16GPRReg< 0, "FSR0">, DwarfRegNum<[0]>;
def FSR1 : PIC16GPRReg< 1, "FSR1">, DwarfRegNum<[1]>;
def STATUS : PIC16Reg<"STATUS">;
// CPU Registers Class
def PTRRegs : RegisterClass<"PIC16", [i16], 8,
[FSR0, FSR1]>
{
let MethodProtos = [{
iterator allocation_order_end(const MachineFunction &MF) const;
}];
let MethodBodies = [{
PTRRegsClass::iterator
PTRRegsClass::allocation_order_end(const MachineFunction &MF) const {
return end();
}
}];
}
// PIC16 Register classes.
def GPR : RegisterClass<"PIC16", [i8], 8, [W]>;
def FSR16 : RegisterClass<"PIC16", [i16], 8, [FSR0, FSR1]>;
def BSR : RegisterClass<"PIC16", [i8], 8, [BS]>;
def WREG : PIC16GPRReg< 0, "WREG">, DwarfRegNum<[0]>;
def STATUSR: RegisterClass<"PIC16", [i8], 8, [STATUS]>;
// CPU Registers Class
def CPURegs : RegisterClass<"PIC16", [i8], 8,
[WREG]>
{
let MethodProtos = [{
iterator allocation_order_end(const MachineFunction &MF) const;
}];
let MethodBodies = [{
CPURegsClass::iterator
CPURegsClass::allocation_order_end(const MachineFunction &MF) const {
return end();
}
}];
}
def STATUSREG : PIC16GPRReg<2, "STATUS">, DwarfRegNum<[0]>;
// STATUS Registers Class
def STATUSRegs : RegisterClass<"PIC16", [i8], 8,
[STATUSREG]>;
// Dummy stack pointer.
def STKPTR : PIC16GPRReg< 0, "SP">, DwarfRegNum<[0]>;
// CPU Registers Class
def STKRegs : RegisterClass<"PIC16", [i8], 8,
[STKPTR]>
{
let MethodProtos = [{
iterator allocation_order_end(const MachineFunction &MF) const;
}];
let MethodBodies = [{
STKRegsClass::iterator
STKRegsClass::allocation_order_end(const MachineFunction &MF) const {
return end();
}
}];
}

View File

@ -11,14 +11,14 @@
//
//===----------------------------------------------------------------------===//
#include "PIC16.h"
#include "PIC16Subtarget.h"
#include "PIC16GenSubtarget.inc"
using namespace llvm;
PIC16Subtarget::PIC16Subtarget(const TargetMachine &TM, const Module &M,
const std::string &FS)
:IsPIC16Old(false)
PIC16Subtarget::PIC16Subtarget(const Module &M, const std::string &FS,
bool Cooper)
:IsCooper(Cooper)
{
std::string CPU = "generic";

View File

@ -14,7 +14,6 @@
#ifndef PIC16SUBTARGET_H
#define PIC16SUBTARGET_H
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetSubtarget.h"
#include <string>
@ -23,19 +22,23 @@ namespace llvm {
class Module;
class PIC16Subtarget : public TargetSubtarget {
bool IsPIC16Old;
// IsCooper - Target ISA is Cooper.
bool IsCooper;
public:
/// This constructor initializes the data members to match that
/// of the specified module.
///
PIC16Subtarget(const TargetMachine &TM, const Module &M,
const std::string &FS);
PIC16Subtarget(const Module &M, const std::string &FS, bool Cooper);
/// isCooper - Returns true if the target ISA is Cooper.
bool isCooper() const { return IsCooper; }
/// ParseSubtargetFeatures - Parses features string setting specified
/// subtarget options. Definition of function is auto generated by tblgen.
void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU);
};
} // End llvm namespace
#endif
#endif // PIC16SUBTARGET_H

View File

@ -17,11 +17,15 @@
using namespace llvm;
PIC16TargetAsmInfo::
PIC16TargetAsmInfo(const PIC16TargetMachine &TM)
PIC16TargetAsmInfo(const PIC16TargetMachine &TM)
: TargetAsmInfo(TM) {
Data16bitsDirective = "\t.half\t";
Data32bitsDirective = "\t.word\t";
CommentString = ";";
COMMDirective = "\t";
COMMDirectiveTakesAlignment = 0;
Data8bitsDirective = " db ";
Data16bitsDirective = " db ";
Data32bitsDirective = " db ";
DataSectionStartSuffix = " IDATA ";
UDataSectionStartSuffix = " UDATA ";
TextSectionStartSuffix = " CODE ";
RomDataSectionStartSuffix = " ROMDATA ";
ZeroDirective = NULL;
}

View File

@ -23,6 +23,17 @@ 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

View File

@ -16,6 +16,7 @@
#include "PIC16TargetMachine.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetMachineRegistry.h"
@ -29,50 +30,42 @@ using namespace llvm;
extern "C" int PIC16TargetMachineModule;
int PIC16TargetMachineModule = 0;
namespace {
// Register the targets
RegisterTarget<PIC16TargetMachine> X("pic16", "PIC16 14-bit [experimental]");
}
PIC16TargetMachine::
PIC16TargetMachine(const Module &M, const std::string &FS) :
Subtarget(*this, M, FS), DataLayout("e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8"),
// Register the targets
static RegisterTarget<PIC16TargetMachine>
X("pic16", "PIC16 14-bit (experimental).");
static RegisterTarget<CooperTargetMachine>
Y("cooper", "PIC16 Cooper (experimental).");
// PIC16TargetMachine - Traditional PIC16 Machine.
PIC16TargetMachine::PIC16TargetMachine(const Module &M, const std::string &FS,
bool Cooper)
: Subtarget(M, FS, Cooper),
DataLayout("e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8"),
InstrInfo(*this), TLInfo(*this),
FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0) { }
// CooperTargetMachine - Uses the same PIC16TargetMachine, but makes IsCooper
// as true.
CooperTargetMachine::CooperTargetMachine(const Module &M, const std::string &FS)
: PIC16TargetMachine(M, FS, true) {}
const TargetAsmInfo *PIC16TargetMachine::createTargetAsmInfo() const
{
const TargetAsmInfo *PIC16TargetMachine::createTargetAsmInfo() const {
return new PIC16TargetAsmInfo(*this);
}
//===----------------------------------------------------------------------===//
// Pass Pipeline Configuration
//===----------------------------------------------------------------------===//
bool PIC16TargetMachine::addInstSelector(PassManagerBase &PM, bool Fast)
{
bool PIC16TargetMachine::addInstSelector(PassManagerBase &PM, bool Fast) {
// Install an instruction selector.
PM.add(createPIC16ISelDag(*this));
return false;
}
bool PIC16TargetMachine::
addPrologEpilogInserter(PassManagerBase &PM, bool Fast)
{
return false;
}
bool PIC16TargetMachine::addPreEmitPass(PassManagerBase &PM, bool Fast)
{
return true;
}
bool PIC16TargetMachine::
addAssemblyEmitter(PassManagerBase &PM, bool Fast, raw_ostream &Out)
{
addAssemblyEmitter(PassManagerBase &PM, bool Fast, raw_ostream &Out) {
// Output assembly language.
PM.add(createPIC16CodePrinterPass(Out, *this));
return false;
}

View File

@ -17,6 +17,7 @@
#include "PIC16InstrInfo.h"
#include "PIC16ISelLowering.h"
#include "PIC16RegisterInfo.h"
#include "PIC16Subtarget.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameInfo.h"
@ -31,31 +32,42 @@ class PIC16TargetMachine : public LLVMTargetMachine {
const TargetData DataLayout; // Calculates type size & alignment
PIC16InstrInfo InstrInfo;
PIC16TargetLowering TLInfo;
// PIC16 does not have any call stack frame, therefore not having
// any PIC16 specific FrameInfo class.
TargetFrameInfo FrameInfo;
protected:
virtual const TargetAsmInfo *createTargetAsmInfo() const;
public:
PIC16TargetMachine(const Module &M, const std::string &FS);
virtual const TargetFrameInfo *getFrameInfo() const
{ return &FrameInfo; }
virtual const PIC16InstrInfo *getInstrInfo() const
{ return &InstrInfo; }
virtual const TargetData *getTargetData() const
{ return &DataLayout; }
virtual PIC16TargetLowering *getTargetLowering() const
{ return const_cast<PIC16TargetLowering*>(&TLInfo); }
virtual const PIC16RegisterInfo *getRegisterInfo() const
{ return &InstrInfo.getRegisterInfo(); }
public:
PIC16TargetMachine(const Module &M, const std::string &FS,
bool Cooper = false);
virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; }
virtual const PIC16InstrInfo *getInstrInfo() const { return &InstrInfo; }
virtual const TargetData *getTargetData() const { return &DataLayout;}
virtual const PIC16Subtarget *getSubtargetImpl() const { return &Subtarget; }
virtual const PIC16RegisterInfo *getRegisterInfo() const {
return &(InstrInfo.getRegisterInfo());
}
virtual PIC16TargetLowering *getTargetLowering() const {
return const_cast<PIC16TargetLowering*>(&TLInfo);
}
virtual bool addInstSelector(PassManagerBase &PM, bool Fast);
virtual bool addPrologEpilogInserter(PassManagerBase &PM, bool Fast);
virtual bool addPreEmitPass(PassManagerBase &PM, bool Fast);
virtual bool addAssemblyEmitter(PassManagerBase &PM, bool Fast,
virtual bool addAssemblyEmitter(PassManagerBase &PM, bool Fast,
raw_ostream &Out);
};
}; // PIC16TargetMachine.
/// CooperTargetMachine
class CooperTargetMachine : public PIC16TargetMachine {
public:
CooperTargetMachine(const Module &M, const std::string &FS);
}; // CooperTargetMachine.
} // end namespace llvm
#endif