aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target
diff options
context:
space:
mode:
authorSanjiv Gupta <sanjiv.gupta@microchip.com>2008-11-19 11:00:54 +0000
committerSanjiv Gupta <sanjiv.gupta@microchip.com>2008-11-19 11:00:54 +0000
commit085ae4ff5f4b703a03668ffd130e204791e9a876 (patch)
tree50927bf30fff92fd28b11b51e72002f26cad7a61 /lib/Target
parent5f334804a5042a5467cd52202f0294ed66c96095 (diff)
downloadexternal_llvm-085ae4ff5f4b703a03668ffd130e204791e9a876.zip
external_llvm-085ae4ff5f4b703a03668ffd130e204791e9a876.tar.gz
external_llvm-085ae4ff5f4b703a03668ffd130e204791e9a876.tar.bz2
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
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/PIC16/PIC16.h5
-rw-r--r--lib/Target/PIC16/PIC16.td26
-rw-r--r--lib/Target/PIC16/PIC16AsmPrinter.cpp696
-rw-r--r--lib/Target/PIC16/PIC16CallingConv.td16
-rw-r--r--lib/Target/PIC16/PIC16ConstantPoolValue.cpp89
-rw-r--r--lib/Target/PIC16/PIC16ConstantPoolValue.h77
-rw-r--r--lib/Target/PIC16/PIC16ISelDAGToDAG.cpp260
-rw-r--r--lib/Target/PIC16/PIC16ISelDAGToDAG.h60
-rw-r--r--lib/Target/PIC16/PIC16ISelLowering.cpp1239
-rw-r--r--lib/Target/PIC16/PIC16ISelLowering.h123
-rw-r--r--lib/Target/PIC16/PIC16InstrFormats.td61
-rw-r--r--lib/Target/PIC16/PIC16InstrInfo.cpp173
-rw-r--r--lib/Target/PIC16/PIC16InstrInfo.h55
-rw-r--r--lib/Target/PIC16/PIC16InstrInfo.td521
-rw-r--r--lib/Target/PIC16/PIC16RegisterInfo.cpp192
-rw-r--r--lib/Target/PIC16/PIC16RegisterInfo.h76
-rw-r--r--lib/Target/PIC16/PIC16RegisterInfo.td74
-rw-r--r--lib/Target/PIC16/PIC16Subtarget.cpp8
-rw-r--r--lib/Target/PIC16/PIC16Subtarget.h13
-rw-r--r--lib/Target/PIC16/PIC16TargetAsmInfo.cpp14
-rw-r--r--lib/Target/PIC16/PIC16TargetAsmInfo.h11
-rw-r--r--lib/Target/PIC16/PIC16TargetMachine.cpp49
-rw-r--r--lib/Target/PIC16/PIC16TargetMachine.h48
23 files changed, 1579 insertions, 2307 deletions
diff --git a/lib/Target/PIC16/PIC16.h b/lib/Target/PIC16/PIC16.h
index 6921bfd..f35acd5 100644
--- a/lib/Target/PIC16/PIC16.h
+++ b/lib/Target/PIC16/PIC16.h
@@ -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;
diff --git a/lib/Target/PIC16/PIC16.td b/lib/Target/PIC16/PIC16.td
index 8355de1..d37075b 100644
--- a/lib/Target/PIC16/PIC16.td
+++ b/lib/Target/PIC16/PIC16.td
@@ -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;
diff --git a/lib/Target/PIC16/PIC16AsmPrinter.cpp b/lib/Target/PIC16/PIC16AsmPrinter.cpp
index d765d75..21f1902 100644
--- a/lib/Target/PIC16/PIC16AsmPrinter.cpp
+++ b/lib/Target/PIC16/PIC16AsmPrinter.cpp
@@ -12,194 +12,70 @@
//
//===----------------------------------------------------------------------===//
-#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 "PIC16AsmPrinter.h"
+#include "PIC16TargetAsmInfo.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Mangler.h"
+#include "llvm/Function.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 "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/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"
-/// 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
-/// regardless of whether the function is in SSA form.
-///
-FunctionPass *llvm::createPIC16CodePrinterPass(raw_ostream &o,
- PIC16TargetMachine &tm) {
- 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++;
+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";
+ }
}
}
- SwitchToTextSection(CurrentFnName.c_str(), F);
- O << "_" << CurrentFnName << ":" ;
- O << "\n";
+ printInstruction(MI);
+ return true;
}
-
/// runOnMachineFunction - This uses the printInstruction()
/// method to print assembly for each instruction.
///
-bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF)
-{
+bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
+ // This calls the base class function required to be called at beginning
+ // of runOnMachineFunction.
SetupMachineFunction(MF);
- O << "\n";
- // What's my mangled name?
- CurrentFnName = Mang->getValueName(MF.getFunction());
+ // Get the mangled name.
+ const Function *F = MF.getFunction();
+ CurrentFnName = Mang->getValueName(F);
- // Emit the function start directives
- emitFunctionStart(MF);
+ // 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();
@@ -209,319 +85,317 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF)
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.
- O << '\t';
- printInstruction(II);
- ++EmittedInsts;
+ printMachineInstruction(II);
}
}
+ return false; // we didn't modify anything.
+}
- // We didn't modify anything.
- return false;
+/// 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
+/// regardless of whether the function is in SSA form.
+///
+FunctionPass *llvm::createPIC16CodePrinterPass(raw_ostream &o,
+ PIC16TargetMachine &tm) {
+ return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo());
}
-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.
+ assert(0 && " Operand type not supported.");
+ }
}
-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;
+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;
}
-/// 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)
+void PIC16AsmPrinter::EmitInitData (Module &M)
{
- const MachineOperand &MO = MI->getOperand(OpNum);
- assert(MO.isImm() && "Not a valid so_imm value!");
- printSOImm(O, MO.getImm(), TAI);
-}
+ 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();
-void PIC16AsmPrinter::printAddrModeOperand(const MachineInstr *MI, int Op)
-{
- const MachineOperand &MO1 = MI->getOperand(Op);
- const MachineOperand &MO2 = MI->getOperand(Op+1);
+ if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::RAM_SPACE)) {
+
+ if (EmitSpecialLLVMGlobal(I))
+ continue;
- if (MO2.isFI()) {
- printOperand(MI, Op+1);
- return;
- }
+ // 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;
- if (!MO1.isReg()) {
- // FIXME: This is for CP entries, but isn't right.
- printOperand(MI, Op);
- return;
+ O << name;
+ EmitGlobalConstant(C);
+ }
}
+}
- // If this is Stack Slot
- if (MO1.isReg()) {
- if (strcmp(TM.getRegisterInfo()->get(MO1.getReg()).Name, "SP") == 0) {
- O << CurrentFnName <<"_"<< MO2.getImm();
- return;
+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;
}
- O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
- O << "+";
- O << MO2.getImm();
- O << "]";
return;
}
-
- O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
- O << "]";
+ AsmPrinter::EmitConstantValueOnly(CV);
}
-
-void PIC16AsmPrinter::printRegisterList(const MachineInstr *MI, int opNum)
+void PIC16AsmPrinter::EmitRomData (Module &M)
{
- O << "{";
- for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) {
- printOperand(MI, i);
- if (i != e-1) O << ", ";
- }
- O << "}";
-}
+ 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;
-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);
+ 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;
}
-bool PIC16AsmPrinter::doInitialization(Module &M)
-{
- bool Result = AsmPrinter::doInitialization(M);
- return Result;
-}
-
-bool PIC16AsmPrinter::doFinalization(Module &M)
+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 (indexBegin < indexEnd)
+ O << CurrentFnName << ".tmp RES"<< " "
+ <<indexEnd - indexBegin <<"\n";
+ /*
+ while (indexBegin < indexEnd) {
+ O << CurrentFnName << "_tmp_" << indexBegin << " " << "RES"<< " "
+ << 1 << "\n" ;
+ indexBegin++;
+ }
+ */
+ }
+}
- 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;
- }
- }
+/// The function is same as AsmPrinter::SwitchtoDataSection except the call
+/// to getUDataSectionStartSuffix.
+void PIC16AsmPrinter::SwitchToUDataSection(const char *NewSection,
+ const GlobalValue *GV) {
+ std::string NS;
+ if (GV && GV->hasSection())
+ NS = TAI->getSwitchToSectionDirective() + GV->getSection();
+ else
+ NS = NewSection;
- if (!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 we're already in this section, we're done.
+ if (CurrentSection == NS) return;
- 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
+ // Close the current section, if applicable.
+ if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
+ O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
- case GlobalValue::ExternalLinkage:
- O << "\t.globl " << name << "\n";
- // FALL THROUGH
+ CurrentSection = NS;
- case GlobalValue::InternalLinkage:
- break;
+ if (!CurrentSection.empty()){}
+ O << CurrentSection << (static_cast<const PIC16TargetAsmInfo *>(TAI))->
+ getUDataSectionStartSuffix() << '\n';
- default:
- assert(0 && "Unknown linkage type!");
- break;
- } // end switch.
+ IsInTextSection = false;
+}
- EmitAlignment(Align, I);
- O << name << ":\t\t\t\t" << TAI->getCommentString() << " " << I->getName()
- << "\n";
+/// The function is same as AsmPrinter::SwitchtoDataSection except the call
+/// to getRomDataSectionStartSuffix.
+void PIC16AsmPrinter::SwitchToRomDataSection(const char *NewSection,
+ const GlobalValue *GV) {
+ std::string NS;
+ if (GV && GV->hasSection())
+ NS = TAI->getSwitchToSectionDirective() + GV->getSection();
+ else
+ NS = NewSection;
- // If 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);
+ // If we're already in this section, we're done.
+ if (CurrentSection == NS) return;
- EmitGlobalConstant(C);
- O << '\n';
- } // end for.
+ // Close the current section, if applicable.
+ if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
+ O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
- O << "\n "<< "END";
- return AsmPrinter::doFinalization(M);
-}
+ CurrentSection = NS;
-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);
-}
+ if (!CurrentSection.empty()) {}
+ O << CurrentSection << (static_cast< const PIC16TargetAsmInfo *>(TAI))->
+ getRomDataSectionStartSuffix() << '\n';
-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);
- }
- else
- AsmPrinter::SwitchToDataSection(NewSection, GV);
+ 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);
- }
- else
- AsmPrinter::SwitchToDataSection(NewSection, GV);
-}
diff --git a/lib/Target/PIC16/PIC16CallingConv.td b/lib/Target/PIC16/PIC16CallingConv.td
deleted file mode 100644
index fb6c9a3..0000000
--- a/lib/Target/PIC16/PIC16CallingConv.td
+++ /dev/null
@@ -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
-//===----------------------------------------------------------------------===//
diff --git a/lib/Target/PIC16/PIC16ConstantPoolValue.cpp b/lib/Target/PIC16/PIC16ConstantPoolValue.cpp
deleted file mode 100644
index 152c737..0000000
--- a/lib/Target/PIC16/PIC16ConstantPoolValue.cpp
+++ /dev/null
@@ -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 << ")";
- }
-}
diff --git a/lib/Target/PIC16/PIC16ConstantPoolValue.h b/lib/Target/PIC16/PIC16ConstantPoolValue.h
deleted file mode 100644
index 657fb15..0000000
--- a/lib/Target/PIC16/PIC16ConstantPoolValue.h
+++ /dev/null
@@ -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
diff --git a/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp b/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp
index d98be99..6c2b8ec 100644
--- a/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp
+++ b/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp
@@ -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
-};
+using namespace llvm;
+/// 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()
-{
+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;
- }
+SDNode* PIC16DAGToDAGISel::Select(SDValue N) {
// 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
-/// PIC16-specific DAG, ready for instruction scheduling.
-FunctionPass *llvm::createPIC16ISelDag(PIC16TargetMachine &TM) {
- return new PIC16DAGToDAGISel(TM);
-}
+// 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;
+}
diff --git a/lib/Target/PIC16/PIC16ISelDAGToDAG.h b/lib/Target/PIC16/PIC16ISelDAGToDAG.h
new file mode 100644
index 0000000..1773133
--- /dev/null
+++ b/lib/Target/PIC16/PIC16ISelDAGToDAG.h
@@ -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);
+
+};
+
+}
+
diff --git a/lib/Target/PIC16/PIC16ISelLowering.cpp b/lib/Target/PIC16/PIC16ISelLowering.cpp
index ed3c645..feb21ef 100644
--- a/lib/Target/PIC16/PIC16ISelLowering.cpp
+++ b/lib/Target/PIC16/PIC16ISelLowering.cpp
@@ -17,751 +17,662 @@
#include "PIC16ISelLowering.h"
#include "PIC16TargetMachine.h"
#include "llvm/DerivedTypes.h"
+#include "llvm/GlobalValue.h"
#include "llvm/Function.h"
-#include "llvm/Intrinsics.h"
-#include "llvm/CallingConv.h"
-#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/CodeGen/SelectionDAGISel.h"
-#include "llvm/CodeGen/ValueTypes.h"
-#include "llvm/Support/Debug.h"
-using namespace llvm;
-const char *PIC16TargetLowering:: getTargetNodeName(unsigned Opcode) const
-{
- switch (Opcode) {
- case PIC16ISD::Hi : return "PIC16ISD::Hi";
- case PIC16ISD::Lo : return "PIC16ISD::Lo";
- case PIC16ISD::Package : return "PIC16ISD::Package";
- case PIC16ISD::Wrapper : return "PIC16ISD::Wrapper";
- case PIC16ISD::SetBank : return "PIC16ISD::SetBank";
- case PIC16ISD::SetPage : return "PIC16ISD::SetPage";
- case PIC16ISD::Branch : return "PIC16ISD::Branch";
- case PIC16ISD::Cmp : return "PIC16ISD::Cmp";
- case PIC16ISD::BTFSS : return "PIC16ISD::BTFSS";
- case PIC16ISD::BTFSC : return "PIC16ISD::BTFSC";
- case PIC16ISD::XORCC : return "PIC16ISD::XORCC";
- case PIC16ISD::SUBCC : return "PIC16ISD::SUBCC";
- default : return NULL;
- }
-}
-PIC16TargetLowering::
-PIC16TargetLowering(PIC16TargetMachine &TM): TargetLowering(TM)
-{
- // Set up the register classes.
- addRegisterClass(MVT::i8, PIC16::CPURegsRegisterClass);
- addRegisterClass(MVT::i16, PIC16::PTRRegsRegisterClass);
-
- // Load extented operations for i1 types must be promoted .
- setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
- setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
- setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
-
- setOperationAction(ISD::ADD, MVT::i1, Promote);
- setOperationAction(ISD::ADD, MVT::i8, Legal);
- setOperationAction(ISD::ADD, MVT::i16, Custom);
- setOperationAction(ISD::ADD, MVT::i32, Expand);
- setOperationAction(ISD::ADD, MVT::i64, Expand);
-
- setOperationAction(ISD::SUB, MVT::i1, Promote);
- setOperationAction(ISD::SUB, MVT::i8, Legal);
- setOperationAction(ISD::SUB, MVT::i16, Custom);
- setOperationAction(ISD::SUB, MVT::i32, Expand);
- setOperationAction(ISD::SUB, MVT::i64, Expand);
-
- setOperationAction(ISD::ADDC, MVT::i1, Promote);
- setOperationAction(ISD::ADDC, MVT::i8, Legal);
- setOperationAction(ISD::ADDC, MVT::i16, Custom);
- setOperationAction(ISD::ADDC, MVT::i32, Expand);
- setOperationAction(ISD::ADDC, MVT::i64, Expand);
-
- setOperationAction(ISD::ADDE, MVT::i1, Promote);
- setOperationAction(ISD::ADDE, MVT::i8, Legal);
- setOperationAction(ISD::ADDE, MVT::i16, Custom);
- setOperationAction(ISD::ADDE, MVT::i32, Expand);
- setOperationAction(ISD::ADDE, MVT::i64, Expand);
-
- setOperationAction(ISD::SUBC, MVT::i1, Promote);
- setOperationAction(ISD::SUBC, MVT::i8, Legal);
- setOperationAction(ISD::SUBC, MVT::i16, Custom);
- setOperationAction(ISD::SUBC, MVT::i32, Expand);
- setOperationAction(ISD::SUBC, MVT::i64, Expand);
-
- setOperationAction(ISD::SUBE, MVT::i1, Promote);
- setOperationAction(ISD::SUBE, MVT::i8, Legal);
- setOperationAction(ISD::SUBE, MVT::i16, Custom);
- setOperationAction(ISD::SUBE, MVT::i32, Expand);
- setOperationAction(ISD::SUBE, MVT::i64, Expand);
-
- // PIC16 does not have these NodeTypes below.
- setOperationAction(ISD::SETCC, MVT::i1, Expand);
- setOperationAction(ISD::SETCC, MVT::i8, Expand);
- setOperationAction(ISD::SETCC, MVT::Other, Expand);
- setOperationAction(ISD::SELECT_CC, MVT::i1, Custom);
- setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
-
- setOperationAction(ISD::BRCOND, MVT::i1, Expand);
- setOperationAction(ISD::BRCOND, MVT::i8, Expand);
- setOperationAction(ISD::BRCOND, MVT::Other, Expand);
-
- setOperationAction(ISD::BR_CC, MVT::i1, Custom);
- setOperationAction(ISD::BR_CC, MVT::i8, Custom);
-
- setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
+using namespace llvm;
+
+// PIC16TargetLowering Constructor.
+PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM)
+ : TargetLowering(TM) {
- // FIXME: Do we really need to Custom lower the GA ??
- setOperationAction(ISD::GlobalAddress, MVT::i8, Custom);
- setOperationAction(ISD::RET, MVT::Other, Custom);
-
- setOperationAction(ISD::CTPOP, MVT::i32, Expand);
- setOperationAction(ISD::CTTZ, MVT::i32, Expand);
- setOperationAction(ISD::CTLZ, MVT::i32, Expand);
- setOperationAction(ISD::ROTL, MVT::i32, Expand);
- setOperationAction(ISD::ROTR, MVT::i32, Expand);
- setOperationAction(ISD::BSWAP, MVT::i32, Expand);
-
- setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
- setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
- setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
-
- // We don't have line number support yet.
- setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
- setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
- setOperationAction(ISD::DBG_LABEL, MVT::Other, Expand);
- setOperationAction(ISD::EH_LABEL, MVT::Other, Expand);
-
- // Use the default for now.
- setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
- setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
-
- setOperationAction(ISD::LOAD, MVT::i1, Promote);
- setOperationAction(ISD::LOAD, MVT::i8, Legal);
-
- setTargetDAGCombine(ISD::LOAD);
- setTargetDAGCombine(ISD::STORE);
- setTargetDAGCombine(ISD::ADDE);
- setTargetDAGCombine(ISD::ADDC);
- setTargetDAGCombine(ISD::ADD);
- setTargetDAGCombine(ISD::SUBE);
- setTargetDAGCombine(ISD::SUBC);
- setTargetDAGCombine(ISD::SUB);
-
- setStackPointerRegisterToSaveRestore(PIC16::STKPTR);
+ Subtarget = &TM.getSubtarget<PIC16Subtarget>();
+
+ addRegisterClass(MVT::i8, PIC16::GPRRegisterClass);
+
+ setShiftAmountType(MVT::i8);
+ setShiftAmountFlavor(Extend);
+
+
+ setOperationAction(ISD::GlobalAddress, MVT::i16, Custom);
+
+ setOperationAction(ISD::LOAD, MVT::i8, Legal);
+ setOperationAction(ISD::LOAD, MVT::i16, Custom);
+ setOperationAction(ISD::LOAD, MVT::i32, Custom);
+
+ setOperationAction(ISD::STORE, MVT::i8, Legal);
+ setOperationAction(ISD::STORE, MVT::i16, Custom);
+ setOperationAction(ISD::STORE, MVT::i32, Custom);
+
+ setOperationAction(ISD::ADDE, MVT::i8, Custom);
+ setOperationAction(ISD::ADDC, MVT::i8, Custom);
+ setOperationAction(ISD::SUBE, MVT::i8, Custom);
+ setOperationAction(ISD::SUBC, MVT::i8, Custom);
+ setOperationAction(ISD::ADD, MVT::i8, Legal);
+ setOperationAction(ISD::ADD, MVT::i16, Custom);
+
+ setOperationAction(ISD::SHL, MVT::i16, Custom);
+ setOperationAction(ISD::SHL, MVT::i32, Custom);
+
+ //setOperationAction(ISD::TRUNCATE, MVT::i16, Custom);
+ setTruncStoreAction(MVT::i16, MVT::i8, Custom);
+
+ // Now deduce the information based on the above mentioned
+ // actions
computeRegisterProperties();
}
+const char *PIC16TargetLowering::getTargetNodeName(unsigned Opcode) const {
+ switch (Opcode) {
+ default: return NULL;
+ case PIC16ISD::Lo: return "PIC16ISD::Lo";
+ case PIC16ISD::Hi: return "PIC16ISD::Hi";
+ case PIC16ISD::MTLO: return "PIC16ISD::MTLO";
+ case PIC16ISD::MTHI: return "PIC16ISD::MTHI";
+ case PIC16ISD::Banksel: return "PIC16ISD::Banksel";
+ case PIC16ISD::PIC16Load: return "PIC16ISD::PIC16Load";
+ case PIC16ISD::PIC16Store: return "PIC16ISD::PIC16Store";
+ case PIC16ISD::BCF: return "PIC16ISD::BCF";
+ case PIC16ISD::LSLF: return "PIC16ISD::LSLF";
+ case PIC16ISD::LRLF: return "PIC16ISD::LRLF";
+ case PIC16ISD::RLF: return "PIC16ISD::RLF";
+ case PIC16ISD::RRF: return "PIC16ISD::RRF";
+ case PIC16ISD::Dummy: return "PIC16ISD::Dummy";
+ }
+}
-SDValue PIC16TargetLowering:: LowerOperation(SDValue Op, SelectionDAG &DAG)
-{
- SDVTList VTList16 = DAG.getVTList(MVT::i16, MVT::i16, MVT::Other);
- switch (Op.getOpcode()) {
- case ISD::STORE:
- DOUT << "reduce store\n";
- break;
+SDNode *PIC16TargetLowering::ReplaceNodeResults(SDNode *N, SelectionDAG &DAG) {
+ switch (N->getOpcode()) {
+ case ISD::GlobalAddress:
+ return ExpandGlobalAddress(N, DAG);
+ case ISD::STORE:
+ return ExpandStore(N, DAG);
+ case ISD::LOAD:
+ return ExpandLoad(N, DAG);
+ case ISD::ADD:
+ return ExpandAdd(N, DAG);
+ case ISD::SHL:
+ return ExpandShift(N, DAG);
+ default:
+ assert (0 && "not implemented");
+ }
+}
- case ISD::FORMAL_ARGUMENTS:
- DOUT << "==== lowering formal args\n";
- return LowerFORMAL_ARGUMENTS(Op, DAG);
+SDNode *PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) {
+ StoreSDNode *St = cast<StoreSDNode>(N);
+ SDValue Chain = St->getChain();
+ SDValue Src = St->getValue();
+ SDValue Ptr = St->getBasePtr();
+ MVT ValueType = Src.getValueType();
+ unsigned StoreOffset = 0;
+
+ SDValue PtrLo, PtrHi;
+ LegalizeAddress(Ptr, DAG, PtrLo, PtrHi, StoreOffset);
+
+ if (ValueType == MVT::i8) {
+ SDValue Store = DAG.getNode (PIC16ISD::PIC16Store, MVT::Other, Chain, Src,
+ PtrLo, PtrHi, DAG.getConstant (0, MVT::i8));
+ return Store.getNode();
+ }
+ else if (ValueType == MVT::i16) {
+ // Get the Lo and Hi parts from MERGE_VALUE or BUILD_PAIR.
+ SDValue SrcLo, SrcHi;
+ GetExpandedParts(Src, DAG, SrcLo, SrcHi);
+ SDValue ChainLo = Chain, ChainHi = Chain;
+ if (Chain.getOpcode() == ISD::TokenFactor) {
+ ChainLo = Chain.getOperand(0);
+ ChainHi = Chain.getOperand(1);
+ }
+ SDValue Store1 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other,
+ ChainLo,
+ SrcLo, PtrLo, PtrHi,
+ DAG.getConstant (0 + StoreOffset, MVT::i8));
+
+ SDValue Store2 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other, ChainHi,
+ SrcHi, PtrLo, PtrHi,
+ DAG.getConstant (1 + StoreOffset, MVT::i8));
- case ISD::GlobalAddress:
- DOUT << "==== lowering GA\n";
- return LowerGlobalAddress(Op, DAG);
+ return DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(Store1),
+ getChain(Store2)).getNode();
+ }
+ else if (ValueType == MVT::i32) {
+ // Get the Lo and Hi parts from MERGE_VALUE or BUILD_PAIR.
+ SDValue SrcLo, SrcHi;
+ GetExpandedParts(Src, DAG, SrcLo, SrcHi);
+
+ // Get the expanded parts of each of SrcLo and SrcHi.
+ SDValue SrcLo1, SrcLo2, SrcHi1, SrcHi2;
+ GetExpandedParts(SrcLo, DAG, SrcLo1, SrcLo2);
+ GetExpandedParts(SrcHi, DAG, SrcHi1, SrcHi2);
+
+ SDValue ChainLo = Chain, ChainHi = Chain;
+ if (Chain.getOpcode() == ISD::TokenFactor) {
+ ChainLo = Chain.getOperand(0);
+ ChainHi = Chain.getOperand(1);
+ }
+ SDValue ChainLo1 = ChainLo, ChainLo2 = ChainLo, ChainHi1 = ChainHi,
+ ChainHi2 = ChainHi;
+ if (ChainLo.getOpcode() == ISD::TokenFactor) {
+ ChainLo1 = ChainLo.getOperand(0);
+ ChainLo2 = ChainLo.getOperand(1);
+ }
+ if (ChainHi.getOpcode() == ISD::TokenFactor) {
+ ChainHi1 = ChainHi.getOperand(0);
+ ChainHi2 = ChainHi.getOperand(1);
+ }
+ SDValue Store1 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other,
+ ChainLo1,
+ SrcLo1, PtrLo, PtrHi,
+ DAG.getConstant (0 + StoreOffset, MVT::i8));
- case ISD::RET:
- DOUT << "==== lowering ret\n";
- return LowerRET(Op, DAG);
+ SDValue Store2 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other, ChainLo2,
+ SrcLo2, PtrLo, PtrHi,
+ DAG.getConstant (1 + StoreOffset, MVT::i8));
- case ISD::FrameIndex:
- DOUT << "==== lowering frame index\n";
- return LowerFrameIndex(Op, DAG);
+ SDValue Store3 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other, ChainHi1,
+ SrcHi1, PtrLo, PtrHi,
+ DAG.getConstant (2 + StoreOffset, MVT::i8));
- case ISD::ADDE:
- DOUT << "==== lowering adde\n";
- break;
+ SDValue Store4 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other, ChainHi2,
+ SrcHi2, PtrLo, PtrHi,
+ DAG.getConstant (3 + StoreOffset, MVT::i8));
- case ISD::LOAD:
- case ISD::ADD:
- break;
+ SDValue RetLo = DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(Store1),
+ getChain(Store2));
+ SDValue RetHi = DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(Store3),
+ getChain(Store4));
+ return DAG.getNode(ISD::TokenFactor, MVT::Other, RetLo, RetHi).getNode();
- case ISD::BR_CC:
- DOUT << "==== lowering BR_CC\n";
- return LowerBR_CC(Op, DAG);
- } // end switch.
- return SDValue();
+ }
+ else {
+ assert (0 && "value type not supported");
+ }
}
+// ExpandGlobalAddress -
+SDNode *PIC16TargetLowering::ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG) {
+ GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(SDValue(N, 0));
+
+ SDValue TGA = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i8,
+ G->getOffset());
+
+ SDValue Lo = DAG.getNode(PIC16ISD::Lo, MVT::i8, TGA);
+ SDValue Hi = DAG.getNode(PIC16ISD::Hi, MVT::i8, TGA);
-//===----------------------------------------------------------------------===//
-// Lower helper functions
-//===----------------------------------------------------------------------===//
+ SDValue BP = DAG.getNode(ISD::BUILD_PAIR, MVT::i16, Lo, Hi);
+ return BP.getNode();
+}
-SDValue PIC16TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG)
-{
- MVT VT = Op.getValueType();
- SDValue Chain = Op.getOperand(0);
- ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
- SDValue LHS = Op.getOperand(2);
- SDValue RHS = Op.getOperand(3);
- SDValue JumpVal = Op.getOperand(4);
- SDValue Result;
- unsigned cmpOpcode;
- unsigned branchOpcode;
- SDValue branchOperand;
-
- SDValue StatusReg = DAG.getRegister(PIC16::STATUSREG, MVT::i8);
- SDValue CPUReg = DAG.getRegister(PIC16::WREG, MVT::i8);
- switch(CC) {
- default:
- assert(0 && "This condition code is not handled yet!!");
- abort();
-
- case ISD::SETNE:
- DOUT << "setne\n";
- cmpOpcode = PIC16ISD::XORCC;
- branchOpcode = PIC16ISD::BTFSS;
- branchOperand = DAG.getConstant(2, MVT::i8);
- break;
-
- case ISD::SETEQ:
- DOUT << "seteq\n";
- cmpOpcode = PIC16ISD::XORCC;
- branchOpcode = PIC16ISD::BTFSC;
- branchOperand = DAG.getConstant(2, MVT::i8);
- break;
-
- case ISD::SETGT:
- assert(0 && "Greater Than condition code is not handled yet!!");
- abort();
- break;
-
- case ISD::SETGE:
- DOUT << "setge\n";
- cmpOpcode = PIC16ISD::SUBCC;
- branchOpcode = PIC16ISD::BTFSS;
- branchOperand = DAG.getConstant(1, MVT::i8);
- break;
-
- case ISD::SETLT:
- DOUT << "setlt\n";
- cmpOpcode = PIC16ISD::SUBCC;
- branchOpcode = PIC16ISD::BTFSC;
- branchOperand = DAG.getConstant(1,MVT::i8);
- break;
-
- case ISD::SETLE:
- assert(0 && "Less Than Equal condition code is not handled yet!!");
- abort();
- break;
- } // End of Switch
-
- SDVTList VTList = DAG.getVTList(MVT::i8, MVT::Flag);
- SDValue CmpValue = DAG.getNode(cmpOpcode, VTList, LHS, RHS).getValue(1);
- Result = DAG.getNode(branchOpcode, VT, Chain, JumpVal, branchOperand,
- StatusReg, CmpValue);
- return Result;
+bool PIC16TargetLowering::isDirectAddress(const SDValue &Op) {
+ assert (Op.getNode() != NULL && "Can't operate on NULL SDNode!!");
+
+ if (Op.getOpcode() == ISD::BUILD_PAIR) {
+ if (Op.getOperand(0).getOpcode() == PIC16ISD::Lo)
+ return true;
+ }
+ return false;
}
+// Return true if DirectAddress is in ROM_SPACE
+bool PIC16TargetLowering::isRomAddress(const SDValue &Op) {
-//===----------------------------------------------------------------------===//
-// Misc Lower Operation implementation
-//===----------------------------------------------------------------------===//
+ // RomAddress is a GlobalAddress in ROM_SPACE_
+ // If the Op is not a GlobalAddress return NULL without checking
+ // anything further.
+ if (!isDirectAddress(Op))
+ return false;
+
+ // Its a GlobalAddress.
+ // It is BUILD_PAIR((PIC16Lo TGA), (PIC16Hi TGA)) and Op is BUILD_PAIR
+ SDValue TGA = Op.getOperand(0).getOperand(0);
+ GlobalAddressSDNode *GSDN = dyn_cast<GlobalAddressSDNode>(TGA);
+ const Type *ValueType = GSDN->getGlobal()->getType();
-// LowerGlobalAddress - Create a constant pool entry for global value
-// and wrap it in a wrapper node.
-SDValue
-PIC16TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG)
-{
- MVT PtrVT = getPointerTy();
- GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
- GlobalValue *GV = GSDN->getGlobal();
-
- // FIXME: for now only do the ram.
- SDValue CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 2);
- SDValue CPBank = DAG.getNode(PIC16ISD::SetBank, MVT::i8, CPAddr);
- CPAddr = DAG.getNode(PIC16ISD::Wrapper, MVT::i8, CPAddr,CPBank);
-
- return CPAddr;
+ if (!isa<PointerType>(ValueType)) {
+ assert(0 && "TGA must be of a PointerType");
+ }
+
+ int AddrSpace = dyn_cast<PointerType>(ValueType)->getAddressSpace();
+ if (AddrSpace == PIC16ISD::ROM_SPACE)
+ return true;
+
+ // Any other address space return it false
+ return false;
}
-SDValue
-PIC16TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG)
-{
- switch(Op.getNumOperands()) {
- default:
- assert(0 && "Do not know how to return this many arguments!");
- abort();
+// 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 PIC16TargetLowering::getChain(SDValue &Op) {
+ SDValue Chain = Op.getValue(Op.getNode()->getNumValues() - 1);
- case 1:
- return SDValue(); // ret void is legal
- }
+ // All nodes may not produce a chain. Therefore following assert
+ // verifies that the node is returning a chain only.
+ assert (Chain.getValueType() == MVT::Other && "Node does not have a chain");
+
+ return Chain;
}
-SDValue
-PIC16TargetLowering::LowerFrameIndex(SDValue N, SelectionDAG &DAG)
-{
- if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
- return DAG.getTargetFrameIndex(FIN->getIndex(), MVT::i32);
+void PIC16TargetLowering::GetExpandedParts(SDValue Op, SelectionDAG &DAG,
+ SDValue &Lo, SDValue &Hi) {
+ SDNode *N = Op.getNode();
+ unsigned NumValues = N->getNumValues();
+ std::vector<MVT> VTs;
+ MVT NewVT;
+ std::vector<SDValue> Opers;
+
+ // EXTRACT_ELEMENT should have same number and type of values that the
+ // node replacing the EXTRACT_ELEMENT should have. (i.e. extracted element)
+ // Some nodes such as LOAD and PIC16Load have more than one values. In such
+ // cases EXTRACT_ELEMENT should have more than one values. Therefore creating
+ // vector of Values for EXTRACT_ELEMENT. This list will have same number of
+ // values as the extracted element will have.
+
+ for (unsigned i=0;i < NumValues; ++i) {
+ NewVT = getTypeToTransformTo(N->getValueType(i));
+ VTs.push_back(NewVT);
}
- return N;
+ // extract the lo component
+ Opers.push_back(Op);
+ Opers.push_back(DAG.getConstant(0,MVT::i8));
+ Lo = DAG.getNode(ISD::EXTRACT_ELEMENT,VTs,&Opers[0],Opers.size());
+
+ // extract the hi component
+ Opers.clear();
+ Opers.push_back(Op);
+ Opers.push_back(DAG.getConstant(1,MVT::i8));
+ Hi = DAG.getNode(ISD::EXTRACT_ELEMENT,VTs,&Opers[0],Opers.size());
}
-SDValue
-PIC16TargetLowering::LowerLOAD(SDNode *N,
- SelectionDAG &DAG,
- DAGCombinerInfo &DCI) const
-{
- SDValue Outs[2];
- SDValue TF; //TokenFactor
- SDValue OutChains[2];
- SDValue Chain = N->getOperand(0);
- SDValue Src = N->getOperand(1);
- SDValue retVal;
- SDVTList VTList;
-
- // If this load is directly stored, replace the load value with the stored
- // value.
- // FIXME: Handle store large -> read small portion.
- // FIXME: Handle TRUNCSTORE/LOADEXT
- LoadSDNode *LD = cast<LoadSDNode>(N);
- SDValue Ptr = LD->getBasePtr();
- if (LD->getExtensionType() == ISD::NON_EXTLOAD) {
- if (ISD::isNON_TRUNCStore(Chain.getNode())) {
- StoreSDNode *PrevST = cast<StoreSDNode>(Chain);
- if (PrevST->getBasePtr() == Ptr &&
- PrevST->getValue().getValueType() == N->getValueType(0))
- return DCI.CombineTo(N, Chain.getOperand(1), Chain);
+// This function legalizes the PIC16 Addresses. If the Pointer is
+// -- Direct address variable residing
+// --> then a Banksel for that variable will be created.
+// -- Rom variable
+// --> then it will be treated as an indirect address.
+// -- Indirect address
+// --> then the address will be loaded into FSR
+// -- ADD with constant operand
+// --> then constant operand of ADD will be returned as Offset
+// and non-constant operand of ADD will be treated as pointer.
+// Returns the high and lo part of the address, and the offset(in case of ADD).
+
+void PIC16TargetLowering:: LegalizeAddress(SDValue Ptr, SelectionDAG &DAG,
+ SDValue &Lo, SDValue &Hi,
+ unsigned &Offset) {
+
+ // Offset, by default, should be 0
+ Offset = 0;
+
+ // If the pointer is ADD with constant,
+ // return the constant value as the offset
+ if (Ptr.getOpcode() == ISD::ADD) {
+ SDValue OperLeft = Ptr.getOperand(0);
+ SDValue OperRight = Ptr.getOperand(1);
+ if (OperLeft.getOpcode() == ISD::Constant) {
+ Offset = dyn_cast<ConstantSDNode>(OperLeft)->getZExtValue();
+ Ptr = OperRight;
+ } else {
+ Ptr = OperLeft;
+ Offset = dyn_cast<ConstantSDNode>(OperRight)->getZExtValue();
}
}
- if (N->getValueType(0) != MVT::i16)
- return SDValue();
+ if (isDirectAddress(Ptr) && !isRomAddress(Ptr)) {
+ // Direct addressing case for RAM variables. The Hi part is constant
+ // and the Lo part is the TGA itself.
+ Lo = Ptr.getOperand(0).getOperand(0);
+
+ // For direct addresses Hi is a constant. Value 1 for the constant
+ // signifies that banksel needs to generated for it. Value 0 for
+ // the constant signifies that banksel does not need to be generated
+ // for it. Mark it as 1 now and optimize later.
+ Hi = DAG.getConstant(1, MVT::i8);
+ return;
+ }
- SDValue toWorklist;
- Outs[0] = DAG.getLoad(MVT::i8, Chain, Src, NULL, 0);
- toWorklist = DAG.getNode(ISD::ADD, MVT::i16, Src,
- DAG.getConstant(1, MVT::i16));
- Outs[1] = DAG.getLoad(MVT::i8, Chain, toWorklist, NULL, 0);
- // FIXME: Add to worklist may not be needed.
- // It is meant to merge sequences of add with constant into one.
- DCI.AddToWorklist(toWorklist.getNode());
-
- // Create the tokenfactors and carry it on to the build_pair node
- OutChains[0] = Outs[0].getValue(1);
- OutChains[1] = Outs[1].getValue(1);
- TF = DAG.getNode(ISD::TokenFactor, MVT::Other, &OutChains[0], 2);
-
- VTList = DAG.getVTList(MVT::i16, MVT::Flag);
- retVal = DAG.getNode (PIC16ISD::Package, VTList, &Outs[0], 2);
+ // Indirect addresses. Get the hi and lo parts of ptr.
+ GetExpandedParts(Ptr, DAG, Lo, Hi);
- DCI.CombineTo (N, retVal, TF);
+ // Put the hi and lo parts into FSR.
+ Lo = DAG.getNode(PIC16ISD::MTLO, MVT::i8, Lo);
+ Hi = DAG.getNode(PIC16ISD::MTHI, MVT::i8, Hi);
- return retVal;
+ return;
}
-SDValue
-PIC16TargetLowering::LowerADDSUB(SDNode *N, SelectionDAG &DAG,
- DAGCombinerInfo &DCI) const
-{
- bool changed = false;
- int i;
- SDValue LoOps[3], HiOps[3];
- SDValue OutOps[3]; // [0]:left, [1]:right, [2]:carry
- SDValue InOp[2];
- SDValue retVal;
- SDValue as1,as2;
- SDVTList VTList;
- unsigned AS = 0, ASE = 0, ASC=0;
-
- InOp[0] = N->getOperand(0);
- InOp[1] = N->getOperand(1);
+SDNode *PIC16TargetLowering::ExpandAdd(SDNode *N, SelectionDAG &DAG) {
+ SDValue OperLeft = N->getOperand(0);
+ SDValue OperRight = N->getOperand(1);
- switch (N->getOpcode()) {
- case ISD::ADD:
- if (InOp[0].getOpcode() == ISD::Constant &&
- InOp[1].getOpcode() == ISD::Constant) {
- ConstantSDNode *CST0 = dyn_cast<ConstantSDNode>(InOp[0]);
- ConstantSDNode *CST1 = dyn_cast<ConstantSDNode>(InOp[1]);
- return DAG.getConstant(CST0->getZExtValue() + CST1->getZExtValue(),
- MVT::i16);
- }
- break;
+ if((OperLeft.getOpcode() == ISD::Constant) ||
+ (OperRight.getOpcode() == ISD::Constant)) {
+ return NULL;
+ }
- case ISD::ADDE:
- case ISD::ADDC:
- AS = ISD::ADD;
- ASE = ISD::ADDE;
- ASC = ISD::ADDC;
- break;
-
- case ISD::SUB:
- if (InOp[0].getOpcode() == ISD::Constant &&
- InOp[1].getOpcode() == ISD::Constant) {
- ConstantSDNode *CST0 = dyn_cast<ConstantSDNode>(InOp[0]);
- ConstantSDNode *CST1 = dyn_cast<ConstantSDNode>(InOp[1]);
- return DAG.getConstant(CST0->getZExtValue() - CST1->getZExtValue(),
- MVT::i16);
- }
- break;
+ // These case are yet to be handled
+ return NULL;
+}
- case ISD::SUBE:
- case ISD::SUBC:
- AS = ISD::SUB;
- ASE = ISD::SUBE;
- ASC = ISD::SUBC;
- break;
- } // end switch.
-
- assert ((N->getValueType(0) == MVT::i16)
- && "expecting an MVT::i16 node for lowering");
- assert ((N->getOperand(0).getValueType() == MVT::i16)
- && (N->getOperand(1).getValueType() == MVT::i16)
- && "both inputs to addx/subx:i16 must be i16");
-
- for (i = 0; i < 2; i++) {
- if (InOp[i].getOpcode() == ISD::GlobalAddress) {
- // We don't want to lower subs/adds with global address yet.
- return SDValue();
- }
- else if (InOp[i].getOpcode() == ISD::Constant) {
- changed = true;
- ConstantSDNode *CST = dyn_cast<ConstantSDNode>(InOp[i]);
- LoOps[i] = DAG.getConstant(CST->getZExtValue() & 0xFF, MVT::i8);
- HiOps[i] = DAG.getConstant(CST->getZExtValue() >> 8, MVT::i8);
- }
- else if (InOp[i].getOpcode() == PIC16ISD::Package) {
- LoOps[i] = InOp[i].getOperand(0);
- HiOps[i] = InOp[i].getOperand(1);
+SDNode *PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) {
+ LoadSDNode *LD = dyn_cast<LoadSDNode>(SDValue(N, 0));
+ SDValue Chain = LD->getChain();
+ SDValue Ptr = LD->getBasePtr();
+
+ SDValue Load, Offset;
+ SDVTList Tys;
+ MVT VT, NewVT;
+ SDValue PtrLo, PtrHi;
+ unsigned LoadOffset;
+
+ // Legalize direct/indirect addresses. This will give the lo and hi parts
+ // of the address and the offset.
+ LegalizeAddress(Ptr, DAG, PtrLo, PtrHi, LoadOffset);
+
+ // Load from the pointer (direct address or FSR)
+ VT = N->getValueType(0);
+ unsigned NumLoads = VT.getSizeInBits() / 8;
+ std::vector<SDValue> PICLoads;
+ unsigned iter;
+ MVT MemVT = LD->getMemoryVT();
+ if(ISD::isNON_EXTLoad(N)) {
+ for (iter=0; iter<NumLoads ; ++iter) {
+ // Add the pointer offset if any
+ Offset = DAG.getConstant(iter + LoadOffset, MVT::i8);
+ Tys = DAG.getVTList(MVT::i8, MVT::Other);
+ Load = DAG.getNode(PIC16ISD::PIC16Load, Tys, Chain, PtrLo, PtrHi,
+ Offset);
+ PICLoads.push_back(Load);
}
- else if (InOp[i].getOpcode() == ISD::LOAD) {
- changed = true;
- // LowerLOAD returns a Package node or it may combine and return
- // anything else.
- SDValue lowered = LowerLOAD(InOp[i].getNode(), DAG, DCI);
-
- // So If LowerLOAD returns something other than Package,
- // then just call ADD again.
- if (lowered.getOpcode() != PIC16ISD::Package)
- return LowerADDSUB(N, DAG, DCI);
-
- LoOps[i] = lowered.getOperand(0);
- HiOps[i] = lowered.getOperand(1);
+ } else {
+ // If it is extended load then use PIC16Load for Memory Bytes
+ // and for all extended bytes perform action based on type of
+ // extention - i.e. SignExtendedLoad or ZeroExtendedLoad
+
+
+ // For extended loads this is the memory value type
+ // i.e. without any extension
+ MVT MemVT = LD->getMemoryVT();
+ unsigned MemBytes = MemVT.getSizeInBits() / 8;
+ unsigned ExtdBytes = VT.getSizeInBits() / 8;
+ Offset = DAG.getConstant(LoadOffset, MVT::i8);
+
+ Tys = DAG.getVTList(MVT::i8, MVT::Other);
+ // For MemBytes generate PIC16Load with proper offset
+ for (iter=0; iter<MemBytes; ++iter) {
+ // Add the pointer offset if any
+ Offset = DAG.getConstant(iter + LoadOffset, MVT::i8);
+ Load = DAG.getNode(PIC16ISD::PIC16Load, Tys, Chain, PtrLo, PtrHi,
+ Offset);
+ PICLoads.push_back(Load);
}
- else if ((InOp[i].getOpcode() == ISD::ADD) ||
- (InOp[i].getOpcode() == ISD::ADDE) ||
- (InOp[i].getOpcode() == ISD::ADDC) ||
- (InOp[i].getOpcode() == ISD::SUB) ||
- (InOp[i].getOpcode() == ISD::SUBE) ||
- (InOp[i].getOpcode() == ISD::SUBC)) {
- changed = true;
- // Must call LowerADDSUB recursively here,
- // LowerADDSUB returns a Package node.
- SDValue lowered = LowerADDSUB(InOp[i].getNode(), DAG, DCI);
-
- LoOps[i] = lowered.getOperand(0);
- HiOps[i] = lowered.getOperand(1);
- }
- else if (InOp[i].getOpcode() == ISD::SIGN_EXTEND) {
- // FIXME: I am just zero extending. for now.
- changed = true;
- LoOps[i] = InOp[i].getOperand(0);
- HiOps[i] = DAG.getConstant(0, MVT::i8);
+
+ // For SignExtendedLoad
+ if (ISD::isSEXTLoad(N)) {
+ // For all ExtdBytes use the Right Shifted(Arithmetic) Value of the
+ // highest MemByte
+ SDValue SRA = DAG.getNode(ISD::SRA, MVT::i8, Load,
+ DAG.getConstant(7, MVT::i8));
+ for (iter=MemBytes; iter<ExtdBytes; ++iter) {
+ PICLoads.push_back(SRA);
+ }
+ } else if (ISD::isZEXTLoad(N)) {
+ // ZeroExtendedLoad -- For all ExtdBytes use constant 0
+ SDValue ConstZero = DAG.getConstant(0, MVT::i8);
+ for (iter=MemBytes; iter<ExtdBytes; ++iter) {
+ PICLoads.push_back(ConstZero);
+ }
}
+ }
+ SDValue BP;
+
+ if (VT == MVT::i8) {
+ // Operand of Load is illegal -- Load itself is legal
+ return PICLoads[0].getNode();
+ }
+ else if (VT == MVT::i16) {
+ BP = DAG.getNode(ISD::BUILD_PAIR, VT, PICLoads[0], PICLoads[1]);
+ if (MemVT == MVT::i8)
+ Chain = getChain(PICLoads[0]);
+ else
+ Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(PICLoads[0]),
+ getChain(PICLoads[1]));
+ } else if (VT == MVT::i32) {
+ SDValue BPs[2];
+ BPs[0] = DAG.getNode(ISD::BUILD_PAIR, MVT::i16, PICLoads[0], PICLoads[1]);
+ BPs[1] = DAG.getNode(ISD::BUILD_PAIR, MVT::i16, PICLoads[2], PICLoads[3]);
+ BP = DAG.getNode(ISD::BUILD_PAIR, VT, BPs[0], BPs[1]);
+ if (MemVT == MVT::i8)
+ Chain = getChain(PICLoads[0]);
+ else if (MemVT == MVT::i16)
+ Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(PICLoads[0]),
+ getChain(PICLoads[1]));
else {
- DAG.setGraphColor(N, "blue");
- DAG.viewGraph();
- assert (0 && "not implemented yet");
+ SDValue Chains[2];
+ Chains[0] = DAG.getNode(ISD::TokenFactor, MVT::Other,
+ getChain(PICLoads[0]), getChain(PICLoads[1]));
+ Chains[1] = DAG.getNode(ISD::TokenFactor, MVT::Other,
+ getChain(PICLoads[2]), getChain(PICLoads[3]));
+ Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, Chains[0], Chains[1]);
}
- } // end for.
+ }
+ Tys = DAG.getVTList(VT, MVT::Other);
+ SDValue MergeV = DAG.getNode(ISD::MERGE_VALUES, Tys, BP, Chain);
+ return MergeV.getNode();
- assert (changed && "nothing changed while lowering SUBx/ADDx");
+}
- VTList = DAG.getVTList(MVT::i8, MVT::Flag);
- if (N->getOpcode() == ASE) {
- // We must take in the existing carry
- // if this node is part of an existing subx/addx sequence.
- LoOps[2] = N->getOperand(2).getValue(1);
- as1 = DAG.getNode (ASE, VTList, LoOps, 3);
- }
- else {
- as1 = DAG.getNode (ASC, VTList, LoOps, 2);
- }
- HiOps[2] = as1.getValue(1);
- as2 = DAG.getNode (ASE, VTList, HiOps, 3);
- // We must build a pair that also provides the carry from sube/adde.
- OutOps[0] = as1;
- OutOps[1] = as2;
- OutOps[2] = as2.getValue(1);
- // Breaking an original i16, so lets make the Package also an i16.
- if (N->getOpcode() == ASE) {
- VTList = DAG.getVTList(MVT::i16, MVT::Flag);
- retVal = DAG.getNode (PIC16ISD::Package, VTList, OutOps, 3);
- DCI.CombineTo (N, retVal, OutOps[2]);
- }
- else if (N->getOpcode() == ASC) {
- VTList = DAG.getVTList(MVT::i16, MVT::Flag);
- retVal = DAG.getNode (PIC16ISD::Package, VTList, OutOps, 2);
- DCI.CombineTo (N, retVal, OutOps[2]);
- }
- else if (N->getOpcode() == AS) {
- VTList = DAG.getVTList(MVT::i16);
- retVal = DAG.getNode (PIC16ISD::Package, VTList, OutOps, 2);
- DCI.CombineTo (N, retVal);
+SDNode *PIC16TargetLowering::ExpandShift(SDNode *N, SelectionDAG &DAG) {
+ SDValue Value = N->getOperand(0);
+ SDValue Amt = N->getOperand(1);
+ SDValue BCF, BCFInput;
+ SDVTList Tys;
+ SDValue ShfCom; // Shift Component - Lo component should be shifted
+ SDValue RotCom; // Rotate Component- Hi component should be rotated
+ PIC16ISD::NodeType ShfNode, RotNode;
+
+ // Currently handling Constant shift only
+ if (Amt.getOpcode() != ISD::Constant)
+ return NULL;
+
+ // Following code considers 16 bit left-shift only
+ if (N->getValueType(0) != MVT::i16)
+ return NULL;
+
+ if (N->getOpcode() == ISD::SHL) {
+ ShfNode = PIC16ISD::LSLF;
+ RotNode = PIC16ISD::RLF;
+ } else if (N->getOpcode() == ISD::SRL) {
+ ShfNode = PIC16ISD::LRLF;
+ RotNode = PIC16ISD::RRF;
}
+ unsigned ShiftAmt = dyn_cast<ConstantSDNode>(Amt)->getZExtValue();
+ SDValue StatusReg = DAG.getRegister(PIC16::STATUS, MVT::i8);
+ // 0th Bit in StatusReg is CarryBit
+ SDValue CarryBit= DAG.getConstant(0, MVT::i8);
- return retVal;
-}
+ GetExpandedParts(Value, DAG, ShfCom, RotCom);
+ BCFInput = DAG.getNode(PIC16ISD::Dummy, MVT::Flag);
+ Tys = DAG.getVTList(MVT::i8, MVT::Flag);
+ for (unsigned i=0;i<ShiftAmt;i++) {
+ BCF = DAG.getNode(PIC16ISD::BCF, MVT::Flag, StatusReg, CarryBit, BCFInput);
-//===----------------------------------------------------------------------===//
-// Calling Convention Implementation
-//===----------------------------------------------------------------------===//
+ // Following are Two-Address Instructions
+ ShfCom = DAG.getNode(ShfNode, Tys, ShfCom, BCF);
+ RotCom = DAG.getNode(RotNode, Tys, RotCom, ShfCom.getValue(1));
-#include "PIC16GenCallingConv.inc"
+ BCFInput = RotCom.getValue(1);
+ }
-//===----------------------------------------------------------------------===//
-// CALL Calling Convention Implementation
-//===----------------------------------------------------------------------===//
+ SDValue BP = DAG.getNode(ISD::BUILD_PAIR, N->getValueType(0), ShfCom, RotCom);
+ return BP.getNode();
+}
+
+SDValue PIC16TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
+ switch (Op.getOpcode()) {
+ case ISD::FORMAL_ARGUMENTS:
+ return LowerFORMAL_ARGUMENTS(Op, DAG);
+ case ISD::ADDC:
+ return LowerADDC(Op, DAG);
+ case ISD::ADDE:
+ return LowerADDE(Op, DAG);
+ case ISD::SUBE:
+ return LowerSUBE(Op, DAG);
+ case ISD::SUBC:
+ return LowerSUBC(Op, DAG);
+ case ISD::LOAD:
+ return SDValue(ExpandLoad(Op.getNode(), DAG), Op.getResNo());
+ case ISD::STORE:
+ return SDValue(ExpandStore(Op.getNode(), DAG), Op.getResNo());
+ case ISD::SHL:
+ return SDValue(ExpandShift(Op.getNode(), DAG), Op.getResNo());
+ }
+ return SDValue();
+}
+SDValue PIC16TargetLowering::ConvertToMemOperand(SDValue Op,
+ SelectionDAG &DAG) {
+
+ assert (Op.getValueType() == MVT::i8
+ && "illegal value type to store on stack.");
+
+ MachineFunction &MF = DAG.getMachineFunction();
+ const Function *Func = MF.getFunction();
+ const std::string FuncName = Func->getName();
+
+ char *tmpName = new char [strlen(FuncName.c_str()) + 6];
+
+ // Put the value on stack.
+ // Get a stack slot index and convert to es.
+ int FI = MF.getFrameInfo()->CreateStackObject(1, 1);
+ sprintf(tmpName, "%s.tmp", FuncName.c_str());
+ SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
+
+ // Store the value to ES.
+ SDValue Store = DAG.getNode (PIC16ISD::PIC16Store, MVT::Other,
+ DAG.getEntryNode(),
+ Op, ES,
+ DAG.getConstant (1, MVT::i8), // Banksel.
+ DAG.getConstant (FI, MVT::i8));
+
+ // Load the value from ES.
+ SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other);
+ SDValue Load = DAG.getNode(PIC16ISD::PIC16Load, Tys, Store,
+ ES, DAG.getConstant (1, MVT::i8),
+ DAG.getConstant (FI, MVT::i8));
+
+ return Load.getValue(0);
+}
-//===----------------------------------------------------------------------===//
-// FORMAL_ARGUMENTS Calling Convention Implementation
-//===----------------------------------------------------------------------===//
-SDValue PIC16TargetLowering::
-LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG)
-{
- SmallVector<SDValue, 8> ArgValues;
- SDValue Root = Op.getOperand(0);
+SDValue PIC16TargetLowering:: LowerADDC(SDValue Op, SelectionDAG &DAG) {
+ // We should have handled larger operands in type legalizer itself.
+ assert (Op.getValueType() == MVT::i8 && "illegal addc to lower");
- // Return the new list of results.
- // FIXME: Just copy right now.
- ArgValues.push_back(Root);
+ // Nothing to do if the one of the operands is already a load.
+ if (Op.getOperand(0).getOpcode() == PIC16ISD::PIC16Load
+ || Op.getOperand(1).getOpcode() == PIC16ISD::PIC16Load)
+ return SDValue();
- return DAG.getMergeValues(Op.getNode()->getVTList(), &ArgValues[0],
- ArgValues.size()).getValue(Op.getResNo());
+ // Put one value on stack.
+ SDValue NewVal = ConvertToMemOperand (Op.getOperand(1), DAG);
+
+ SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag);
+ return DAG.getNode(ISD::ADDC, Tys, Op.getOperand(0), NewVal);
}
+SDValue PIC16TargetLowering:: LowerADDE(SDValue Op, SelectionDAG &DAG) {
+ // We should have handled larger operands in type legalizer itself.
+ assert (Op.getValueType() == MVT::i8 && "illegal adde to lower");
-//===----------------------------------------------------------------------===//
-// Return Value Calling Convention Implementation
-//===----------------------------------------------------------------------===//
+ // Nothing to do if the one of the operands is already a load.
+ if (Op.getOperand(0).getOpcode() == PIC16ISD::PIC16Load
+ || Op.getOperand(1).getOpcode() == PIC16ISD::PIC16Load)
+ return SDValue();
-//===----------------------------------------------------------------------===//
-// PIC16 Inline Assembly Support
-//===----------------------------------------------------------------------===//
+ // Put one value on stack.
+ SDValue NewVal = ConvertToMemOperand (Op.getOperand(1), DAG);
+
+ SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag);
+ return DAG.getNode(ISD::ADDE, Tys, Op.getOperand(0), NewVal,
+ Op.getOperand(2));
+}
-//===----------------------------------------------------------------------===//
-// Target Optimization Hooks
-//===----------------------------------------------------------------------===//
+SDValue PIC16TargetLowering:: LowerSUBC(SDValue Op, SelectionDAG &DAG) {
+ // We should have handled larger operands in type legalizer itself.
+ assert (Op.getValueType() == MVT::i8 && "illegal subc to lower");
-SDValue PIC16TargetLowering::PerformDAGCombine(SDNode *N,
- DAGCombinerInfo &DCI) const
-{
- int i;
- ConstantSDNode *CST;
- SelectionDAG &DAG = DCI.DAG;
+ // Nothing to do if the first operand is already a load.
+ if (Op.getOperand(0).getOpcode() == PIC16ISD::PIC16Load)
+ return SDValue();
- switch (N->getOpcode()) {
- default:
- break;
+ // Put first operand on stack.
+ SDValue NewVal = ConvertToMemOperand (Op.getOperand(0), DAG);
- case PIC16ISD::Package:
- DOUT << "==== combining PIC16ISD::Package\n";
- return SDValue();
+ SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag);
+ return DAG.getNode(ISD::SUBC, Tys, NewVal, Op.getOperand(1));
+}
- case ISD::ADD:
- case ISD::SUB:
- if ((N->getOperand(0).getOpcode() == ISD::GlobalAddress) ||
- (N->getOperand(0).getOpcode() == ISD::FrameIndex)) {
- // Do not touch pointer adds.
- return SDValue ();
- }
- break;
-
- case ISD::ADDE :
- case ISD::ADDC :
- case ISD::SUBE :
- case ISD::SUBC :
- if (N->getValueType(0) == MVT::i16) {
- SDValue retVal = LowerADDSUB(N, DAG,DCI);
- // LowerADDSUB has already combined the result,
- // so we just return nothing to avoid assertion failure from llvm
- // if N has been deleted already.
- return SDValue();
- }
- else if (N->getValueType(0) == MVT::i8) {
- // Sanity check ....
- for (int i=0; i<2; i++) {
- if (N->getOperand (i).getOpcode() == PIC16ISD::Package) {
- assert (0 &&
- "don't want to have PIC16ISD::Package as intput to add:i8");
- }
- }
- }
- break;
-
- // FIXME: split this large chunk of code.
- case ISD::STORE :
- {
- SDValue Chain = N->getOperand(0);
- SDValue Src = N->getOperand(1);
- SDValue Dest = N->getOperand(2);
- unsigned int DstOff = 0;
- int NUM_STORES = 0;
- SDValue Stores[6];
-
- // if source operand is expected to be extended to
- // some higher type then - remove this extension
- // SDNode and do the extension manually
- if ((Src.getOpcode() == ISD::ANY_EXTEND) ||
- (Src.getOpcode() == ISD::SIGN_EXTEND) ||
- (Src.getOpcode() == ISD::ZERO_EXTEND)) {
- Src = Src.getNode()->getOperand(0);
- Stores[0] = DAG.getStore(Chain, Src, Dest, NULL,0);
- return Stores[0];
- }
+SDValue PIC16TargetLowering:: LowerSUBE(SDValue Op, SelectionDAG &DAG) {
+ // We should have handled larger operands in type legalizer itself.
+ assert (Op.getValueType() == MVT::i8 && "illegal sube to lower");
- switch(Src.getValueType().getSimpleVT()) {
- default:
- assert(false && "Invalid value type!");
+ // Nothing to do if the first operand is already a load.
+ if (Op.getOperand(0).getOpcode() == PIC16ISD::PIC16Load)
+ return SDValue();
- case MVT::i8:
- break;
+ // Put first operand on stack.
+ SDValue NewVal = ConvertToMemOperand (Op.getOperand(0), DAG);
- case MVT::i16:
- NUM_STORES = 2;
- break;
+ SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag);
+ return DAG.getNode(ISD::SUBE, Tys, NewVal, Op.getOperand(1),
+ Op.getOperand(2));
+}
- case MVT::i32:
- NUM_STORES = 4;
- break;
+// LowerFORMAL_ARGUMENTS - In Lowering FORMAL ARGUMENTS - MERGE_VALUES nodes
+// is returned. MERGE_VALUES nodes number of operands and number of values are
+// equal. Therefore to construct MERGE_VALUE node, UNDEF nodes equal to the
+// number of arguments of function have been created.
- case MVT::i64:
- NUM_STORES = 8;
- break;
- }
+SDValue PIC16TargetLowering:: LowerFORMAL_ARGUMENTS(SDValue Op,
+ SelectionDAG &DAG) {
+ SmallVector<SDValue, 8> ArgValues;
+ unsigned NumArgs = Op.getNumOperands() - 3;
- if (isa<GlobalAddressSDNode>(Dest) && isa<LoadSDNode>(Src) &&
- (Src.getValueType() != MVT::i8)) {
- //create direct addressing a = b
- Chain = Src.getOperand(0);
- for (i=0; i<NUM_STORES; i++) {
- SDValue ADN = DAG.getNode(ISD::ADD, MVT::i16, Src.getOperand(1),
- DAG.getConstant(DstOff, MVT::i16));
- SDValue LDN = DAG.getLoad(MVT::i8, Chain, ADN, NULL, 0);
- SDValue DSTADDR = DAG.getNode(ISD::ADD, MVT::i16, Dest,
- DAG.getConstant(DstOff, MVT::i16));
- Stores[i] = DAG.getStore(Chain, LDN, DSTADDR, NULL, 0);
- Chain = Stores[i];
- DstOff += 1;
- }
-
- Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], i);
- return Chain;
- }
- else if (isa<GlobalAddressSDNode>(Dest) && isa<ConstantSDNode>(Src)
- && (Src.getValueType() != MVT::i8)) {
- //create direct addressing a = CONST
- CST = dyn_cast<ConstantSDNode>(Src);
- for (i = 0; i < NUM_STORES; i++) {
- SDValue CNST = DAG.getConstant(CST->getZExtValue() >> i*8, MVT::i8);
- SDValue ADN = DAG.getNode(ISD::ADD, MVT::i16, Dest,
- DAG.getConstant(DstOff, MVT::i16));
- Stores[i] = DAG.getStore(Chain, CNST, ADN, NULL, 0);
- Chain = Stores[i];
- DstOff += 1;
- }
-
- Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], i);
- return Chain;
- }
- else if (isa<LoadSDNode>(Dest) && isa<ConstantSDNode>(Src)
- && (Src.getValueType() != MVT::i8)) {
- // Create indirect addressing.
- CST = dyn_cast<ConstantSDNode>(Src);
- Chain = Dest.getOperand(0);
- SDValue Load;
- Load = DAG.getLoad(MVT::i16, Chain,Dest.getOperand(1), NULL, 0);
- Chain = Load.getValue(1);
- for (i=0; i<NUM_STORES; i++) {
- SDValue CNST = DAG.getConstant(CST->getZExtValue() >> i*8, MVT::i8);
- Stores[i] = DAG.getStore(Chain, CNST, Load, NULL, 0);
- Chain = Stores[i];
- DstOff += 1;
- }
-
- Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], i);
- return Chain;
- }
- else if (isa<LoadSDNode>(Dest) && isa<GlobalAddressSDNode>(Src)) {
- // GlobalAddressSDNode *GAD = dyn_cast<GlobalAddressSDNode>(Src);
- return SDValue();
- }
- else if (Src.getOpcode() == PIC16ISD::Package) {
- StoreSDNode *st = dyn_cast<StoreSDNode>(N);
- SDValue toWorkList, retVal;
- Chain = N->getOperand(0);
-
- if (st->isTruncatingStore()) {
- retVal = DAG.getStore(Chain, Src.getOperand(0), Dest, NULL, 0);
- }
- else {
- toWorkList = DAG.getNode(ISD::ADD, MVT::i16, Dest,
- DAG.getConstant(1, MVT::i16));
- Stores[1] = DAG.getStore(Chain, Src.getOperand(0), Dest, NULL, 0);
- Stores[0] = DAG.getStore(Chain, Src.getOperand(1), toWorkList, NULL,
- 0);
-
- // We want to merge sequence of add with constant to one add and a
- // constant, so add the ADD node to worklist to have llvm do that
- // automatically.
- DCI.AddToWorklist(toWorkList.getNode());
-
- // We don't need the Package so add to worklist so llvm deletes it
- DCI.AddToWorklist(Src.getNode());
- retVal = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], 2);
- }
-
- return retVal;
- }
- else if (Src.getOpcode() == ISD::TRUNCATE) {
- }
- else {
- }
- } // end ISD::STORE.
- break;
-
- case ISD::LOAD :
- {
- SDValue Ptr = N->getOperand(1);
- if (Ptr.getOpcode() == PIC16ISD::Package) {
- assert (0 && "not implemented yet");
- }
- }
- break;
- } // end switch.
+ // Creating UNDEF nodes to meet the requirement of MERGE_VALUES node.
+ for(unsigned i = 0 ; i<NumArgs ; i++) {
+ SDValue TempNode = DAG.getNode(ISD::UNDEF, Op.getNode()->getValueType(i));
+ ArgValues.push_back(TempNode);
+ }
- return SDValue();
+ ArgValues.push_back(Op.getOperand(0));
+ return DAG.getNode(ISD::MERGE_VALUES, Op.getNode()->getVTList(),
+ &ArgValues[0],
+ ArgValues.size()).getValue(Op.getResNo());
}
-//===----------------------------------------------------------------------===//
-// Utility functions
-//===----------------------------------------------------------------------===//
-const SDValue *PIC16TargetLowering::
-findLoadi8(const SDValue &Src, SelectionDAG &DAG) const
-{
- unsigned int i;
- if ((Src.getOpcode() == ISD::LOAD) && (Src.getValueType() == MVT::i8))
- return &Src;
- for (i=0; i<Src.getNumOperands(); i++) {
- const SDValue *retVal = findLoadi8(Src.getOperand(i),DAG);
- if (retVal) return retVal;
+// Perform DAGCombine of PIC16Load
+SDValue PIC16TargetLowering::
+PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const {
+ SelectionDAG &DAG = DCI.DAG;
+ SDValue Chain = N->getOperand(0);
+ if (N->hasNUsesOfValue(0, 0)) {
+ DAG.ReplaceAllUsesOfValueWith(SDValue(N,1), Chain);
}
+ return SDValue();
+}
- return NULL;
+
+SDValue PIC16TargetLowering::PerformDAGCombine(SDNode *N,
+ DAGCombinerInfo &DCI) const {
+ switch (N->getOpcode()) {
+ case PIC16ISD::PIC16Load:
+ return PerformPIC16LoadCombine(N, DCI);
+ }
+ return SDValue();
}
diff --git a/lib/Target/PIC16/PIC16ISelLowering.h b/lib/Target/PIC16/PIC16ISelLowering.h
index e14a0c2..dfe5b5f 100644
--- a/lib/Target/PIC16/PIC16ISelLowering.h
+++ b/lib/Target/PIC16/PIC16ISelLowering.h
@@ -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,
-
- // 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
+ 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
+ };
+
+ // 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;
-
- // utility function.
- const SDValue *findLoadi8(const SDValue &Src, SelectionDAG &DAG) 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);
+
+ 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
diff --git a/lib/Target/PIC16/PIC16InstrFormats.td b/lib/Target/PIC16/PIC16InstrFormats.td
index e8ecf6a..e213ea8 100644
--- a/lib/Target/PIC16/PIC16InstrFormats.td
+++ b/lib/Target/PIC16/PIC16InstrFormats.td
@@ -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;
}
diff --git a/lib/Target/PIC16/PIC16InstrInfo.cpp b/lib/Target/PIC16/PIC16InstrInfo.cpp
index 7cb2379..d70ebc6 100644
--- a/lib/Target/PIC16/PIC16InstrInfo.cpp
+++ b/lib/Target/PIC16/PIC16InstrInfo.cpp
@@ -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();
- }
+/// 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.
+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;
}
-/// 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
+/// 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::
-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::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 {
+
+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);
-
- 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.
+ sprintf(tmpName, "%s.tmp", FuncName.c_str());
+
+ // 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);
-
- 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.
+ sprintf(tmpName, "%s.tmp", FuncName.c_str());
+
+ // 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;
}
diff --git a/lib/Target/PIC16/PIC16InstrInfo.h b/lib/Target/PIC16/PIC16InstrInfo.h
index 250142d..bd3e488 100644
--- a/lib/Target/PIC16/PIC16InstrInfo.h
+++ b/lib/Target/PIC16/PIC16InstrInfo.h
@@ -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;
};
diff --git a/lib/Target/PIC16/PIC16InstrInfo.td b/lib/Target/PIC16/PIC16InstrInfo.td
index a0e7f7c..0335e92 100644
--- a/lib/Target/PIC16/PIC16InstrInfo.td
+++ b/lib/Target/PIC16/PIC16InstrInfo.td
@@ -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.
+//
//===----------------------------------------------------------------------===//
-include "PIC16InstrFormats.td"
-
//===----------------------------------------------------------------------===//
-// PIC16 profiles and nodes
+// PIC16 Specific Type Constraints.
//===----------------------------------------------------------------------===//
+class SDTCisI8<int OpNum> : SDTCisVT<OpNum, i8>;
+class SDTCisI16<int OpNum> : SDTCisVT<OpNum, i16>;
//===----------------------------------------------------------------------===//
-// PIC16 addressing mode.
+// PIC16 Specific Type Profiles.
//===----------------------------------------------------------------------===//
-// 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>;
+// 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>]>;
-// 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]>;
+// 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>]>;
-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)))]>;
+// 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>]>;
//===----------------------------------------------------------------------===//
-// Instruction definition
+// PIC16 addressing modes matching via DAG.
//===----------------------------------------------------------------------===//
+def diraddr : ComplexPattern<i8, 1, "SelectDirectAddr", [], []>;
//===----------------------------------------------------------------------===//
-// PIC16I Instructions
+// PIC16 Specific Node Definitions.
//===----------------------------------------------------------------------===//
+def PIC16callseq_start : SDNode<"ISD::CALLSEQ_START", SDTI8VoidOp,
+ [SDNPHasChain, SDNPOutFlag]>;
+def PIC16callseq_end : SDNode<"ISD::CALLSEQ_END", SDTI8VoidOp,
+ [SDNPHasChain, SDNPOutFlag]>;
-// 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>;
-
-let isReMaterializable = 1 in {
-def MOVLW : MovLit<0x24, "movlw">;
-}
-
-// Load/Store
-def LFSR1 : LoadInDirect <0x4, "lfsr", load>;
-
-let isReMaterializable = 1 in {
-def MOVF : LoadDirect <0x23, "movf", load>;
-}
-
-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>;
+// Low 8-bits of GlobalAddress.
+def PIC16Lo : SDNode<"PIC16ISD::Lo", SDTI8UnaryOp>;
-def SUBWF : Arith1M<0x07, "subwf", sub>;
-def SUBFW : Arith1R<0x08, "subfw", sub>;
+// High 8-bits of GlobalAddress.
+def PIC16Hi : SDNode<"PIC16ISD::Hi", SDTI8UnaryOp>;
-def SUBWFE : Arith1M<0x09, "subwfe", sube>;
-def SUBFWE : Arith1R<0x0a, "subfwe", sube>;
+// 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>;
-def SUBWFC : Arith1M<0x0b, "subwfc", subc>;
-def SUBFWC : Arith1R<0x0d, "subfwc", subc>;
+// Node to generate Bank Select for a GlobalAddress.
+def Banksel : SDNode<"PIC16ISD::Banksel", SDTI8UnaryOp>;
-def SUBRFW : Arith2R<0x08, "subfw", sub>;
+// Node to match a direct store operation.
+def PIC16Store : SDNode<"PIC16ISD::PIC16Store", SDT_PIC16Store, [SDNPHasChain]>;
-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>;
+// Node to match a direct load operation.
+def PIC16Load : SDNode<"PIC16ISD::PIC16Load", SDT_PIC16Load, [SDNPHasChain]>;
+//===----------------------------------------------------------------------===//
+// PIC16 Operand Definitions.
+//===----------------------------------------------------------------------===//
+def i8mem : Operand<i8>;
-/* 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]>;
+//===----------------------------------------------------------------------===//
+// PIC16 Instructions.
+//===----------------------------------------------------------------------===//
+include "PIC16InstrFormats.td"
-def PIC16BTFSC : SDNode<"PIC16ISD::BTFSC",SDT_PIC16Branch,
- [SDNPHasChain, SDNPInFlag]>;
+// Pseudo-instructions.
+def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i8imm:$amt),
+ "!ADJCALLSTACKDOWN $amt",
+ [(PIC16callseq_start imm:$amt)]>;
-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 ADJCALLSTACKUP : Pseudo<(outs), (ins i8imm:$amt),
+ "!ADJCALLSTACKUP $amt",
+ [(PIC16callseq_end imm:$amt)]>;
-def BTFSS : InstrBitTestCC<0x1,"btfss",PIC16BTFSS>;
-def BTFSC : InstrBitTestCC<0x1,"btfsc",PIC16BTFSC>;
+//-----------------------------------
+// Vaious movlw insn patterns.
+//-----------------------------------
+let isReMaterializable = 1 in {
+// 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))]>;
+}
+//-------------------
+// 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 banksel :
+ Pseudo<(outs BSR:$dst),
+ (ins i8mem:$ptr),
+ "banksel $ptr",
+ [(set BSR:$dst, (Banksel tglobaladdr:$ptr))]>;
+}
+// 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)>;
diff --git a/lib/Target/PIC16/PIC16RegisterInfo.cpp b/lib/Target/PIC16/PIC16RegisterInfo.cpp
index d05f62c..838e848 100644
--- a/lib/Target/PIC16/PIC16RegisterInfo.cpp
+++ b/lib/Target/PIC16/PIC16RegisterInfo.cpp
@@ -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) {}
-
-/// 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;
-}
+ TII(tii),
+ ST(st) {}
-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);
-}
-
-// 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);
-}
+eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
+ RegScavenger *RS) const
+{ /* NOT YET IMPLEMENTED */ }
-void PIC16RegisterInfo::
-emitPrologue(MachineFunction &MF) const
-{
-}
+void PIC16RegisterInfo::emitPrologue(MachineFunction &MF) const
+{ /* NOT YET IMPLEMENTED */ }
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;
-}
+emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
+{ /* NOT YET IMPLEMENTED */ }
-unsigned PIC16RegisterInfo::
-getFrameRegister(MachineFunction &MF) const {
- return PIC16::STKPTR;
+int PIC16RegisterInfo::
+getDwarfRegNum(unsigned RegNum, bool isEH) const {
+ assert(0 && "Not keeping track of debug information yet!!");
+ return -1;
}
-unsigned PIC16RegisterInfo::
-getEHExceptionRegister() const {
- assert(0 && "What is the exception register");
+unsigned PIC16RegisterInfo::getFrameRegister(MachineFunction &MF) const {
+ assert(0 && "PIC16 Does not have any frame register");
return 0;
}
-unsigned PIC16RegisterInfo::
-getEHHandlerRegister() const {
- assert(0 && "What is the exception handler register");
+unsigned PIC16RegisterInfo::getRARegister() const {
+ assert(0 && "PIC16 Does not have any return address register");
return 0;
}
-int PIC16RegisterInfo::
-getDwarfRegNum(unsigned RegNum, bool isEH) const {
- assert(0 && "What is the dwarf register number");
- return -1;
-}
-
-
-#include "PIC16GenRegisterInfo.inc"
diff --git a/lib/Target/PIC16/PIC16RegisterInfo.h b/lib/Target/PIC16/PIC16RegisterInfo.h
index 8a85adc..aaabb41 100644
--- a/lib/Target/PIC16/PIC16RegisterInfo.h
+++ b/lib/Target/PIC16/PIC16RegisterInfo.h
@@ -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;
-
-
- const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const;
-
- const TargetRegisterClass* const*
- getCalleeSavedRegClasses(const MachineFunction* MF = 0) const;
-
- BitVector getReservedRegs(const MachineFunction &MF) const;
-
- bool hasFP(const MachineFunction &MF) const;
+ virtual BitVector getReservedRegs(const MachineFunction &MF) const;
+ virtual 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;
+ virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI,
+ int SPAdj, RegScavenger *RS=NULL) const;
- /// Exception handling queries.
- unsigned getEHExceptionRegister() const;
- unsigned getEHHandlerRegister() 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;
- int getDwarfRegNum(unsigned RegNum, bool isEH) const;
};
} // end namespace llvm
diff --git a/lib/Target/PIC16/PIC16RegisterInfo.td b/lib/Target/PIC16/PIC16RegisterInfo.td
index 21cc3e5..938974f 100644
--- a/lib/Target/PIC16/PIC16RegisterInfo.td
+++ b/lib/Target/PIC16/PIC16RegisterInfo.td
@@ -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;
-}
-
-// CPU GPR Registers
-def FSR0 : PIC16GPRReg< 0, "FSR0">, DwarfRegNum<[0]>;
-def FSR1 : PIC16GPRReg< 1, "FSR1">, DwarfRegNum<[1]>;
+// PIC16 Registers.
+def W : PIC16Reg<"W">;
+def FSR0 : PIC16Reg<"FSR0">;
+def FSR1 : PIC16Reg<"FSR1">;
+def BS : PIC16Reg<"BS">;
-// 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();
- }
- }];
-}
+def STATUS : PIC16Reg<"STATUS">;
-def WREG : PIC16GPRReg< 0, "WREG">, DwarfRegNum<[0]>;
-
-// 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();
- }
- }];
-}
+// 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 STATUSREG : PIC16GPRReg<2, "STATUS">, DwarfRegNum<[0]>;
+def STATUSR: RegisterClass<"PIC16", [i8], 8, [STATUS]>;
-// 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();
- }
- }];
-}
diff --git a/lib/Target/PIC16/PIC16Subtarget.cpp b/lib/Target/PIC16/PIC16Subtarget.cpp
index b7ebf94..db8a5d8 100644
--- a/lib/Target/PIC16/PIC16Subtarget.cpp
+++ b/lib/Target/PIC16/PIC16Subtarget.cpp
@@ -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";
diff --git a/lib/Target/PIC16/PIC16Subtarget.h b/lib/Target/PIC16/PIC16Subtarget.h
index d7cb239..c6eb711 100644
--- a/lib/Target/PIC16/PIC16Subtarget.h
+++ b/lib/Target/PIC16/PIC16Subtarget.h
@@ -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
diff --git a/lib/Target/PIC16/PIC16TargetAsmInfo.cpp b/lib/Target/PIC16/PIC16TargetAsmInfo.cpp
index 91dcbe3..4dcd41a 100644
--- a/lib/Target/PIC16/PIC16TargetAsmInfo.cpp
+++ b/lib/Target/PIC16/PIC16TargetAsmInfo.cpp
@@ -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;
}
diff --git a/lib/Target/PIC16/PIC16TargetAsmInfo.h b/lib/Target/PIC16/PIC16TargetAsmInfo.h
index 1401bab..680c8e7 100644
--- a/lib/Target/PIC16/PIC16TargetAsmInfo.h
+++ b/lib/Target/PIC16/PIC16TargetAsmInfo.h
@@ -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
diff --git a/lib/Target/PIC16/PIC16TargetMachine.cpp b/lib/Target/PIC16/PIC16TargetMachine.cpp
index f2ddad1..f3a96f7 100644
--- a/lib/Target/PIC16/PIC16TargetMachine.cpp
+++ b/lib/Target/PIC16/PIC16TargetMachine.cpp
@@ -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;
}
+
diff --git a/lib/Target/PIC16/PIC16TargetMachine.h b/lib/Target/PIC16/PIC16TargetMachine.h
index bf0642f..85e14c1 100644
--- a/lib/Target/PIC16/PIC16TargetMachine.h
+++ b/lib/Target/PIC16/PIC16TargetMachine.h
@@ -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(); }
-
+ 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