aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/Target/PIC16/Makefile21
-rw-r--r--lib/Target/PIC16/PIC16.h38
-rw-r--r--lib/Target/PIC16/PIC16.td46
-rw-r--r--lib/Target/PIC16/PIC16AsmPrinter.cpp569
-rw-r--r--lib/Target/PIC16/PIC16CallingConv.td17
-rw-r--r--lib/Target/PIC16/PIC16ConstantPoolValue.cpp88
-rw-r--r--lib/Target/PIC16/PIC16ConstantPoolValue.h75
-rw-r--r--lib/Target/PIC16/PIC16ISelDAGToDAG.cpp291
-rw-r--r--lib/Target/PIC16/PIC16ISelLowering.cpp801
-rw-r--r--lib/Target/PIC16/PIC16ISelLowering.h92
-rw-r--r--lib/Target/PIC16/PIC16InstrFormats.td112
-rw-r--r--lib/Target/PIC16/PIC16InstrInfo.cpp143
-rw-r--r--lib/Target/PIC16/PIC16InstrInfo.h78
-rw-r--r--lib/Target/PIC16/PIC16InstrInfo.td302
-rw-r--r--lib/Target/PIC16/PIC16RegisterInfo.cpp223
-rw-r--r--lib/Target/PIC16/PIC16RegisterInfo.h86
-rw-r--r--lib/Target/PIC16/PIC16RegisterInfo.td84
-rw-r--r--lib/Target/PIC16/PIC16Subtarget.cpp27
-rw-r--r--lib/Target/PIC16/PIC16Subtarget.h41
-rw-r--r--lib/Target/PIC16/PIC16TargetAsmInfo.cpp26
-rw-r--r--lib/Target/PIC16/PIC16TargetAsmInfo.h30
-rw-r--r--lib/Target/PIC16/PIC16TargetMachine.cpp72
-rw-r--r--lib/Target/PIC16/PIC16TargetMachine.h61
23 files changed, 3323 insertions, 0 deletions
diff --git a/lib/Target/PIC16/Makefile b/lib/Target/PIC16/Makefile
new file mode 100644
index 0000000..c429324
--- /dev/null
+++ b/lib/Target/PIC16/Makefile
@@ -0,0 +1,21 @@
+##===- lib/Target/PIC16/Makefile ---------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+LEVEL = ../../..
+LIBRARYNAME = LLVMPIC16
+TARGET = PIC16
+
+# Make sure that tblgen is run, first thing.
+BUILT_SOURCES = PIC16GenRegisterInfo.h.inc PIC16GenRegisterNames.inc \
+ PIC16GenRegisterInfo.inc PIC16GenInstrNames.inc \
+ PIC16GenInstrInfo.inc PIC16GenAsmWriter.inc \
+ PIC16GenDAGISel.inc PIC16GenCallingConv.inc \
+ PIC16GenSubtarget.inc
+
+include $(LEVEL)/Makefile.common
+
diff --git a/lib/Target/PIC16/PIC16.h b/lib/Target/PIC16/PIC16.h
new file mode 100644
index 0000000..5c2a4cc
--- /dev/null
+++ b/lib/Target/PIC16/PIC16.h
@@ -0,0 +1,38 @@
+//===-- PIC16.h - Top-level interface for PIC16 representation --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the entry points for global functions defined in
+// the LLVM PIC16 back-end.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TARGET_PIC16_H
+#define TARGET_PIC16_H
+
+#include <iosfwd>
+
+namespace llvm {
+ class PIC16TargetMachine;
+ class FunctionPassManager;
+ class FunctionPass;
+ class MachineCodeEmitter;
+
+ FunctionPass *createPIC16ISelDag(PIC16TargetMachine &TM);
+ FunctionPass *createPIC16CodePrinterPass(std::ostream &OS,
+ PIC16TargetMachine &TM);
+} // end namespace llvm;
+
+// Defines symbolic names for PIC16 registers. This defines a mapping from
+// register name to register number.
+#include "PIC16GenRegisterNames.inc"
+
+// Defines symbolic names for the PIC16 instructions.
+#include "PIC16GenInstrNames.inc"
+
+#endif
diff --git a/lib/Target/PIC16/PIC16.td b/lib/Target/PIC16/PIC16.td
new file mode 100644
index 0000000..0ab4a34
--- /dev/null
+++ b/lib/Target/PIC16/PIC16.td
@@ -0,0 +1,46 @@
+//===- PIC16.td - Describe the PIC16 Target Machine -----------*- tblgen -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This is the top level entry point for the PIC16 target.
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Target-independent interfaces
+//===----------------------------------------------------------------------===//
+
+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">;
+
+//===----------------------------------------------------------------------===//
+// PIC16 processors supported.
+//===----------------------------------------------------------------------===//
+
+def : Processor<"generic", NoItineraries, []>;
+
+def PIC16 : Target {
+ let InstructionSet = PIC16InstrInfo;
+}
+
diff --git a/lib/Target/PIC16/PIC16AsmPrinter.cpp b/lib/Target/PIC16/PIC16AsmPrinter.cpp
new file mode 100644
index 0000000..151fafc
--- /dev/null
+++ b/lib/Target/PIC16/PIC16AsmPrinter.cpp
@@ -0,0 +1,569 @@
+//===-- PIC16AsmPrinter.cpp - PIC16 LLVM assembly writer ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a printer that converts from our internal representation
+// of machine-dependent LLVM code to PIC16 assembly language.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "asm-printer"
+#include "PIC16.h"
+#include "PIC16TargetMachine.h"
+#include "PIC16ConstantPoolValue.h"
+#include "PIC16InstrInfo.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Module.h"
+#include "llvm/ADT/SetVector.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/Target/TargetAsmInfo.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include <cctype>
+
+using namespace llvm;
+
+STATISTIC(EmittedInsts, "Number of machine instrs printed");
+
+namespace {
+ struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter {
+ PIC16AsmPrinter(std::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(std::ostream &o,
+ PIC16TargetMachine &tm) {
+ return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo());
+}
+
+void PIC16AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const
+{
+ // 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);
+}
+
+/// Emit the directives used by ASM on the start of functions
+void PIC16AsmPrinter:: emitFunctionStart(MachineFunction &MF)
+{
+ // Print out the label for the function.
+ const Function *F = MF.getFunction();
+ MachineFrameInfo *FrameInfo = MF.getFrameInfo();
+ if (FrameInfo->hasStackObjects()) {
+ int indexBegin = FrameInfo->getObjectIndexBegin();
+ int indexEnd = FrameInfo->getObjectIndexEnd();
+ while (indexBegin<indexEnd) {
+ if (indexBegin ==0)
+ SwitchToDataOvrSection(F->getParent()->getModuleIdentifier().c_str(),
+ F);
+
+ O << "\t\t" << CurrentFnName << "_" << indexBegin << " " << "RES"
+ << " " << FrameInfo->getObjectSize(indexBegin) << "\n" ;
+ indexBegin++;
+ }
+ }
+ SwitchToTextSection(CurrentFnName.c_str(), F);
+ O << "_" << CurrentFnName << ":" ;
+ O << "\n";
+}
+
+
+/// runOnMachineFunction - This uses the printInstruction()
+/// method to print assembly for each instruction.
+///
+bool PIC16AsmPrinter::
+runOnMachineFunction(MachineFunction &MF)
+{
+
+ // DW.SetModuleInfo(&getAnalysis<MachineModuleInfo>());
+ SetupMachineFunction(MF);
+ O << "\n";
+
+ // NOTE: we don't print out constant pools here, they are handled as
+ // instructions.
+ O << "\n";
+
+ // What's my mangled name?
+ CurrentFnName = Mang->getValueName(MF.getFunction());
+
+ // Emit the function start directives
+ emitFunctionStart(MF);
+
+ // Emit pre-function debug information.
+ // DW.BeginFunction(&MF);
+
+ // Print out code for the function.
+ for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
+ I != E; ++I) {
+ // Print a label for the basic block.
+ if (I != MF.begin()) {
+ printBasicBlockLabel(I, true);
+ O << '\n';
+ }
+ for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
+ II != E; ++II) {
+ // Print the assembly for the instruction.
+ O << '\t';
+ printInstruction(II);
+ ++EmittedInsts;
+ }
+ }
+
+ // Emit post-function debug information.
+ // DW.EndFunction();
+
+ // We didn't modify anything.
+ return false;
+}
+
+void PIC16AsmPrinter::
+printOperand(const MachineInstr *MI, int opNum, const char *Modifier)
+{
+ 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;
+ else
+ assert(0 && "not implemented");
+ break;
+ }
+ case MachineOperand::MO_Immediate:
+ {
+ if (!Modifier || strcmp(Modifier, "no_hash") != 0)
+ O << "#";
+ O << (int)MO.getImm();
+ break;
+ }
+ case MachineOperand::MO_MachineBasicBlock:
+ {
+ printBasicBlockLabel(MO.getMBB());
+ return;
+ }
+ case MachineOperand::MO_GlobalAddress:
+ {
+ O << Mang->getValueName(MO.getGlobal())<<'+'<<MO.getOffset();
+ break;
+ }
+ case MachineOperand::MO_ExternalSymbol:
+ {
+ O << MO.getSymbolName();
+ break;
+ }
+ case MachineOperand::MO_ConstantPoolIndex:
+ {
+ O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
+ << '_' << MO.getIndex();
+ break;
+ }
+ case MachineOperand::MO_FrameIndex:
+ {
+ O << "_" << CurrentFnName
+ << '+' << MO.getIndex();
+ break;
+ }
+ case MachineOperand::MO_JumpTableIndex:
+ {
+ O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
+ << '_' << MO.getIndex();
+ break;
+ }
+ default:
+ {
+ O << "<unknown operand type>"; abort ();
+ break;
+ }
+ } // end switch.
+}
+
+static void
+printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI)
+{
+ assert(V < (1 << 12) && "Not a valid so_imm value!");
+ unsigned Imm = V;
+
+ O << Imm;
+}
+
+/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
+/// immediate in bits 0-7.
+void PIC16AsmPrinter::
+printSOImmOperand(const MachineInstr *MI, int OpNum)
+{
+ const MachineOperand &MO = MI->getOperand(OpNum);
+ assert(MO.isImmediate() && "Not a valid so_imm value!");
+ printSOImm(O, MO.getImm(), TAI);
+}
+
+
+void PIC16AsmPrinter:: printAddrModeOperand(const MachineInstr *MI, int Op)
+{
+ const MachineOperand &MO1 = MI->getOperand(Op);
+ const MachineOperand &MO2 = MI->getOperand(Op+1);
+
+ if (MO2.isFrameIndex ()) {
+ printOperand(MI, Op+1);
+ return;
+ }
+
+ if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right.
+ printOperand(MI, Op);
+ return;
+ }
+
+ // If this is Stack Slot
+ if (MO1.isRegister()) {
+ if(strcmp(TM.getRegisterInfo()->get(MO1.getReg()).Name, "SP")==0)
+ {
+ O << CurrentFnName <<"_"<< MO2.getImm();
+ return;
+ }
+ O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+ O << "+";
+ O << MO2.getImm();
+ O << "]";
+ return;
+ }
+
+ O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
+ O << "]";
+}
+
+
+void PIC16AsmPrinter:: printRegisterList(const MachineInstr *MI, int opNum)
+{
+ O << "{";
+ for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) {
+ printOperand(MI, i);
+ if (i != e-1) O << ", ";
+ }
+ O << "}";
+}
+
+void PIC16AsmPrinter::
+printCPInstOperand(const MachineInstr *MI, int OpNo, const char *Modifier)
+{
+ assert(Modifier && "This operand only works with a modifier!");
+
+ // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
+ // data itself.
+ if (!strcmp(Modifier, "label")) {
+ unsigned ID = MI->getOperand(OpNo).getImm();
+ O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
+ << '_' << ID << ":\n";
+ } else {
+ assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
+ unsigned CPI = MI->getOperand(OpNo).getIndex();
+
+ const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun?
+ MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI];
+
+ if (MCPE.isMachineConstantPoolEntry())
+ EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
+ else {
+ EmitGlobalConstant(MCPE.Val.ConstVal);
+ // remember to emit the weak reference
+ if (const GlobalValue *GV = dyn_cast<GlobalValue>(MCPE.Val.ConstVal))
+ if (GV->hasExternalWeakLinkage())
+ ExtWeakSymbols.insert(GV);
+ }
+ }
+}
+
+
+bool PIC16AsmPrinter:: doInitialization(Module &M)
+{
+ // Emit initial debug information.
+ // DW.BeginModule(&M);
+
+ bool Result = AsmPrinter::doInitialization(M);
+ return Result;
+}
+
+bool PIC16AsmPrinter:: doFinalization(Module &M)
+{
+ 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
+ continue;
+
+ if (EmitSpecialLLVMGlobal(I)) {
+ continue;
+ }
+
+ std::string name = Mang->getValueName(I);
+ Constant *C = I->getInitializer();
+ const Type *Type = C->getType();
+ unsigned Size = TD->getABITypeSize(Type);
+ unsigned Align = TD->getPreferredAlignmentLog(I);
+
+ const char *VisibilityDirective = NULL;
+ if (I->hasHiddenVisibility())
+ VisibilityDirective = TAI->getHiddenDirective();
+ else if (I->hasProtectedVisibility())
+ VisibilityDirective = TAI->getProtectedDirective();
+
+ if (VisibilityDirective)
+ O << VisibilityDirective << name << "\n";
+
+ if (C->isNullValue()) {
+ if (I->hasExternalLinkage()) {
+ if (const char *Directive = TAI->getZeroFillDirective()) {
+ O << "\t.globl\t" << name << "\n";
+ O << Directive << "__DATA__, __common, " << name << ", "
+ << Size << ", " << Align << "\n";
+ continue;
+ }
+ }
+
+ if (!I->hasSection() &&
+ (I->hasInternalLinkage() || I->hasWeakLinkage() ||
+ I->hasLinkOnceLinkage())) {
+ if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
+ if (!NoZerosInBSS && TAI->getBSSSection())
+ SwitchToDataSection(M.getModuleIdentifier().c_str(), I);
+ else
+ SwitchToDataSection(TAI->getDataSection(), 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;
+ }
+ }
+
+ switch (I->getLinkage())
+ {
+ case GlobalValue::AppendingLinkage:
+ {
+ // FIXME: appending linkage variables should go into a section of
+ // their name or something. For now, just emit them as external.
+ // Fall through
+ }
+ case GlobalValue::ExternalLinkage:
+ {
+ O << "\t.globl " << name << "\n";
+ // FALL THROUGH
+ }
+ case GlobalValue::InternalLinkage:
+ {
+ if (I->isConstant()) {
+ const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
+ if (TAI->getCStringSection() && CVA && CVA->isCString()) {
+ SwitchToDataSection(TAI->getCStringSection(), I);
+ break;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ assert(0 && "Unknown linkage type!");
+ break;
+ }
+ } // end switch.
+
+ EmitAlignment(Align, I);
+ O << name << ":\t\t\t\t" << TAI->getCommentString() << " " << I->getName()
+ << "\n";
+
+ // If the initializer is a extern weak symbol, remember to emit the weak
+ // reference!
+ if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
+ if (GV->hasExternalWeakLinkage())
+ ExtWeakSymbols.insert(GV);
+
+ EmitGlobalConstant(C);
+ O << '\n';
+ } // end for.
+
+ O << "\n "<< "END";
+ return AsmPrinter::doFinalization(M);
+}
+
+void PIC16AsmPrinter::
+SwitchToTextSection(const char *NewSection, const GlobalValue *GV)
+{
+ O << "\n";
+ if (NewSection && *NewSection) {
+ std::string codeSection = "code_";
+ codeSection += NewSection;
+ codeSection += " ";
+ codeSection += "CODE";
+ AsmPrinter::SwitchToTextSection(codeSection.c_str(),GV);
+ }
+ else
+ AsmPrinter::SwitchToTextSection(NewSection,GV);
+}
+
+void PIC16AsmPrinter::
+SwitchToDataSection(const char *NewSection, const GlobalValue *GV)
+{
+ //Need to append index for page
+ O << "\n";
+ if (NewSection && *NewSection) {
+ std::string dataSection ="udata_";
+ dataSection+=NewSection;
+ if (dataSection.substr(dataSection.length()-2).compare(".o") == 0) {
+ dataSection = dataSection.substr(0,dataSection.length()-2);
+ }
+ dataSection += " ";
+ dataSection += "UDATA";
+ AsmPrinter::SwitchToDataSection(dataSection.c_str(),GV);
+ }
+ else
+ AsmPrinter::SwitchToDataSection(NewSection,GV);
+}
+
+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
new file mode 100644
index 0000000..bcd5f7c
--- /dev/null
+++ b/lib/Target/PIC16/PIC16CallingConv.td
@@ -0,0 +1,17 @@
+//===- PIC16CallingConv.td - Calling Conventions Sparc -----*- 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
new file mode 100644
index 0000000..6e324f9
--- /dev/null
+++ b/lib/Target/PIC16/PIC16ConstantPoolValue.cpp
@@ -0,0 +1,88 @@
+//===- 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"
+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(std::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
new file mode 100644
index 0000000..04d4a17
--- /dev/null
+++ b/lib/Target/PIC16/PIC16ConstantPoolValue.h
@@ -0,0 +1,75 @@
+//===- 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 {
+
+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(std::ostream &O) const;
+};
+
+}
+
+#endif
diff --git a/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp b/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp
new file mode 100644
index 0000000..07ebd99
--- /dev/null
+++ b/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp
@@ -0,0 +1,291 @@
+//===-- 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 "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/CodeGen/SelectionDAGNodes.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Target/TargetMachine.h"
+#include <queue>
+#include <set>
+
+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;
+
+ /// PIC16Lowering - This object fully describes how to lower LLVM code to an
+ /// PIC16-specific SelectionDAG.
+ PIC16TargetLowering PIC16Lowering;
+
+ /// Subtarget - Keep a pointer to the PIC16Subtarget around so that we can
+ /// make the right decision when generating code for different targets.
+ //TODO: add initialization on constructor
+ //const PIC16Subtarget *Subtarget;
+
+public:
+ PIC16DAGToDAGISel(PIC16TargetMachine &tm) :
+ SelectionDAGISel(PIC16Lowering),
+ TM(tm), PIC16Lowering(*TM.getTargetLowering()) {}
+
+ virtual void InstructionSelectBasicBlock(SelectionDAG &SD);
+
+ // 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(SDOperand N);
+
+ // Select addressing mode. currently assume base + offset addr mode.
+ bool SelectAM(SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset);
+ bool SelectDirectAM(SDOperand Op, SDOperand N, SDOperand &Base,
+ SDOperand &Offset);
+ bool StoreInDirectAM(SDOperand Op, SDOperand N, SDOperand &fsr);
+ bool LoadFSR(SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset);
+ bool LoadNothing(SDOperand Op, SDOperand N, SDOperand &Base,
+ SDOperand &Offset);
+
+ // getI8Imm - Return a target constant with the specified
+ // value, of type i8.
+ inline SDOperand getI8Imm(unsigned Imm) {
+ return CurDAG->getTargetConstant(Imm, MVT::i8);
+ }
+
+
+ #ifndef NDEBUG
+ unsigned Indent;
+ #endif
+};
+
+}
+
+/// InstructionSelectBasicBlock - This callback is invoked by
+/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
+void PIC16DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &SD)
+{
+ DEBUG(BB->dump());
+ // Codegen the basic block.
+ #ifndef NDEBUG
+ DOUT << "===== Instruction selection begins:\n";
+ Indent = 0;
+ #endif
+
+ // Select target instructions for the DAG.
+ SD.setRoot(SelectRoot(SD.getRoot()));
+
+ #ifndef NDEBUG
+ DOUT << "===== Instruction selection ends:\n";
+ #endif
+
+ SD.RemoveDeadNodes();
+
+ // Emit machine code to BB.
+ ScheduleAndEmitDAG(SD);
+}
+
+
+bool PIC16DAGToDAGISel::
+SelectDirectAM (SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset)
+{
+ GlobalAddressSDNode *GA;
+ ConstantSDNode *GC;
+
+ // if Address is FI, get the TargetFrameIndex.
+ if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
+ cout << "--------- 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->getValue(), MVT::i8);
+ if ((GA = dyn_cast<GlobalAddressSDNode>(N.getOperand(0)))) {
+ Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
+ GC->getValue());
+ 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 (SDOperand Op, SDOperand N, SDOperand &fsr)
+{
+ RegisterSDNode *Reg;
+ if (N.getOpcode() == ISD::LOAD) {
+ LoadSDNode *LD = dyn_cast<LoadSDNode>(N);
+ if (LD) {
+ fsr = LD->getBasePtr();
+ }
+ else if (isa<RegisterSDNode>(N.Val)) {
+ //FIXME an attempt to retrieve the register number
+ //but does not work
+ cout << "this is a register\n";
+ Reg = dyn_cast<RegisterSDNode>(N.Val);
+ fsr = CurDAG->getRegister(Reg->getReg(),MVT::i16);
+ }
+ else {
+ cout << "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 (SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &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.Val, "blue");
+ CurDAG->viewGraph();
+ }
+
+ return false;
+}
+
+//don't thake this seriously, it will change
+bool PIC16DAGToDAGISel::
+LoadNothing (SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset)
+{
+ GlobalAddressSDNode *GA;
+ if (N.getOpcode() == ISD::GlobalAddress) {
+ GA = dyn_cast<GlobalAddressSDNode>(N);
+ cout << "==========" << 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 instructions not customized! Used for
+/// expanded, promoted and normal instructions
+SDNode* PIC16DAGToDAGISel::Select(SDOperand N)
+{
+ SDNode *Node = N.Val;
+ 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 (Opcode >= ISD::BUILTIN_OP_END && Opcode < PIC16ISD::FIRST_NUMBER) {
+ #ifndef NDEBUG
+ DOUT << std::string(Indent-2, ' ') << "== ";
+ DEBUG(Node->dump(CurDAG));
+ DOUT << "\n";
+ Indent -= 2;
+ #endif
+ return NULL;
+ }
+
+ ///
+ // Instruction Selection not handled by custom or by the
+ // auto-generated tablegen selection should be handled here.
+ ///
+ switch(Opcode) {
+ default: break;
+ }
+
+ // Select the default instruction.
+ SDNode *ResNode = SelectCode(N);
+
+ #ifndef NDEBUG
+ DOUT << std::string(Indent-2, ' ') << "=> ";
+ if (ResNode == NULL || ResNode == N.Val)
+ DEBUG(N.Val->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);
+}
+
diff --git a/lib/Target/PIC16/PIC16ISelLowering.cpp b/lib/Target/PIC16/PIC16ISelLowering.cpp
new file mode 100644
index 0000000..45aaeda
--- /dev/null
+++ b/lib/Target/PIC16/PIC16ISelLowering.cpp
@@ -0,0 +1,801 @@
+//===-- PIC16ISelLowering.cpp - PIC16 DAG Lowering Implementation ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interfaces that PIC16 uses to lower LLVM code into a
+// selection DAG.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "pic16-lower"
+
+#include "PIC16ISelLowering.h"
+#include "PIC16TargetMachine.h"
+#include "llvm/DerivedTypes.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"
+#include <queue>
+#include <set>
+
+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)
+{
+ // PIC16 does not have i1 type, so use i8 for
+ // setcc operations results (slt, sgt, ...).
+ // setSetCCResultType(MVT::i8);
+ // setSetCCResultContents(ZeroOrOneSetCCResult);
+
+ // Set up the register classes
+ addRegisterClass(MVT::i8, PIC16::CPURegsRegisterClass);
+ addRegisterClass(MVT::i16, PIC16::PTRRegsRegisterClass);
+ // Custom
+
+ // Load extented operations for i1 types must be promoted
+ setLoadXAction(ISD::EXTLOAD, MVT::i1, Promote);
+ setLoadXAction(ISD::ZEXTLOAD, MVT::i1, Promote);
+ setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote);
+
+ // Store operations for i1 types must be promoted
+ // setStoreXAction(MVT::i1, Promote);
+ // setStoreXAction(MVT::i8, Legal);
+ // setStoreXAction(MVT::i16, Custom);
+ // setStoreXAction(MVT::i32, Expand);
+
+ // setOperationAction(ISD::BUILD_PAIR, MVT::i32, Expand);
+ // setOperationAction(ISD::BUILD_PAIR, MVT::i16, Expand);
+
+ 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);
+
+
+ // Do we really need to Custom lower the GA ??
+ // setOperationAction(ISD::GlobalAddress, MVT::i16, Custom);
+ setOperationAction(ISD::GlobalAddress, MVT::i8, Custom);
+ setOperationAction(ISD::RET, MVT::Other, Custom);
+
+ // PIC16 not supported intrinsics.
+ // setOperationAction(ISD::MEMMOVE, MVT::Other, Expand);
+ // setOperationAction(ISD::MEMSET, MVT::Other, Expand);
+ // setOperationAction(ISD::MEMCPY, MVT::Other, Expand);
+
+ 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::LOCATION, MVT::Other, Expand);
+ setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
+ setOperationAction(ISD::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);
+ // setOperationAction(ISD::LOAD, MVT::i16, Expand);
+ // setOperationAction(ISD::LOAD, MVT::i32, Expand);
+
+ setTargetDAGCombine(ISD::LOAD);
+ setTargetDAGCombine(ISD::STORE);
+ setTargetDAGCombine(ISD::ADDE);
+ setTargetDAGCombine(ISD::ADDC);
+ setTargetDAGCombine(ISD::ADD);
+ setTargetDAGCombine(ISD::SUBE);
+ setTargetDAGCombine(ISD::SUBC);
+ setTargetDAGCombine(ISD::SUB);
+
+ // We must find a way to get rid of Package nodes in the map
+ // setTargetDAGCombine(PIC16ISD::Package);
+
+ // getValueTypeActions().setTypeAction((MVT::ValueType)MVT::i16, Expand);
+
+ setStackPointerRegisterToSaveRestore(PIC16::STKPTR);
+ computeRegisterProperties();
+}
+
+
+SDOperand PIC16TargetLowering:: LowerOperation(SDOperand Op, SelectionDAG &DAG)
+{
+ SDVTList VTList16 = DAG.getVTList(MVT::i16, MVT::i16, MVT::Other);
+ switch (Op.getOpcode())
+ {
+ case ISD::STORE:
+ cout << "reduce store\n";
+ break;
+ case ISD::FORMAL_ARGUMENTS:
+ cout<<"==== lowering formal args\n";
+ return LowerFORMAL_ARGUMENTS(Op, DAG);
+ case ISD::GlobalAddress:
+ cout<<"==== lowering GA\n";
+ return LowerGlobalAddress(Op, DAG);
+ case ISD::RET:
+ cout<<"==== lowering ret\n";
+ return LowerRET(Op, DAG);
+ case ISD::FrameIndex:
+ cout<<"==== lowering frame index\n";
+ return LowerFrameIndex(Op, DAG);
+ case ISD::ADDE:
+ cout <<"==== lowering adde\n";
+ break;
+ case ISD::LOAD:
+ case ISD::ADD:
+ break;
+ case ISD::BR_CC:
+ cout << "==== lowering BR_CC\n";
+ return LowerBR_CC(Op, DAG);
+ } //end swithch
+ return SDOperand();
+}
+
+
+//===----------------------------------------------------------------------===//
+// Lower helper functions
+//===----------------------------------------------------------------------===//
+
+
+SDOperand
+PIC16TargetLowering::LowerBR_CC(SDOperand Op, SelectionDAG &DAG)
+{
+ MVT::ValueType VT = Op.getValueType();
+ SDOperand Chain = Op.getOperand(0);
+ ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
+ SDOperand LHS = Op.getOperand(2);
+ SDOperand RHS = Op.getOperand(3);
+ SDOperand JumpVal = Op.getOperand(4);
+ SDOperand Result;
+ unsigned cmpOpcode;
+ unsigned branchOpcode;
+ SDOperand branchOperand;
+
+ SDOperand StatusReg = DAG.getRegister(PIC16::STATUSREG,MVT::i8);
+ SDOperand CPUReg = DAG.getRegister(PIC16::WREG,MVT::i8);
+ switch(CC)
+ {
+ default:
+ assert(0 && "This condition code is not handled yet!!");
+ abort();
+ case ISD::SETNE:
+ {
+ cout << "setne\n";
+ cmpOpcode = PIC16ISD::XORCC;
+ branchOpcode = PIC16ISD::BTFSS;
+ branchOperand = DAG.getConstant(2,MVT::i8);
+ break;
+ }
+ case ISD::SETEQ:
+ {
+ cout << "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();
+ }
+ case ISD::SETGE:
+ {
+ cout << "setge\n";
+ cmpOpcode = PIC16ISD::SUBCC;
+ branchOpcode = PIC16ISD::BTFSS;
+ branchOperand = DAG.getConstant(1, MVT::i8);
+ break;
+ }
+ case ISD::SETLT:
+ {
+ cout << "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();
+ }
+ } // End of Switch
+
+ SDVTList VTList = DAG.getVTList(MVT::i8, MVT::Flag);
+ SDOperand CmpValue = DAG.getNode(cmpOpcode, VTList, LHS, RHS).getValue(1);
+ // SDOperand CCOper = DAG.getConstant(CC,MVT::i8);
+ // Result = DAG.getNode(branchOpcode,VT, Chain, JumpVal, CCOper, StatusReg,
+ // CmpValue);
+ Result = DAG.getNode(branchOpcode, VT, Chain, JumpVal, branchOperand,
+ StatusReg, CmpValue);
+ return Result;
+
+ // return SDOperand();
+}
+
+
+//===----------------------------------------------------------------------===//
+// Misc Lower Operation implementation
+//===----------------------------------------------------------------------===//
+// Create a constant pool entry for global value and wrap it in a wrapper node.
+SDOperand
+PIC16TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG)
+{
+ MVT::ValueType PtrVT = getPointerTy();
+ GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
+ GlobalValue *GV = GSDN->getGlobal();
+
+ //for now only do the ram.
+ SDOperand CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 2);
+ SDOperand CPBank = DAG.getNode(PIC16ISD::SetBank, MVT::i8, CPAddr);
+ CPAddr = DAG.getNode(PIC16ISD::Wrapper, MVT::i8, CPAddr,CPBank);
+
+ return CPAddr;
+}
+
+SDOperand
+PIC16TargetLowering::LowerRET(SDOperand Op, SelectionDAG &DAG)
+{
+ switch(Op.getNumOperands())
+ {
+ default:
+ assert(0 && "Do not know how to return this many arguments!");
+ abort();
+ case 1:
+ return SDOperand(); // ret void is legal
+ }
+}
+
+SDOperand
+PIC16TargetLowering::LowerFrameIndex(SDOperand N, SelectionDAG &DAG)
+{
+ if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
+ return DAG.getTargetFrameIndex(FIN->getIndex(), MVT::i32);
+ }
+
+ return N;
+}
+
+SDOperand
+PIC16TargetLowering::LowerLOAD(SDNode *N,
+ SelectionDAG &DAG,
+ DAGCombinerInfo &DCI) const
+{
+ SDOperand Outs[2];
+ SDOperand TF; //TokenFactor
+ SDOperand OutChains[2];
+ SDOperand Chain = N->getOperand(0);
+ SDOperand Src = N->getOperand(1);
+ SDOperand retVal;
+ SDVTList VTList;
+
+ // If this load is directly stored, replace the load value with the stored
+ // value.
+ // TODO: Handle store large -> read small portion.
+ // TODO: Handle TRUNCSTORE/LOADEXT
+ LoadSDNode *LD = cast<LoadSDNode>(N);
+ SDOperand Ptr = LD->getBasePtr();
+ if (LD->getExtensionType() == ISD::NON_EXTLOAD) {
+ if (ISD::isNON_TRUNCStore(Chain.Val)) {
+ StoreSDNode *PrevST = cast<StoreSDNode>(Chain);
+ if (PrevST->getBasePtr() == Ptr &&
+ PrevST->getValue().getValueType() == N->getValueType(0))
+ return DCI.CombineTo(N, Chain.getOperand(1), Chain);
+ }
+ }
+
+ if (N->getValueType(0) != MVT::i16)
+ return SDOperand();
+
+ SDOperand 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);
+ // Add to worklist may not be needed.
+ // It is meant to merge sequences of add with constant into one.
+ DCI.AddToWorklist(toWorklist.Val);
+
+ // 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);
+
+ DCI.CombineTo (N, retVal, TF);
+
+ return retVal;
+}
+
+SDOperand
+PIC16TargetLowering::LowerADDSUB(SDNode *N, SelectionDAG &DAG,
+ DAGCombinerInfo &DCI) const
+{
+ bool changed = false;
+ int i;
+ SDOperand LoOps[3], HiOps[3];
+ SDOperand OutOps[3]; //[0]:left, [1]:right, [2]:carry
+ SDOperand InOp[2];
+ SDOperand retVal;
+ SDOperand as1,as2;
+ SDVTList VTList;
+ unsigned AS,ASE,ASC;
+
+ InOp[0] = N->getOperand(0);
+ InOp[1] = 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->getValue() + CST1->getValue(), MVT::i16);
+ }
+ 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->getValue() - CST1->getValue(), MVT::i16);
+ }
+ case ISD::SUBE:
+ case ISD::SUBC:
+ AS = ISD::SUB;
+ ASE = ISD::SUBE;
+ ASC = ISD::SUBC;
+ break;
+ }
+
+ 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 (at least not yet)
+ return SDOperand();
+ }
+ else if (InOp[i].getOpcode() == ISD::Constant) {
+ changed = true;
+ ConstantSDNode *CST = dyn_cast<ConstantSDNode>(InOp[i]);
+ LoOps[i] = DAG.getConstant(CST->getValue() & 0xFF, MVT::i8);
+ HiOps[i] = DAG.getConstant(CST->getValue() >> 8, MVT::i8);
+ }
+ else if (InOp[i].getOpcode() == PIC16ISD::Package) {
+ LoOps[i] = InOp[i].getOperand(0);
+ HiOps[i] = InOp[i].getOperand(1);
+ }
+ else if (InOp[i].getOpcode() == ISD::LOAD) {
+ changed = true;
+ // LowerLOAD returns a Package node or it may combine and return
+ // anything else
+ SDOperand lowered = LowerLOAD(InOp[i].Val, 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 ((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
+ SDOperand lowered = LowerADDSUB(InOp[i].Val, 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);
+ }
+ else {
+ DAG.setGraphColor(N, "blue");
+ DAG.viewGraph();
+ assert (0 && "not implemented yet");
+ }
+ } //end for
+
+ 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);
+ }
+
+ return retVal;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Calling Convention Implementation
+//
+// The lower operations present on calling convention works on this order:
+// LowerCALL (virt regs --> phys regs, virt regs --> stack)
+// LowerFORMAL_ARGUMENTS (phys --> virt regs, stack --> virt regs)
+// LowerRET (virt regs --> phys regs)
+// LowerCALL (phys regs --> virt regs)
+//
+//===----------------------------------------------------------------------===//
+
+#include "PIC16GenCallingConv.inc"
+
+//===----------------------------------------------------------------------===//
+// CALL Calling Convention Implementation
+//===----------------------------------------------------------------------===//
+
+
+//===----------------------------------------------------------------------===//
+// FORMAL_ARGUMENTS Calling Convention Implementation
+//===----------------------------------------------------------------------===//
+SDOperand PIC16TargetLowering::
+LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG)
+{
+ SmallVector<SDOperand, 8> ArgValues;
+ SDOperand Root = Op.getOperand(0);
+
+ // Return the new list of results.
+ // Just copy right now.
+ ArgValues.push_back(Root);
+
+ return DAG.getNode(ISD::MERGE_VALUES, Op.Val->getVTList(), &ArgValues[0],
+ ArgValues.size()).getValue(Op.ResNo);
+}
+
+
+//===----------------------------------------------------------------------===//
+// Return Value Calling Convention Implementation
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// PIC16 Inline Assembly Support
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Target Optimization Hooks
+//===----------------------------------------------------------------------===//
+
+SDOperand PIC16TargetLowering::PerformDAGCombine(SDNode *N,
+ DAGCombinerInfo &DCI) const
+{
+ int i;
+ ConstantSDNode *CST;
+ SelectionDAG &DAG = DCI.DAG;
+
+ switch (N->getOpcode())
+ {
+ default: break;
+ case PIC16ISD::Package :
+ cout <<"==== combining PIC16ISD::Package\n";
+ return SDOperand();
+ 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 SDOperand ();
+ }
+ case ISD::ADDE :
+ case ISD::ADDC :
+ case ISD::SUBE :
+ case ISD::SUBC :
+ if (N->getValueType(0) == MVT::i16) {
+ SDOperand 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 SDOperand();
+ }
+ 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;
+ case ISD::STORE :
+ {
+ SDOperand Chain = N->getOperand(0);
+ SDOperand Src = N->getOperand(1);
+ SDOperand Dest = N->getOperand(2);
+ unsigned int DstOff = 0;
+ int NUM_STORES;
+ SDOperand 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.Val->getOperand(0);
+ Stores[0] = DAG.getStore(Chain, Src, Dest, NULL,0);
+ return Stores[0];
+ }
+
+ switch(Src.getValueType())
+ {
+ case MVT::i8:
+ break;
+ case MVT::i16:
+ NUM_STORES = 2;
+ break;
+ case MVT::i32:
+ NUM_STORES = 4;
+ break;
+ case MVT::i64:
+ NUM_STORES = 8;
+ break;
+ }
+
+ 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++) {
+ SDOperand ADN = DAG.getNode(ISD::ADD, MVT::i16, Src.getOperand(1),
+ DAG.getConstant(DstOff, MVT::i16));
+ SDOperand LDN = DAG.getLoad(MVT::i8, Chain, ADN, NULL, 0);
+ SDOperand 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++) {
+ SDOperand CNST = DAG.getConstant(CST->getValue() >> i*8, MVT::i8);
+ SDOperand 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);
+ SDOperand Load;
+ Load = DAG.getLoad(MVT::i16, Chain,Dest.getOperand(1), NULL, 0);
+ Chain = Load.getValue(1);
+ for (i=0; i<NUM_STORES; i++) {
+ SDOperand CNST = DAG.getConstant(CST->getValue() >> 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 SDOperand();
+ }
+ else if (Src.getOpcode() == PIC16ISD::Package) {
+ StoreSDNode *st = dyn_cast<StoreSDNode>(N);
+ SDOperand 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.Val);
+
+ // We don't need the Package so add to worklist so llvm deletes it
+ DCI.AddToWorklist(Src.Val);
+ retVal = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], 2);
+ }
+
+ return retVal;
+ }
+ else if (Src.getOpcode() == ISD::TRUNCATE) {
+ }
+ else {
+ // DAG.setGraphColor(N, "blue");
+ // DAG.viewGraph();
+ // assert (0 && "input to store not implemented yet");
+ }
+ } //end ISD::STORE
+
+ break;
+ case ISD::LOAD :
+ {
+ SDOperand Ptr = N->getOperand(1);
+ if (Ptr.getOpcode() == PIC16ISD::Package) {
+ // DAG.setGraphColor(N, "blue");
+ // DAG.viewGraph();
+ // Here we must make so that:
+ // Ptr.getOperand(0) --> fsrl
+ // Ptr.getOperand(1) --> fsrh
+ assert (0 && "not implemented yet");
+ }
+ //return SDOperand();
+ //break;
+ }
+ }//end switch
+
+ return SDOperand();
+}
+
+//===----------------------------------------------------------------------===//
+// Utility functions
+//===----------------------------------------------------------------------===//
+const SDOperand *PIC16TargetLowering::
+findLoadi8(const SDOperand &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 SDOperand *retVal = findLoadi8(Src.getOperand(i),DAG);
+ if (retVal) return retVal;
+ }
+
+ return NULL;
+}
diff --git a/lib/Target/PIC16/PIC16ISelLowering.h b/lib/Target/PIC16/PIC16ISelLowering.h
new file mode 100644
index 0000000..a94ec4a
--- /dev/null
+++ b/lib/Target/PIC16/PIC16ISelLowering.h
@@ -0,0 +1,92 @@
+//===-- PIC16ISelLowering.h - PIC16 DAG Lowering Interface ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interfaces that PIC16 uses to lower LLVM code into a
+// selection DAG.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PIC16ISELLOWERING_H
+#define PIC16ISELLOWERING_H
+
+#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/Target/TargetLowering.h"
+#include "PIC16.h"
+#include "PIC16Subtarget.h"
+
+namespace llvm {
+ namespace PIC16ISD {
+ enum NodeType {
+ // Start the numbering from where ISD NodeType finishes.
+ FIRST_NUMBER = ISD::BUILTIN_OP_END+PIC16::INSTRUCTION_LIST_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
+ };
+ }
+
+ //===--------------------------------------------------------------------===//
+ // TargetLowering Implementation
+ //===--------------------------------------------------------------------===//
+ 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 SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
+
+ SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG);
+ SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG);
+ SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG);
+ SDOperand LowerFrameIndex(SDOperand Op, SelectionDAG &DAG);
+ SDOperand LowerBR_CC(SDOperand Op, SelectionDAG &DAG);
+
+ SDOperand RemoveHiLo(SDNode *, SelectionDAG &DAG,
+ DAGCombinerInfo &DCI) const;
+ SDOperand LowerADDSUB(SDNode *, SelectionDAG &DAG,
+ DAGCombinerInfo &DCI) const;
+ SDOperand LowerLOAD(SDNode *, SelectionDAG &DAG,
+ DAGCombinerInfo &DCI) const;
+
+ /// getTargetNodeName - This method returns the name of a target specific
+ // DAG node.
+ virtual const char *getTargetNodeName(unsigned Opcode) const;
+ virtual SDOperand PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
+
+ // utility function.
+ const SDOperand *findLoadi8(const SDOperand &Src, SelectionDAG &DAG) const;
+ };
+} // namespace llvm
+
+#endif // PIC16ISELLOWERING_H
diff --git a/lib/Target/PIC16/PIC16InstrFormats.td b/lib/Target/PIC16/PIC16InstrFormats.td
new file mode 100644
index 0000000..d4b3ee7
--- /dev/null
+++ b/lib/Target/PIC16/PIC16InstrFormats.td
@@ -0,0 +1,112 @@
+//===- PIC16RegisterInfo.td - PIC16 Register defs ------------*- tblgen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Describe PIC16 instructions format
+//
+// All the possible PIC16 fields are:
+//
+// opcode - operation code.
+// f - 7-bit register file address.
+// d - 1-bit direction specifier
+// k - 8/11 bit literals
+// b - 3 bits bit num specifier
+//
+//===----------------------------------------------------------------------===//
+
+// Generic PIC16 Format
+class PIC16Inst<dag outs, dag ins, string asmstr, list<dag> pattern>
+ : Instruction
+{
+ field bits<14> Inst;
+
+ let Namespace = "PIC16";
+
+ dag OutOperandList = outs;
+ dag InOperandList = ins;
+
+ let AsmString = asmstr;
+ let Pattern = pattern;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Byte Oriented instruction class in PIC16 : <|opcode|d|f|>
+//===----------------------------------------------------------------------===//
+
+class ByteFormat<bits<6> op, 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{7} = d;
+ let Inst{6-0} = f;
+}
+
+//===----------------------------------------------------------------------===//
+// Bit Oriented instruction class in PIC16 : <|opcode|b|f|>
+//===----------------------------------------------------------------------===//
+
+class BitFormat<bits<4> op, 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{9-7} = b;
+ let Inst{6-0} = f;
+}
+
+//===----------------------------------------------------------------------===//
+// Literal Format instruction class in PIC16 : <|opcode|k|>
+//===----------------------------------------------------------------------===//
+
+class LiteralFormat<bits<6> op, dag outs, dag ins, string asmstr,
+ list<dag> pattern>
+ : PIC16Inst<outs, ins, asmstr, pattern>
+{
+ bits<8> k;
+
+
+ let Inst{13-8} = op;
+
+ let Inst{7-0} = k;
+}
+
+//===----------------------------------------------------------------------===//
+// Control Format instruction class in PIC16 : <|opcode|k|>
+//===----------------------------------------------------------------------===//
+
+class ControlFormat<bits<3> op, dag outs, dag ins, string asmstr,
+ list<dag> pattern>
+ :PIC16Inst<outs, ins, asmstr, pattern>
+{
+ bits<11> k;
+
+
+ let Inst{13-11} = op;
+
+ let Inst{10-0} = k;
+}
+
+//===----------------------------------------------------------------------===//
+// 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;
+}
diff --git a/lib/Target/PIC16/PIC16InstrInfo.cpp b/lib/Target/PIC16/PIC16InstrInfo.cpp
new file mode 100644
index 0000000..ad38382
--- /dev/null
+++ b/lib/Target/PIC16/PIC16InstrInfo.cpp
@@ -0,0 +1,143 @@
+//===- PIC16InstrInfo.cpp - PIC16 Instruction Information -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the PIC16 implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PIC16.h"
+#include "PIC16InstrInfo.h"
+#include "llvm/Function.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "PIC16GenInstrInfo.inc"
+
+using namespace llvm;
+
+// TODO: Add the subtarget support on this constructor.
+PIC16InstrInfo::PIC16InstrInfo(PIC16TargetMachine &tm)
+ : TargetInstrInfoImpl(PIC16Insts, array_lengthof(PIC16Insts)),
+ TM(tm), RI(*this) {}
+
+static bool isZeroImm(const MachineOperand &op) {
+ return op.isImmediate() && 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(MachineInstr *MI, int &FrameIndex) const
+{
+ if (MI->getOpcode() == PIC16::MOVF) {
+ if ((MI->getOperand(2).isFrameIndex()) && // is a stack slot
+ (MI->getOperand(1).isImmediate()) && // the imm is zero
+ (isZeroImm(MI->getOperand(1)))) {
+ FrameIndex = MI->getOperand(2).getIndex();
+ return MI->getOperand(0).getReg();
+ }
+ }
+
+ return 0;
+}
+
+/// isStoreToStackSlot - If the specified machine instruction is a direct
+/// store to a stack slot, return the virtual or physical register number of
+/// the source reg along with the FrameIndex of the loaded stack slot. If
+/// not, return 0. This predicate must return 0 if the instruction has
+/// any side effects other than storing to the stack slot.
+unsigned PIC16InstrInfo::
+isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const
+{
+ if (MI->getOpcode() == PIC16::MOVWF) {
+ if ((MI->getOperand(0).isFrameIndex()) && // is a stack slot
+ (MI->getOperand(1).isImmediate()) && // the imm is zero
+ (isZeroImm(MI->getOperand(1)))) {
+ FrameIndex = MI->getOperand(0).getIndex();
+ return MI->getOperand(2).getReg();
+ }
+ }
+ return 0;
+}
+
+void PIC16InstrInfo::
+storeRegToStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I,
+ unsigned SrcReg, bool isKill, int FI,
+ const TargetRegisterClass *RC) const {
+ const Function *Func = MBB.getParent()->getFunction();
+ const std::string FuncName = Func->getName();
+
+ char *tmpName = new char [strlen(FuncName.c_str()) + 6];
+ sprintf(tmpName, "%s_tmp_%d",FuncName.c_str(),FI);
+
+ 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.
+ }
+ 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
+{
+ 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.
+ 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 std::vector<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;
+ }
+
+ // TODO: 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;
+}
+
diff --git a/lib/Target/PIC16/PIC16InstrInfo.h b/lib/Target/PIC16/PIC16InstrInfo.h
new file mode 100644
index 0000000..f764668
--- /dev/null
+++ b/lib/Target/PIC16/PIC16InstrInfo.h
@@ -0,0 +1,78 @@
+//===- PIC16InstrInfo.h - PIC16 Instruction Information----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the niversity of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the PIC16 implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PIC16INSTRUCTIONINFO_H
+#define PIC16INSTRUCTIONINFO_H
+
+#include "PIC16.h"
+#include "PIC16RegisterInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
+
+namespace llvm {
+
+
+class PIC16InstrInfo : public TargetInstrInfoImpl
+{
+ PIC16TargetMachine &TM;
+ const PIC16RegisterInfo RI;
+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 TargetRegisterInfo &getRegisterInfo() const { return RI; }
+
+
+ /// 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(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(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;
+
+
+ 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 std::vector<MachineOperand> &Cond) const ;
+
+};
+
+} // namespace llvm
+
+#endif
diff --git a/lib/Target/PIC16/PIC16InstrInfo.td b/lib/Target/PIC16/PIC16InstrInfo.td
new file mode 100644
index 0000000..34c9f06
--- /dev/null
+++ b/lib/Target/PIC16/PIC16InstrInfo.td
@@ -0,0 +1,302 @@
+//===- PIC16InstrInfo.td - PIC16 Register defs ----------------*- tblgen-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Instruction format superclass
+//===----------------------------------------------------------------------===//
+
+include "PIC16InstrFormats.td"
+
+//===----------------------------------------------------------------------===//
+// PIC16 profiles and nodes
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// PIC16 addressing mode.
+//===----------------------------------------------------------------------===//
+// It matches address of globals as well as the stack slots
+// that are created for locals and temporaries. This addressing mode
+// converts the GlobalAddress and FrameIndex nodes to TargetGlobalAddress
+// and TargetFrameIndex nodes.
+def diraddrmode : ComplexPattern<i16, 2, "SelectDirectAM", [frameindex], []>;
+def dirloadmode : ComplexPattern<i16, 2, "LoadNothing", [frameindex], []>;
+def indirloadmode : ComplexPattern<i16, 2, "LoadFSR", [frameindex], []>;
+
+
+// Address operand.
+def mem : Operand<i16> {
+ let PrintMethod = "printAddrModeOperand";
+ let MIOperandInfo = (ops i16imm, PTRRegs);
+}
+
+// Instruction operand types
+def simm8 : Operand<i8>;
+
+
+// These are target-independent nodes, but have target-specific formats.
+def SDT_PIC16CallSeq : SDTypeProfile<0, 1, [ SDTCisVT<0, i8> ]>;
+def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PIC16CallSeq,
+ [SDNPHasChain, SDNPOutFlag]>;
+def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PIC16CallSeq,
+ [SDNPHasChain, SDNPOutFlag]>;
+
+def PIC16Wrapper : SDNode<"PIC16ISD::Wrapper", SDTIntUnaryOp>;
+
+// so_imm_XFORM - Return a so_imm value packed into the format described for
+// so_imm def below.
+def so_imm_XFORM : SDNodeXForm<imm, [{
+ return CurDAG->getTargetConstant((int8_t)N->getValue(), MVT::i32);
+}]>;
+
+def so_imm : Operand<i8>,
+ PatLeaf<(imm), [{}]> {
+ let PrintMethod = "printSOImmOperand";
+}
+
+
+
+// PIC16 Address Mode! SDNode frameindex could possibily be a match
+// since load and store instructions from stack used it.
+def addr : Operand<i16>;
+
+// Arithmetic 2 register operands
+class ArithI<bits<6> op, string instr_asm, SDNode OpNode,
+ Operand Od> :
+ LiteralFormat< op,
+ (outs CPURegs:$dst),
+ (ins CPURegs:$b, Od:$c),
+ !strconcat(instr_asm, " $c"),
+ [(set CPURegs:$dst, (OpNode CPURegs:$b, Od:$c))]>;
+
+// Memory Load/Store
+class LoadDirect<bits<6> op, string instr_asm, PatFrag OpNode>:
+ ByteFormat< op,
+ (outs CPURegs:$dst),
+ (ins mem:$addr),
+ !strconcat(instr_asm, " $addr"),
+ [(set CPURegs:$dst, (OpNode diraddrmode:$addr))]>;
+
+class LoadInDirect<bits<6> op, string instr_asm, PatFrag OpNode>:
+ ByteFormat< op,
+ (outs PTRRegs:$dst),
+ (ins mem:$addr),
+ !strconcat(instr_asm, " $addr, $dst"),
+ [(set PTRRegs:$dst, (OpNode indirloadmode:$addr))]>;
+
+class StoreDirect<bits<6> op, string instr_asm, PatFrag OpNode>:
+ ByteFormat< op,
+ (outs),
+ (ins CPURegs:$src, mem:$addr),
+ !strconcat(instr_asm, " $addr"),
+ [(OpNode CPURegs:$src, diraddrmode:$addr)]>;
+
+class StoreInDirect<bits<6> op, string instr_asm, PatFrag OpNode>:
+ ByteFormat< op,
+ (outs),
+ (ins CPURegs:$src, PTRRegs:$fsr),
+ !strconcat(instr_asm, " $fsr"),
+ [(OpNode CPURegs:$src, PTRRegs:$fsr)]>;
+
+// Move
+class MovLit<bits<6> op, string instr_asm>:
+ LiteralFormat< op,
+ (outs CPURegs:$dst),
+ (ins i8imm:$src),
+ !strconcat(instr_asm, " $src"),
+ [(set CPURegs:$dst, imm:$src)]>;
+
+
+// Arithmetic with memory store.
+// Arithmetic instrunctions involving W and memory location.
+// Since W is implicit, we only print the memory operand.
+class Arith1M<bits<6> op, string instr_asm, SDNode OpNode>:
+ ByteFormat< op,
+ (outs),
+ (ins CPURegs:$b, mem:$dst),
+ !strconcat(instr_asm, " $dst"),
+ [(store (OpNode (load diraddrmode:$dst), CPURegs:$b), diraddrmode:$dst),
+ (store (OpNode CPURegs:$b, (load diraddrmode:$dst)), diraddrmode:$dst)]>;
+
+// Arithmetic with memory load.
+// Arithmetic instrunctions involving W and memory location.
+// Since W is implicit, we only print the memory operand.
+class Arith1R<bits<6> op, string instr_asm, SDNode OpNode>:
+ ByteFormat< op,
+ (outs CPURegs:$dst),
+ (ins mem:$src1, CPURegs:$src2),
+ !strconcat(instr_asm, " $src1"),
+ [(set CPURegs:$dst, (OpNode (load diraddrmode:$src1), CPURegs:$src2))]>;
+
+// Arithmetic with memory load.
+// Arithmetic instrunctions involving W and memory location.
+// Since W is implicit, we only print the memory operand.
+class Arith2R<bits<6> op, string instr_asm, SDNode OpNode>:
+ ByteFormat< op,
+ (outs CPURegs:$dst),
+ (ins mem:$src1, CPURegs:$src2),
+ !strconcat(instr_asm, " $src1"),
+ [(set CPURegs:$dst, (OpNode CPURegs:$src2, (load diraddrmode:$src1)))]>;
+
+//===----------------------------------------------------------------------===//
+// Instruction definition
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// PIC16I Instructions
+//===----------------------------------------------------------------------===//
+
+// Arithmetic
+
+// ADDiu just accept 16-bit immediates but we handle this on Pat's.
+// immZExt32 is used here so it can match GlobalAddress immediates.
+// def ADDLW : ArithI<0x09, "addlw", add, so_imm>;
+
+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>;
+
+def SUBWF : Arith1M<0x07, "subwf", sub>;
+def SUBFW : Arith1R<0x08, "subfw", sub>;
+
+def SUBWFE : Arith1M<0x09, "subwfe", sube>;
+def SUBFWE : Arith1R<0x0a, "subfwe", sube>;
+
+def SUBWFC : Arith1M<0x0b, "subwfc", subc>;
+def SUBFWC : Arith1R<0x0d, "subfwc", subc>;
+
+def SUBRFW : Arith2R<0x08, "subfw", sub>;
+
+def SUBRFWE : Arith2R<0x0a, "subfwe", sube>;
+
+def SUBRFWC : Arith2R<0x0d, "subfwc", subc>;
+
+def brtarget : Operand<OtherVT>;
+
+class UncondJump< bits<4> op, string instr_asm>:
+ BitFormat< op,
+ (outs),
+ (ins brtarget:$target),
+ !strconcat(instr_asm, " $target"),
+ [(br bb:$target)]>;
+
+def GOTO : UncondJump<0x1, "goto">;
+
+class LogicM<bits<6> op, string instr_asm, SDNode OpNode> :
+ ByteFormat< op,
+ (outs),
+ (ins CPURegs:$b, mem:$dst),
+ !strconcat(instr_asm, " $dst"),
+ [(store (OpNode (load diraddrmode:$dst), CPURegs:$b), diraddrmode:$dst)]>;
+
+class LogicR<bits<6> op, string instr_asm, SDNode OpNode> :
+ ByteFormat< op,
+ (outs CPURegs:$dst),
+ (ins CPURegs:$b, mem:$c),
+ !strconcat(instr_asm, " $c"),
+ [(set CPURegs:$dst, (OpNode (load diraddrmode:$c), CPURegs:$b))]>;
+
+class LogicI<bits<6> op, string instr_asm, SDNode OpNode, Operand Od> :
+ LiteralFormat< op,
+ (outs CPURegs:$dst),
+ (ins CPURegs:$b, Od:$c),
+ !strconcat(instr_asm, " $c"),
+ [(set CPURegs:$dst, (OpNode CPURegs:$b, Od:$c ))]>;
+
+def XORWF : LogicM<0x1,"xorwf",xor>;
+def XORFW : LogicR<0x1,"xorfw",xor>;
+def XORLW : LogicI<0x1,"xorlw",xor, so_imm>;
+
+def ANDWF : LogicM<0x1,"andwf",and>;
+def ANDFW : LogicR<0x1,"andfw",and>;
+def ANDLW : LogicI<0x1,"andlw",and, so_imm>;
+
+def IORWF : LogicM<0x1,"iorwf",or>;
+def IORFW : LogicR<0x1,"iorfw",or>;
+def IORLW : LogicI<0x1,"iorlw",or, so_imm>;
+
+
+/* For comparison before branch */
+def SDT_PIC16Cmp : SDTypeProfile<1, 3, [SDTCisSameAs<0,1>]>;
+def SDTIntBinOpPIC16 : SDTypeProfile<1, 2, [SDTCisSameAs<0,1>,
+ SDTCisSameAs<1,2>, SDTCisInt<1>]>;
+
+def PIC16Cmp : SDNode<"PIC16ISD::Cmp",SDTIntBinOpPIC16, [SDNPOutFlag]>;
+def PIC16XORCC : SDNode<"PIC16ISD::XORCC",SDTIntBinOpPIC16, [SDNPOutFlag]>;
+def PIC16SUBCC : SDNode<"PIC16ISD::SUBCC",SDTIntBinOpPIC16, [SDNPOutFlag]>;
+
+def XORFWCC : LogicR<0x1,"xorfw",PIC16XORCC>;
+def XORLWCC : LogicI<0x1,"xorlw",PIC16XORCC, so_imm>;
+def SUBFWCC : Arith1R<0x1,"subfw",PIC16SUBCC>;
+def SUBLWCC : ArithI<0x1,"sublw",PIC16SUBCC, so_imm>;
+
+
+/* For branch conditions */
+def SDT_PIC16Branch : SDTypeProfile<0, 3, [SDTCisVT<0, OtherVT>,
+ SDTCisVT<1,i8>, SDTCisVT<2,i8>]>;
+
+def PIC16Branch : SDNode<"PIC16ISD::Branch",SDT_PIC16Branch,
+ [SDNPHasChain, SDNPInFlag]>;
+
+def PIC16BTFSS : SDNode<"PIC16ISD::BTFSS",SDT_PIC16Branch,
+ [SDNPHasChain, SDNPInFlag]>;
+
+def PIC16BTFSC : SDNode<"PIC16ISD::BTFSC",SDT_PIC16Branch,
+ [SDNPHasChain, SDNPInFlag]>;
+
+class InstrBitTestCC<bits<4> op, string instr_asm,SDNode OpNode>:
+ BitFormat< op,
+ (outs),
+ (ins brtarget:$target ,so_imm:$i, STATUSRegs:$s ),
+ !strconcat(instr_asm, " $s, $i, $target"),
+ [(OpNode bb:$target, so_imm:$i, STATUSRegs:$s )]>;
+
+def BTFSS : InstrBitTestCC<0x1,"btfss",PIC16BTFSS>;
+def BTFSC : InstrBitTestCC<0x1,"btfsc",PIC16BTFSC>;
+
+
+//===----------------------------------------------------------------------===//
+// Pseudo instructions
+//===----------------------------------------------------------------------===//
+
+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)]>;
+}
+
+
+//===----------------------------------------------------------------------===//
+// 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
new file mode 100644
index 0000000..2c1b54f
--- /dev/null
+++ b/lib/Target/PIC16/PIC16RegisterInfo.cpp
@@ -0,0 +1,223 @@
+//===- PIC16RegisterInfo.cpp - PIC16 Register Information -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the PIC16 implementation of the TargetRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "pic16-reg-info"
+
+#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;
+
+// TODO: add subtarget support
+PIC16RegisterInfo::PIC16RegisterInfo(const TargetInstrInfo &tii)
+ : 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;
+}
+
+void PIC16RegisterInfo::reMaterialize(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I,
+ unsigned DestReg,
+ const MachineInstr *Orig) const
+{
+ MachineInstr *MI = Orig->clone();
+ 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
+//
+//===----------------------------------------------------------------------===//
+
+/// PIC16 Callee Saved Registers
+const unsigned* PIC16RegisterInfo::
+getCalleeSavedRegs(const MachineFunction *MF) const
+{
+ // PIC16 calle-save register range is $16-$26(s0-s7)
+ static const unsigned CalleeSavedRegs[] = { 0 };
+ return CalleeSavedRegs;
+}
+
+/// PIC16 Callee Saved Register 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 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 {
+ 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).isFrameIndex()) {
+ ++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);
+
+ #ifndef NDEBUG
+ DOUT << "\nFunction : " << MF.getFunction()->getName() << "\n";
+ DOUT << "<--------->\n";
+ MI.print(DOUT);
+ DOUT << "FrameIndex : " << FrameIndex << "\n";
+ DOUT << "spOffset : " << spOffset << "\n";
+ DOUT << "stackSize : " << stackSize << "\n";
+ #endif
+
+ // as explained on LowerFORMAL_ARGUMENTS, detect negative offsets
+ // and adjust SPOffsets considering the final stack size.
+ int Offset = ((spOffset < 0) ? (stackSize + (-(spOffset+4))) : (spOffset));
+ //Offset += MI.getOperand(i+1).getImm();
+
+ #ifndef NDEBUG
+ DOUT << "Offset : " << Offset << "\n";
+ DOUT << "<--------->\n";
+ #endif
+
+ // MI.getOperand(i+1).ChangeToImmediate(Offset);
+ MI.getOperand(i).ChangeToRegister(getFrameRegister(MF),false);
+}
+
+void PIC16RegisterInfo::
+emitPrologue(MachineFunction &MF) const
+{
+}
+
+void PIC16RegisterInfo::
+emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
+{
+}
+
+void PIC16RegisterInfo::
+processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
+}
+
+unsigned PIC16RegisterInfo::
+getRARegister() const {
+ assert(0 && "What is the return address register");
+ return 0;
+}
+
+unsigned PIC16RegisterInfo::
+getFrameRegister(MachineFunction &MF) const {
+ return PIC16::STKPTR;
+}
+
+unsigned PIC16RegisterInfo::
+getEHExceptionRegister() const {
+ assert(0 && "What is the exception register");
+ return 0;
+}
+
+unsigned PIC16RegisterInfo::
+getEHHandlerRegister() const {
+ assert(0 && "What is the exception handler register");
+ return 0;
+}
+
+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
new file mode 100644
index 0000000..246d5ee
--- /dev/null
+++ b/lib/Target/PIC16/PIC16RegisterInfo.h
@@ -0,0 +1,86 @@
+//===- PIC16RegisterInfo.h - PIC16 Register Information Impl ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the PIC16 implementation of the TargetRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PIC16REGISTERINFO_H
+#define PIC16REGISTERINFO_H
+
+#include "PIC16GenRegisterInfo.h.inc"
+#include "llvm/Target/TargetRegisterInfo.h"
+
+namespace llvm {
+
+// Forward Declarations.
+class TargetInstrInfo;
+class Type;
+
+struct PIC16RegisterInfo : public PIC16GenRegisterInfo {
+ const TargetInstrInfo &TII;
+
+ explicit PIC16RegisterInfo(const TargetInstrInfo &tii);
+
+ /// 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;
+
+ MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
+ int FrameIndex) const;
+
+ MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
+ MachineInstr* LoadMI) const {
+ return 0;
+ }
+
+ 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;
+
+ void eliminateCallFramePseudoInstr(MachineFunction &MF,
+ MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I) const;
+
+ /// Stack Frame Processing Methods.
+ void eliminateFrameIndex(MachineBasicBlock::iterator II,
+ int SPAdj, RegScavenger *RS = NULL) const;
+
+ void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
+
+ void emitPrologue(MachineFunction &MF) const;
+ void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
+
+ /// Debug information queries.
+ unsigned getRARegister() const;
+ unsigned getFrameRegister(MachineFunction &MF) const;
+
+ /// Exception handling queries.
+ unsigned getEHExceptionRegister() const;
+ unsigned getEHHandlerRegister() const;
+
+ int getDwarfRegNum(unsigned RegNum, bool isEH) const;
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/lib/Target/PIC16/PIC16RegisterInfo.td b/lib/Target/PIC16/PIC16RegisterInfo.td
new file mode 100644
index 0000000..21cc3e5
--- /dev/null
+++ b/lib/Target/PIC16/PIC16RegisterInfo.td
@@ -0,0 +1,84 @@
+//===- PIC16RegisterInfo.td - PIC16 Register defs ------------*- tblgen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// 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]>;
+
+// 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 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();
+ }
+ }];
+}
+
+def STATUSREG : PIC16GPRReg<2, "STATUS">, DwarfRegNum<[0]>;
+
+// STATUS Registers Class
+def STATUSRegs : RegisterClass<"PIC16", [i8], 8,
+ [STATUSREG]>;
+
+
+// Dummy stack pointer.
+def STKPTR : PIC16GPRReg< 0, "SP">, DwarfRegNum<[0]>;
+
+// CPU Registers Class
+def STKRegs : RegisterClass<"PIC16", [i8], 8,
+ [STKPTR]>
+{
+ let MethodProtos = [{
+ iterator allocation_order_end(const MachineFunction &MF) const;
+ }];
+ let MethodBodies = [{
+ STKRegsClass::iterator
+ STKRegsClass::allocation_order_end(const MachineFunction &MF) const {
+ return end();
+ }
+ }];
+}
diff --git a/lib/Target/PIC16/PIC16Subtarget.cpp b/lib/Target/PIC16/PIC16Subtarget.cpp
new file mode 100644
index 0000000..77448a7
--- /dev/null
+++ b/lib/Target/PIC16/PIC16Subtarget.cpp
@@ -0,0 +1,27 @@
+//===- PIC16Subtarget.cpp - PIC16 Subtarget Information -------------------===//
+//
+// 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 subclass of TargetSubtarget.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PIC16Subtarget.h"
+#include "PIC16.h"
+#include "PIC16GenSubtarget.inc"
+using namespace llvm;
+
+PIC16Subtarget::PIC16Subtarget(const TargetMachine &TM, const Module &M,
+ const std::string &FS)
+ :IsPIC16Old(false)
+{
+ std::string CPU = "generic";
+
+ // Parse features string.
+ ParseSubtargetFeatures(FS, CPU);
+}
diff --git a/lib/Target/PIC16/PIC16Subtarget.h b/lib/Target/PIC16/PIC16Subtarget.h
new file mode 100644
index 0000000..e208496
--- /dev/null
+++ b/lib/Target/PIC16/PIC16Subtarget.h
@@ -0,0 +1,41 @@
+//=====-- PIC16Subtarget.h - Define Subtarget for the PIC16 ---*- C++ -*--====//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the PIC16 specific subclass of TargetSubtarget.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PIC16SUBTARGET_H
+#define PIC16SUBTARGET_H
+
+#include "llvm/Target/TargetSubtarget.h"
+#include "llvm/Target/TargetMachine.h"
+
+#include <string>
+
+namespace llvm {
+class Module;
+
+class PIC16Subtarget : public TargetSubtarget {
+ bool IsPIC16Old;
+
+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);
+
+ /// 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
diff --git a/lib/Target/PIC16/PIC16TargetAsmInfo.cpp b/lib/Target/PIC16/PIC16TargetAsmInfo.cpp
new file mode 100644
index 0000000..0a56a6e
--- /dev/null
+++ b/lib/Target/PIC16/PIC16TargetAsmInfo.cpp
@@ -0,0 +1,26 @@
+//===-- PIC16TargetAsmInfo.cpp - PIC16 asm properties ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declarations of the PIC16TargetAsmInfo properties.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PIC16TargetAsmInfo.h"
+
+using namespace llvm;
+
+PIC16TargetAsmInfo::
+PIC16TargetAsmInfo(const PIC16TargetMachine &TM)
+{
+ Data16bitsDirective = "\t.half\t";
+ Data32bitsDirective = "\t.word\t";
+ CommentString = ";";
+ COMMDirective = "\t";
+ COMMDirectiveTakesAlignment = 0;
+}
diff --git a/lib/Target/PIC16/PIC16TargetAsmInfo.h b/lib/Target/PIC16/PIC16TargetAsmInfo.h
new file mode 100644
index 0000000..1401bab
--- /dev/null
+++ b/lib/Target/PIC16/PIC16TargetAsmInfo.h
@@ -0,0 +1,30 @@
+//=====-- PIC16TargetAsmInfo.h - PIC16 asm properties ---------*- C++ -*--====//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the PIC16TargetAsmInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PIC16TARGETASMINFO_H
+#define PIC16TARGETASMINFO_H
+
+#include "llvm/Target/TargetAsmInfo.h"
+
+namespace llvm {
+
+ // Forward declaration.
+ class PIC16TargetMachine;
+
+ struct PIC16TargetAsmInfo : public TargetAsmInfo {
+ PIC16TargetAsmInfo(const PIC16TargetMachine &TM);
+ };
+
+} // namespace llvm
+
+#endif
diff --git a/lib/Target/PIC16/PIC16TargetMachine.cpp b/lib/Target/PIC16/PIC16TargetMachine.cpp
new file mode 100644
index 0000000..2be0afb
--- /dev/null
+++ b/lib/Target/PIC16/PIC16TargetMachine.cpp
@@ -0,0 +1,72 @@
+//===-- PIC16TargetMachine.cpp - Define TargetMachine for PIC16 -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Top-level implementation for the PIC16 target.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PIC16.h"
+#include "PIC16TargetMachine.h"
+#include "PIC16TargetAsmInfo.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Target/TargetMachineRegistry.h"
+#include "llvm/Target/TargetAsmInfo.h"
+
+using namespace llvm;
+
+namespace {
+ // Register the targets
+ RegisterTarget<PIC16TargetMachine> X("pic16", " PIC16 14-bit");
+}
+
+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"),
+ InstrInfo(*this), TLInfo(*this),
+ FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0) { }
+
+
+const TargetAsmInfo *PIC16TargetMachine::
+createTargetAsmInfo() const
+{
+ return new PIC16TargetAsmInfo(*this);
+}
+
+//===----------------------------------------------------------------------===//
+// Pass Pipeline Configuration
+//===----------------------------------------------------------------------===//
+
+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, std::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
new file mode 100644
index 0000000..93ef0d1
--- /dev/null
+++ b/lib/Target/PIC16/PIC16TargetMachine.h
@@ -0,0 +1,61 @@
+//===-- PIC16TargetMachine.h - Define TargetMachine for PIC16 ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the PIC16 specific subclass of TargetMachine.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef PIC16_TARGETMACHINE_H
+#define PIC16_TARGETMACHINE_H
+
+#include "PIC16InstrInfo.h"
+#include "PIC16ISelLowering.h"
+#include "PIC16Subtarget.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetFrameInfo.h"
+#include "llvm/Target/TargetMachine.h"
+
+namespace llvm {
+
+/// PIC16TargetMachine
+///
+class PIC16TargetMachine : public LLVMTargetMachine {
+ PIC16Subtarget Subtarget;
+ const TargetData DataLayout; // Calculates type size & alignment
+ PIC16InstrInfo InstrInfo;
+ PIC16TargetLowering TLInfo;
+ 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 TargetRegisterInfo *getRegisterInfo() const
+ { return &InstrInfo.getRegisterInfo(); }
+
+ 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,
+ std::ostream &Out);
+};
+} // end namespace llvm
+
+#endif