mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-22 10:29:35 +00:00
Added a more function PIC16 backend. However to get this working a patch in
ExpandIntegerOperand (LegalizeIntegerTypes.cpp) is needed which is yet to be reworked and submitted. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59617 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2f45f9762d
commit
b1b5ffd827
@ -12,14 +12,13 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef TARGET_PIC16_H
|
||||
#define TARGET_PIC16_H
|
||||
#ifndef LLVM_TARGET_PIC16_H
|
||||
#define LLVM_TARGET_PIC16_H
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
namespace llvm {
|
||||
class PIC16TargetMachine;
|
||||
class FunctionPassManager;
|
||||
class FunctionPass;
|
||||
class MachineCodeEmitter;
|
||||
class raw_ostream;
|
||||
|
@ -15,30 +15,24 @@
|
||||
|
||||
include "../Target.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Descriptions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "PIC16RegisterInfo.td"
|
||||
include "PIC16CallingConv.td"
|
||||
include "PIC16InstrInfo.td"
|
||||
|
||||
def PIC16InstrInfo : InstrInfo {
|
||||
let TSFlagsFields = [];
|
||||
let TSFlagsShifts = [];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Not currently supported, but work as SubtargetFeature placeholder.
|
||||
def FeaturePIC16Old : SubtargetFeature<"pic16old", "IsPIC16Old", "true",
|
||||
"PIC16 Old ISA Support">;
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Subtarget Features.
|
||||
//===----------------------------------------------------------------------===//
|
||||
def FeatureCooper : SubtargetFeature<"cooper", "IsCooper", "true",
|
||||
"PIC16 Cooper ISA Support">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PIC16 processors supported.
|
||||
// PIC16 supported processors.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def : Processor<"generic", NoItineraries, []>;
|
||||
def : Processor<"cooper", NoItineraries, [FeatureCooper]>;
|
||||
|
||||
|
||||
def PIC16InstrInfo : InstrInfo {}
|
||||
|
||||
def PIC16 : Target {
|
||||
let InstructionSet = PIC16InstrInfo;
|
||||
|
@ -12,99 +12,91 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "asm-printer"
|
||||
#include "PIC16.h"
|
||||
#include "PIC16TargetMachine.h"
|
||||
#include "PIC16ConstantPoolValue.h"
|
||||
#include "PIC16InstrInfo.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Mangler.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "PIC16AsmPrinter.h"
|
||||
#include "PIC16TargetAsmInfo.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetAsmInfo.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include <cctype>
|
||||
#include "llvm/Support/Mangler.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
STATISTIC(EmittedInsts, "Number of machine instrs printed");
|
||||
|
||||
namespace {
|
||||
struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter {
|
||||
PIC16AsmPrinter(raw_ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
|
||||
: AsmPrinter(O, TM, T) {
|
||||
}
|
||||
|
||||
|
||||
/// We name each basic block in a Function with a unique number, so
|
||||
/// that we can consistently refer to them later. This is cleared
|
||||
/// at the beginning of each call to runOnMachineFunction().
|
||||
///
|
||||
typedef std::map<const Value *, unsigned> ValueMapTy;
|
||||
ValueMapTy NumberForBB;
|
||||
|
||||
/// Keeps the set of GlobalValues that require non-lazy-pointers for
|
||||
/// indirect access.
|
||||
std::set<std::string> GVNonLazyPtrs;
|
||||
|
||||
/// Keeps the set of external function GlobalAddresses that the asm
|
||||
/// printer should generate stubs for.
|
||||
std::set<std::string> FnStubs;
|
||||
|
||||
/// True if asm printer is printing a series of CONSTPOOL_ENTRY.
|
||||
bool InCPMode;
|
||||
|
||||
virtual const char *getPassName() const {
|
||||
return "PIC16 Assembly Printer";
|
||||
}
|
||||
|
||||
void printOperand(const MachineInstr *MI, int opNum,
|
||||
const char *Modifier = 0);
|
||||
|
||||
void printSOImmOperand(const MachineInstr *MI, int opNum);
|
||||
|
||||
void printAddrModeOperand(const MachineInstr *MI, int OpNo);
|
||||
|
||||
void printRegisterList(const MachineInstr *MI, int opNum);
|
||||
void printCPInstOperand(const MachineInstr *MI, int opNum,
|
||||
const char *Modifier);
|
||||
|
||||
|
||||
bool printInstruction(const MachineInstr *MI); // autogenerated.
|
||||
void emitFunctionStart(MachineFunction &F);
|
||||
bool runOnMachineFunction(MachineFunction &F);
|
||||
bool doInitialization(Module &M);
|
||||
bool doFinalization(Module &M);
|
||||
|
||||
virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV);
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
public:
|
||||
void SwitchToTextSection(const char *NewSection,
|
||||
const GlobalValue *GV = NULL);
|
||||
void SwitchToDataSection(const char *NewSection,
|
||||
const GlobalValue *GV = NULL);
|
||||
void SwitchToDataOvrSection(const char *NewSection,
|
||||
const GlobalValue *GV = NULL);
|
||||
};
|
||||
} // end of anonymous namespace
|
||||
|
||||
#include "PIC16GenAsmWriter.inc"
|
||||
|
||||
bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
|
||||
std::string NewBankselLabel;
|
||||
unsigned Operands = MI->getNumOperands();
|
||||
if (Operands > 1) {
|
||||
// Global address or external symbol should be second operand from last
|
||||
// if we want to print banksel for it.
|
||||
const MachineOperand &Op = MI->getOperand(Operands-2);
|
||||
unsigned OpType = Op.getType();
|
||||
if (OpType == MachineOperand::MO_GlobalAddress ||
|
||||
OpType == MachineOperand::MO_ExternalSymbol) {
|
||||
if (OpType == MachineOperand::MO_GlobalAddress )
|
||||
NewBankselLabel = Mang->getValueName(Op.getGlobal());
|
||||
else
|
||||
NewBankselLabel = Op.getSymbolName();
|
||||
|
||||
// Operand after global address or external symbol should be banksel.
|
||||
// Value 1 for this operand means we need to generate banksel else do not
|
||||
// generate banksel.
|
||||
const MachineOperand &BS = MI->getOperand(Operands-1);
|
||||
if (((int)BS.getImm() == 1) &&
|
||||
(strcmp (CurrentBankselLabelInBasicBlock.c_str(),
|
||||
NewBankselLabel.c_str()))) {
|
||||
CurrentBankselLabelInBasicBlock = NewBankselLabel;
|
||||
O << "\tbanksel ";
|
||||
printOperand(MI, Operands-2);
|
||||
O << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
printInstruction(MI);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// runOnMachineFunction - This uses the printInstruction()
|
||||
/// method to print assembly for each instruction.
|
||||
///
|
||||
bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
||||
// This calls the base class function required to be called at beginning
|
||||
// of runOnMachineFunction.
|
||||
SetupMachineFunction(MF);
|
||||
|
||||
// Get the mangled name.
|
||||
const Function *F = MF.getFunction();
|
||||
CurrentFnName = Mang->getValueName(F);
|
||||
|
||||
// Emit the function variables.
|
||||
emitFunctionData(MF);
|
||||
std::string codeSection;
|
||||
codeSection = "code." + CurrentFnName + ".#";
|
||||
O << "\n";
|
||||
SwitchToTextSection (codeSection.c_str(),F);
|
||||
|
||||
// Print out code for the function.
|
||||
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
|
||||
I != E; ++I) {
|
||||
// Print a label for the basic block.
|
||||
if (I != MF.begin()) {
|
||||
printBasicBlockLabel(I, true);
|
||||
O << '\n';
|
||||
}
|
||||
else
|
||||
O << "_" << CurrentFnName << ":\n";
|
||||
CurrentBankselLabelInBasicBlock = "";
|
||||
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
|
||||
II != E; ++II) {
|
||||
// Print the assembly for the instruction.
|
||||
printMachineInstruction(II);
|
||||
}
|
||||
}
|
||||
return false; // we didn't modify anything.
|
||||
}
|
||||
|
||||
/// createPIC16CodePrinterPass - Returns a pass that prints the PIC16
|
||||
/// assembly code for a MachineFunction to the given output stream,
|
||||
/// using the given target machine description. This should work
|
||||
@ -115,413 +107,295 @@ FunctionPass *llvm::createPIC16CodePrinterPass(raw_ostream &o,
|
||||
return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo());
|
||||
}
|
||||
|
||||
void PIC16AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const
|
||||
{
|
||||
// FIXME: Currently unimplemented.
|
||||
}
|
||||
|
||||
|
||||
void PIC16AsmPrinter ::
|
||||
EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV)
|
||||
{
|
||||
printDataDirective(MCPV->getType());
|
||||
|
||||
PIC16ConstantPoolValue *ACPV = (PIC16ConstantPoolValue*)MCPV;
|
||||
GlobalValue *GV = ACPV->getGV();
|
||||
std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix();
|
||||
if (!GV)
|
||||
Name += ACPV->getSymbol();
|
||||
if (ACPV->isNonLazyPointer()) {
|
||||
GVNonLazyPtrs.insert(Name);
|
||||
O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr";
|
||||
} else if (ACPV->isStub()) {
|
||||
FnStubs.insert(Name);
|
||||
O << TAI->getPrivateGlobalPrefix() << Name << "$stub";
|
||||
} else {
|
||||
O << Name;
|
||||
}
|
||||
|
||||
if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
|
||||
|
||||
if (ACPV->getPCAdjustment() != 0) {
|
||||
O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
|
||||
<< utostr(ACPV->getLabelId())
|
||||
<< "+" << (unsigned)ACPV->getPCAdjustment();
|
||||
|
||||
if (ACPV->mustAddCurrentAddress())
|
||||
O << "-.";
|
||||
|
||||
O << ")";
|
||||
}
|
||||
O << "\n";
|
||||
|
||||
// If the constant pool value is a extern weak symbol, remember to emit
|
||||
// the weak reference.
|
||||
if (GV && GV->hasExternalWeakLinkage())
|
||||
ExtWeakSymbols.insert(GV);
|
||||
}
|
||||
|
||||
/// emitFunctionStart - Emit the directives used by ASM on the start of
|
||||
/// functions.
|
||||
void PIC16AsmPrinter::emitFunctionStart(MachineFunction &MF)
|
||||
{
|
||||
// Print out the label for the function.
|
||||
const Function *F = MF.getFunction();
|
||||
MachineFrameInfo *FrameInfo = MF.getFrameInfo();
|
||||
if (FrameInfo->hasStackObjects()) {
|
||||
int indexBegin = FrameInfo->getObjectIndexBegin();
|
||||
int indexEnd = FrameInfo->getObjectIndexEnd();
|
||||
while (indexBegin < indexEnd) {
|
||||
if (indexBegin == 0)
|
||||
SwitchToDataOvrSection(F->getParent()->getModuleIdentifier().c_str(),
|
||||
F);
|
||||
|
||||
O << "\t\t" << CurrentFnName << "_" << indexBegin << " " << "RES"
|
||||
<< " " << FrameInfo->getObjectSize(indexBegin) << "\n" ;
|
||||
indexBegin++;
|
||||
}
|
||||
}
|
||||
SwitchToTextSection(CurrentFnName.c_str(), F);
|
||||
O << "_" << CurrentFnName << ":" ;
|
||||
O << "\n";
|
||||
}
|
||||
|
||||
|
||||
/// runOnMachineFunction - This uses the printInstruction()
|
||||
/// method to print assembly for each instruction.
|
||||
///
|
||||
bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF)
|
||||
{
|
||||
SetupMachineFunction(MF);
|
||||
O << "\n";
|
||||
|
||||
// What's my mangled name?
|
||||
CurrentFnName = Mang->getValueName(MF.getFunction());
|
||||
|
||||
// Emit the function start directives
|
||||
emitFunctionStart(MF);
|
||||
|
||||
// Print out code for the function.
|
||||
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
|
||||
I != E; ++I) {
|
||||
// Print a label for the basic block.
|
||||
if (I != MF.begin()) {
|
||||
printBasicBlockLabel(I, true);
|
||||
O << '\n';
|
||||
}
|
||||
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
|
||||
II != E; ++II) {
|
||||
// Print the assembly for the instruction.
|
||||
O << '\t';
|
||||
printInstruction(II);
|
||||
++EmittedInsts;
|
||||
}
|
||||
}
|
||||
|
||||
// We didn't modify anything.
|
||||
return false;
|
||||
}
|
||||
|
||||
void PIC16AsmPrinter::
|
||||
printOperand(const MachineInstr *MI, int opNum, const char *Modifier)
|
||||
{
|
||||
void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
|
||||
const MachineOperand &MO = MI->getOperand(opNum);
|
||||
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
|
||||
|
||||
switch (MO.getType()) {
|
||||
case MachineOperand::MO_Register:
|
||||
if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
|
||||
O << RI.get(MO.getReg()).Name;
|
||||
O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
|
||||
else
|
||||
assert(0 && "not implemented");
|
||||
break;
|
||||
return;
|
||||
|
||||
case MachineOperand::MO_Immediate:
|
||||
if (!Modifier || strcmp(Modifier, "no_hash") != 0)
|
||||
O << "#";
|
||||
case MachineOperand::MO_Immediate:
|
||||
O << (int)MO.getImm();
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_MachineBasicBlock:
|
||||
printBasicBlockLabel(MO.getMBB());
|
||||
return;
|
||||
|
||||
case MachineOperand::MO_GlobalAddress:
|
||||
O << Mang->getValueName(MO.getGlobal())<<'+'<<MO.getOffset();
|
||||
case MachineOperand::MO_GlobalAddress:
|
||||
O << Mang->getValueName(MO.getGlobal());
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_ExternalSymbol:
|
||||
case MachineOperand::MO_ExternalSymbol:
|
||||
O << MO.getSymbolName();
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_ConstantPoolIndex:
|
||||
O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
|
||||
<< '_' << MO.getIndex();
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_FrameIndex:
|
||||
O << "_" << CurrentFnName
|
||||
<< '+' << MO.getIndex();
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_JumpTableIndex:
|
||||
O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
|
||||
<< '_' << MO.getIndex();
|
||||
break;
|
||||
|
||||
default:
|
||||
O << "<unknown operand type>"; abort ();
|
||||
break;
|
||||
} // end switch.
|
||||
}
|
||||
|
||||
static void
|
||||
printSOImm(raw_ostream &O, int64_t V, const TargetAsmInfo *TAI)
|
||||
{
|
||||
assert(V < (1 << 12) && "Not a valid so_imm value!");
|
||||
|
||||
O << (unsigned) V;
|
||||
}
|
||||
|
||||
/// printSOImmOperand - SOImm is 4-bit rotated amount in bits 8-11 with 8-bit
|
||||
/// immediate in bits 0-7.
|
||||
void PIC16AsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum)
|
||||
{
|
||||
const MachineOperand &MO = MI->getOperand(OpNum);
|
||||
assert(MO.isImm() && "Not a valid so_imm value!");
|
||||
printSOImm(O, MO.getImm(), TAI);
|
||||
}
|
||||
|
||||
|
||||
void PIC16AsmPrinter::printAddrModeOperand(const MachineInstr *MI, int Op)
|
||||
{
|
||||
const MachineOperand &MO1 = MI->getOperand(Op);
|
||||
const MachineOperand &MO2 = MI->getOperand(Op+1);
|
||||
|
||||
if (MO2.isFI()) {
|
||||
printOperand(MI, Op+1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MO1.isReg()) {
|
||||
// FIXME: This is for CP entries, but isn't right.
|
||||
printOperand(MI, Op);
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is Stack Slot
|
||||
if (MO1.isReg()) {
|
||||
if (strcmp(TM.getRegisterInfo()->get(MO1.getReg()).Name, "SP") == 0) {
|
||||
O << CurrentFnName <<"_"<< MO2.getImm();
|
||||
return;
|
||||
}
|
||||
O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
|
||||
O << "+";
|
||||
O << MO2.getImm();
|
||||
O << "]";
|
||||
return;
|
||||
}
|
||||
|
||||
O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
|
||||
void PIC16AsmPrinter::printRegisterList(const MachineInstr *MI, int opNum)
|
||||
{
|
||||
O << "{";
|
||||
for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) {
|
||||
printOperand(MI, i);
|
||||
if (i != e-1) O << ", ";
|
||||
}
|
||||
O << "}";
|
||||
}
|
||||
|
||||
void PIC16AsmPrinter::
|
||||
printCPInstOperand(const MachineInstr *MI, int OpNo, const char *Modifier)
|
||||
{
|
||||
assert(Modifier && "This operand only works with a modifier!");
|
||||
|
||||
// There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
|
||||
// data itself.
|
||||
if (!strcmp(Modifier, "label")) {
|
||||
unsigned ID = MI->getOperand(OpNo).getImm();
|
||||
O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
|
||||
<< '_' << ID << ":\n";
|
||||
} else {
|
||||
assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
|
||||
unsigned CPI = MI->getOperand(OpNo).getIndex();
|
||||
|
||||
const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun?
|
||||
MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI];
|
||||
|
||||
if (MCPE.isMachineConstantPoolEntry())
|
||||
EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
|
||||
else {
|
||||
EmitGlobalConstant(MCPE.Val.ConstVal);
|
||||
// remember to emit the weak reference
|
||||
if (const GlobalValue *GV = dyn_cast<GlobalValue>(MCPE.Val.ConstVal))
|
||||
if (GV->hasExternalWeakLinkage())
|
||||
ExtWeakSymbols.insert(GV);
|
||||
}
|
||||
assert(0 && " Operand type not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool PIC16AsmPrinter::doInitialization(Module &M)
|
||||
{
|
||||
bool PIC16AsmPrinter::doInitialization (Module &M) {
|
||||
bool Result = AsmPrinter::doInitialization(M);
|
||||
// FIXME:: This is temporary solution to generate the include file.
|
||||
// The processor should be passed to llc as in input and the header file
|
||||
// should be generated accordingly.
|
||||
O << "\t#include P16F1937.INC\n";
|
||||
|
||||
EmitInitData (M);
|
||||
EmitUnInitData(M);
|
||||
EmitRomData(M);
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool PIC16AsmPrinter::doFinalization(Module &M)
|
||||
void PIC16AsmPrinter::EmitInitData (Module &M)
|
||||
{
|
||||
std::string iDataSection = "idata.#";
|
||||
SwitchToDataSection(iDataSection.c_str());
|
||||
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
|
||||
I != E; ++I) {
|
||||
if (!I->hasInitializer()) // External global require no code.
|
||||
continue;
|
||||
|
||||
Constant *C = I->getInitializer();
|
||||
const PointerType *PtrTy = I->getType();
|
||||
int AddrSpace = PtrTy->getAddressSpace();
|
||||
|
||||
if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::RAM_SPACE)) {
|
||||
|
||||
if (EmitSpecialLLVMGlobal(I))
|
||||
continue;
|
||||
|
||||
// Any variables reaching here with "." in its name is a local scope
|
||||
// variable and should not be printed in global data section.
|
||||
std::string name = Mang->getValueName(I);
|
||||
if (name.find(".") != std::string::npos)
|
||||
continue;
|
||||
|
||||
O << name;
|
||||
EmitGlobalConstant(C);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PIC16AsmPrinter::EmitConstantValueOnly(const Constant* CV) {
|
||||
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
|
||||
unsigned BitWidth = CI->getBitWidth();
|
||||
int Val = CI->getZExtValue();
|
||||
if (BitWidth == 8) {
|
||||
// Expecting db directive here. In case of romdata we need to pad the
|
||||
// word with zeros.
|
||||
if (IsRomData)
|
||||
O << 0 <<", ";
|
||||
O << Val;
|
||||
}
|
||||
else if (BitWidth == 16) {
|
||||
unsigned Element1, Element2;
|
||||
Element1 = 0x00ff & Val;
|
||||
Element2 = 0x00ff & (Val >> 8);
|
||||
if (IsRomData)
|
||||
O << 0 <<", "<<Element1 <<", "<< 0 <<", "<< Element2;
|
||||
else
|
||||
O << Element1 <<", "<< Element2;
|
||||
}
|
||||
else if (BitWidth == 32) {
|
||||
unsigned Element1, Element2, Element3, Element4;
|
||||
Element1 = 0x00ff & Val;
|
||||
Element2 = 0x00ff & (Val >> 8);
|
||||
Element3 = 0x00ff & (Val >> 16);
|
||||
Element4 = 0x00ff & (Val >> 24);
|
||||
if (IsRomData)
|
||||
O << 0 <<", "<< Element1 <<", "<< 0 <<", "<< Element2 <<", "<< 0
|
||||
<<", "<< Element3 <<", "<< 0 <<", "<< Element4;
|
||||
else
|
||||
O << Element1 <<", "<< Element2 <<", "<< Element3 <<", "<< Element4;
|
||||
}
|
||||
return;
|
||||
}
|
||||
AsmPrinter::EmitConstantValueOnly(CV);
|
||||
}
|
||||
|
||||
void PIC16AsmPrinter::EmitRomData (Module &M)
|
||||
{
|
||||
std::string romDataSection = "romdata.#";
|
||||
SwitchToRomDataSection(romDataSection.c_str());
|
||||
IsRomData = true;
|
||||
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
|
||||
I != E; ++I) {
|
||||
if (!I->hasInitializer()) // External global require no code.
|
||||
continue;
|
||||
|
||||
Constant *C = I->getInitializer();
|
||||
const PointerType *PtrTy = I->getType();
|
||||
int AddrSpace = PtrTy->getAddressSpace();
|
||||
if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::ROM_SPACE)) {
|
||||
|
||||
if (EmitSpecialLLVMGlobal(I))
|
||||
continue;
|
||||
|
||||
// Any variables reaching here with "." in its name is a local scope
|
||||
// variable and should not be printed in global data section.
|
||||
std::string name = Mang->getValueName(I);
|
||||
if (name.find(".") != std::string::npos)
|
||||
continue;
|
||||
|
||||
O << name;
|
||||
EmitGlobalConstant(C);
|
||||
O << "\n";
|
||||
}
|
||||
}
|
||||
IsRomData = false;
|
||||
}
|
||||
|
||||
|
||||
void PIC16AsmPrinter::EmitUnInitData (Module &M)
|
||||
{
|
||||
std::string uDataSection = "udata.#";
|
||||
SwitchToUDataSection(uDataSection.c_str());
|
||||
const TargetData *TD = TM.getTargetData();
|
||||
|
||||
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
|
||||
I != E; ++I) {
|
||||
if (!I->hasInitializer()) // External global require no code
|
||||
if (!I->hasInitializer()) // External global require no code.
|
||||
continue;
|
||||
|
||||
if (EmitSpecialLLVMGlobal(I)) {
|
||||
continue;
|
||||
Constant *C = I->getInitializer();
|
||||
if (C->isNullValue()) {
|
||||
|
||||
if (EmitSpecialLLVMGlobal(I))
|
||||
continue;
|
||||
|
||||
// Any variables reaching here with "." in its name is a local scope
|
||||
// variable and should not be printed in global data section.
|
||||
std::string name = Mang->getValueName(I);
|
||||
if (name.find(".") != std::string::npos)
|
||||
continue;
|
||||
|
||||
const Type *Ty = C->getType();
|
||||
unsigned Size = TD->getABITypeSize(Ty);
|
||||
O << name << " " <<"RES"<< " " << Size ;
|
||||
O << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name = Mang->getValueName(I);
|
||||
bool PIC16AsmPrinter::doFinalization(Module &M) {
|
||||
O << "\t" << "END\n";
|
||||
bool Result = AsmPrinter::doFinalization(M);
|
||||
return Result;
|
||||
}
|
||||
|
||||
void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
|
||||
const Function *F = MF.getFunction();
|
||||
std::string FuncName = Mang->getValueName(F);
|
||||
const Module *M = F->getParent();
|
||||
const TargetData *TD = TM.getTargetData();
|
||||
|
||||
// Emit the data section name.
|
||||
O << "\n";
|
||||
std::string fDataSection = "fdata." + CurrentFnName + ".#";
|
||||
SwitchToUDataSection(fDataSection.c_str(), F);
|
||||
// Emit the label for data section of current function.
|
||||
O << "_frame_" << CurrentFnName << ":" ;
|
||||
O << "\n";
|
||||
|
||||
// Emit the function variables.
|
||||
|
||||
if (F->hasExternalLinkage()) {
|
||||
O << "\t" << "GLOBAL _frame_" << CurrentFnName << "\n";
|
||||
O << "\t" << "GLOBAL _" << CurrentFnName << "\n";
|
||||
}
|
||||
// In PIC16 all the function arguments and local variables are global.
|
||||
// Therefore to get the variable belonging to this function entire
|
||||
// global list will be traversed and variables belonging to this function
|
||||
// will be emitted in the current data section.
|
||||
for (Module::const_global_iterator I = M->global_begin(), E = M->global_end();
|
||||
I != E; ++I) {
|
||||
std::string VarName = Mang->getValueName(I);
|
||||
|
||||
// The variables of a function are of form FuncName.* . If this variable
|
||||
// does not belong to this function then continue.
|
||||
if (!(VarName.find(FuncName + ".") == 0 ? true : false))
|
||||
continue;
|
||||
|
||||
Constant *C = I->getInitializer();
|
||||
const Type *Ty = C->getType();
|
||||
unsigned Size = TD->getABITypeSize(Ty);
|
||||
unsigned Align = TD->getPreferredAlignmentLog(I);
|
||||
// Emit memory reserve directive.
|
||||
O << VarName << " RES " << Size << "\n";
|
||||
}
|
||||
emitFunctionTempData(MF);
|
||||
}
|
||||
|
||||
const char *VisibilityDirective = NULL;
|
||||
if (I->hasHiddenVisibility())
|
||||
VisibilityDirective = TAI->getHiddenDirective();
|
||||
else if (I->hasProtectedVisibility())
|
||||
VisibilityDirective = TAI->getProtectedDirective();
|
||||
void PIC16AsmPrinter::emitFunctionTempData(MachineFunction &MF) {
|
||||
// Emit temporary variables.
|
||||
MachineFrameInfo *FrameInfo = MF.getFrameInfo();
|
||||
if (FrameInfo->hasStackObjects()) {
|
||||
int indexBegin = FrameInfo->getObjectIndexBegin();
|
||||
int indexEnd = FrameInfo->getObjectIndexEnd();
|
||||
|
||||
if (VisibilityDirective)
|
||||
O << VisibilityDirective << name << "\n";
|
||||
|
||||
if (C->isNullValue()) {
|
||||
if (I->hasExternalLinkage()) {
|
||||
if (const char *Directive = TAI->getZeroFillDirective()) {
|
||||
O << "\t.globl\t" << name << "\n";
|
||||
O << Directive << "__DATA__, __common, " << name << ", "
|
||||
<< Size << ", " << Align << "\n";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!I->hasSection() &&
|
||||
(I->hasInternalLinkage() || I->hasWeakLinkage() ||
|
||||
I->hasLinkOnceLinkage() || I->hasCommonLinkage())) {
|
||||
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
|
||||
SwitchToDataSection(M.getModuleIdentifier().c_str(), I);
|
||||
if (TAI->getLCOMMDirective() != NULL) {
|
||||
if (I->hasInternalLinkage()) {
|
||||
O << TAI->getLCOMMDirective() << name << "," << Size;
|
||||
} else
|
||||
O << TAI->getCOMMDirective() << name << "," << Size;
|
||||
} else {
|
||||
if (I->hasInternalLinkage())
|
||||
O << "\t.local\t" << name << "\n";
|
||||
|
||||
O << TAI->getCOMMDirective() <<"\t" << name << " " <<"RES"<< " "
|
||||
<< Size;
|
||||
O << "\n\t\tGLOBAL" <<" "<< name;
|
||||
if (TAI->getCOMMDirectiveTakesAlignment())
|
||||
O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (indexBegin < indexEnd)
|
||||
O << CurrentFnName << ".tmp RES"<< " "
|
||||
<<indexEnd - indexBegin <<"\n";
|
||||
/*
|
||||
while (indexBegin < indexEnd) {
|
||||
O << CurrentFnName << "_tmp_" << indexBegin << " " << "RES"<< " "
|
||||
<< 1 << "\n" ;
|
||||
indexBegin++;
|
||||
}
|
||||
|
||||
switch (I->getLinkage()) {
|
||||
case GlobalValue::AppendingLinkage:
|
||||
// FIXME: appending linkage variables should go into a section of
|
||||
// their name or something. For now, just emit them as external.
|
||||
// FALL THROUGH
|
||||
|
||||
case GlobalValue::ExternalLinkage:
|
||||
O << "\t.globl " << name << "\n";
|
||||
// FALL THROUGH
|
||||
|
||||
case GlobalValue::InternalLinkage:
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0 && "Unknown linkage type!");
|
||||
break;
|
||||
} // end switch.
|
||||
|
||||
EmitAlignment(Align, I);
|
||||
O << name << ":\t\t\t\t" << TAI->getCommentString() << " " << I->getName()
|
||||
<< "\n";
|
||||
|
||||
// If the initializer is a extern weak symbol, remember to emit the weak
|
||||
// reference!
|
||||
if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
|
||||
if (GV->hasExternalWeakLinkage())
|
||||
ExtWeakSymbols.insert(GV);
|
||||
|
||||
EmitGlobalConstant(C);
|
||||
O << '\n';
|
||||
} // end for.
|
||||
|
||||
O << "\n "<< "END";
|
||||
return AsmPrinter::doFinalization(M);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
void PIC16AsmPrinter::
|
||||
SwitchToTextSection(const char *NewSection, const GlobalValue *GV)
|
||||
{
|
||||
O << "\n";
|
||||
if (NewSection && *NewSection) {
|
||||
std::string codeSection = "code_";
|
||||
codeSection += NewSection;
|
||||
codeSection += " ";
|
||||
codeSection += "CODE";
|
||||
AsmPrinter::SwitchToTextSection(codeSection.c_str(), GV);
|
||||
}
|
||||
else
|
||||
AsmPrinter::SwitchToTextSection(NewSection, GV);
|
||||
}
|
||||
|
||||
void PIC16AsmPrinter::
|
||||
SwitchToDataSection(const char *NewSection, const GlobalValue *GV)
|
||||
{
|
||||
// Need to append index for page.
|
||||
O << "\n";
|
||||
if (NewSection && *NewSection) {
|
||||
std::string dataSection = "udata_";
|
||||
dataSection += NewSection;
|
||||
if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) {
|
||||
dataSection = dataSection.substr(0, dataSection.length() - 2);
|
||||
}
|
||||
dataSection += " ";
|
||||
dataSection += "UDATA";
|
||||
AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV);
|
||||
}
|
||||
/// The function is same as AsmPrinter::SwitchtoDataSection except the call
|
||||
/// to getUDataSectionStartSuffix.
|
||||
void PIC16AsmPrinter::SwitchToUDataSection(const char *NewSection,
|
||||
const GlobalValue *GV) {
|
||||
std::string NS;
|
||||
if (GV && GV->hasSection())
|
||||
NS = TAI->getSwitchToSectionDirective() + GV->getSection();
|
||||
else
|
||||
AsmPrinter::SwitchToDataSection(NewSection, GV);
|
||||
NS = NewSection;
|
||||
|
||||
// If we're already in this section, we're done.
|
||||
if (CurrentSection == NS) return;
|
||||
|
||||
// Close the current section, if applicable.
|
||||
if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
|
||||
O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
|
||||
|
||||
CurrentSection = NS;
|
||||
|
||||
if (!CurrentSection.empty()){}
|
||||
O << CurrentSection << (static_cast<const PIC16TargetAsmInfo *>(TAI))->
|
||||
getUDataSectionStartSuffix() << '\n';
|
||||
|
||||
IsInTextSection = false;
|
||||
}
|
||||
|
||||
void PIC16AsmPrinter::
|
||||
SwitchToDataOvrSection(const char *NewSection, const GlobalValue *GV)
|
||||
{
|
||||
O << "\n";
|
||||
if (NewSection && *NewSection) {
|
||||
std::string dataSection = "frame_";
|
||||
dataSection += NewSection;
|
||||
if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) {
|
||||
dataSection = dataSection.substr(0, dataSection.length() - 2);
|
||||
}
|
||||
dataSection += "_";
|
||||
dataSection += CurrentFnName;
|
||||
dataSection += " ";
|
||||
dataSection += "UDATA_OVR";
|
||||
AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV);
|
||||
}
|
||||
/// The function is same as AsmPrinter::SwitchtoDataSection except the call
|
||||
/// to getRomDataSectionStartSuffix.
|
||||
void PIC16AsmPrinter::SwitchToRomDataSection(const char *NewSection,
|
||||
const GlobalValue *GV) {
|
||||
std::string NS;
|
||||
if (GV && GV->hasSection())
|
||||
NS = TAI->getSwitchToSectionDirective() + GV->getSection();
|
||||
else
|
||||
AsmPrinter::SwitchToDataSection(NewSection, GV);
|
||||
NS = NewSection;
|
||||
|
||||
// If we're already in this section, we're done.
|
||||
if (CurrentSection == NS) return;
|
||||
|
||||
// Close the current section, if applicable.
|
||||
if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
|
||||
O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
|
||||
|
||||
CurrentSection = NS;
|
||||
|
||||
if (!CurrentSection.empty()) {}
|
||||
O << CurrentSection << (static_cast< const PIC16TargetAsmInfo *>(TAI))->
|
||||
getRomDataSectionStartSuffix() << '\n';
|
||||
|
||||
IsInTextSection = false;
|
||||
}
|
||||
|
||||
|
@ -1,16 +0,0 @@
|
||||
//===- PIC16CallingConv.td - Calling Conventions PIC16 -----*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This describes the calling conventions for the PIC16 architectures.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Return Value Calling Conventions
|
||||
//===----------------------------------------------------------------------===//
|
@ -1,89 +0,0 @@
|
||||
//===- PIC16ConstantPoolValue.cpp - PIC16 constantpool value --------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the PIC16 specific constantpool value class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "PIC16ConstantPoolValue.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/GlobalValue.h"
|
||||
#include "llvm/Type.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
PIC16ConstantPoolValue::PIC16ConstantPoolValue(GlobalValue *gv, unsigned id,
|
||||
PIC16CP::PIC16CPKind k,
|
||||
unsigned char PCAdj,
|
||||
const char *Modif, bool AddCA)
|
||||
: MachineConstantPoolValue((const Type*)gv->getType()),
|
||||
GV(gv), S(NULL), LabelId(id), Kind(k), PCAdjust(PCAdj),
|
||||
Modifier(Modif), AddCurrentAddress(AddCA) {}
|
||||
|
||||
PIC16ConstantPoolValue::PIC16ConstantPoolValue(const char *s, unsigned id,
|
||||
PIC16CP::PIC16CPKind k,
|
||||
unsigned char PCAdj,
|
||||
const char *Modif, bool AddCA)
|
||||
: MachineConstantPoolValue((const Type*)Type::Int32Ty),
|
||||
GV(NULL), S(s), LabelId(id), Kind(k), PCAdjust(PCAdj),
|
||||
Modifier(Modif), AddCurrentAddress(AddCA) {}
|
||||
|
||||
PIC16ConstantPoolValue::PIC16ConstantPoolValue(GlobalValue *gv,
|
||||
PIC16CP::PIC16CPKind k,
|
||||
const char *Modif)
|
||||
: MachineConstantPoolValue((const Type*)Type::Int32Ty),
|
||||
GV(gv), S(NULL), LabelId(0), Kind(k), PCAdjust(0),
|
||||
Modifier(Modif) {}
|
||||
|
||||
int PIC16ConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
|
||||
unsigned Alignment) {
|
||||
unsigned AlignMask = (1 << Alignment)-1;
|
||||
const std::vector<MachineConstantPoolEntry> Constants = CP->getConstants();
|
||||
for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
|
||||
if (Constants[i].isMachineConstantPoolEntry() &&
|
||||
(Constants[i].Offset & AlignMask) == 0) {
|
||||
PIC16ConstantPoolValue *CPV =
|
||||
(PIC16ConstantPoolValue *)Constants[i].Val.MachineCPVal;
|
||||
if (CPV->GV == GV &&
|
||||
CPV->S == S &&
|
||||
CPV->LabelId == LabelId &&
|
||||
CPV->Kind == Kind &&
|
||||
CPV->PCAdjust == PCAdjust)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
PIC16ConstantPoolValue::AddSelectionDAGCSEId(FoldingSetNodeID &ID) {
|
||||
ID.AddPointer(GV);
|
||||
ID.AddPointer(S);
|
||||
ID.AddInteger(LabelId);
|
||||
ID.AddInteger((unsigned)Kind);
|
||||
ID.AddInteger(PCAdjust);
|
||||
}
|
||||
|
||||
void PIC16ConstantPoolValue::print(raw_ostream &O) const {
|
||||
if (GV)
|
||||
O << GV->getName();
|
||||
else
|
||||
O << S;
|
||||
if (isNonLazyPointer()) O << "$non_lazy_ptr";
|
||||
else if (isStub()) O << "$stub";
|
||||
if (Modifier) O << "(" << Modifier << ")";
|
||||
if (PCAdjust != 0) {
|
||||
O << "-(LPIC" << LabelId << "+"
|
||||
<< (unsigned)PCAdjust;
|
||||
if (AddCurrentAddress)
|
||||
O << "-.";
|
||||
O << ")";
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
//===- PIC16ConstantPoolValue.h - PIC16 constantpool value ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the PIC16 specific constantpool value class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TARGET_PIC16_CONSTANTPOOLVALUE_H
|
||||
#define LLVM_TARGET_PIC16_CONSTANTPOOLVALUE_H
|
||||
|
||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class GlobalValue;
|
||||
|
||||
namespace PIC16CP {
|
||||
enum PIC16CPKind {
|
||||
CPValue,
|
||||
CPNonLazyPtr,
|
||||
CPStub
|
||||
};
|
||||
}
|
||||
|
||||
/// PIC16ConstantPoolValue - PIC16 specific constantpool value. This is used to
|
||||
/// represent PC relative displacement between the address of the load
|
||||
/// instruction and the global value being loaded, i.e. (&GV-(LPIC+8)).
|
||||
class PIC16ConstantPoolValue : public MachineConstantPoolValue {
|
||||
GlobalValue *GV; // GlobalValue being loaded.
|
||||
const char *S; // ExtSymbol being loaded.
|
||||
unsigned LabelId; // Label id of the load.
|
||||
PIC16CP::PIC16CPKind Kind; // non_lazy_ptr or stub?
|
||||
unsigned char PCAdjust; // Extra adjustment if constantpool is pc relative.
|
||||
// 8 for PIC16
|
||||
const char *Modifier; // GV modifier i.e. (&GV(modifier)-(LPIC+8))
|
||||
bool AddCurrentAddress;
|
||||
|
||||
public:
|
||||
PIC16ConstantPoolValue(GlobalValue *gv, unsigned id,
|
||||
PIC16CP::PIC16CPKind Kind = PIC16CP::CPValue,
|
||||
unsigned char PCAdj = 0, const char *Modifier = NULL,
|
||||
bool AddCurrentAddress = false);
|
||||
PIC16ConstantPoolValue(const char *s, unsigned id,
|
||||
PIC16CP::PIC16CPKind Kind = PIC16CP::CPValue,
|
||||
unsigned char PCAdj = 0, const char *Modifier = NULL,
|
||||
bool AddCurrentAddress = false);
|
||||
PIC16ConstantPoolValue(GlobalValue *GV, PIC16CP::PIC16CPKind Kind,
|
||||
const char *Modifier);
|
||||
|
||||
|
||||
GlobalValue *getGV() const { return GV; }
|
||||
const char *getSymbol() const { return S; }
|
||||
const char *getModifier() const { return Modifier; }
|
||||
bool hasModifier() const { return Modifier != NULL; }
|
||||
bool mustAddCurrentAddress() const { return AddCurrentAddress; }
|
||||
unsigned getLabelId() const { return LabelId; }
|
||||
bool isNonLazyPointer() const { return Kind == PIC16CP::CPNonLazyPtr; }
|
||||
bool isStub() const { return Kind == PIC16CP::CPStub; }
|
||||
unsigned char getPCAdjustment() const { return PCAdjust; }
|
||||
|
||||
virtual int getExistingMachineCPValue(MachineConstantPool *CP,
|
||||
unsigned Alignment);
|
||||
|
||||
virtual void AddSelectionDAGCSEId(FoldingSetNodeID &ID);
|
||||
|
||||
virtual void print(raw_ostream &O) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -13,263 +13,47 @@
|
||||
|
||||
#define DEBUG_TYPE "pic16-isel"
|
||||
|
||||
#include "PIC16.h"
|
||||
#include "PIC16ISelLowering.h"
|
||||
#include "PIC16RegisterInfo.h"
|
||||
#include "PIC16Subtarget.h"
|
||||
#include "PIC16TargetMachine.h"
|
||||
#include "llvm/GlobalValue.h"
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/Intrinsics.h"
|
||||
#include "llvm/Type.h"
|
||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/SelectionDAGISel.h"
|
||||
#include "llvm/Support/CFG.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "PIC16ISelDAGToDAG.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction Selector Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PIC16DAGToDAGISel - PIC16 specific code to select PIC16 machine
|
||||
// instructions for SelectionDAG operations.
|
||||
//===----------------------------------------------------------------------===//
|
||||
namespace {
|
||||
|
||||
class VISIBILITY_HIDDEN PIC16DAGToDAGISel : public SelectionDAGISel {
|
||||
|
||||
/// TM - Keep a reference to PIC16TargetMachine.
|
||||
PIC16TargetMachine &TM;
|
||||
|
||||
public:
|
||||
explicit PIC16DAGToDAGISel(PIC16TargetMachine &tm) :
|
||||
SelectionDAGISel(*tm.getTargetLowering()),
|
||||
TM(tm) {}
|
||||
|
||||
virtual void InstructionSelect();
|
||||
|
||||
// Pass Name
|
||||
virtual const char *getPassName() const {
|
||||
return "PIC16 DAG->DAG Pattern Instruction Selection";
|
||||
}
|
||||
|
||||
private:
|
||||
// Include the pieces autogenerated from the target description.
|
||||
#include "PIC16GenDAGISel.inc"
|
||||
|
||||
SDNode *Select(SDValue N);
|
||||
|
||||
// Select addressing mode. currently assume base + offset addr mode.
|
||||
bool SelectAM(SDValue Op, SDValue N, SDValue &Base, SDValue &Offset);
|
||||
bool SelectDirectAM(SDValue Op, SDValue N, SDValue &Base,
|
||||
SDValue &Offset);
|
||||
bool StoreInDirectAM(SDValue Op, SDValue N, SDValue &fsr);
|
||||
bool LoadFSR(SDValue Op, SDValue N, SDValue &Base, SDValue &Offset);
|
||||
bool LoadNothing(SDValue Op, SDValue N, SDValue &Base,
|
||||
SDValue &Offset);
|
||||
|
||||
// getI8Imm - Return a target constant with the specified
|
||||
// value, of type i8.
|
||||
inline SDValue getI8Imm(unsigned Imm) {
|
||||
return CurDAG->getTargetConstant(Imm, MVT::i8);
|
||||
}
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
unsigned Indent;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/// InstructionSelect - This callback is invoked by
|
||||
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
|
||||
void PIC16DAGToDAGISel::InstructionSelect()
|
||||
{
|
||||
DEBUG(BB->dump());
|
||||
// Codegen the basic block.
|
||||
|
||||
DOUT << "===== Instruction selection begins:\n";
|
||||
#ifndef NDEBUG
|
||||
Indent = 0;
|
||||
#endif
|
||||
|
||||
// Select target instructions for the DAG.
|
||||
SelectRoot(*CurDAG);
|
||||
|
||||
DOUT << "===== Instruction selection ends:\n";
|
||||
|
||||
CurDAG->RemoveDeadNodes();
|
||||
}
|
||||
|
||||
|
||||
bool PIC16DAGToDAGISel::
|
||||
SelectDirectAM (SDValue Op, SDValue N, SDValue &Base, SDValue &Offset)
|
||||
{
|
||||
GlobalAddressSDNode *GA;
|
||||
ConstantSDNode *GC;
|
||||
|
||||
// if Address is FI, get the TargetFrameIndex.
|
||||
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
|
||||
DOUT << "--------- its frame Index\n";
|
||||
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
|
||||
Offset = CurDAG->getTargetConstant(0, MVT::i32);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (N.getOpcode() == ISD::GlobalAddress) {
|
||||
GA = dyn_cast<GlobalAddressSDNode>(N);
|
||||
Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8);
|
||||
Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
|
||||
GA->getOffset());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (N.getOpcode() == ISD::ADD) {
|
||||
GC = dyn_cast<ConstantSDNode>(N.getOperand(1));
|
||||
Offset = CurDAG->getTargetConstant((unsigned char)GC->getZExtValue(),
|
||||
MVT::i8);
|
||||
if ((GA = dyn_cast<GlobalAddressSDNode>(N.getOperand(0)))) {
|
||||
Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
|
||||
GC->getZExtValue());
|
||||
return true;
|
||||
}
|
||||
else if (FrameIndexSDNode *FIN
|
||||
= dyn_cast<FrameIndexSDNode>(N.getOperand(0))) {
|
||||
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// FIXME: must also account for preinc/predec/postinc/postdec.
|
||||
bool PIC16DAGToDAGISel::
|
||||
StoreInDirectAM (SDValue Op, SDValue N, SDValue &fsr)
|
||||
{
|
||||
RegisterSDNode *Reg;
|
||||
if (N.getOpcode() == ISD::LOAD) {
|
||||
LoadSDNode *LD = dyn_cast<LoadSDNode>(N);
|
||||
if (LD) {
|
||||
fsr = LD->getBasePtr();
|
||||
}
|
||||
else if (isa<RegisterSDNode>(N.getNode())) {
|
||||
//FIXME an attempt to retrieve the register number
|
||||
//but does not work
|
||||
DOUT << "this is a register\n";
|
||||
Reg = dyn_cast<RegisterSDNode>(N.getNode());
|
||||
fsr = CurDAG->getRegister(Reg->getReg(),MVT::i16);
|
||||
}
|
||||
else {
|
||||
DOUT << "this is not a register\n";
|
||||
// FIXME must use whatever load is using
|
||||
fsr = CurDAG->getRegister(1,MVT::i16);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PIC16DAGToDAGISel::
|
||||
LoadFSR (SDValue Op, SDValue N, SDValue &Base, SDValue &Offset)
|
||||
{
|
||||
GlobalAddressSDNode *GA;
|
||||
|
||||
if (N.getOpcode() == ISD::GlobalAddress) {
|
||||
GA = dyn_cast<GlobalAddressSDNode>(N);
|
||||
Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8);
|
||||
Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
|
||||
GA->getOffset());
|
||||
return true;
|
||||
}
|
||||
else if (N.getOpcode() == PIC16ISD::Package) {
|
||||
CurDAG->setGraphColor(Op.getNode(), "blue");
|
||||
CurDAG->viewGraph();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// LoadNothing - Don't thake this seriously, it will change.
|
||||
bool PIC16DAGToDAGISel::
|
||||
LoadNothing (SDValue Op, SDValue N, SDValue &Base, SDValue &Offset)
|
||||
{
|
||||
GlobalAddressSDNode *GA;
|
||||
if (N.getOpcode() == ISD::GlobalAddress) {
|
||||
GA = dyn_cast<GlobalAddressSDNode>(N);
|
||||
DOUT << "==========" << GA->getOffset() << "\n";
|
||||
Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8);
|
||||
Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
|
||||
GA->getOffset());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// Select - Select instructions not customized! Used for
|
||||
/// expanded, promoted and normal instructions.
|
||||
SDNode* PIC16DAGToDAGISel::Select(SDValue N)
|
||||
{
|
||||
SDNode *Node = N.getNode();
|
||||
unsigned Opcode = Node->getOpcode();
|
||||
|
||||
// Dump information about the Node being selected
|
||||
#ifndef NDEBUG
|
||||
DOUT << std::string(Indent, ' ') << "Selecting: ";
|
||||
DEBUG(Node->dump(CurDAG));
|
||||
DOUT << "\n";
|
||||
Indent += 2;
|
||||
#endif
|
||||
|
||||
// If we have a custom node, we already have selected!
|
||||
if (Node->isMachineOpcode()) {
|
||||
#ifndef NDEBUG
|
||||
DOUT << std::string(Indent-2, ' ') << "== ";
|
||||
DEBUG(Node->dump(CurDAG));
|
||||
DOUT << "\n";
|
||||
Indent -= 2;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
///
|
||||
// FIXME: Instruction Selection not handled by custom or by the
|
||||
// auto-generated tablegen selection should be handled here.
|
||||
///
|
||||
switch(Opcode) {
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Select the default instruction.
|
||||
SDNode *ResNode = SelectCode(N);
|
||||
|
||||
#ifndef NDEBUG
|
||||
DOUT << std::string(Indent-2, ' ') << "=> ";
|
||||
if (ResNode == NULL || ResNode == N.getNode())
|
||||
DEBUG(N.getNode()->dump(CurDAG));
|
||||
else
|
||||
DEBUG(ResNode->dump(CurDAG));
|
||||
DOUT << "\n";
|
||||
Indent -= 2;
|
||||
#endif
|
||||
|
||||
return ResNode;
|
||||
}
|
||||
|
||||
/// createPIC16ISelDag - This pass converts a legalized DAG into a
|
||||
/// createPIC16ISelDag - This pass converts a legalized DAG into a
|
||||
/// PIC16-specific DAG, ready for instruction scheduling.
|
||||
FunctionPass *llvm::createPIC16ISelDag(PIC16TargetMachine &TM) {
|
||||
return new PIC16DAGToDAGISel(TM);
|
||||
}
|
||||
|
||||
|
||||
/// InstructionSelect - This callback is invoked by
|
||||
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
|
||||
void PIC16DAGToDAGISel::InstructionSelect() {
|
||||
DEBUG(BB->dump());
|
||||
SelectRoot(*CurDAG);
|
||||
CurDAG->RemoveDeadNodes();
|
||||
}
|
||||
|
||||
/// Select - Select instructions not customized! Used for
|
||||
/// expanded, promoted and normal instructions.
|
||||
SDNode* PIC16DAGToDAGISel::Select(SDValue N) {
|
||||
|
||||
// Select the default instruction.
|
||||
SDNode *ResNode = SelectCode(N);
|
||||
|
||||
return ResNode;
|
||||
}
|
||||
|
||||
|
||||
// SelectDirectAddr - Match a direct address for DAG.
|
||||
// A direct address could be a globaladdress or externalsymbol.
|
||||
bool PIC16DAGToDAGISel::SelectDirectAddr(SDValue Op, SDValue N,
|
||||
SDValue &Address) {
|
||||
// Return true if TGA or ES.
|
||||
if (N.getOpcode() == ISD::TargetGlobalAddress
|
||||
|| N.getOpcode() == ISD::TargetExternalSymbol) {
|
||||
Address = N;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
60
lib/Target/PIC16/PIC16ISelDAGToDAG.h
Normal file
60
lib/Target/PIC16/PIC16ISelDAGToDAG.h
Normal file
@ -0,0 +1,60 @@
|
||||
//===-- PIC16ISelDAGToDAG.cpp - A dag to dag inst selector for PIC16 ------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines an instruction selector for the PIC16 target.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "pic16-isel"
|
||||
|
||||
#include "PIC16.h"
|
||||
#include "PIC16ISelLowering.h"
|
||||
#include "PIC16RegisterInfo.h"
|
||||
#include "PIC16TargetMachine.h"
|
||||
#include "llvm/CodeGen/SelectionDAGISel.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Intrinsics.h"
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
class VISIBILITY_HIDDEN PIC16DAGToDAGISel : public SelectionDAGISel {
|
||||
|
||||
/// TM - Keep a reference to PIC16TargetMachine.
|
||||
PIC16TargetMachine &TM;
|
||||
|
||||
/// PIC16Lowering - This object fully describes how to lower LLVM code to an
|
||||
/// PIC16-specific SelectionDAG.
|
||||
PIC16TargetLowering PIC16Lowering;
|
||||
|
||||
public:
|
||||
explicit PIC16DAGToDAGISel(PIC16TargetMachine &tm) :
|
||||
SelectionDAGISel(PIC16Lowering),
|
||||
TM(tm), PIC16Lowering(*TM.getTargetLowering()) {}
|
||||
|
||||
// Pass Name
|
||||
virtual const char *getPassName() const {
|
||||
return "PIC16 DAG->DAG Pattern Instruction Selection";
|
||||
}
|
||||
|
||||
virtual void InstructionSelect();
|
||||
|
||||
private:
|
||||
// Include the pieces autogenerated from the target description.
|
||||
#include "PIC16GenDAGISel.inc"
|
||||
|
||||
SDNode *Select(SDValue N);
|
||||
|
||||
// Match direct address complex pattern.
|
||||
bool SelectDirectAddr(SDValue Op, SDValue N, SDValue &Address);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -26,66 +26,89 @@ namespace llvm {
|
||||
// Start the numbering from where ISD NodeType finishes.
|
||||
FIRST_NUMBER = ISD::BUILTIN_OP_END,
|
||||
|
||||
// used for encapsulating the expanded nodes into one node.
|
||||
Package,
|
||||
Lo, // Low 8-bits of GlobalAddress.
|
||||
Hi, // High 8-bits of GlobalAddress.
|
||||
PIC16Load,
|
||||
PIC16Store,
|
||||
Banksel,
|
||||
MTLO,
|
||||
MTHI,
|
||||
BCF,
|
||||
LSLF, // PIC16 Logical shift left
|
||||
LRLF, // PIC16 Logical shift right
|
||||
RLF, // Rotate left through carry
|
||||
RRF, // Rotate right through carry
|
||||
Dummy
|
||||
};
|
||||
|
||||
// Get the Higher 16 bits from a 32-bit immediate
|
||||
Hi,
|
||||
|
||||
// Get the Lower 16 bits from a 32-bit immediate
|
||||
Lo,
|
||||
|
||||
Cmp, // PIC16 Generic Comparison instruction.
|
||||
Branch, // PIC16 Generic Branch Instruction.
|
||||
BTFSS, // PIC16 BitTest Instruction (Skip if set).
|
||||
BTFSC, // PIC16 BitTest Instruction (Skip if clear).
|
||||
|
||||
// PIC16 comparison to be converted to either XOR or SUB
|
||||
// Following instructions cater to those convertions.
|
||||
XORCC,
|
||||
SUBCC,
|
||||
|
||||
// Get the Global Address wrapped into a wrapper that also captures
|
||||
// the bank or page.
|
||||
Wrapper,
|
||||
SetBank,
|
||||
SetPage
|
||||
// Keep track of different address spaces.
|
||||
enum AddressSpace {
|
||||
RAM_SPACE = 0, // RAM address space
|
||||
ROM_SPACE = 1 // ROM address space number is 1
|
||||
};
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// TargetLowering Implementation
|
||||
//===--------------------------------------------------------------------===//
|
||||
class PIC16TargetLowering : public TargetLowering
|
||||
{
|
||||
class PIC16TargetLowering : public TargetLowering {
|
||||
public:
|
||||
typedef std::map<SDNode *, SDNode *> NodeMap_t;
|
||||
|
||||
explicit PIC16TargetLowering(PIC16TargetMachine &TM);
|
||||
|
||||
/// LowerOperation - Provide custom lowering hooks for some operations.
|
||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
||||
|
||||
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerRET(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerFrameIndex(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG);
|
||||
|
||||
SDValue RemoveHiLo(SDNode *, SelectionDAG &DAG,
|
||||
DAGCombinerInfo &DCI) const;
|
||||
SDValue LowerADDSUB(SDNode *, SelectionDAG &DAG,
|
||||
DAGCombinerInfo &DCI) const;
|
||||
SDValue LowerLOAD(SDNode *, SelectionDAG &DAG,
|
||||
DAGCombinerInfo &DCI) const;
|
||||
|
||||
/// getTargetNodeName - This method returns the name of a target specific
|
||||
// DAG node.
|
||||
/// getTargetNodeName - This method returns the name of a target specific
|
||||
/// DAG node.
|
||||
virtual const char *getTargetNodeName(unsigned Opcode) const;
|
||||
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerADDE(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerADDC(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerSUBE(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerSUBC(SDValue Op, SelectionDAG &DAG);
|
||||
|
||||
// utility function.
|
||||
const SDValue *findLoadi8(const SDValue &Src, SelectionDAG &DAG) const;
|
||||
SDNode *ReplaceNodeResults(SDNode *N, SelectionDAG &DAG);
|
||||
SDNode *ExpandStore(SDNode *N, SelectionDAG &DAG);
|
||||
SDNode *ExpandLoad(SDNode *N, SelectionDAG &DAG);
|
||||
SDNode *ExpandAdd(SDNode *N, SelectionDAG &DAG);
|
||||
SDNode *ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG);
|
||||
SDNode *ExpandShift(SDNode *N, SelectionDAG &DAG);
|
||||
|
||||
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||
SDValue PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||
|
||||
private:
|
||||
// If the Node is a BUILD_PAIR representing representing an Address
|
||||
// then this function will return true
|
||||
bool isDirectAddress(const SDValue &Op);
|
||||
|
||||
// If the Node is a DirectAddress in ROM_SPACE then this
|
||||
// function will return true
|
||||
bool isRomAddress(const SDValue &Op);
|
||||
|
||||
// To extract chain value from the SDValue Nodes
|
||||
// This function will help to maintain the chain extracting
|
||||
// code at one place. In case of any change in future it will
|
||||
// help maintain the code
|
||||
SDValue getChain(SDValue &Op);
|
||||
|
||||
|
||||
// Extract the Lo and Hi component of Op.
|
||||
void GetExpandedParts(SDValue Op, SelectionDAG &DAG, SDValue &Lo,
|
||||
SDValue &Hi);
|
||||
|
||||
|
||||
// Load pointer can be a direct or indirect address. In PIC16 direct
|
||||
// addresses need Banksel and Indirect addresses need to be loaded to
|
||||
// FSR first. Handle address specific cases here.
|
||||
void LegalizeAddress(SDValue Ptr, SelectionDAG &DAG, SDValue &Chain,
|
||||
SDValue &NewPtr, unsigned &Offset);
|
||||
|
||||
// We can not have both operands of a binary operation in W.
|
||||
// This function is used to put one operand on stack and generate a load.
|
||||
SDValue ConvertToMemOperand(SDValue Op, SelectionDAG &DAG);
|
||||
|
||||
/// Subtarget - Keep a pointer to the PIC16Subtarget around so that we can
|
||||
/// make the right decision when generating code for different targets.
|
||||
const PIC16Subtarget *Subtarget;
|
||||
};
|
||||
} // namespace llvm
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===- PIC16RegisterInfo.td - PIC16 Register defs ------------*- tblgen -*-===//
|
||||
//===- PIC16InstrFormats.td - PIC16 Instruction Formats-------*- tblgen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -21,16 +21,17 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Generic PIC16 Format
|
||||
// PIC16 Instructions are 14-bit wide.
|
||||
|
||||
// FIXME: Add Cooper Specific Formats if any.
|
||||
|
||||
class PIC16Inst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: Instruction
|
||||
{
|
||||
: Instruction {
|
||||
field bits<14> Inst;
|
||||
|
||||
let Namespace = "PIC16";
|
||||
|
||||
dag OutOperandList = outs;
|
||||
dag InOperandList = ins;
|
||||
|
||||
let AsmString = asmstr;
|
||||
let Pattern = pattern;
|
||||
}
|
||||
@ -38,16 +39,18 @@ class PIC16Inst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Byte Oriented instruction class in PIC16 : <|opcode|d|f|>
|
||||
// opcode = 6 bits.
|
||||
// d = direction = 1 bit.
|
||||
// f = file register address = 7 bits.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class ByteFormat<bits<6> op, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern>
|
||||
:PIC16Inst<outs, ins, asmstr, pattern>
|
||||
{
|
||||
class ByteFormat<bits<6> opcode, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern>
|
||||
:PIC16Inst<outs, ins, asmstr, pattern> {
|
||||
bits<1> d;
|
||||
bits<7> f;
|
||||
|
||||
let Inst{13-8} = op;
|
||||
let Inst{13-8} = opcode;
|
||||
|
||||
let Inst{7} = d;
|
||||
let Inst{6-0} = f;
|
||||
@ -55,15 +58,18 @@ class ByteFormat<bits<6> op, dag outs, dag ins, string asmstr,
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Bit Oriented instruction class in PIC16 : <|opcode|b|f|>
|
||||
// opcode = 4 bits.
|
||||
// b = bit specifier = 3 bits.
|
||||
// f = file register address = 7 bits.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class BitFormat<bits<4> op, dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: PIC16Inst<outs, ins, asmstr, pattern>
|
||||
{
|
||||
class BitFormat<bits<4> opcode, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern>
|
||||
: PIC16Inst<outs, ins, asmstr, pattern> {
|
||||
bits<3> b;
|
||||
bits<7> f;
|
||||
|
||||
let Inst{13-10} = op;
|
||||
let Inst{13-10} = opcode;
|
||||
|
||||
let Inst{9-7} = b;
|
||||
let Inst{6-0} = f;
|
||||
@ -71,32 +77,32 @@ class BitFormat<bits<4> op, dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Literal Format instruction class in PIC16 : <|opcode|k|>
|
||||
// opcode = 6 bits
|
||||
// k = literal = 8 bits
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class LiteralFormat<bits<6> op, dag outs, dag ins, string asmstr,
|
||||
class LiteralFormat<bits<6> opcode, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern>
|
||||
: PIC16Inst<outs, ins, asmstr, pattern>
|
||||
{
|
||||
: PIC16Inst<outs, ins, asmstr, pattern> {
|
||||
bits<8> k;
|
||||
|
||||
|
||||
let Inst{13-8} = op;
|
||||
let Inst{13-8} = opcode;
|
||||
|
||||
let Inst{7-0} = k;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Control Format instruction class in PIC16 : <|opcode|k|>
|
||||
// opcode = 3 bits.
|
||||
// k = jump address = 11 bits.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class ControlFormat<bits<3> op, dag outs, dag ins, string asmstr,
|
||||
class ControlFormat<bits<3> opcode, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern>
|
||||
:PIC16Inst<outs, ins, asmstr, pattern>
|
||||
{
|
||||
: PIC16Inst<outs, ins, asmstr, pattern> {
|
||||
bits<11> k;
|
||||
|
||||
|
||||
let Inst{13-11} = op;
|
||||
let Inst{13-11} = opcode;
|
||||
|
||||
let Inst{10-0} = k;
|
||||
}
|
||||
@ -105,8 +111,7 @@ class ControlFormat<bits<3> op, dag outs, dag ins, string asmstr,
|
||||
// Pseudo instruction class in PIC16
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class Pseudo<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern>:
|
||||
PIC16Inst<outs, ins, asmstr, pattern>
|
||||
{
|
||||
let Inst{13-6} = op;
|
||||
class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: PIC16Inst<outs, ins, asmstr, pattern> {
|
||||
let Inst{13-6} = 0;
|
||||
}
|
||||
|
@ -13,132 +13,131 @@
|
||||
|
||||
#include "PIC16.h"
|
||||
#include "PIC16InstrInfo.h"
|
||||
#include "PIC16TargetMachine.h"
|
||||
#include "PIC16GenInstrInfo.inc"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "PIC16GenInstrInfo.inc"
|
||||
#include <cstdio>
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
// FIXME: Add the subtarget support on this constructor.
|
||||
PIC16InstrInfo::PIC16InstrInfo(PIC16TargetMachine &tm)
|
||||
: TargetInstrInfoImpl(PIC16Insts, array_lengthof(PIC16Insts)),
|
||||
TM(tm), RI(*this) {}
|
||||
TM(tm),
|
||||
RegInfo(*this, *TM.getSubtargetImpl()) {}
|
||||
|
||||
static bool isZeroImm(const MachineOperand &op) {
|
||||
return op.isImm() && op.getImm() == 0;
|
||||
}
|
||||
|
||||
|
||||
/// isLoadFromStackSlot - If the specified machine instruction is a direct
|
||||
/// load from a stack slot, return the virtual or physical register number of
|
||||
/// the destination along with the FrameIndex of the loaded stack slot. If
|
||||
/// not, return 0. This predicate must return 0 if the instruction has
|
||||
/// any side effects other than loading from the stack slot.
|
||||
unsigned PIC16InstrInfo::
|
||||
isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const
|
||||
{
|
||||
if (MI->getOpcode() == PIC16::MOVF) {
|
||||
if ((MI->getOperand(2).isFI()) && // is a stack slot
|
||||
(MI->getOperand(1).isImm()) && // the imm is zero
|
||||
(isZeroImm(MI->getOperand(1)))) {
|
||||
FrameIndex = MI->getOperand(2).getIndex();
|
||||
return MI->getOperand(0).getReg();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// isStoreToStackSlot - If the specified machine instruction is a direct
|
||||
/// store to a stack slot, return the virtual or physical register number of
|
||||
/// the source reg along with the FrameIndex of the loaded stack slot. If
|
||||
/// not, return 0. This predicate must return 0 if the instruction has
|
||||
/// the source reg along with the FrameIndex of the loaded stack slot.
|
||||
/// If not, return 0. This predicate must return 0 if the instruction has
|
||||
/// any side effects other than storing to the stack slot.
|
||||
unsigned PIC16InstrInfo::
|
||||
isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const
|
||||
{
|
||||
if (MI->getOpcode() == PIC16::MOVWF) {
|
||||
if ((MI->getOperand(0).isFI()) && // is a stack slot
|
||||
(MI->getOperand(1).isImm()) && // the imm is zero
|
||||
(isZeroImm(MI->getOperand(1)))) {
|
||||
FrameIndex = MI->getOperand(0).getIndex();
|
||||
return MI->getOperand(2).getReg();
|
||||
}
|
||||
unsigned PIC16InstrInfo::isStoreToStackSlot(MachineInstr *MI,
|
||||
int &FrameIndex) const {
|
||||
if (MI->getOpcode() == PIC16::movwf
|
||||
&& MI->getOperand(0).isReg()
|
||||
&& MI->getOperand(1).isSymbol()) {
|
||||
FrameIndex = MI->getOperand(1).getIndex();
|
||||
return MI->getOperand(0).getReg();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PIC16InstrInfo::
|
||||
storeRegToStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I,
|
||||
unsigned SrcReg, bool isKill, int FI,
|
||||
const TargetRegisterClass *RC) const {
|
||||
/// isLoadFromStackSlot - If the specified machine instruction is a direct
|
||||
/// load from a stack slot, return the virtual or physical register number of
|
||||
/// the dest reg along with the FrameIndex of the stack slot.
|
||||
/// If not, return 0. This predicate must return 0 if the instruction has
|
||||
/// any side effects other than storing to the stack slot.
|
||||
unsigned PIC16InstrInfo::isLoadFromStackSlot(MachineInstr *MI,
|
||||
int &FrameIndex) const {
|
||||
if (MI->getOpcode() == PIC16::movf
|
||||
&& MI->getOperand(0).isReg()
|
||||
&& MI->getOperand(1).isSymbol()) {
|
||||
FrameIndex = MI->getOperand(1).getIndex();
|
||||
return MI->getOperand(0).getReg();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void PIC16InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I,
|
||||
unsigned SrcReg, bool isKill, int FI,
|
||||
const TargetRegisterClass *RC) const {
|
||||
|
||||
const Function *Func = MBB.getParent()->getFunction();
|
||||
const std::string FuncName = Func->getName();
|
||||
|
||||
char *tmpName = new char [strlen(FuncName.c_str()) + 6];
|
||||
sprintf(tmpName, "%s_tmp_%d",FuncName.c_str(),FI);
|
||||
sprintf(tmpName, "%s.tmp", FuncName.c_str());
|
||||
|
||||
if (RC == PIC16::CPURegsRegisterClass) {
|
||||
//src is always WREG.
|
||||
BuildMI(MBB, I, this->get(PIC16::MOVWF))
|
||||
.addReg(SrcReg,false,false,true,true)
|
||||
.addExternalSymbol(tmpName) // the current printer expects 3 operands,
|
||||
.addExternalSymbol(tmpName); // all we need is actually one,
|
||||
// so we repeat.
|
||||
// On the order of operands here: think "movwf SrcReg, tmp_slot, offset".
|
||||
if (RC == PIC16::GPRRegisterClass) {
|
||||
//MachineFunction &MF = *MBB.getParent();
|
||||
//MachineRegisterInfo &RI = MF.getRegInfo();
|
||||
BuildMI(MBB, I, get(PIC16::movwf))
|
||||
.addReg(SrcReg, false, false, isKill)
|
||||
.addImm(FI)
|
||||
.addExternalSymbol(tmpName)
|
||||
.addImm(1); // Emit banksel for it.
|
||||
}
|
||||
else if (RC == PIC16::FSR16RegisterClass)
|
||||
assert(0 && "Don't know yet how to store a FSR16 to stack slot");
|
||||
else
|
||||
assert(0 && "Can't store this register to stack slot");
|
||||
}
|
||||
|
||||
void PIC16InstrInfo::
|
||||
loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
unsigned DestReg, int FI,
|
||||
const TargetRegisterClass *RC) const
|
||||
{
|
||||
void PIC16InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I,
|
||||
unsigned DestReg, int FI,
|
||||
const TargetRegisterClass *RC) const {
|
||||
|
||||
const Function *Func = MBB.getParent()->getFunction();
|
||||
const std::string FuncName = Func->getName();
|
||||
|
||||
char *tmpName = new char [strlen(FuncName.c_str()) + 6];
|
||||
sprintf(tmpName, "%s_tmp_%d",FuncName.c_str(),FI);
|
||||
sprintf(tmpName, "%s.tmp", FuncName.c_str());
|
||||
|
||||
if (RC == PIC16::CPURegsRegisterClass)
|
||||
BuildMI(MBB, I, this->get(PIC16::MOVF), DestReg)
|
||||
.addExternalSymbol(tmpName) // the current printer expects 3 operands,
|
||||
.addExternalSymbol(tmpName); // all we need is actually one,so we repeat.
|
||||
// On the order of operands here: think "movf FrameIndex, W".
|
||||
if (RC == PIC16::GPRRegisterClass) {
|
||||
//MachineFunction &MF = *MBB.getParent();
|
||||
//MachineRegisterInfo &RI = MF.getRegInfo();
|
||||
BuildMI(MBB, I, get(PIC16::movf), DestReg)
|
||||
.addImm(FI)
|
||||
.addExternalSymbol(tmpName)
|
||||
.addImm(1); // Emit banksel for it.
|
||||
}
|
||||
else if (RC == PIC16::FSR16RegisterClass)
|
||||
assert(0 && "Don't know yet how to load an FSR16 from stack slot");
|
||||
else
|
||||
assert(0 && "Can't load this register from stack slot");
|
||||
}
|
||||
|
||||
/// InsertBranch - Insert a branch into the end of the specified
|
||||
/// MachineBasicBlock. This operands to this method are the same as those
|
||||
/// returned by AnalyzeBranch. This is invoked in cases where AnalyzeBranch
|
||||
/// returns success and when an unconditional branch (TBB is non-null, FBB is
|
||||
/// null, Cond is empty) needs to be inserted. It returns the number of
|
||||
/// instructions inserted.
|
||||
unsigned PIC16InstrInfo::
|
||||
InsertBranch(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock *TBB, MachineBasicBlock *FBB,
|
||||
const SmallVectorImpl<MachineOperand> &Cond) const
|
||||
{
|
||||
// Shouldn't be a fall through.
|
||||
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
|
||||
|
||||
if (FBB == 0) { // One way branch.
|
||||
if (Cond.empty()) {
|
||||
// Unconditional branch?
|
||||
BuildMI(&MBB, get(PIC16::GOTO)).addMBB(TBB);
|
||||
}
|
||||
return 1;
|
||||
bool PIC16InstrInfo::copyRegToReg (MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
const TargetRegisterClass *DestRC,
|
||||
const TargetRegisterClass *SrcRC) const {
|
||||
if (DestRC == PIC16::FSR16RegisterClass) {
|
||||
BuildMI(MBB, I, get(PIC16::copy_fsr), DestReg).addReg(SrcReg);
|
||||
}
|
||||
|
||||
// FIXME: If the there are some conditions specified then conditional branch
|
||||
// should be generated.
|
||||
// For the time being no instruction is being generated therefore
|
||||
// returning NULL.
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PIC16InstrInfo::isMoveInstr(const MachineInstr &MI,
|
||||
unsigned &SrcReg,
|
||||
unsigned &DestReg) const {
|
||||
|
||||
if (MI.getOpcode() == PIC16::copy_fsr) {
|
||||
DestReg = MI.getOperand(0).getReg();
|
||||
SrcReg = MI.getOperand(1).getReg();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -24,54 +24,43 @@ namespace llvm {
|
||||
class PIC16InstrInfo : public TargetInstrInfoImpl
|
||||
{
|
||||
PIC16TargetMachine &TM;
|
||||
const PIC16RegisterInfo RI;
|
||||
const PIC16RegisterInfo RegInfo;
|
||||
public:
|
||||
explicit PIC16InstrInfo(PIC16TargetMachine &TM);
|
||||
|
||||
/// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
|
||||
/// such, whenever a client has an instance of instruction info, it should
|
||||
/// always be able to get register info as well (through this method).
|
||||
///
|
||||
virtual const PIC16RegisterInfo &getRegisterInfo() const { return RI; }
|
||||
virtual const PIC16RegisterInfo &getRegisterInfo() const { return RegInfo; }
|
||||
|
||||
|
||||
/// isLoadFromStackSlot - If the specified machine instruction is a direct
|
||||
/// load from a stack slot, return the virtual or physical register number of
|
||||
/// the destination along with the FrameIndex of the loaded stack slot. If
|
||||
/// not, return 0. This predicate must return 0 if the instruction has
|
||||
/// any side effects other than loading from the stack slot.
|
||||
virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const;
|
||||
|
||||
virtual unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const;
|
||||
|
||||
/// isStoreToStackSlot - If the specified machine instruction is a direct
|
||||
/// store to a stack slot, return the virtual or physical register number of
|
||||
/// the source reg along with the FrameIndex of the loaded stack slot. If
|
||||
/// not, return 0. This predicate must return 0 if the instruction has
|
||||
/// any side effects other than storing to the stack slot.
|
||||
virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const;
|
||||
|
||||
/// Used for spilling a register
|
||||
void storeRegToStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
unsigned SrcReg, bool isKill, int FrameIndex,
|
||||
const TargetRegisterClass *RC) const;
|
||||
virtual unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const;
|
||||
|
||||
|
||||
void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
unsigned DestReg, int FrameIndex,
|
||||
const TargetRegisterClass *RC) const;
|
||||
|
||||
/// InsertBranch - Insert a branch into the end of the specified
|
||||
/// MachineBasicBlock. This operands to this method are the same as those
|
||||
/// returned by AnalyzeBranch. This is invoked in cases where AnalyzeBranch
|
||||
/// returns success and when an unconditional branch (TBB is non-null, FBB is
|
||||
/// null, Cond is empty) needs to be inserted. It returns the number of
|
||||
/// instructions inserted.
|
||||
virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
MachineBasicBlock *FBB,
|
||||
const SmallVectorImpl<MachineOperand> &Cond) const ;
|
||||
virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
unsigned SrcReg, bool isKill, int FrameIndex,
|
||||
const TargetRegisterClass *RC) const;
|
||||
|
||||
virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, int FrameIndex,
|
||||
const TargetRegisterClass *RC) const;
|
||||
virtual bool copyRegToReg(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
const TargetRegisterClass *DestRC,
|
||||
const TargetRegisterClass *SrcRC) const;
|
||||
virtual bool isMoveInstr(const MachineInstr &MI,
|
||||
unsigned &SrcReg,
|
||||
unsigned &DestReg) const;
|
||||
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===- PIC16InstrInfo.td - PIC16 Register defs ----------------*- tblgen-*-===//
|
||||
//===- PIC16InstrInfo.td - PIC16 Instruction defs -------------*- tblgen-*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -6,297 +6,302 @@
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction format superclass
|
||||
//
|
||||
// This file describes the ARM instructions in TableGen format.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PIC16 Specific Type Constraints.
|
||||
//===----------------------------------------------------------------------===//
|
||||
class SDTCisI8<int OpNum> : SDTCisVT<OpNum, i8>;
|
||||
class SDTCisI16<int OpNum> : SDTCisVT<OpNum, i16>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PIC16 Specific Type Profiles.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Generic type profiles for i8/i16 unary/binary operations.
|
||||
// Taking one i8 or i16 and producing void.
|
||||
def SDTI8VoidOp : SDTypeProfile<0, 1, [SDTCisI8<0>]>;
|
||||
def SDTI16VoidOp : SDTypeProfile<0, 1, [SDTCisI16<0>]>;
|
||||
|
||||
// Taking one value and producing an output of same type.
|
||||
def SDTI8UnaryOp : SDTypeProfile<1, 1, [SDTCisI8<0>, SDTCisI8<1>]>;
|
||||
def SDTI16UnaryOp : SDTypeProfile<1, 1, [SDTCisI16<0>, SDTCisI16<1>]>;
|
||||
|
||||
// Taking two values and producing an output of same type.
|
||||
def SDTI8BinOp : SDTypeProfile<1, 2, [SDTCisI8<0>, SDTCisI8<1>, SDTCisI8<2>]>;
|
||||
def SDTI16BinOp : SDTypeProfile<1, 2, [SDTCisI16<0>, SDTCisI16<1>,
|
||||
SDTCisI16<2>]>;
|
||||
|
||||
// Node specific type profiles.
|
||||
def SDT_PIC16Load : SDTypeProfile<1, 3, [SDTCisI8<0>, SDTCisI8<1>,
|
||||
SDTCisI8<2>, SDTCisI8<3>]>;
|
||||
def SDT_PIC16Store : SDTypeProfile<0, 4, [SDTCisI8<0>, SDTCisI8<1>,
|
||||
SDTCisI8<2>, SDTCisI8<3>]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PIC16 addressing modes matching via DAG.
|
||||
//===----------------------------------------------------------------------===//
|
||||
def diraddr : ComplexPattern<i8, 1, "SelectDirectAddr", [], []>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PIC16 Specific Node Definitions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
def PIC16callseq_start : SDNode<"ISD::CALLSEQ_START", SDTI8VoidOp,
|
||||
[SDNPHasChain, SDNPOutFlag]>;
|
||||
def PIC16callseq_end : SDNode<"ISD::CALLSEQ_END", SDTI8VoidOp,
|
||||
[SDNPHasChain, SDNPOutFlag]>;
|
||||
|
||||
// Low 8-bits of GlobalAddress.
|
||||
def PIC16Lo : SDNode<"PIC16ISD::Lo", SDTI8UnaryOp>;
|
||||
|
||||
// High 8-bits of GlobalAddress.
|
||||
def PIC16Hi : SDNode<"PIC16ISD::Hi", SDTI8UnaryOp>;
|
||||
|
||||
// The MTHI and MTLO nodes are used only to match them in the incoming
|
||||
// DAG for replacement by corresponding set_fsrhi, set_fsrlo insntructions.
|
||||
// These nodes are not used for defining any instructions.
|
||||
def MTLO : SDNode<"PIC16ISD::MTLO", SDTI8UnaryOp>;
|
||||
def MTHI : SDNode<"PIC16ISD::MTHI", SDTI8UnaryOp>;
|
||||
|
||||
// Node to generate Bank Select for a GlobalAddress.
|
||||
def Banksel : SDNode<"PIC16ISD::Banksel", SDTI8UnaryOp>;
|
||||
|
||||
// Node to match a direct store operation.
|
||||
def PIC16Store : SDNode<"PIC16ISD::PIC16Store", SDT_PIC16Store, [SDNPHasChain]>;
|
||||
|
||||
// Node to match a direct load operation.
|
||||
def PIC16Load : SDNode<"PIC16ISD::PIC16Load", SDT_PIC16Load, [SDNPHasChain]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PIC16 Operand Definitions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
def i8mem : Operand<i8>;
|
||||
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PIC16 Instructions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
include "PIC16InstrFormats.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PIC16 profiles and nodes
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pseudo-instructions.
|
||||
def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i8imm:$amt),
|
||||
"!ADJCALLSTACKDOWN $amt",
|
||||
[(PIC16callseq_start imm:$amt)]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PIC16 addressing mode.
|
||||
//===----------------------------------------------------------------------===//
|
||||
// It matches address of globals as well as the stack slots
|
||||
// that are created for locals and temporaries. This addressing mode
|
||||
// converts the GlobalAddress and FrameIndex nodes to TargetGlobalAddress
|
||||
// and TargetFrameIndex nodes.
|
||||
def diraddrmode : ComplexPattern<i16, 2, "SelectDirectAM", [frameindex], []>;
|
||||
def dirloadmode : ComplexPattern<i16, 2, "LoadNothing", [frameindex], []>;
|
||||
def indirloadmode : ComplexPattern<i16, 2, "LoadFSR", [frameindex], []>;
|
||||
|
||||
|
||||
// Address operand.
|
||||
def mem : Operand<i16> {
|
||||
let PrintMethod = "printAddrModeOperand";
|
||||
let MIOperandInfo = (ops i16imm, PTRRegs);
|
||||
}
|
||||
|
||||
// Instruction operand types
|
||||
def simm8 : Operand<i8>;
|
||||
|
||||
|
||||
// These are target-independent nodes, but have target-specific formats.
|
||||
def SDT_PIC16CallSeq : SDTypeProfile<0, 1, [ SDTCisVT<0, i8> ]>;
|
||||
def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PIC16CallSeq,
|
||||
[SDNPHasChain, SDNPOutFlag]>;
|
||||
def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PIC16CallSeq,
|
||||
[SDNPHasChain, SDNPOutFlag]>;
|
||||
|
||||
def PIC16Wrapper : SDNode<"PIC16ISD::Wrapper", SDTIntUnaryOp>;
|
||||
|
||||
// so_imm_XFORM - Return a so_imm value packed into the format described for
|
||||
// so_imm def below.
|
||||
def so_imm_XFORM : SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant((int8_t)N->getZExtValue(), MVT::i32);
|
||||
}]>;
|
||||
|
||||
def so_imm : Operand<i8>,
|
||||
PatLeaf<(imm), [{}]> {
|
||||
let PrintMethod = "printSOImmOperand";
|
||||
}
|
||||
|
||||
|
||||
|
||||
// PIC16 Address Mode! SDNode frameindex could possibily be a match
|
||||
// since load and store instructions from stack used it.
|
||||
def addr : Operand<i16>;
|
||||
|
||||
// Arithmetic 2 register operands
|
||||
class ArithI<bits<6> op, string instr_asm, SDNode OpNode,
|
||||
Operand Od> :
|
||||
LiteralFormat< op,
|
||||
(outs CPURegs:$dst),
|
||||
(ins CPURegs:$b, Od:$c),
|
||||
!strconcat(instr_asm, " $c"),
|
||||
[(set CPURegs:$dst, (OpNode CPURegs:$b, Od:$c))]>;
|
||||
|
||||
// Memory Load/Store.
|
||||
class LoadDirect<bits<6> op, string instr_asm, PatFrag OpNode>:
|
||||
ByteFormat< op,
|
||||
(outs CPURegs:$dst),
|
||||
(ins mem:$addr),
|
||||
!strconcat(instr_asm, " $addr"),
|
||||
[(set CPURegs:$dst, (OpNode diraddrmode:$addr))]>;
|
||||
|
||||
class LoadInDirect<bits<6> op, string instr_asm, PatFrag OpNode>:
|
||||
ByteFormat< op,
|
||||
(outs PTRRegs:$dst),
|
||||
(ins mem:$addr),
|
||||
!strconcat(instr_asm, " $addr, $dst"),
|
||||
[(set PTRRegs:$dst, (OpNode indirloadmode:$addr))]>;
|
||||
|
||||
class StoreDirect<bits<6> op, string instr_asm, PatFrag OpNode>:
|
||||
ByteFormat< op,
|
||||
(outs),
|
||||
(ins CPURegs:$src, mem:$addr),
|
||||
!strconcat(instr_asm, " $addr"),
|
||||
[(OpNode CPURegs:$src, diraddrmode:$addr)]>;
|
||||
|
||||
class StoreInDirect<bits<6> op, string instr_asm, PatFrag OpNode>:
|
||||
ByteFormat< op,
|
||||
(outs),
|
||||
(ins CPURegs:$src, PTRRegs:$fsr),
|
||||
!strconcat(instr_asm, " $fsr"),
|
||||
[(OpNode CPURegs:$src, PTRRegs:$fsr)]>;
|
||||
|
||||
// Move.
|
||||
class MovLit<bits<6> op, string instr_asm>:
|
||||
LiteralFormat< op,
|
||||
(outs CPURegs:$dst),
|
||||
(ins i8imm:$src),
|
||||
!strconcat(instr_asm, " $src"),
|
||||
[(set CPURegs:$dst, imm:$src)]>;
|
||||
|
||||
|
||||
// Arithmetic with memory store.
|
||||
// Arithmetic instrunctions involving W and memory location.
|
||||
// Since W is implicit, we only print the memory operand.
|
||||
class Arith1M<bits<6> op, string instr_asm, SDNode OpNode>:
|
||||
ByteFormat< op,
|
||||
(outs),
|
||||
(ins CPURegs:$b, mem:$dst),
|
||||
!strconcat(instr_asm, " $dst"),
|
||||
[(store (OpNode (load diraddrmode:$dst), CPURegs:$b), diraddrmode:$dst),
|
||||
(store (OpNode CPURegs:$b, (load diraddrmode:$dst)), diraddrmode:$dst)]>;
|
||||
|
||||
// Arithmetic with memory load.
|
||||
// Arithmetic instrunctions involving W and memory location.
|
||||
// Since W is implicit, we only print the memory operand.
|
||||
class Arith1R<bits<6> op, string instr_asm, SDNode OpNode>:
|
||||
ByteFormat< op,
|
||||
(outs CPURegs:$dst),
|
||||
(ins mem:$src1, CPURegs:$src2),
|
||||
!strconcat(instr_asm, " $src1"),
|
||||
[(set CPURegs:$dst, (OpNode (load diraddrmode:$src1), CPURegs:$src2))]>;
|
||||
|
||||
// Arithmetic with memory load.
|
||||
// Arithmetic instrunctions involving W and memory location.
|
||||
// Since W is implicit, we only print the memory operand.
|
||||
class Arith2R<bits<6> op, string instr_asm, SDNode OpNode>:
|
||||
ByteFormat< op,
|
||||
(outs CPURegs:$dst),
|
||||
(ins mem:$src1, CPURegs:$src2),
|
||||
!strconcat(instr_asm, " $src1"),
|
||||
[(set CPURegs:$dst, (OpNode CPURegs:$src2, (load diraddrmode:$src1)))]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction definition
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PIC16I Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Arithmetic
|
||||
|
||||
// ADDiu just accept 16-bit immediates but we handle this on Pat's.
|
||||
// immZExt32 is used here so it can match GlobalAddress immediates.
|
||||
// def ADDLW : ArithI<0x09, "addlw", add, so_imm>;
|
||||
def ADJCALLSTACKUP : Pseudo<(outs), (ins i8imm:$amt),
|
||||
"!ADJCALLSTACKUP $amt",
|
||||
[(PIC16callseq_end imm:$amt)]>;
|
||||
|
||||
//-----------------------------------
|
||||
// Vaious movlw insn patterns.
|
||||
//-----------------------------------
|
||||
let isReMaterializable = 1 in {
|
||||
def MOVLW : MovLit<0x24, "movlw">;
|
||||
// Move 8-bit literal to W.
|
||||
def movlw : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
|
||||
"movlw $src",
|
||||
[(set GPR:$dst, (i8 imm:$src))]>;
|
||||
|
||||
// Move a Lo(TGA) to W.
|
||||
def movlw_lo : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
|
||||
"movlw LOW(${src})",
|
||||
[(set GPR:$dst, (PIC16Lo tglobaladdr:$src))]>;
|
||||
|
||||
// Move a Hi(TGA) to W.
|
||||
def movlw_hi : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
|
||||
"movlw HIGH(${src})",
|
||||
[(set GPR:$dst, (PIC16Hi tglobaladdr:$src))]>;
|
||||
}
|
||||
|
||||
// Load/Store
|
||||
def LFSR1 : LoadInDirect <0x4, "lfsr", load>;
|
||||
//-------------------
|
||||
// FSR setting insns.
|
||||
//-------------------
|
||||
// These insns are matched via a DAG replacement pattern.
|
||||
def set_fsrlo:
|
||||
ByteFormat<0, (outs FSR16:$fsr),
|
||||
(ins GPR:$val),
|
||||
"movwf ${fsr}L",
|
||||
[]>;
|
||||
|
||||
let isTwoAddress = 1 in
|
||||
def set_fsrhi:
|
||||
ByteFormat<0, (outs FSR16:$dst),
|
||||
(ins FSR16:$src, GPR:$val),
|
||||
"movwf ${dst}H",
|
||||
[]>;
|
||||
|
||||
def copy_fsr:
|
||||
Pseudo<(outs FSR16:$dst), (ins FSR16:$src), "copy_fsr $dst, $src", []>;
|
||||
|
||||
//--------------------------
|
||||
// Store to memory
|
||||
//-------------------------
|
||||
// Direct store.
|
||||
def movwf :
|
||||
ByteFormat<0, (outs),
|
||||
(ins GPR:$val, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
|
||||
"movwf ${ptrlo} + ${offset}",
|
||||
[(PIC16Store GPR:$val, tglobaladdr:$ptrlo, (i8 imm:$ptrhi),
|
||||
(i8 imm:$offset))]>;
|
||||
|
||||
def movwf_1 :
|
||||
ByteFormat<0, (outs),
|
||||
(ins GPR:$val, i8mem:$ptrlo, i8imm:$ptrhi, i8imm:$offset),
|
||||
"movwf ${ptrlo} + ${offset}",
|
||||
[(PIC16Store GPR:$val, texternalsym:$ptrlo, (i8 imm:$ptrhi),
|
||||
(i8 imm:$offset))]>;
|
||||
|
||||
// Indirect store. Matched via a DAG replacement pattern.
|
||||
def store_indirect :
|
||||
ByteFormat<0, (outs),
|
||||
(ins GPR:$val, FSR16:$fsr, i8imm:$offset),
|
||||
"movwi $offset[$fsr]",
|
||||
[]>;
|
||||
|
||||
//----------------------------
|
||||
// Load from memory
|
||||
//----------------------------
|
||||
// Direct load.
|
||||
def movf :
|
||||
ByteFormat<0, (outs GPR:$dst),
|
||||
(ins i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
|
||||
"movf ${ptrlo} + ${offset}, W",
|
||||
[(set GPR:$dst,
|
||||
(PIC16Load tglobaladdr:$ptrlo, (i8 imm:$ptrhi),
|
||||
(i8 imm:$offset)))]>;
|
||||
|
||||
def movf_1 :
|
||||
ByteFormat<0, (outs GPR:$dst),
|
||||
(ins i8mem:$ptrlo, i8imm:$ptrhi, i8imm:$offset),
|
||||
"movf ${ptrlo} + ${offset}, W",
|
||||
[(set GPR:$dst,
|
||||
(PIC16Load texternalsym:$ptrlo, (i8 imm:$ptrhi),
|
||||
(i8 imm:$offset)))]>;
|
||||
|
||||
// Indirect load. Matched via a DAG replacement pattern.
|
||||
def load_indirect :
|
||||
ByteFormat<0, (outs GPR:$dst),
|
||||
(ins FSR16:$fsr, i8imm:$offset),
|
||||
"moviw $offset[$fsr]",
|
||||
[]>;
|
||||
|
||||
//-------------------------
|
||||
// Various add/sub patterns.
|
||||
//-------------------------
|
||||
// W += [F] ; load from F and add the value to W.
|
||||
class ADDFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
|
||||
ByteFormat<OpCode, (outs GPR:$dst),
|
||||
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
|
||||
!strconcat(OpcStr, " $ptrlo + $offset, W"),
|
||||
[(set GPR:$dst, (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
|
||||
(i8 imm:$ptrhi),
|
||||
(i8 imm:$offset))))]>;
|
||||
// let isTwoAddress = 1 in {
|
||||
def addfw_1: ADDFW<0, "addwf", add>;
|
||||
def addfw_2: ADDFW<0, "addwf", addc>;
|
||||
def addfwc: ADDFW<0, "addwfc", adde>; // With Carry.
|
||||
// }
|
||||
|
||||
// [F] += W ; add the value of W to [F].
|
||||
class ADDWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
|
||||
ByteFormat<OpCode, (outs),
|
||||
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
|
||||
!strconcat(OpcStr, " $ptrlo + $offset"),
|
||||
[(PIC16Store (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
|
||||
(i8 imm:$ptrhi),
|
||||
(i8 imm:$offset))),
|
||||
diraddr:$ptrlo,
|
||||
(i8 imm:$ptrhi), (i8 imm:$offset)
|
||||
)]>;
|
||||
def addwf_1: ADDWF<0, "addwf", add>;
|
||||
def addwf_2: ADDWF<0, "addwf", addc>;
|
||||
def addwfc: ADDWF<0, "addwfc", adde>; // With Carry.
|
||||
|
||||
// W -= [F] ; load from F and sub the value from W.
|
||||
class SUBFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
|
||||
ByteFormat<OpCode, (outs GPR:$dst),
|
||||
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
|
||||
!strconcat(OpcStr, " $ptrlo + $offset, W"),
|
||||
[(set GPR:$dst, (OpNode (PIC16Load diraddr:$ptrlo,
|
||||
(i8 imm:$ptrhi), (i8 imm:$offset)),
|
||||
GPR:$src))]>;
|
||||
//let isTwoAddress = 1 in {
|
||||
def subfw_1: SUBFW<0, "subwf", sub>;
|
||||
def subfw_2: SUBFW<0, "subwf", subc>;
|
||||
def subfwb: SUBFW<0, "subwfb", sube>; // With Borrow.
|
||||
//}
|
||||
|
||||
// [F] -= W ;
|
||||
class SUBWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
|
||||
ByteFormat<OpCode, (outs),
|
||||
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
|
||||
!strconcat(OpcStr, " $ptrlo + $offset"),
|
||||
[(PIC16Store (OpNode (PIC16Load diraddr:$ptrlo,
|
||||
(i8 imm:$ptrhi), (i8 imm:$offset)),
|
||||
GPR:$src), diraddr:$ptrlo,
|
||||
(i8 imm:$ptrhi), (i8 imm:$offset))]>;
|
||||
|
||||
def subwf_1: SUBWF<0, "subwf", sub>;
|
||||
def subwf_2: SUBWF<0, "subwf", subc>;
|
||||
def subwfb: SUBWF<0, "subwfb", sube>; // With Borrow.
|
||||
|
||||
// addlw
|
||||
// W += C ; add literal to W. (Without carry). May Produce a carry.
|
||||
class ADDLW<bits<6> opcode, string OpcStr, SDNode OpNode> :
|
||||
LiteralFormat<opcode, (outs GPR:$dst),
|
||||
(ins GPR:$src, i8imm:$literal),
|
||||
!strconcat(OpcStr, " $literal"),
|
||||
[(set GPR:$dst, (OpNode GPR:$src, (i8 imm:$literal)))]>;
|
||||
|
||||
// let isTwoAddress = 1 in {
|
||||
def addlw_1 : ADDLW<0, "addlw", add>;
|
||||
def addlw_2 : ADDLW<0, "addlw", addc>;
|
||||
def addlwc : ADDLW<0, "addlwc", adde>; // With Carry. (Assembler macro).
|
||||
//}
|
||||
|
||||
// sublw
|
||||
// W = C - W ; sub W from literal. (Without borrow).
|
||||
class SUBLW<bits<6> opcode, SDNode OpNode> :
|
||||
LiteralFormat<opcode, (outs GPR:$dst),
|
||||
(ins GPR:$src, i8imm:$literal),
|
||||
"addlw $literal",
|
||||
[(set GPR:$dst, (OpNode (i8 imm:$literal), GPR:$src))]>;
|
||||
|
||||
//let isTwoAddress = 1 in {
|
||||
def sublw_1 : SUBLW<0, sub>;
|
||||
def sublw_2 : SUBLW<0, subc>;
|
||||
//}
|
||||
|
||||
// Banksel.
|
||||
let isReMaterializable = 1 in {
|
||||
def MOVF : LoadDirect <0x23, "movf", load>;
|
||||
def banksel :
|
||||
Pseudo<(outs BSR:$dst),
|
||||
(ins i8mem:$ptr),
|
||||
"banksel $ptr",
|
||||
[(set BSR:$dst, (Banksel tglobaladdr:$ptr))]>;
|
||||
}
|
||||
|
||||
def MOVWF : StoreDirect <0x2b, "movwf", store>;
|
||||
|
||||
def MOVFSRINC : StoreInDirect <0x5, "movfsrinc", store>;
|
||||
|
||||
def RETURN : ControlFormat<0x03, (outs), (ins), "return", []>;
|
||||
|
||||
def ADDWF : Arith1M<0x01, "addwf", add>;
|
||||
def ADDFW : Arith1R<0x02, "addfw", add>;
|
||||
|
||||
def ADDWFE : Arith1M<0x03, "addwfe", adde>;
|
||||
def ADDFWE : Arith1R<0x04, "addfwe", adde>;
|
||||
|
||||
def ADDWFC : Arith1M<0x05, "addwfc", addc>;
|
||||
def ADDFWC : Arith1R<0x06, "addfwc", addc>;
|
||||
|
||||
def SUBWF : Arith1M<0x07, "subwf", sub>;
|
||||
def SUBFW : Arith1R<0x08, "subfw", sub>;
|
||||
|
||||
def SUBWFE : Arith1M<0x09, "subwfe", sube>;
|
||||
def SUBFWE : Arith1R<0x0a, "subfwe", sube>;
|
||||
|
||||
def SUBWFC : Arith1M<0x0b, "subwfc", subc>;
|
||||
def SUBFWC : Arith1R<0x0d, "subfwc", subc>;
|
||||
|
||||
def SUBRFW : Arith2R<0x08, "subfw", sub>;
|
||||
|
||||
def SUBRFWE : Arith2R<0x0a, "subfwe", sube>;
|
||||
|
||||
def SUBRFWC : Arith2R<0x0d, "subfwc", subc>;
|
||||
|
||||
def brtarget : Operand<OtherVT>;
|
||||
|
||||
class UncondJump< bits<4> op, string instr_asm>:
|
||||
BitFormat< op,
|
||||
(outs),
|
||||
(ins brtarget:$target),
|
||||
!strconcat(instr_asm, " $target"),
|
||||
[(br bb:$target)]>;
|
||||
|
||||
def GOTO : UncondJump<0x1, "goto">;
|
||||
|
||||
class LogicM<bits<6> op, string instr_asm, SDNode OpNode> :
|
||||
ByteFormat< op,
|
||||
(outs),
|
||||
(ins CPURegs:$b, mem:$dst),
|
||||
!strconcat(instr_asm, " $dst"),
|
||||
[(store (OpNode (load diraddrmode:$dst), CPURegs:$b), diraddrmode:$dst)]>;
|
||||
|
||||
class LogicR<bits<6> op, string instr_asm, SDNode OpNode> :
|
||||
ByteFormat< op,
|
||||
(outs CPURegs:$dst),
|
||||
(ins CPURegs:$b, mem:$c),
|
||||
!strconcat(instr_asm, " $c"),
|
||||
[(set CPURegs:$dst, (OpNode (load diraddrmode:$c), CPURegs:$b))]>;
|
||||
|
||||
class LogicI<bits<6> op, string instr_asm, SDNode OpNode, Operand Od> :
|
||||
LiteralFormat< op,
|
||||
(outs CPURegs:$dst),
|
||||
(ins CPURegs:$b, Od:$c),
|
||||
!strconcat(instr_asm, " $c"),
|
||||
[(set CPURegs:$dst, (OpNode CPURegs:$b, Od:$c ))]>;
|
||||
|
||||
def XORWF : LogicM<0x1,"xorwf",xor>;
|
||||
def XORFW : LogicR<0x1,"xorfw",xor>;
|
||||
def XORLW : LogicI<0x1,"xorlw",xor, so_imm>;
|
||||
|
||||
def ANDWF : LogicM<0x1,"andwf",and>;
|
||||
def ANDFW : LogicR<0x1,"andfw",and>;
|
||||
def ANDLW : LogicI<0x1,"andlw",and, so_imm>;
|
||||
|
||||
def IORWF : LogicM<0x1,"iorwf",or>;
|
||||
def IORFW : LogicR<0x1,"iorfw",or>;
|
||||
def IORLW : LogicI<0x1,"iorlw",or, so_imm>;
|
||||
|
||||
|
||||
/* For comparison before branch */
|
||||
def SDT_PIC16Cmp : SDTypeProfile<1, 3, [SDTCisSameAs<0,1>]>;
|
||||
def SDTIntBinOpPIC16 : SDTypeProfile<1, 2, [SDTCisSameAs<0,1>,
|
||||
SDTCisSameAs<1,2>, SDTCisInt<1>]>;
|
||||
|
||||
def PIC16Cmp : SDNode<"PIC16ISD::Cmp",SDTIntBinOpPIC16, [SDNPOutFlag]>;
|
||||
def PIC16XORCC : SDNode<"PIC16ISD::XORCC",SDTIntBinOpPIC16, [SDNPOutFlag]>;
|
||||
def PIC16SUBCC : SDNode<"PIC16ISD::SUBCC",SDTIntBinOpPIC16, [SDNPOutFlag]>;
|
||||
|
||||
def XORFWCC : LogicR<0x1,"xorfw",PIC16XORCC>;
|
||||
def XORLWCC : LogicI<0x1,"xorlw",PIC16XORCC, so_imm>;
|
||||
def SUBFWCC : Arith1R<0x1,"subfw",PIC16SUBCC>;
|
||||
def SUBLWCC : ArithI<0x1,"sublw",PIC16SUBCC, so_imm>;
|
||||
|
||||
|
||||
/* For branch conditions */
|
||||
def SDT_PIC16Branch : SDTypeProfile<0, 3, [SDTCisVT<0, OtherVT>,
|
||||
SDTCisVT<1,i8>, SDTCisVT<2,i8>]>;
|
||||
|
||||
def PIC16Branch : SDNode<"PIC16ISD::Branch",SDT_PIC16Branch,
|
||||
[SDNPHasChain, SDNPInFlag]>;
|
||||
|
||||
def PIC16BTFSS : SDNode<"PIC16ISD::BTFSS",SDT_PIC16Branch,
|
||||
[SDNPHasChain, SDNPInFlag]>;
|
||||
|
||||
def PIC16BTFSC : SDNode<"PIC16ISD::BTFSC",SDT_PIC16Branch,
|
||||
[SDNPHasChain, SDNPInFlag]>;
|
||||
|
||||
class InstrBitTestCC<bits<4> op, string instr_asm,SDNode OpNode>:
|
||||
BitFormat< op,
|
||||
(outs),
|
||||
(ins brtarget:$target ,so_imm:$i, STATUSRegs:$s ),
|
||||
!strconcat(instr_asm, " $s, $i, $target"),
|
||||
[(OpNode bb:$target, so_imm:$i, STATUSRegs:$s )]>;
|
||||
|
||||
def BTFSS : InstrBitTestCC<0x1,"btfss",PIC16BTFSS>;
|
||||
def BTFSC : InstrBitTestCC<0x1,"btfsc",PIC16BTFSC>;
|
||||
|
||||
|
||||
// Return insn.
|
||||
def Return :
|
||||
ControlFormat<0, (outs), (ins), "return", [(ret)]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pseudo instructions
|
||||
// PIC16 Replacment Patterns.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let Defs = [STKPTR], Uses = [STKPTR] in {
|
||||
def ADJCALLSTACKDOWN : Pseudo<255, (outs), (ins i8imm:$amt),
|
||||
"!ADJCALLSTACKDOWN $amt",
|
||||
[(callseq_start imm:$amt)]>;
|
||||
def ADJCALLSTACKUP : Pseudo<254, (outs), (ins i8imm:$amt),
|
||||
"!ADJCALLSTACKUP $amt",
|
||||
[(callseq_end imm:$amt)]>;
|
||||
}
|
||||
// Identify an indirect store and select insns for it.
|
||||
def : Pat<(PIC16Store GPR:$val, (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
|
||||
imm:$offset),
|
||||
(store_indirect GPR:$val,
|
||||
(set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
|
||||
imm:$offset)>;
|
||||
|
||||
// Identify an indirect load and select insns for it.
|
||||
def : Pat<(PIC16Load (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
|
||||
imm:$offset),
|
||||
(load_indirect (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
|
||||
imm:$offset)>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Arbitrary patterns that map to one or more instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
def : Pat<(ret), (RETURN)>;
|
||||
|
@ -15,206 +15,68 @@
|
||||
|
||||
#include "PIC16.h"
|
||||
#include "PIC16RegisterInfo.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/Type.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineLocation.h"
|
||||
#include "llvm/CodeGen/ValueTypes.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Target/TargetFrameInfo.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
// FIXME: add subtarget support.
|
||||
PIC16RegisterInfo::PIC16RegisterInfo(const TargetInstrInfo &tii)
|
||||
PIC16RegisterInfo::PIC16RegisterInfo(const TargetInstrInfo &tii,
|
||||
const PIC16Subtarget &st)
|
||||
: PIC16GenRegisterInfo(PIC16::ADJCALLSTACKDOWN, PIC16::ADJCALLSTACKUP),
|
||||
TII(tii) {}
|
||||
TII(tii),
|
||||
ST(st) {}
|
||||
|
||||
/// getRegisterNumbering - Given the enum value for some register, e.g.
|
||||
/// PIC16::RA, return the number that it corresponds to (e.g. 31).
|
||||
unsigned PIC16RegisterInfo::
|
||||
getRegisterNumbering(unsigned RegEnum)
|
||||
{
|
||||
assert (RegEnum <= 31 && "Unknown register number!");
|
||||
return RegEnum;
|
||||
}
|
||||
|
||||
void PIC16RegisterInfo::
|
||||
copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
const TargetRegisterClass *RC) const
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void PIC16RegisterInfo::reMaterialize(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I,
|
||||
unsigned DestReg,
|
||||
const MachineInstr *Orig) const
|
||||
{
|
||||
MachineInstr *MI = MBB.getParent()->CloneMachineInstr(Orig);
|
||||
MI->getOperand(0).setReg(DestReg);
|
||||
MBB.insert(I, MI);
|
||||
}
|
||||
|
||||
MachineInstr *PIC16RegisterInfo::
|
||||
foldMemoryOperand(MachineInstr* MI, unsigned OpNum, int FI) const
|
||||
{
|
||||
MachineInstr *NewMI = NULL;
|
||||
return NewMI;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Callee Saved Registers methods
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "PIC16GenRegisterInfo.inc"
|
||||
|
||||
/// PIC16 Callee Saved Registers
|
||||
const unsigned* PIC16RegisterInfo::
|
||||
getCalleeSavedRegs(const MachineFunction *MF) const
|
||||
{
|
||||
// PIC16 calle-save register range is $16-$26(s0-s7)
|
||||
getCalleeSavedRegs(const MachineFunction *MF) const {
|
||||
static const unsigned CalleeSavedRegs[] = { 0 };
|
||||
return CalleeSavedRegs;
|
||||
}
|
||||
|
||||
/// PIC16 Callee Saved Register Classes
|
||||
const TargetRegisterClass* const*
|
||||
PIC16RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const
|
||||
{
|
||||
// PIC16 Callee Saved Reg Classes
|
||||
const TargetRegisterClass* const*
|
||||
PIC16RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
||||
static const TargetRegisterClass * const CalleeSavedRegClasses[] = { 0 };
|
||||
return CalleeSavedRegClasses;
|
||||
}
|
||||
|
||||
BitVector PIC16RegisterInfo::
|
||||
getReservedRegs(const MachineFunction &MF) const
|
||||
{
|
||||
BitVector PIC16RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
||||
BitVector Reserved(getNumRegs());
|
||||
return Reserved;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Stack Frame Processing methods
|
||||
// +----------------------------+
|
||||
//
|
||||
// FIXME: Add stack layout description here.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// hasFP - Return true if the specified function should have a dedicated frame
|
||||
// pointer register. This is true if the function has variable sized allocas or
|
||||
// if frame pointer elimination is disabled.
|
||||
bool PIC16RegisterInfo::
|
||||
hasFP(const MachineFunction &MF) const {
|
||||
bool PIC16RegisterInfo::hasFP(const MachineFunction &MF) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This function eliminate ADJCALLSTACKDOWN,
|
||||
// ADJCALLSTACKUP pseudo instructions
|
||||
void PIC16RegisterInfo::
|
||||
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I) const {
|
||||
// Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions.
|
||||
MBB.erase(I);
|
||||
}
|
||||
eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
||||
RegScavenger *RS) const
|
||||
{ /* NOT YET IMPLEMENTED */ }
|
||||
|
||||
// FrameIndex represent objects inside a abstract stack.
|
||||
// We must replace FrameIndex with an stack/frame pointer
|
||||
// direct reference.
|
||||
void PIC16RegisterInfo::
|
||||
eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
||||
RegScavenger *RS) const
|
||||
{
|
||||
MachineInstr &MI = *II;
|
||||
MachineFunction &MF = *MI.getParent()->getParent();
|
||||
|
||||
unsigned i = 0;
|
||||
while (!MI.getOperand(i).isFI()) {
|
||||
++i;
|
||||
assert(i < MI.getNumOperands() &&
|
||||
"Instr doesn't have FrameIndex operand!");
|
||||
}
|
||||
|
||||
int FrameIndex = MI.getOperand(i).getIndex();
|
||||
int stackSize = MF.getFrameInfo()->getStackSize();
|
||||
int spOffset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
|
||||
|
||||
DOUT << "\nFunction : " << MF.getFunction()->getName() << "\n";
|
||||
DOUT << "<--------->\n";
|
||||
#ifndef NDEBUG
|
||||
MI.print(DOUT);
|
||||
#endif
|
||||
DOUT << "FrameIndex : " << FrameIndex << "\n";
|
||||
DOUT << "spOffset : " << spOffset << "\n";
|
||||
DOUT << "stackSize : " << stackSize << "\n";
|
||||
|
||||
// As explained on LowerFORMAL_ARGUMENTS, detect negative offsets
|
||||
// and adjust SPOffsets considering the final stack size.
|
||||
int Offset = ((spOffset < 0) ? (stackSize + (-(spOffset+4))) : (spOffset));
|
||||
|
||||
DOUT << "Offset : " << Offset << "\n";
|
||||
DOUT << "<--------->\n";
|
||||
|
||||
// MI.getOperand(i+1).ChangeToImmediate(Offset);
|
||||
MI.getOperand(i).ChangeToRegister(getFrameRegister(MF), false);
|
||||
}
|
||||
void PIC16RegisterInfo::emitPrologue(MachineFunction &MF) const
|
||||
{ /* NOT YET IMPLEMENTED */ }
|
||||
|
||||
void PIC16RegisterInfo::
|
||||
emitPrologue(MachineFunction &MF) const
|
||||
{
|
||||
}
|
||||
|
||||
void PIC16RegisterInfo::
|
||||
emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
|
||||
{
|
||||
}
|
||||
|
||||
void PIC16RegisterInfo::
|
||||
processFunctionBeforeFrameFinalized(MachineFunction &MF) const
|
||||
{
|
||||
}
|
||||
|
||||
unsigned PIC16RegisterInfo::
|
||||
getRARegister() const {
|
||||
assert(0 && "What is the return address register");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PIC16RegisterInfo::
|
||||
getFrameRegister(MachineFunction &MF) const {
|
||||
return PIC16::STKPTR;
|
||||
}
|
||||
|
||||
unsigned PIC16RegisterInfo::
|
||||
getEHExceptionRegister() const {
|
||||
assert(0 && "What is the exception register");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PIC16RegisterInfo::
|
||||
getEHHandlerRegister() const {
|
||||
assert(0 && "What is the exception handler register");
|
||||
return 0;
|
||||
}
|
||||
emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
|
||||
{ /* NOT YET IMPLEMENTED */ }
|
||||
|
||||
int PIC16RegisterInfo::
|
||||
getDwarfRegNum(unsigned RegNum, bool isEH) const {
|
||||
assert(0 && "What is the dwarf register number");
|
||||
assert(0 && "Not keeping track of debug information yet!!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned PIC16RegisterInfo::getFrameRegister(MachineFunction &MF) const {
|
||||
assert(0 && "PIC16 Does not have any frame register");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PIC16RegisterInfo::getRARegister() const {
|
||||
assert(0 && "PIC16 Does not have any return address register");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "PIC16GenRegisterInfo.inc"
|
||||
|
||||
|
@ -20,65 +20,43 @@
|
||||
namespace llvm {
|
||||
|
||||
// Forward Declarations.
|
||||
class TargetInstrInfo;
|
||||
class Type;
|
||||
class PIC16Subtarget;
|
||||
class TargetInstrInfo;
|
||||
|
||||
struct PIC16RegisterInfo : public PIC16GenRegisterInfo {
|
||||
const TargetInstrInfo &TII;
|
||||
class PIC16RegisterInfo : public PIC16GenRegisterInfo {
|
||||
private:
|
||||
const TargetInstrInfo &TII;
|
||||
const PIC16Subtarget &ST;
|
||||
|
||||
explicit PIC16RegisterInfo(const TargetInstrInfo &tii);
|
||||
public:
|
||||
PIC16RegisterInfo(const TargetInstrInfo &tii,
|
||||
const PIC16Subtarget &st);
|
||||
|
||||
/// getRegisterNumbering - Given the enum value for some register, e.g.
|
||||
/// PIC16::RA, return the number that it corresponds to (e.g. 31).
|
||||
static unsigned getRegisterNumbering(unsigned RegEnum);
|
||||
|
||||
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
|
||||
unsigned DestReg, const MachineInstr *Orig) const;
|
||||
//------------------------------------------------------
|
||||
// Pure virtual functions from TargetRegisterInfo
|
||||
//------------------------------------------------------
|
||||
|
||||
MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
|
||||
int FrameIndex) const;
|
||||
// PIC16 callee saved registers
|
||||
virtual const unsigned*
|
||||
getCalleeSavedRegs(const MachineFunction *MF = 0) const;
|
||||
|
||||
MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
|
||||
MachineInstr* LoadMI) const {
|
||||
return 0;
|
||||
}
|
||||
// PIC16 callee saved register classes
|
||||
virtual const TargetRegisterClass* const *
|
||||
getCalleeSavedRegClasses(const MachineFunction *MF) const;
|
||||
|
||||
void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
const TargetRegisterClass *RC) const;
|
||||
|
||||
virtual BitVector getReservedRegs(const MachineFunction &MF) const;
|
||||
virtual bool hasFP(const MachineFunction &MF) const;
|
||||
|
||||
const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const;
|
||||
virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI,
|
||||
int SPAdj, RegScavenger *RS=NULL) const;
|
||||
|
||||
const TargetRegisterClass* const*
|
||||
getCalleeSavedRegClasses(const MachineFunction* MF = 0) const;
|
||||
virtual void emitPrologue(MachineFunction &MF) const;
|
||||
virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||
virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const;
|
||||
virtual unsigned getFrameRegister(MachineFunction &MF) const;
|
||||
virtual unsigned getRARegister() const;
|
||||
|
||||
BitVector getReservedRegs(const MachineFunction &MF) const;
|
||||
|
||||
bool hasFP(const MachineFunction &MF) const;
|
||||
|
||||
void eliminateCallFramePseudoInstr(MachineFunction &MF,
|
||||
MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I) const;
|
||||
|
||||
/// Stack Frame Processing Methods.
|
||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, RegScavenger *RS = NULL) const;
|
||||
|
||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
||||
|
||||
void emitPrologue(MachineFunction &MF) const;
|
||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||
|
||||
/// Debug information queries.
|
||||
unsigned getRARegister() const;
|
||||
unsigned getFrameRegister(MachineFunction &MF) const;
|
||||
|
||||
/// Exception handling queries.
|
||||
unsigned getEHExceptionRegister() const;
|
||||
unsigned getEHHandlerRegister() const;
|
||||
|
||||
int getDwarfRegNum(unsigned RegNum, bool isEH) const;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -11,74 +11,22 @@
|
||||
// Declarations that describe the PIC16 register file
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// We have banks of 32 registers each.
|
||||
class PIC16Reg<string n> : Register<n> {
|
||||
field bits<5> Num;
|
||||
let Namespace = "PIC16";
|
||||
}
|
||||
|
||||
// PIC16 CPU Registers
|
||||
class PIC16GPRReg<bits<5> num, string n> : PIC16Reg<n> {
|
||||
let Num = num;
|
||||
}
|
||||
// PIC16 Registers.
|
||||
def W : PIC16Reg<"W">;
|
||||
def FSR0 : PIC16Reg<"FSR0">;
|
||||
def FSR1 : PIC16Reg<"FSR1">;
|
||||
def BS : PIC16Reg<"BS">;
|
||||
|
||||
// CPU GPR Registers
|
||||
def FSR0 : PIC16GPRReg< 0, "FSR0">, DwarfRegNum<[0]>;
|
||||
def FSR1 : PIC16GPRReg< 1, "FSR1">, DwarfRegNum<[1]>;
|
||||
def STATUS : PIC16Reg<"STATUS">;
|
||||
|
||||
// CPU Registers Class
|
||||
def PTRRegs : RegisterClass<"PIC16", [i16], 8,
|
||||
[FSR0, FSR1]>
|
||||
{
|
||||
let MethodProtos = [{
|
||||
iterator allocation_order_end(const MachineFunction &MF) const;
|
||||
}];
|
||||
let MethodBodies = [{
|
||||
PTRRegsClass::iterator
|
||||
PTRRegsClass::allocation_order_end(const MachineFunction &MF) const {
|
||||
return end();
|
||||
}
|
||||
}];
|
||||
}
|
||||
// PIC16 Register classes.
|
||||
def GPR : RegisterClass<"PIC16", [i8], 8, [W]>;
|
||||
def FSR16 : RegisterClass<"PIC16", [i16], 8, [FSR0, FSR1]>;
|
||||
def BSR : RegisterClass<"PIC16", [i8], 8, [BS]>;
|
||||
|
||||
def WREG : PIC16GPRReg< 0, "WREG">, DwarfRegNum<[0]>;
|
||||
def STATUSR: RegisterClass<"PIC16", [i8], 8, [STATUS]>;
|
||||
|
||||
// CPU Registers Class
|
||||
def CPURegs : RegisterClass<"PIC16", [i8], 8,
|
||||
[WREG]>
|
||||
{
|
||||
let MethodProtos = [{
|
||||
iterator allocation_order_end(const MachineFunction &MF) const;
|
||||
}];
|
||||
let MethodBodies = [{
|
||||
CPURegsClass::iterator
|
||||
CPURegsClass::allocation_order_end(const MachineFunction &MF) const {
|
||||
return end();
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
def STATUSREG : PIC16GPRReg<2, "STATUS">, DwarfRegNum<[0]>;
|
||||
|
||||
// STATUS Registers Class
|
||||
def STATUSRegs : RegisterClass<"PIC16", [i8], 8,
|
||||
[STATUSREG]>;
|
||||
|
||||
|
||||
// Dummy stack pointer.
|
||||
def STKPTR : PIC16GPRReg< 0, "SP">, DwarfRegNum<[0]>;
|
||||
|
||||
// CPU Registers Class
|
||||
def STKRegs : RegisterClass<"PIC16", [i8], 8,
|
||||
[STKPTR]>
|
||||
{
|
||||
let MethodProtos = [{
|
||||
iterator allocation_order_end(const MachineFunction &MF) const;
|
||||
}];
|
||||
let MethodBodies = [{
|
||||
STKRegsClass::iterator
|
||||
STKRegsClass::allocation_order_end(const MachineFunction &MF) const {
|
||||
return end();
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
@ -11,14 +11,14 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "PIC16.h"
|
||||
#include "PIC16Subtarget.h"
|
||||
#include "PIC16GenSubtarget.inc"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
PIC16Subtarget::PIC16Subtarget(const TargetMachine &TM, const Module &M,
|
||||
const std::string &FS)
|
||||
:IsPIC16Old(false)
|
||||
PIC16Subtarget::PIC16Subtarget(const Module &M, const std::string &FS,
|
||||
bool Cooper)
|
||||
:IsCooper(Cooper)
|
||||
{
|
||||
std::string CPU = "generic";
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
#ifndef PIC16SUBTARGET_H
|
||||
#define PIC16SUBTARGET_H
|
||||
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetSubtarget.h"
|
||||
|
||||
#include <string>
|
||||
@ -23,19 +22,23 @@ namespace llvm {
|
||||
class Module;
|
||||
|
||||
class PIC16Subtarget : public TargetSubtarget {
|
||||
bool IsPIC16Old;
|
||||
|
||||
// IsCooper - Target ISA is Cooper.
|
||||
bool IsCooper;
|
||||
|
||||
public:
|
||||
/// This constructor initializes the data members to match that
|
||||
/// of the specified module.
|
||||
///
|
||||
PIC16Subtarget(const TargetMachine &TM, const Module &M,
|
||||
const std::string &FS);
|
||||
PIC16Subtarget(const Module &M, const std::string &FS, bool Cooper);
|
||||
|
||||
/// isCooper - Returns true if the target ISA is Cooper.
|
||||
bool isCooper() const { return IsCooper; }
|
||||
|
||||
/// ParseSubtargetFeatures - Parses features string setting specified
|
||||
/// subtarget options. Definition of function is auto generated by tblgen.
|
||||
void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU);
|
||||
};
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
#endif // PIC16SUBTARGET_H
|
||||
|
@ -17,11 +17,15 @@
|
||||
using namespace llvm;
|
||||
|
||||
PIC16TargetAsmInfo::
|
||||
PIC16TargetAsmInfo(const PIC16TargetMachine &TM)
|
||||
PIC16TargetAsmInfo(const PIC16TargetMachine &TM)
|
||||
: TargetAsmInfo(TM) {
|
||||
Data16bitsDirective = "\t.half\t";
|
||||
Data32bitsDirective = "\t.word\t";
|
||||
CommentString = ";";
|
||||
COMMDirective = "\t";
|
||||
COMMDirectiveTakesAlignment = 0;
|
||||
Data8bitsDirective = " db ";
|
||||
Data16bitsDirective = " db ";
|
||||
Data32bitsDirective = " db ";
|
||||
DataSectionStartSuffix = " IDATA ";
|
||||
UDataSectionStartSuffix = " UDATA ";
|
||||
TextSectionStartSuffix = " CODE ";
|
||||
RomDataSectionStartSuffix = " ROMDATA ";
|
||||
ZeroDirective = NULL;
|
||||
}
|
||||
|
@ -23,6 +23,17 @@ namespace llvm {
|
||||
|
||||
struct PIC16TargetAsmInfo : public TargetAsmInfo {
|
||||
PIC16TargetAsmInfo(const PIC16TargetMachine &TM);
|
||||
const char *UDataSectionStartSuffix;
|
||||
const char *RomDataSectionStartSuffix;
|
||||
public :
|
||||
const char *getUDataSectionStartSuffix() const {
|
||||
return UDataSectionStartSuffix;
|
||||
}
|
||||
const char *getRomDataSectionStartSuffix() const {
|
||||
return RomDataSectionStartSuffix;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "PIC16TargetMachine.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/PassManager.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/Target/TargetAsmInfo.h"
|
||||
#include "llvm/Target/TargetMachineRegistry.h"
|
||||
|
||||
@ -29,50 +30,42 @@ using namespace llvm;
|
||||
extern "C" int PIC16TargetMachineModule;
|
||||
int PIC16TargetMachineModule = 0;
|
||||
|
||||
namespace {
|
||||
// Register the targets
|
||||
RegisterTarget<PIC16TargetMachine> X("pic16", "PIC16 14-bit [experimental]");
|
||||
}
|
||||
|
||||
PIC16TargetMachine::
|
||||
PIC16TargetMachine(const Module &M, const std::string &FS) :
|
||||
Subtarget(*this, M, FS), DataLayout("e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8"),
|
||||
// Register the targets
|
||||
static RegisterTarget<PIC16TargetMachine>
|
||||
X("pic16", "PIC16 14-bit (experimental).");
|
||||
static RegisterTarget<CooperTargetMachine>
|
||||
Y("cooper", "PIC16 Cooper (experimental).");
|
||||
|
||||
// PIC16TargetMachine - Traditional PIC16 Machine.
|
||||
PIC16TargetMachine::PIC16TargetMachine(const Module &M, const std::string &FS,
|
||||
bool Cooper)
|
||||
: Subtarget(M, FS, Cooper),
|
||||
DataLayout("e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8"),
|
||||
InstrInfo(*this), TLInfo(*this),
|
||||
FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0) { }
|
||||
|
||||
// CooperTargetMachine - Uses the same PIC16TargetMachine, but makes IsCooper
|
||||
// as true.
|
||||
CooperTargetMachine::CooperTargetMachine(const Module &M, const std::string &FS)
|
||||
: PIC16TargetMachine(M, FS, true) {}
|
||||
|
||||
const TargetAsmInfo *PIC16TargetMachine::createTargetAsmInfo() const
|
||||
{
|
||||
|
||||
const TargetAsmInfo *PIC16TargetMachine::createTargetAsmInfo() const {
|
||||
return new PIC16TargetAsmInfo(*this);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pass Pipeline Configuration
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
bool PIC16TargetMachine::addInstSelector(PassManagerBase &PM, bool Fast)
|
||||
{
|
||||
bool PIC16TargetMachine::addInstSelector(PassManagerBase &PM, bool Fast) {
|
||||
// Install an instruction selector.
|
||||
PM.add(createPIC16ISelDag(*this));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PIC16TargetMachine::
|
||||
addPrologEpilogInserter(PassManagerBase &PM, bool Fast)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PIC16TargetMachine::addPreEmitPass(PassManagerBase &PM, bool Fast)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PIC16TargetMachine::
|
||||
addAssemblyEmitter(PassManagerBase &PM, bool Fast, raw_ostream &Out)
|
||||
{
|
||||
addAssemblyEmitter(PassManagerBase &PM, bool Fast, raw_ostream &Out) {
|
||||
// Output assembly language.
|
||||
PM.add(createPIC16CodePrinterPass(Out, *this));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "PIC16InstrInfo.h"
|
||||
#include "PIC16ISelLowering.h"
|
||||
#include "PIC16RegisterInfo.h"
|
||||
#include "PIC16Subtarget.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetFrameInfo.h"
|
||||
@ -31,31 +32,42 @@ class PIC16TargetMachine : public LLVMTargetMachine {
|
||||
const TargetData DataLayout; // Calculates type size & alignment
|
||||
PIC16InstrInfo InstrInfo;
|
||||
PIC16TargetLowering TLInfo;
|
||||
|
||||
// PIC16 does not have any call stack frame, therefore not having
|
||||
// any PIC16 specific FrameInfo class.
|
||||
TargetFrameInfo FrameInfo;
|
||||
|
||||
protected:
|
||||
virtual const TargetAsmInfo *createTargetAsmInfo() const;
|
||||
|
||||
public:
|
||||
PIC16TargetMachine(const Module &M, const std::string &FS);
|
||||
|
||||
virtual const TargetFrameInfo *getFrameInfo() const
|
||||
{ return &FrameInfo; }
|
||||
virtual const PIC16InstrInfo *getInstrInfo() const
|
||||
{ return &InstrInfo; }
|
||||
virtual const TargetData *getTargetData() const
|
||||
{ return &DataLayout; }
|
||||
virtual PIC16TargetLowering *getTargetLowering() const
|
||||
{ return const_cast<PIC16TargetLowering*>(&TLInfo); }
|
||||
virtual const PIC16RegisterInfo *getRegisterInfo() const
|
||||
{ return &InstrInfo.getRegisterInfo(); }
|
||||
|
||||
public:
|
||||
PIC16TargetMachine(const Module &M, const std::string &FS,
|
||||
bool Cooper = false);
|
||||
|
||||
virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; }
|
||||
virtual const PIC16InstrInfo *getInstrInfo() const { return &InstrInfo; }
|
||||
virtual const TargetData *getTargetData() const { return &DataLayout;}
|
||||
virtual const PIC16Subtarget *getSubtargetImpl() const { return &Subtarget; }
|
||||
|
||||
virtual const PIC16RegisterInfo *getRegisterInfo() const {
|
||||
return &(InstrInfo.getRegisterInfo());
|
||||
}
|
||||
|
||||
virtual PIC16TargetLowering *getTargetLowering() const {
|
||||
return const_cast<PIC16TargetLowering*>(&TLInfo);
|
||||
}
|
||||
|
||||
virtual bool addInstSelector(PassManagerBase &PM, bool Fast);
|
||||
virtual bool addPrologEpilogInserter(PassManagerBase &PM, bool Fast);
|
||||
virtual bool addPreEmitPass(PassManagerBase &PM, bool Fast);
|
||||
virtual bool addAssemblyEmitter(PassManagerBase &PM, bool Fast,
|
||||
virtual bool addAssemblyEmitter(PassManagerBase &PM, bool Fast,
|
||||
raw_ostream &Out);
|
||||
};
|
||||
}; // PIC16TargetMachine.
|
||||
|
||||
/// CooperTargetMachine
|
||||
class CooperTargetMachine : public PIC16TargetMachine {
|
||||
public:
|
||||
CooperTargetMachine(const Module &M, const std::string &FS);
|
||||
}; // CooperTargetMachine.
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user