mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-28 23:38:59 +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
|
#ifndef LLVM_TARGET_PIC16_H
|
||||||
#define TARGET_PIC16_H
|
#define LLVM_TARGET_PIC16_H
|
||||||
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class PIC16TargetMachine;
|
class PIC16TargetMachine;
|
||||||
class FunctionPassManager;
|
|
||||||
class FunctionPass;
|
class FunctionPass;
|
||||||
class MachineCodeEmitter;
|
class MachineCodeEmitter;
|
||||||
class raw_ostream;
|
class raw_ostream;
|
||||||
|
@ -15,30 +15,24 @@
|
|||||||
|
|
||||||
include "../Target.td"
|
include "../Target.td"
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Descriptions
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
include "PIC16RegisterInfo.td"
|
include "PIC16RegisterInfo.td"
|
||||||
include "PIC16CallingConv.td"
|
|
||||||
include "PIC16InstrInfo.td"
|
include "PIC16InstrInfo.td"
|
||||||
|
|
||||||
def PIC16InstrInfo : InstrInfo {
|
//===----------------------------------------------------------------------===//
|
||||||
let TSFlagsFields = [];
|
// Subtarget Features.
|
||||||
let TSFlagsShifts = [];
|
//===----------------------------------------------------------------------===//
|
||||||
}
|
def FeatureCooper : SubtargetFeature<"cooper", "IsCooper", "true",
|
||||||
|
"PIC16 Cooper ISA Support">;
|
||||||
|
|
||||||
|
|
||||||
// Not currently supported, but work as SubtargetFeature placeholder.
|
|
||||||
def FeaturePIC16Old : SubtargetFeature<"pic16old", "IsPIC16Old", "true",
|
|
||||||
"PIC16 Old ISA Support">;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// PIC16 processors supported.
|
// PIC16 supported processors.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
def : Processor<"generic", NoItineraries, []>;
|
def : Processor<"generic", NoItineraries, []>;
|
||||||
|
def : Processor<"cooper", NoItineraries, [FeatureCooper]>;
|
||||||
|
|
||||||
|
|
||||||
|
def PIC16InstrInfo : InstrInfo {}
|
||||||
|
|
||||||
def PIC16 : Target {
|
def PIC16 : Target {
|
||||||
let InstructionSet = PIC16InstrInfo;
|
let InstructionSet = PIC16InstrInfo;
|
||||||
|
@ -12,99 +12,91 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#define DEBUG_TYPE "asm-printer"
|
#include "PIC16AsmPrinter.h"
|
||||||
#include "PIC16.h"
|
#include "PIC16TargetAsmInfo.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 "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/Target/TargetAsmInfo.h"
|
#include "llvm/Support/Mangler.h"
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Function.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/Target/TargetOptions.h"
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||||
#include <cctype>
|
#include "llvm/DerivedTypes.h"
|
||||||
|
|
||||||
using namespace llvm;
|
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"
|
#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
|
/// createPIC16CodePrinterPass - Returns a pass that prints the PIC16
|
||||||
/// assembly code for a MachineFunction to the given output stream,
|
/// assembly code for a MachineFunction to the given output stream,
|
||||||
/// using the given target machine description. This should work
|
/// 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());
|
return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PIC16AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const
|
void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
|
||||||
{
|
|
||||||
// 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)
|
|
||||||
{
|
|
||||||
const MachineOperand &MO = MI->getOperand(opNum);
|
const MachineOperand &MO = MI->getOperand(opNum);
|
||||||
const TargetRegisterInfo &RI = *TM.getRegisterInfo();
|
|
||||||
|
|
||||||
switch (MO.getType()) {
|
switch (MO.getType()) {
|
||||||
case MachineOperand::MO_Register:
|
case MachineOperand::MO_Register:
|
||||||
if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
|
if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
|
||||||
O << RI.get(MO.getReg()).Name;
|
O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
|
||||||
else
|
else
|
||||||
assert(0 && "not implemented");
|
assert(0 && "not implemented");
|
||||||
break;
|
return;
|
||||||
|
|
||||||
case MachineOperand::MO_Immediate:
|
case MachineOperand::MO_Immediate:
|
||||||
if (!Modifier || strcmp(Modifier, "no_hash") != 0)
|
|
||||||
O << "#";
|
|
||||||
O << (int)MO.getImm();
|
O << (int)MO.getImm();
|
||||||
break;
|
|
||||||
|
|
||||||
case MachineOperand::MO_MachineBasicBlock:
|
|
||||||
printBasicBlockLabel(MO.getMBB());
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case MachineOperand::MO_GlobalAddress:
|
case MachineOperand::MO_GlobalAddress:
|
||||||
O << Mang->getValueName(MO.getGlobal())<<'+'<<MO.getOffset();
|
O << Mang->getValueName(MO.getGlobal());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MachineOperand::MO_ExternalSymbol:
|
case MachineOperand::MO_ExternalSymbol:
|
||||||
O << MO.getSymbolName();
|
O << MO.getSymbolName();
|
||||||
break;
|
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:
|
default:
|
||||||
O << "<unknown operand type>"; abort ();
|
assert(0 && " Operand type not supported.");
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PIC16AsmPrinter::doInitialization (Module &M) {
|
||||||
bool PIC16AsmPrinter::doInitialization(Module &M)
|
|
||||||
{
|
|
||||||
bool Result = AsmPrinter::doInitialization(M);
|
bool Result = AsmPrinter::doInitialization(M);
|
||||||
|
// FIXME:: This is temporary solution to generate the include file.
|
||||||
|
// 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;
|
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();
|
const TargetData *TD = TM.getTargetData();
|
||||||
|
|
||||||
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
|
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
if (!I->hasInitializer()) // External global require no code
|
if (!I->hasInitializer()) // External global require no code.
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (EmitSpecialLLVMGlobal(I)) {
|
Constant *C = I->getInitializer();
|
||||||
continue;
|
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();
|
Constant *C = I->getInitializer();
|
||||||
const Type *Ty = C->getType();
|
const Type *Ty = C->getType();
|
||||||
unsigned Size = TD->getABITypeSize(Ty);
|
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;
|
void PIC16AsmPrinter::emitFunctionTempData(MachineFunction &MF) {
|
||||||
if (I->hasHiddenVisibility())
|
// Emit temporary variables.
|
||||||
VisibilityDirective = TAI->getHiddenDirective();
|
MachineFrameInfo *FrameInfo = MF.getFrameInfo();
|
||||||
else if (I->hasProtectedVisibility())
|
if (FrameInfo->hasStackObjects()) {
|
||||||
VisibilityDirective = TAI->getProtectedDirective();
|
int indexBegin = FrameInfo->getObjectIndexBegin();
|
||||||
|
int indexEnd = FrameInfo->getObjectIndexEnd();
|
||||||
|
|
||||||
if (VisibilityDirective)
|
if (indexBegin < indexEnd)
|
||||||
O << VisibilityDirective << name << "\n";
|
O << CurrentFnName << ".tmp RES"<< " "
|
||||||
|
<<indexEnd - indexBegin <<"\n";
|
||||||
if (C->isNullValue()) {
|
/*
|
||||||
if (I->hasExternalLinkage()) {
|
while (indexBegin < indexEnd) {
|
||||||
if (const char *Directive = TAI->getZeroFillDirective()) {
|
O << CurrentFnName << "_tmp_" << indexBegin << " " << "RES"<< " "
|
||||||
O << "\t.globl\t" << name << "\n";
|
<< 1 << "\n" ;
|
||||||
O << Directive << "__DATA__, __common, " << name << ", "
|
indexBegin++;
|
||||||
<< 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
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::
|
/// The function is same as AsmPrinter::SwitchtoDataSection except the call
|
||||||
SwitchToTextSection(const char *NewSection, const GlobalValue *GV)
|
/// to getUDataSectionStartSuffix.
|
||||||
{
|
void PIC16AsmPrinter::SwitchToUDataSection(const char *NewSection,
|
||||||
O << "\n";
|
const GlobalValue *GV) {
|
||||||
if (NewSection && *NewSection) {
|
std::string NS;
|
||||||
std::string codeSection = "code_";
|
if (GV && GV->hasSection())
|
||||||
codeSection += NewSection;
|
NS = TAI->getSwitchToSectionDirective() + GV->getSection();
|
||||||
codeSection += " ";
|
|
||||||
codeSection += "CODE";
|
|
||||||
AsmPrinter::SwitchToTextSection(codeSection.c_str(), GV);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
AsmPrinter::SwitchToTextSection(NewSection, GV);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIC16AsmPrinter::
|
|
||||||
SwitchToDataSection(const char *NewSection, const GlobalValue *GV)
|
|
||||||
{
|
|
||||||
// Need to append index for page.
|
|
||||||
O << "\n";
|
|
||||||
if (NewSection && *NewSection) {
|
|
||||||
std::string dataSection = "udata_";
|
|
||||||
dataSection += NewSection;
|
|
||||||
if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) {
|
|
||||||
dataSection = dataSection.substr(0, dataSection.length() - 2);
|
|
||||||
}
|
|
||||||
dataSection += " ";
|
|
||||||
dataSection += "UDATA";
|
|
||||||
AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV);
|
|
||||||
}
|
|
||||||
else
|
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::
|
/// The function is same as AsmPrinter::SwitchtoDataSection except the call
|
||||||
SwitchToDataOvrSection(const char *NewSection, const GlobalValue *GV)
|
/// to getRomDataSectionStartSuffix.
|
||||||
{
|
void PIC16AsmPrinter::SwitchToRomDataSection(const char *NewSection,
|
||||||
O << "\n";
|
const GlobalValue *GV) {
|
||||||
if (NewSection && *NewSection) {
|
std::string NS;
|
||||||
std::string dataSection = "frame_";
|
if (GV && GV->hasSection())
|
||||||
dataSection += NewSection;
|
NS = TAI->getSwitchToSectionDirective() + GV->getSection();
|
||||||
if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) {
|
|
||||||
dataSection = dataSection.substr(0, dataSection.length() - 2);
|
|
||||||
}
|
|
||||||
dataSection += "_";
|
|
||||||
dataSection += CurrentFnName;
|
|
||||||
dataSection += " ";
|
|
||||||
dataSection += "UDATA_OVR";
|
|
||||||
AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV);
|
|
||||||
}
|
|
||||||
else
|
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"
|
#define DEBUG_TYPE "pic16-isel"
|
||||||
|
|
||||||
#include "PIC16.h"
|
#include "PIC16ISelDAGToDAG.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 "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
/// createPIC16ISelDag - This pass converts a legalized DAG into a
|
||||||
// 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
|
|
||||||
/// PIC16-specific DAG, ready for instruction scheduling.
|
/// PIC16-specific DAG, ready for instruction scheduling.
|
||||||
FunctionPass *llvm::createPIC16ISelDag(PIC16TargetMachine &TM) {
|
FunctionPass *llvm::createPIC16ISelDag(PIC16TargetMachine &TM) {
|
||||||
return new PIC16DAGToDAGISel(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.
|
// Start the numbering from where ISD NodeType finishes.
|
||||||
FIRST_NUMBER = ISD::BUILTIN_OP_END,
|
FIRST_NUMBER = ISD::BUILTIN_OP_END,
|
||||||
|
|
||||||
// used for encapsulating the expanded nodes into one node.
|
Lo, // Low 8-bits of GlobalAddress.
|
||||||
Package,
|
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
|
// Keep track of different address spaces.
|
||||||
Hi,
|
enum AddressSpace {
|
||||||
|
RAM_SPACE = 0, // RAM address space
|
||||||
// Get the Lower 16 bits from a 32-bit immediate
|
ROM_SPACE = 1 // ROM address space number is 1
|
||||||
Lo,
|
|
||||||
|
|
||||||
Cmp, // PIC16 Generic Comparison instruction.
|
|
||||||
Branch, // PIC16 Generic Branch Instruction.
|
|
||||||
BTFSS, // PIC16 BitTest Instruction (Skip if set).
|
|
||||||
BTFSC, // PIC16 BitTest Instruction (Skip if clear).
|
|
||||||
|
|
||||||
// PIC16 comparison to be converted to either XOR or SUB
|
|
||||||
// Following instructions cater to those convertions.
|
|
||||||
XORCC,
|
|
||||||
SUBCC,
|
|
||||||
|
|
||||||
// Get the Global Address wrapped into a wrapper that also captures
|
|
||||||
// the bank or page.
|
|
||||||
Wrapper,
|
|
||||||
SetBank,
|
|
||||||
SetPage
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// TargetLowering Implementation
|
// TargetLowering Implementation
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
class PIC16TargetLowering : public TargetLowering
|
class PIC16TargetLowering : public TargetLowering {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
typedef std::map<SDNode *, SDNode *> NodeMap_t;
|
|
||||||
|
|
||||||
explicit PIC16TargetLowering(PIC16TargetMachine &TM);
|
explicit PIC16TargetLowering(PIC16TargetMachine &TM);
|
||||||
|
|
||||||
/// LowerOperation - Provide custom lowering hooks for some operations.
|
/// getTargetNodeName - This method returns the name of a target specific
|
||||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
/// DAG node.
|
||||||
|
|
||||||
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.
|
|
||||||
virtual const char *getTargetNodeName(unsigned Opcode) const;
|
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.
|
SDNode *ReplaceNodeResults(SDNode *N, SelectionDAG &DAG);
|
||||||
const SDValue *findLoadi8(const SDValue &Src, SelectionDAG &DAG) const;
|
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
|
} // namespace llvm
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//===- PIC16RegisterInfo.td - PIC16 Register defs ------------*- tblgen -*-===//
|
//===- PIC16InstrFormats.td - PIC16 Instruction Formats-------*- tblgen -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
@ -21,16 +21,17 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// Generic PIC16 Format
|
// 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>
|
class PIC16Inst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||||
: Instruction
|
: Instruction {
|
||||||
{
|
|
||||||
field bits<14> Inst;
|
field bits<14> Inst;
|
||||||
|
|
||||||
let Namespace = "PIC16";
|
let Namespace = "PIC16";
|
||||||
|
|
||||||
dag OutOperandList = outs;
|
dag OutOperandList = outs;
|
||||||
dag InOperandList = ins;
|
dag InOperandList = ins;
|
||||||
|
|
||||||
let AsmString = asmstr;
|
let AsmString = asmstr;
|
||||||
let Pattern = pattern;
|
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|>
|
// 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,
|
class ByteFormat<bits<6> opcode, dag outs, dag ins, string asmstr,
|
||||||
list<dag> pattern>
|
list<dag> pattern>
|
||||||
:PIC16Inst<outs, ins, asmstr, pattern>
|
:PIC16Inst<outs, ins, asmstr, pattern> {
|
||||||
{
|
|
||||||
bits<1> d;
|
bits<1> d;
|
||||||
bits<7> f;
|
bits<7> f;
|
||||||
|
|
||||||
let Inst{13-8} = op;
|
let Inst{13-8} = opcode;
|
||||||
|
|
||||||
let Inst{7} = d;
|
let Inst{7} = d;
|
||||||
let Inst{6-0} = f;
|
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|>
|
// 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>
|
class BitFormat<bits<4> opcode, dag outs, dag ins, string asmstr,
|
||||||
: PIC16Inst<outs, ins, asmstr, pattern>
|
list<dag> pattern>
|
||||||
{
|
: PIC16Inst<outs, ins, asmstr, pattern> {
|
||||||
bits<3> b;
|
bits<3> b;
|
||||||
bits<7> f;
|
bits<7> f;
|
||||||
|
|
||||||
let Inst{13-10} = op;
|
let Inst{13-10} = opcode;
|
||||||
|
|
||||||
let Inst{9-7} = b;
|
let Inst{9-7} = b;
|
||||||
let Inst{6-0} = f;
|
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|>
|
// 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>
|
list<dag> pattern>
|
||||||
: PIC16Inst<outs, ins, asmstr, pattern>
|
: PIC16Inst<outs, ins, asmstr, pattern> {
|
||||||
{
|
|
||||||
bits<8> k;
|
bits<8> k;
|
||||||
|
|
||||||
|
|
||||||
let Inst{13-8} = op;
|
let Inst{13-8} = opcode;
|
||||||
|
|
||||||
let Inst{7-0} = k;
|
let Inst{7-0} = k;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Control Format instruction class in PIC16 : <|opcode|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>
|
list<dag> pattern>
|
||||||
:PIC16Inst<outs, ins, asmstr, pattern>
|
: PIC16Inst<outs, ins, asmstr, pattern> {
|
||||||
{
|
|
||||||
bits<11> k;
|
bits<11> k;
|
||||||
|
|
||||||
|
let Inst{13-11} = opcode;
|
||||||
let Inst{13-11} = op;
|
|
||||||
|
|
||||||
let Inst{10-0} = k;
|
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
|
// Pseudo instruction class in PIC16
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
class Pseudo<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern>:
|
class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||||
PIC16Inst<outs, ins, asmstr, pattern>
|
: PIC16Inst<outs, ins, asmstr, pattern> {
|
||||||
{
|
let Inst{13-6} = 0;
|
||||||
let Inst{13-6} = op;
|
|
||||||
}
|
}
|
||||||
|
@ -13,132 +13,131 @@
|
|||||||
|
|
||||||
#include "PIC16.h"
|
#include "PIC16.h"
|
||||||
#include "PIC16InstrInfo.h"
|
#include "PIC16InstrInfo.h"
|
||||||
|
#include "PIC16TargetMachine.h"
|
||||||
|
#include "PIC16GenInstrInfo.inc"
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
#include "PIC16GenInstrInfo.inc"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
// FIXME: Add the subtarget support on this constructor.
|
// FIXME: Add the subtarget support on this constructor.
|
||||||
PIC16InstrInfo::PIC16InstrInfo(PIC16TargetMachine &tm)
|
PIC16InstrInfo::PIC16InstrInfo(PIC16TargetMachine &tm)
|
||||||
: TargetInstrInfoImpl(PIC16Insts, array_lengthof(PIC16Insts)),
|
: 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
|
/// isStoreToStackSlot - If the specified machine instruction is a direct
|
||||||
/// store to a stack slot, return the virtual or physical register number of
|
/// 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
|
/// the source reg along with the FrameIndex of the loaded stack slot.
|
||||||
/// not, return 0. This predicate must return 0 if the instruction has
|
/// If not, return 0. This predicate must return 0 if the instruction has
|
||||||
/// any side effects other than storing to the stack slot.
|
/// any side effects other than storing to the stack slot.
|
||||||
unsigned PIC16InstrInfo::
|
unsigned PIC16InstrInfo::isStoreToStackSlot(MachineInstr *MI,
|
||||||
isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const
|
int &FrameIndex) const {
|
||||||
{
|
if (MI->getOpcode() == PIC16::movwf
|
||||||
if (MI->getOpcode() == PIC16::MOVWF) {
|
&& MI->getOperand(0).isReg()
|
||||||
if ((MI->getOperand(0).isFI()) && // is a stack slot
|
&& MI->getOperand(1).isSymbol()) {
|
||||||
(MI->getOperand(1).isImm()) && // the imm is zero
|
FrameIndex = MI->getOperand(1).getIndex();
|
||||||
(isZeroImm(MI->getOperand(1)))) {
|
return MI->getOperand(0).getReg();
|
||||||
FrameIndex = MI->getOperand(0).getIndex();
|
|
||||||
return MI->getOperand(2).getReg();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PIC16InstrInfo::
|
/// isLoadFromStackSlot - If the specified machine instruction is a direct
|
||||||
storeRegToStackSlot(MachineBasicBlock &MBB,
|
/// load from a stack slot, return the virtual or physical register number of
|
||||||
MachineBasicBlock::iterator I,
|
/// the dest reg along with the FrameIndex of the stack slot.
|
||||||
unsigned SrcReg, bool isKill, int FI,
|
/// If not, return 0. This predicate must return 0 if the instruction has
|
||||||
const TargetRegisterClass *RC) const {
|
/// 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 Function *Func = MBB.getParent()->getFunction();
|
||||||
const std::string FuncName = Func->getName();
|
const std::string FuncName = Func->getName();
|
||||||
|
|
||||||
char *tmpName = new char [strlen(FuncName.c_str()) + 6];
|
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) {
|
// On the order of operands here: think "movwf SrcReg, tmp_slot, offset".
|
||||||
//src is always WREG.
|
if (RC == PIC16::GPRRegisterClass) {
|
||||||
BuildMI(MBB, I, this->get(PIC16::MOVWF))
|
//MachineFunction &MF = *MBB.getParent();
|
||||||
.addReg(SrcReg,false,false,true,true)
|
//MachineRegisterInfo &RI = MF.getRegInfo();
|
||||||
.addExternalSymbol(tmpName) // the current printer expects 3 operands,
|
BuildMI(MBB, I, get(PIC16::movwf))
|
||||||
.addExternalSymbol(tmpName); // all we need is actually one,
|
.addReg(SrcReg, false, false, isKill)
|
||||||
// so we repeat.
|
.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
|
else
|
||||||
assert(0 && "Can't store this register to stack slot");
|
assert(0 && "Can't store this register to stack slot");
|
||||||
}
|
}
|
||||||
|
|
||||||
void PIC16InstrInfo::
|
void PIC16InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||||
loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
MachineBasicBlock::iterator I,
|
||||||
unsigned DestReg, int FI,
|
unsigned DestReg, int FI,
|
||||||
const TargetRegisterClass *RC) const
|
const TargetRegisterClass *RC) const {
|
||||||
{
|
|
||||||
const Function *Func = MBB.getParent()->getFunction();
|
const Function *Func = MBB.getParent()->getFunction();
|
||||||
const std::string FuncName = Func->getName();
|
const std::string FuncName = Func->getName();
|
||||||
|
|
||||||
char *tmpName = new char [strlen(FuncName.c_str()) + 6];
|
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)
|
// On the order of operands here: think "movf FrameIndex, W".
|
||||||
BuildMI(MBB, I, this->get(PIC16::MOVF), DestReg)
|
if (RC == PIC16::GPRRegisterClass) {
|
||||||
.addExternalSymbol(tmpName) // the current printer expects 3 operands,
|
//MachineFunction &MF = *MBB.getParent();
|
||||||
.addExternalSymbol(tmpName); // all we need is actually one,so we repeat.
|
//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
|
else
|
||||||
assert(0 && "Can't load this register from stack slot");
|
assert(0 && "Can't load this register from stack slot");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// InsertBranch - Insert a branch into the end of the specified
|
bool PIC16InstrInfo::copyRegToReg (MachineBasicBlock &MBB,
|
||||||
/// MachineBasicBlock. This operands to this method are the same as those
|
MachineBasicBlock::iterator I,
|
||||||
/// returned by AnalyzeBranch. This is invoked in cases where AnalyzeBranch
|
unsigned DestReg, unsigned SrcReg,
|
||||||
/// returns success and when an unconditional branch (TBB is non-null, FBB is
|
const TargetRegisterClass *DestRC,
|
||||||
/// null, Cond is empty) needs to be inserted. It returns the number of
|
const TargetRegisterClass *SrcRC) const {
|
||||||
/// instructions inserted.
|
if (DestRC == PIC16::FSR16RegisterClass) {
|
||||||
unsigned PIC16InstrInfo::
|
BuildMI(MBB, I, get(PIC16::copy_fsr), DestReg).addReg(SrcReg);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: If the there are some conditions specified then conditional branch
|
return true;
|
||||||
// should be generated.
|
}
|
||||||
// For the time being no instruction is being generated therefore
|
|
||||||
// returning NULL.
|
bool PIC16InstrInfo::isMoveInstr(const MachineInstr &MI,
|
||||||
return 0;
|
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
|
class PIC16InstrInfo : public TargetInstrInfoImpl
|
||||||
{
|
{
|
||||||
PIC16TargetMachine &TM;
|
PIC16TargetMachine &TM;
|
||||||
const PIC16RegisterInfo RI;
|
const PIC16RegisterInfo RegInfo;
|
||||||
public:
|
public:
|
||||||
explicit PIC16InstrInfo(PIC16TargetMachine &TM);
|
explicit PIC16InstrInfo(PIC16TargetMachine &TM);
|
||||||
|
|
||||||
/// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
|
virtual const PIC16RegisterInfo &getRegisterInfo() const { return RegInfo; }
|
||||||
/// 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; }
|
|
||||||
|
|
||||||
|
|
||||||
/// isLoadFromStackSlot - If the specified machine instruction is a direct
|
/// isLoadFromStackSlot - If the specified machine instruction is a direct
|
||||||
/// load from a stack slot, return the virtual or physical register number of
|
/// 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
|
/// the destination along with the FrameIndex of the loaded stack slot. If
|
||||||
/// not, return 0. This predicate must return 0 if the instruction has
|
/// not, return 0. This predicate must return 0 if the instruction has
|
||||||
/// any side effects other than loading from the stack slot.
|
/// any side effects other than loading from the stack slot.
|
||||||
virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
|
virtual unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const;
|
||||||
int &FrameIndex) const;
|
|
||||||
|
|
||||||
/// isStoreToStackSlot - If the specified machine instruction is a direct
|
/// isStoreToStackSlot - If the specified machine instruction is a direct
|
||||||
/// store to a stack slot, return the virtual or physical register number of
|
/// 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
|
/// 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
|
/// not, return 0. This predicate must return 0 if the instruction has
|
||||||
/// any side effects other than storing to the stack slot.
|
/// any side effects other than storing to the stack slot.
|
||||||
virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
|
virtual unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const;
|
||||||
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 void storeRegToStackSlot(MachineBasicBlock &MBB,
|
||||||
void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
MachineBasicBlock::iterator MBBI,
|
||||||
MachineBasicBlock::iterator MI,
|
unsigned SrcReg, bool isKill, int FrameIndex,
|
||||||
unsigned DestReg, int FrameIndex,
|
const TargetRegisterClass *RC) const;
|
||||||
const TargetRegisterClass *RC) const;
|
|
||||||
|
virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||||
/// InsertBranch - Insert a branch into the end of the specified
|
MachineBasicBlock::iterator MBBI,
|
||||||
/// MachineBasicBlock. This operands to this method are the same as those
|
unsigned DestReg, int FrameIndex,
|
||||||
/// returned by AnalyzeBranch. This is invoked in cases where AnalyzeBranch
|
const TargetRegisterClass *RC) const;
|
||||||
/// returns success and when an unconditional branch (TBB is non-null, FBB is
|
virtual bool copyRegToReg(MachineBasicBlock &MBB,
|
||||||
/// null, Cond is empty) needs to be inserted. It returns the number of
|
MachineBasicBlock::iterator MBBI,
|
||||||
/// instructions inserted.
|
unsigned DestReg, unsigned SrcReg,
|
||||||
virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
const TargetRegisterClass *DestRC,
|
||||||
MachineBasicBlock *FBB,
|
const TargetRegisterClass *SrcRC) const;
|
||||||
const SmallVectorImpl<MachineOperand> &Cond) 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
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
@ -6,297 +6,302 @@
|
|||||||
// License. See LICENSE.TXT for details.
|
// License. See LICENSE.TXT for details.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
// This file describes the ARM instructions in TableGen format.
|
||||||
// Instruction format superclass
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// 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"
|
include "PIC16InstrFormats.td"
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
// Pseudo-instructions.
|
||||||
// PIC16 profiles and nodes
|
def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i8imm:$amt),
|
||||||
//===----------------------------------------------------------------------===//
|
"!ADJCALLSTACKDOWN $amt",
|
||||||
|
[(PIC16callseq_start imm:$amt)]>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
def ADJCALLSTACKUP : Pseudo<(outs), (ins i8imm:$amt),
|
||||||
// PIC16 addressing mode.
|
"!ADJCALLSTACKUP $amt",
|
||||||
//===----------------------------------------------------------------------===//
|
[(PIC16callseq_end imm:$amt)]>;
|
||||||
// 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>;
|
|
||||||
|
|
||||||
|
//-----------------------------------
|
||||||
|
// Vaious movlw insn patterns.
|
||||||
|
//-----------------------------------
|
||||||
let isReMaterializable = 1 in {
|
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 {
|
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>;
|
// Return insn.
|
||||||
|
def Return :
|
||||||
def MOVFSRINC : StoreInDirect <0x5, "movfsrinc", store>;
|
ControlFormat<0, (outs), (ins), "return", [(ret)]>;
|
||||||
|
|
||||||
def RETURN : ControlFormat<0x03, (outs), (ins), "return", []>;
|
|
||||||
|
|
||||||
def ADDWF : Arith1M<0x01, "addwf", add>;
|
|
||||||
def ADDFW : Arith1R<0x02, "addfw", add>;
|
|
||||||
|
|
||||||
def ADDWFE : Arith1M<0x03, "addwfe", adde>;
|
|
||||||
def ADDFWE : Arith1R<0x04, "addfwe", adde>;
|
|
||||||
|
|
||||||
def ADDWFC : Arith1M<0x05, "addwfc", addc>;
|
|
||||||
def ADDFWC : Arith1R<0x06, "addfwc", addc>;
|
|
||||||
|
|
||||||
def SUBWF : Arith1M<0x07, "subwf", sub>;
|
|
||||||
def SUBFW : Arith1R<0x08, "subfw", sub>;
|
|
||||||
|
|
||||||
def SUBWFE : Arith1M<0x09, "subwfe", sube>;
|
|
||||||
def SUBFWE : Arith1R<0x0a, "subfwe", sube>;
|
|
||||||
|
|
||||||
def SUBWFC : Arith1M<0x0b, "subwfc", subc>;
|
|
||||||
def SUBFWC : Arith1R<0x0d, "subfwc", subc>;
|
|
||||||
|
|
||||||
def SUBRFW : Arith2R<0x08, "subfw", sub>;
|
|
||||||
|
|
||||||
def SUBRFWE : Arith2R<0x0a, "subfwe", sube>;
|
|
||||||
|
|
||||||
def SUBRFWC : Arith2R<0x0d, "subfwc", subc>;
|
|
||||||
|
|
||||||
def brtarget : Operand<OtherVT>;
|
|
||||||
|
|
||||||
class UncondJump< bits<4> op, string instr_asm>:
|
|
||||||
BitFormat< op,
|
|
||||||
(outs),
|
|
||||||
(ins brtarget:$target),
|
|
||||||
!strconcat(instr_asm, " $target"),
|
|
||||||
[(br bb:$target)]>;
|
|
||||||
|
|
||||||
def GOTO : UncondJump<0x1, "goto">;
|
|
||||||
|
|
||||||
class LogicM<bits<6> op, string instr_asm, SDNode OpNode> :
|
|
||||||
ByteFormat< op,
|
|
||||||
(outs),
|
|
||||||
(ins CPURegs:$b, mem:$dst),
|
|
||||||
!strconcat(instr_asm, " $dst"),
|
|
||||||
[(store (OpNode (load diraddrmode:$dst), CPURegs:$b), diraddrmode:$dst)]>;
|
|
||||||
|
|
||||||
class LogicR<bits<6> op, string instr_asm, SDNode OpNode> :
|
|
||||||
ByteFormat< op,
|
|
||||||
(outs CPURegs:$dst),
|
|
||||||
(ins CPURegs:$b, mem:$c),
|
|
||||||
!strconcat(instr_asm, " $c"),
|
|
||||||
[(set CPURegs:$dst, (OpNode (load diraddrmode:$c), CPURegs:$b))]>;
|
|
||||||
|
|
||||||
class LogicI<bits<6> op, string instr_asm, SDNode OpNode, Operand Od> :
|
|
||||||
LiteralFormat< op,
|
|
||||||
(outs CPURegs:$dst),
|
|
||||||
(ins CPURegs:$b, Od:$c),
|
|
||||||
!strconcat(instr_asm, " $c"),
|
|
||||||
[(set CPURegs:$dst, (OpNode CPURegs:$b, Od:$c ))]>;
|
|
||||||
|
|
||||||
def XORWF : LogicM<0x1,"xorwf",xor>;
|
|
||||||
def XORFW : LogicR<0x1,"xorfw",xor>;
|
|
||||||
def XORLW : LogicI<0x1,"xorlw",xor, so_imm>;
|
|
||||||
|
|
||||||
def ANDWF : LogicM<0x1,"andwf",and>;
|
|
||||||
def ANDFW : LogicR<0x1,"andfw",and>;
|
|
||||||
def ANDLW : LogicI<0x1,"andlw",and, so_imm>;
|
|
||||||
|
|
||||||
def IORWF : LogicM<0x1,"iorwf",or>;
|
|
||||||
def IORFW : LogicR<0x1,"iorfw",or>;
|
|
||||||
def IORLW : LogicI<0x1,"iorlw",or, so_imm>;
|
|
||||||
|
|
||||||
|
|
||||||
/* For comparison before branch */
|
|
||||||
def SDT_PIC16Cmp : SDTypeProfile<1, 3, [SDTCisSameAs<0,1>]>;
|
|
||||||
def SDTIntBinOpPIC16 : SDTypeProfile<1, 2, [SDTCisSameAs<0,1>,
|
|
||||||
SDTCisSameAs<1,2>, SDTCisInt<1>]>;
|
|
||||||
|
|
||||||
def PIC16Cmp : SDNode<"PIC16ISD::Cmp",SDTIntBinOpPIC16, [SDNPOutFlag]>;
|
|
||||||
def PIC16XORCC : SDNode<"PIC16ISD::XORCC",SDTIntBinOpPIC16, [SDNPOutFlag]>;
|
|
||||||
def PIC16SUBCC : SDNode<"PIC16ISD::SUBCC",SDTIntBinOpPIC16, [SDNPOutFlag]>;
|
|
||||||
|
|
||||||
def XORFWCC : LogicR<0x1,"xorfw",PIC16XORCC>;
|
|
||||||
def XORLWCC : LogicI<0x1,"xorlw",PIC16XORCC, so_imm>;
|
|
||||||
def SUBFWCC : Arith1R<0x1,"subfw",PIC16SUBCC>;
|
|
||||||
def SUBLWCC : ArithI<0x1,"sublw",PIC16SUBCC, so_imm>;
|
|
||||||
|
|
||||||
|
|
||||||
/* For branch conditions */
|
|
||||||
def SDT_PIC16Branch : SDTypeProfile<0, 3, [SDTCisVT<0, OtherVT>,
|
|
||||||
SDTCisVT<1,i8>, SDTCisVT<2,i8>]>;
|
|
||||||
|
|
||||||
def PIC16Branch : SDNode<"PIC16ISD::Branch",SDT_PIC16Branch,
|
|
||||||
[SDNPHasChain, SDNPInFlag]>;
|
|
||||||
|
|
||||||
def PIC16BTFSS : SDNode<"PIC16ISD::BTFSS",SDT_PIC16Branch,
|
|
||||||
[SDNPHasChain, SDNPInFlag]>;
|
|
||||||
|
|
||||||
def PIC16BTFSC : SDNode<"PIC16ISD::BTFSC",SDT_PIC16Branch,
|
|
||||||
[SDNPHasChain, SDNPInFlag]>;
|
|
||||||
|
|
||||||
class InstrBitTestCC<bits<4> op, string instr_asm,SDNode OpNode>:
|
|
||||||
BitFormat< op,
|
|
||||||
(outs),
|
|
||||||
(ins brtarget:$target ,so_imm:$i, STATUSRegs:$s ),
|
|
||||||
!strconcat(instr_asm, " $s, $i, $target"),
|
|
||||||
[(OpNode bb:$target, so_imm:$i, STATUSRegs:$s )]>;
|
|
||||||
|
|
||||||
def BTFSS : InstrBitTestCC<0x1,"btfss",PIC16BTFSS>;
|
|
||||||
def BTFSC : InstrBitTestCC<0x1,"btfsc",PIC16BTFSC>;
|
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Pseudo instructions
|
// PIC16 Replacment Patterns.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
let Defs = [STKPTR], Uses = [STKPTR] in {
|
// Identify an indirect store and select insns for it.
|
||||||
def ADJCALLSTACKDOWN : Pseudo<255, (outs), (ins i8imm:$amt),
|
def : Pat<(PIC16Store GPR:$val, (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
|
||||||
"!ADJCALLSTACKDOWN $amt",
|
imm:$offset),
|
||||||
[(callseq_start imm:$amt)]>;
|
(store_indirect GPR:$val,
|
||||||
def ADJCALLSTACKUP : Pseudo<254, (outs), (ins i8imm:$amt),
|
(set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
|
||||||
"!ADJCALLSTACKUP $amt",
|
imm:$offset)>;
|
||||||
[(callseq_end imm:$amt)]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// 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 "PIC16.h"
|
||||||
#include "PIC16RegisterInfo.h"
|
#include "PIC16RegisterInfo.h"
|
||||||
#include "llvm/Constants.h"
|
|
||||||
#include "llvm/Function.h"
|
|
||||||
#include "llvm/Type.h"
|
|
||||||
#include "llvm/ADT/BitVector.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;
|
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),
|
: PIC16GenRegisterInfo(PIC16::ADJCALLSTACKDOWN, PIC16::ADJCALLSTACKUP),
|
||||||
TII(tii) {}
|
TII(tii),
|
||||||
|
ST(st) {}
|
||||||
|
|
||||||
/// getRegisterNumbering - Given the enum value for some register, e.g.
|
#include "PIC16GenRegisterInfo.inc"
|
||||||
/// 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
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
/// PIC16 Callee Saved Registers
|
/// PIC16 Callee Saved Registers
|
||||||
const unsigned* PIC16RegisterInfo::
|
const unsigned* PIC16RegisterInfo::
|
||||||
getCalleeSavedRegs(const MachineFunction *MF) const
|
getCalleeSavedRegs(const MachineFunction *MF) const {
|
||||||
{
|
|
||||||
// PIC16 calle-save register range is $16-$26(s0-s7)
|
|
||||||
static const unsigned CalleeSavedRegs[] = { 0 };
|
static const unsigned CalleeSavedRegs[] = { 0 };
|
||||||
return CalleeSavedRegs;
|
return CalleeSavedRegs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PIC16 Callee Saved Register Classes
|
// PIC16 Callee Saved Reg Classes
|
||||||
const TargetRegisterClass* const*
|
const TargetRegisterClass* const*
|
||||||
PIC16RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const
|
PIC16RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
||||||
{
|
|
||||||
static const TargetRegisterClass * const CalleeSavedRegClasses[] = { 0 };
|
static const TargetRegisterClass * const CalleeSavedRegClasses[] = { 0 };
|
||||||
return CalleeSavedRegClasses;
|
return CalleeSavedRegClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
BitVector PIC16RegisterInfo::
|
BitVector PIC16RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
||||||
getReservedRegs(const MachineFunction &MF) const
|
|
||||||
{
|
|
||||||
BitVector Reserved(getNumRegs());
|
BitVector Reserved(getNumRegs());
|
||||||
return Reserved;
|
return Reserved;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
bool PIC16RegisterInfo::hasFP(const MachineFunction &MF) const {
|
||||||
//
|
|
||||||
// Stack Frame Processing methods
|
|
||||||
// +----------------------------+
|
|
||||||
//
|
|
||||||
// FIXME: Add stack layout description here.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
// hasFP - Return true if the specified function should have a dedicated frame
|
|
||||||
// pointer register. This is true if the function has variable sized allocas or
|
|
||||||
// if frame pointer elimination is disabled.
|
|
||||||
bool PIC16RegisterInfo::
|
|
||||||
hasFP(const MachineFunction &MF) const {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function eliminate ADJCALLSTACKDOWN,
|
|
||||||
// ADJCALLSTACKUP pseudo instructions
|
|
||||||
void PIC16RegisterInfo::
|
void PIC16RegisterInfo::
|
||||||
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
||||||
MachineBasicBlock::iterator I) const {
|
RegScavenger *RS) const
|
||||||
// Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions.
|
{ /* NOT YET IMPLEMENTED */ }
|
||||||
MBB.erase(I);
|
|
||||||
}
|
|
||||||
|
|
||||||
// FrameIndex represent objects inside a abstract stack.
|
void PIC16RegisterInfo::emitPrologue(MachineFunction &MF) const
|
||||||
// We must replace FrameIndex with an stack/frame pointer
|
{ /* NOT YET IMPLEMENTED */ }
|
||||||
// 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::
|
void PIC16RegisterInfo::
|
||||||
emitPrologue(MachineFunction &MF) const
|
emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
|
||||||
{
|
{ /* NOT YET IMPLEMENTED */ }
|
||||||
}
|
|
||||||
|
|
||||||
void PIC16RegisterInfo::
|
|
||||||
emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIC16RegisterInfo::
|
|
||||||
processFunctionBeforeFrameFinalized(MachineFunction &MF) const
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned PIC16RegisterInfo::
|
|
||||||
getRARegister() const {
|
|
||||||
assert(0 && "What is the return address register");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned PIC16RegisterInfo::
|
|
||||||
getFrameRegister(MachineFunction &MF) const {
|
|
||||||
return PIC16::STKPTR;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned PIC16RegisterInfo::
|
|
||||||
getEHExceptionRegister() const {
|
|
||||||
assert(0 && "What is the exception register");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned PIC16RegisterInfo::
|
|
||||||
getEHHandlerRegister() const {
|
|
||||||
assert(0 && "What is the exception handler register");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PIC16RegisterInfo::
|
int PIC16RegisterInfo::
|
||||||
getDwarfRegNum(unsigned RegNum, bool isEH) const {
|
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;
|
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 {
|
namespace llvm {
|
||||||
|
|
||||||
// Forward Declarations.
|
// Forward Declarations.
|
||||||
class TargetInstrInfo;
|
class PIC16Subtarget;
|
||||||
class Type;
|
class TargetInstrInfo;
|
||||||
|
|
||||||
struct PIC16RegisterInfo : public PIC16GenRegisterInfo {
|
class PIC16RegisterInfo : public PIC16GenRegisterInfo {
|
||||||
const TargetInstrInfo &TII;
|
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,
|
// PIC16 callee saved registers
|
||||||
int FrameIndex) const;
|
virtual const unsigned*
|
||||||
|
getCalleeSavedRegs(const MachineFunction *MF = 0) const;
|
||||||
|
|
||||||
MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
|
// PIC16 callee saved register classes
|
||||||
MachineInstr* LoadMI) const {
|
virtual const TargetRegisterClass* const *
|
||||||
return 0;
|
getCalleeSavedRegClasses(const MachineFunction *MF) const;
|
||||||
}
|
|
||||||
|
|
||||||
void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
virtual BitVector getReservedRegs(const MachineFunction &MF) const;
|
||||||
unsigned DestReg, unsigned SrcReg,
|
virtual bool hasFP(const MachineFunction &MF) const;
|
||||||
const TargetRegisterClass *RC) const;
|
|
||||||
|
|
||||||
|
|
||||||
const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const;
|
virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI,
|
||||||
|
int SPAdj, RegScavenger *RS=NULL) const;
|
||||||
|
|
||||||
const TargetRegisterClass* const*
|
virtual void emitPrologue(MachineFunction &MF) const;
|
||||||
getCalleeSavedRegClasses(const MachineFunction* MF = 0) 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
|
} // end namespace llvm
|
||||||
|
@ -11,74 +11,22 @@
|
|||||||
// Declarations that describe the PIC16 register file
|
// Declarations that describe the PIC16 register file
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// We have banks of 32 registers each.
|
|
||||||
class PIC16Reg<string n> : Register<n> {
|
class PIC16Reg<string n> : Register<n> {
|
||||||
field bits<5> Num;
|
|
||||||
let Namespace = "PIC16";
|
let Namespace = "PIC16";
|
||||||
}
|
}
|
||||||
|
|
||||||
// PIC16 CPU Registers
|
// PIC16 Registers.
|
||||||
class PIC16GPRReg<bits<5> num, string n> : PIC16Reg<n> {
|
def W : PIC16Reg<"W">;
|
||||||
let Num = num;
|
def FSR0 : PIC16Reg<"FSR0">;
|
||||||
}
|
def FSR1 : PIC16Reg<"FSR1">;
|
||||||
|
def BS : PIC16Reg<"BS">;
|
||||||
|
|
||||||
// CPU GPR Registers
|
def STATUS : PIC16Reg<"STATUS">;
|
||||||
def FSR0 : PIC16GPRReg< 0, "FSR0">, DwarfRegNum<[0]>;
|
|
||||||
def FSR1 : PIC16GPRReg< 1, "FSR1">, DwarfRegNum<[1]>;
|
|
||||||
|
|
||||||
// CPU Registers Class
|
// PIC16 Register classes.
|
||||||
def PTRRegs : RegisterClass<"PIC16", [i16], 8,
|
def GPR : RegisterClass<"PIC16", [i8], 8, [W]>;
|
||||||
[FSR0, FSR1]>
|
def FSR16 : RegisterClass<"PIC16", [i16], 8, [FSR0, FSR1]>;
|
||||||
{
|
def BSR : RegisterClass<"PIC16", [i8], 8, [BS]>;
|
||||||
let MethodProtos = [{
|
|
||||||
iterator allocation_order_end(const MachineFunction &MF) const;
|
|
||||||
}];
|
|
||||||
let MethodBodies = [{
|
|
||||||
PTRRegsClass::iterator
|
|
||||||
PTRRegsClass::allocation_order_end(const MachineFunction &MF) const {
|
|
||||||
return end();
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
def WREG : PIC16GPRReg< 0, "WREG">, DwarfRegNum<[0]>;
|
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 "PIC16Subtarget.h"
|
||||||
#include "PIC16GenSubtarget.inc"
|
#include "PIC16GenSubtarget.inc"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
PIC16Subtarget::PIC16Subtarget(const TargetMachine &TM, const Module &M,
|
PIC16Subtarget::PIC16Subtarget(const Module &M, const std::string &FS,
|
||||||
const std::string &FS)
|
bool Cooper)
|
||||||
:IsPIC16Old(false)
|
:IsCooper(Cooper)
|
||||||
{
|
{
|
||||||
std::string CPU = "generic";
|
std::string CPU = "generic";
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#ifndef PIC16SUBTARGET_H
|
#ifndef PIC16SUBTARGET_H
|
||||||
#define PIC16SUBTARGET_H
|
#define PIC16SUBTARGET_H
|
||||||
|
|
||||||
#include "llvm/Target/TargetMachine.h"
|
|
||||||
#include "llvm/Target/TargetSubtarget.h"
|
#include "llvm/Target/TargetSubtarget.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -23,19 +22,23 @@ namespace llvm {
|
|||||||
class Module;
|
class Module;
|
||||||
|
|
||||||
class PIC16Subtarget : public TargetSubtarget {
|
class PIC16Subtarget : public TargetSubtarget {
|
||||||
bool IsPIC16Old;
|
|
||||||
|
// IsCooper - Target ISA is Cooper.
|
||||||
|
bool IsCooper;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// This constructor initializes the data members to match that
|
/// This constructor initializes the data members to match that
|
||||||
/// of the specified module.
|
/// of the specified module.
|
||||||
///
|
///
|
||||||
PIC16Subtarget(const TargetMachine &TM, const Module &M,
|
PIC16Subtarget(const Module &M, const std::string &FS, bool Cooper);
|
||||||
const std::string &FS);
|
|
||||||
|
|
||||||
|
/// isCooper - Returns true if the target ISA is Cooper.
|
||||||
|
bool isCooper() const { return IsCooper; }
|
||||||
|
|
||||||
/// ParseSubtargetFeatures - Parses features string setting specified
|
/// ParseSubtargetFeatures - Parses features string setting specified
|
||||||
/// subtarget options. Definition of function is auto generated by tblgen.
|
/// subtarget options. Definition of function is auto generated by tblgen.
|
||||||
void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU);
|
void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU);
|
||||||
};
|
};
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
|
||||||
#endif
|
#endif // PIC16SUBTARGET_H
|
||||||
|
@ -17,11 +17,15 @@
|
|||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
PIC16TargetAsmInfo::
|
PIC16TargetAsmInfo::
|
||||||
PIC16TargetAsmInfo(const PIC16TargetMachine &TM)
|
PIC16TargetAsmInfo(const PIC16TargetMachine &TM)
|
||||||
: TargetAsmInfo(TM) {
|
: TargetAsmInfo(TM) {
|
||||||
Data16bitsDirective = "\t.half\t";
|
|
||||||
Data32bitsDirective = "\t.word\t";
|
|
||||||
CommentString = ";";
|
CommentString = ";";
|
||||||
COMMDirective = "\t";
|
Data8bitsDirective = " db ";
|
||||||
COMMDirectiveTakesAlignment = 0;
|
Data16bitsDirective = " db ";
|
||||||
|
Data32bitsDirective = " db ";
|
||||||
|
DataSectionStartSuffix = " IDATA ";
|
||||||
|
UDataSectionStartSuffix = " UDATA ";
|
||||||
|
TextSectionStartSuffix = " CODE ";
|
||||||
|
RomDataSectionStartSuffix = " ROMDATA ";
|
||||||
|
ZeroDirective = NULL;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,17 @@ namespace llvm {
|
|||||||
|
|
||||||
struct PIC16TargetAsmInfo : public TargetAsmInfo {
|
struct PIC16TargetAsmInfo : public TargetAsmInfo {
|
||||||
PIC16TargetAsmInfo(const PIC16TargetMachine &TM);
|
PIC16TargetAsmInfo(const PIC16TargetMachine &TM);
|
||||||
|
const char *UDataSectionStartSuffix;
|
||||||
|
const char *RomDataSectionStartSuffix;
|
||||||
|
public :
|
||||||
|
const char *getUDataSectionStartSuffix() const {
|
||||||
|
return UDataSectionStartSuffix;
|
||||||
|
}
|
||||||
|
const char *getRomDataSectionStartSuffix() const {
|
||||||
|
return RomDataSectionStartSuffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "PIC16TargetMachine.h"
|
#include "PIC16TargetMachine.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/PassManager.h"
|
#include "llvm/PassManager.h"
|
||||||
|
#include "llvm/CodeGen/Passes.h"
|
||||||
#include "llvm/Target/TargetAsmInfo.h"
|
#include "llvm/Target/TargetAsmInfo.h"
|
||||||
#include "llvm/Target/TargetMachineRegistry.h"
|
#include "llvm/Target/TargetMachineRegistry.h"
|
||||||
|
|
||||||
@ -29,50 +30,42 @@ using namespace llvm;
|
|||||||
extern "C" int PIC16TargetMachineModule;
|
extern "C" int PIC16TargetMachineModule;
|
||||||
int PIC16TargetMachineModule = 0;
|
int PIC16TargetMachineModule = 0;
|
||||||
|
|
||||||
namespace {
|
|
||||||
// Register the targets
|
|
||||||
RegisterTarget<PIC16TargetMachine> X("pic16", "PIC16 14-bit [experimental]");
|
|
||||||
}
|
|
||||||
|
|
||||||
PIC16TargetMachine::
|
// Register the targets
|
||||||
PIC16TargetMachine(const Module &M, const std::string &FS) :
|
static RegisterTarget<PIC16TargetMachine>
|
||||||
Subtarget(*this, M, FS), DataLayout("e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8"),
|
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),
|
InstrInfo(*this), TLInfo(*this),
|
||||||
FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0) { }
|
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);
|
return new PIC16TargetAsmInfo(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
bool PIC16TargetMachine::addInstSelector(PassManagerBase &PM, bool Fast) {
|
||||||
// Pass Pipeline Configuration
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
bool PIC16TargetMachine::addInstSelector(PassManagerBase &PM, bool Fast)
|
|
||||||
{
|
|
||||||
// Install an instruction selector.
|
// Install an instruction selector.
|
||||||
PM.add(createPIC16ISelDag(*this));
|
PM.add(createPIC16ISelDag(*this));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PIC16TargetMachine::
|
bool PIC16TargetMachine::
|
||||||
addPrologEpilogInserter(PassManagerBase &PM, bool Fast)
|
addAssemblyEmitter(PassManagerBase &PM, bool Fast, raw_ostream &Out) {
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PIC16TargetMachine::addPreEmitPass(PassManagerBase &PM, bool Fast)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PIC16TargetMachine::
|
|
||||||
addAssemblyEmitter(PassManagerBase &PM, bool Fast, raw_ostream &Out)
|
|
||||||
{
|
|
||||||
// Output assembly language.
|
// Output assembly language.
|
||||||
PM.add(createPIC16CodePrinterPass(Out, *this));
|
PM.add(createPIC16CodePrinterPass(Out, *this));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "PIC16InstrInfo.h"
|
#include "PIC16InstrInfo.h"
|
||||||
#include "PIC16ISelLowering.h"
|
#include "PIC16ISelLowering.h"
|
||||||
|
#include "PIC16RegisterInfo.h"
|
||||||
#include "PIC16Subtarget.h"
|
#include "PIC16Subtarget.h"
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/Target/TargetFrameInfo.h"
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
@ -31,31 +32,42 @@ class PIC16TargetMachine : public LLVMTargetMachine {
|
|||||||
const TargetData DataLayout; // Calculates type size & alignment
|
const TargetData DataLayout; // Calculates type size & alignment
|
||||||
PIC16InstrInfo InstrInfo;
|
PIC16InstrInfo InstrInfo;
|
||||||
PIC16TargetLowering TLInfo;
|
PIC16TargetLowering TLInfo;
|
||||||
|
|
||||||
|
// PIC16 does not have any call stack frame, therefore not having
|
||||||
|
// any PIC16 specific FrameInfo class.
|
||||||
TargetFrameInfo FrameInfo;
|
TargetFrameInfo FrameInfo;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual const TargetAsmInfo *createTargetAsmInfo() const;
|
virtual const TargetAsmInfo *createTargetAsmInfo() const;
|
||||||
|
|
||||||
public:
|
|
||||||
PIC16TargetMachine(const Module &M, const std::string &FS);
|
|
||||||
|
|
||||||
virtual const TargetFrameInfo *getFrameInfo() const
|
public:
|
||||||
{ return &FrameInfo; }
|
PIC16TargetMachine(const Module &M, const std::string &FS,
|
||||||
virtual const PIC16InstrInfo *getInstrInfo() const
|
bool Cooper = false);
|
||||||
{ return &InstrInfo; }
|
|
||||||
virtual const TargetData *getTargetData() const
|
virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; }
|
||||||
{ return &DataLayout; }
|
virtual const PIC16InstrInfo *getInstrInfo() const { return &InstrInfo; }
|
||||||
virtual PIC16TargetLowering *getTargetLowering() const
|
virtual const TargetData *getTargetData() const { return &DataLayout;}
|
||||||
{ return const_cast<PIC16TargetLowering*>(&TLInfo); }
|
virtual const PIC16Subtarget *getSubtargetImpl() const { return &Subtarget; }
|
||||||
virtual const PIC16RegisterInfo *getRegisterInfo() const
|
|
||||||
{ return &InstrInfo.getRegisterInfo(); }
|
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 addInstSelector(PassManagerBase &PM, bool Fast);
|
||||||
virtual bool addPrologEpilogInserter(PassManagerBase &PM, bool Fast);
|
virtual bool addAssemblyEmitter(PassManagerBase &PM, bool Fast,
|
||||||
virtual bool addPreEmitPass(PassManagerBase &PM, bool Fast);
|
|
||||||
virtual bool addAssemblyEmitter(PassManagerBase &PM, bool Fast,
|
|
||||||
raw_ostream &Out);
|
raw_ostream &Out);
|
||||||
};
|
}; // PIC16TargetMachine.
|
||||||
|
|
||||||
|
/// CooperTargetMachine
|
||||||
|
class CooperTargetMachine : public PIC16TargetMachine {
|
||||||
|
public:
|
||||||
|
CooperTargetMachine(const Module &M, const std::string &FS);
|
||||||
|
}; // CooperTargetMachine.
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user