using namespace llvm;
#include "PIC16GenAsmWriter.inc"
+bool PIC16AsmPrinter::inSameBank (char *s1, char *s2){
+
+ assert (s1 && s2 && "Null pointer assignment");
+
+ if ((*s1 == '.') && (*s2 == '.')) { //skip if they both start with '.'
+ s1++;
+ s2++;
+ }
+ while (*s1 && *s2) {
+ if (*s1 != *s2)
+ goto _NotInSameBank;
+
+ if ((*s1 == '.') && (*s2 == '.')) //both symbols in same function
+ goto _InSameBank; //in the same bank
+
+ s1++;
+ s2++;
+ }
+
+ if (*s1 && *s1) {
+ _InSameBank:
+ return true;
+ }
+
+ _NotInSameBank:
+ return false;
+}
bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
std::string NewBankselLabel;
// generate banksel.
const MachineOperand &BS = MI->getOperand(Operands-1);
if (((int)BS.getImm() == 1) &&
- (strcmp (CurrentBankselLabelInBasicBlock.c_str(),
- NewBankselLabel.c_str()))) {
+ (!inSameBank ((char *)CurrentBankselLabelInBasicBlock.c_str(),
+ (char *)NewBankselLabel.c_str()))) {
CurrentBankselLabelInBasicBlock = NewBankselLabel;
O << "\tbanksel ";
printOperand(MI, Operands-2);
// Emit the function variables.
emitFunctionData(MF);
std::string codeSection;
- codeSection = "code." + CurrentFnName + ".#";
+ codeSection = "code." + CurrentFnName + ".# " + "CODE";
+ const Section *fCodeSection = TAI->getNamedSection(codeSection.c_str(),
+ SectionFlags::Code);
O << "\n";
- SwitchToTextSection (codeSection.c_str(),F);
+ SwitchToSection (fCodeSection);
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
O << '\n';
}
else
- O << "_" << CurrentFnName << ":\n";
+ O << CurrentFnName << ":\n";
CurrentBankselLabelInBasicBlock = "";
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
O << MO.getSymbolName();
break;
+ case MachineOperand::MO_MachineBasicBlock:
+ printBasicBlockLabel(MO.getMBB());
+ return;
+
default:
assert(0 && " Operand type not supported.");
}
}
+void PIC16AsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
+ int CC = (int)MI->getOperand(opNum).getImm();
+ O << PIC16CondCodeToString((PIC16CC::CondCodes)CC);
+}
+
+
bool PIC16AsmPrinter::doInitialization (Module &M) {
bool Result = AsmPrinter::doInitialization(M);
// FIXME:: This is temporary solution to generate the include file.
// The processor should be passed to llc as in input and the header file
// should be generated accordingly.
O << "\t#include P16F1937.INC\n";
-
+ EmitExternsAndGlobals (M);
EmitInitData (M);
EmitUnInitData(M);
EmitRomData(M);
return Result;
}
-void PIC16AsmPrinter::EmitInitData (Module &M)
-{
- std::string iDataSection = "idata.#";
- SwitchToDataSection(iDataSection.c_str());
+void PIC16AsmPrinter::EmitExternsAndGlobals (Module &M) {
+ // Emit declarations for external functions.
+ O << "section.0" <<"\n";
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) {
+ std::string Name = Mang->getValueName(I);
+ if (Name.compare("abort") == 0)
+ continue;
+ if (I->isDeclaration()) {
+ O << "\textern " <<Name << "\n";
+ O << "\textern " << Name << ".retval\n";
+ O << "\textern " << Name << ".args\n";
+ }
+ else if (I->hasExternalLinkage()) {
+ O << "\tglobal " << Name << "\n";
+ O << "\tglobal " << Name << ".retval\n";
+ O << "\tglobal " << Name << ".args\n";
+ }
+ }
+
+ // Emit header file to include declaration of library functions
+ O << "\t#include C16IntrinsicCalls.INC\n";
+
+ // Emit declarations for external globals.
+ for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
+ I != E; I++) {
+ std::string Name = Mang->getValueName(I);
+ if (I->isDeclaration())
+ O << "\textern "<< Name << "\n";
+ else if (I->getLinkage() == GlobalValue::CommonLinkage)
+ O << "\tglobal "<< Name << "\n";
+ }
+}
+void PIC16AsmPrinter::EmitInitData (Module &M) {
+ SwitchToSection(TAI->getDataSection());
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;
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;
+ EmitGlobalConstant(C, AddrSpace);
}
- return;
}
- AsmPrinter::EmitConstantValueOnly(CV);
}
void PIC16AsmPrinter::EmitRomData (Module &M)
{
- std::string romDataSection = "romdata.#";
- SwitchToRomDataSection(romDataSection.c_str());
+ SwitchToSection(TAI->getReadOnlySection());
IsRomData = true;
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
continue;
O << name;
- EmitGlobalConstant(C);
+ EmitGlobalConstant(C, AddrSpace);
O << "\n";
}
}
IsRomData = false;
}
-
void PIC16AsmPrinter::EmitUnInitData (Module &M)
{
- std::string uDataSection = "udata.#";
- SwitchToUDataSection(uDataSection.c_str());
+ SwitchToSection(TAI->getBSSSection_());
const TargetData *TD = TM.getTargetData();
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
continue;
const Type *Ty = C->getType();
- unsigned Size = TD->getABITypeSize(Ty);
+ unsigned Size = TD->getTypePaddedSize(Ty);
+
O << name << " " <<"RES"<< " " << Size ;
O << "\n";
}
std::string FuncName = Mang->getValueName(F);
const Module *M = F->getParent();
const TargetData *TD = TM.getTargetData();
-
+ unsigned FrameSize = 0;
// 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";
-
+ std::string SectionName = "fdata." + CurrentFnName + ".# " + "UDATA";
+
+ const Section *fDataSection = TAI->getNamedSection(SectionName.c_str(),
+ SectionFlags::Writeable);
+ SwitchToSection(fDataSection);
+
+ //Emit function return value.
+ O << CurrentFnName << ".retval:\n";
+ const Type *RetType = F->getReturnType();
+ unsigned RetSize = 0;
+ if (RetType->getTypeID() != Type::VoidTyID)
+ RetSize = TD->getTypePaddedSize(RetType);
+
+ // Emit function arguments.
+ O << CurrentFnName << ".args:\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
Constant *C = I->getInitializer();
const Type *Ty = C->getType();
- unsigned Size = TD->getABITypeSize(Ty);
+ unsigned Size = TD->getTypePaddedSize(Ty);
+ FrameSize += Size;
// Emit memory reserve directive.
O << VarName << " RES " << Size << "\n";
}
- emitFunctionTempData(MF);
+ emitFunctionTempData(MF, FrameSize);
+ if (RetSize > FrameSize)
+ O << CurrentFnName << ".dummy" << "RES" << (RetSize - FrameSize);
}
-void PIC16AsmPrinter::emitFunctionTempData(MachineFunction &MF) {
+void PIC16AsmPrinter::emitFunctionTempData(MachineFunction &MF,
+ unsigned &FrameSize) {
// Emit temporary variables.
MachineFrameInfo *FrameInfo = MF.getFrameInfo();
if (FrameInfo->hasStackObjects()) {
int indexBegin = FrameInfo->getObjectIndexBegin();
int indexEnd = FrameInfo->getObjectIndexEnd();
- if (indexBegin < indexEnd)
+ if (indexBegin < indexEnd) {
+ FrameSize += indexEnd - indexBegin;
O << CurrentFnName << ".tmp RES"<< " "
<<indexEnd - indexBegin <<"\n";
+ }
/*
while (indexBegin < indexEnd) {
O << CurrentFnName << "_tmp_" << indexBegin << " " << "RES"<< " "
*/
}
}
-
-/// The function is same as AsmPrinter::SwitchtoDataSection except the call
-/// to getUDataSectionStartSuffix.
-void PIC16AsmPrinter::SwitchToUDataSection(const char *NewSection,
- const GlobalValue *GV) {
- std::string NS;
- if (GV && GV->hasSection())
- NS = TAI->getSwitchToSectionDirective() + GV->getSection();
- else
- NS = NewSection;
-
- // If 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;
-}
-
-/// The function is same as AsmPrinter::SwitchtoDataSection except the call
-/// to getRomDataSectionStartSuffix.
-void PIC16AsmPrinter::SwitchToRomDataSection(const char *NewSection,
- const GlobalValue *GV) {
- std::string NS;
- if (GV && GV->hasSection())
- NS = TAI->getSwitchToSectionDirective() + GV->getSection();
- else
- NS = NewSection;
-
- // If 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;
-}
-