blob: d468efd7b34cc73f7a4f5f6c3842397a7f563519 [file] [log] [blame]
Sanjiv Gupta0e687712008-05-13 09:02:57 +00001//===-- PIC16AsmPrinter.cpp - PIC16 LLVM assembly writer ------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains a printer that converts from our internal representation
11// of machine-dependent LLVM code to PIC16 assembly language.
12//
13//===----------------------------------------------------------------------===//
14
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +000015#include "PIC16AsmPrinter.h"
16#include "PIC16TargetAsmInfo.h"
Owen Andersoncb371882008-08-21 00:14:44 +000017#include "llvm/Support/raw_ostream.h"
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +000018#include "llvm/Support/Mangler.h"
19#include "llvm/Function.h"
20#include "llvm/Module.h"
21#include "llvm/CodeGen/MachineFrameInfo.h"
22#include "llvm/DerivedTypes.h"
Sanjiv Gupta0e687712008-05-13 09:02:57 +000023
24using namespace llvm;
25
Sanjiv Gupta0e687712008-05-13 09:02:57 +000026#include "PIC16GenAsmWriter.inc"
27
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +000028bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
29 std::string NewBankselLabel;
30 unsigned Operands = MI->getNumOperands();
31 if (Operands > 1) {
32 // Global address or external symbol should be second operand from last
33 // if we want to print banksel for it.
34 const MachineOperand &Op = MI->getOperand(Operands-2);
35 unsigned OpType = Op.getType();
36 if (OpType == MachineOperand::MO_GlobalAddress ||
37 OpType == MachineOperand::MO_ExternalSymbol) {
38 if (OpType == MachineOperand::MO_GlobalAddress )
39 NewBankselLabel = Mang->getValueName(Op.getGlobal());
40 else
41 NewBankselLabel = Op.getSymbolName();
42
43 // Operand after global address or external symbol should be banksel.
44 // Value 1 for this operand means we need to generate banksel else do not
45 // generate banksel.
46 const MachineOperand &BS = MI->getOperand(Operands-1);
47 if (((int)BS.getImm() == 1) &&
48 (strcmp (CurrentBankselLabelInBasicBlock.c_str(),
49 NewBankselLabel.c_str()))) {
50 CurrentBankselLabelInBasicBlock = NewBankselLabel;
51 O << "\tbanksel ";
52 printOperand(MI, Operands-2);
53 O << "\n";
54 }
55 }
56 }
57 printInstruction(MI);
58 return true;
59}
60
61/// runOnMachineFunction - This uses the printInstruction()
62/// method to print assembly for each instruction.
63///
64bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
65 // This calls the base class function required to be called at beginning
66 // of runOnMachineFunction.
67 SetupMachineFunction(MF);
68
69 // Get the mangled name.
70 const Function *F = MF.getFunction();
71 CurrentFnName = Mang->getValueName(F);
72
73 // Emit the function variables.
74 emitFunctionData(MF);
75 std::string codeSection;
76 codeSection = "code." + CurrentFnName + ".#";
77 O << "\n";
78 SwitchToTextSection (codeSection.c_str(),F);
79
80 // Print out code for the function.
81 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
82 I != E; ++I) {
83 // Print a label for the basic block.
84 if (I != MF.begin()) {
85 printBasicBlockLabel(I, true);
86 O << '\n';
87 }
88 else
Sanjiv Gupta8f78fa82008-11-26 10:53:50 +000089 O << CurrentFnName << ":\n";
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +000090 CurrentBankselLabelInBasicBlock = "";
91 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
92 II != E; ++II) {
93 // Print the assembly for the instruction.
94 printMachineInstruction(II);
95 }
96 }
97 return false; // we didn't modify anything.
98}
99
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000100/// createPIC16CodePrinterPass - Returns a pass that prints the PIC16
101/// assembly code for a MachineFunction to the given output stream,
102/// using the given target machine description. This should work
103/// regardless of whether the function is in SSA form.
104///
Owen Andersoncb371882008-08-21 00:14:44 +0000105FunctionPass *llvm::createPIC16CodePrinterPass(raw_ostream &o,
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000106 PIC16TargetMachine &tm) {
107 return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo());
108}
109
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000110void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000111 const MachineOperand &MO = MI->getOperand(opNum);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000112
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000113 switch (MO.getType()) {
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000114 case MachineOperand::MO_Register:
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000115 if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000116 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000117 else
118 assert(0 && "not implemented");
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000119 return;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000120
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000121 case MachineOperand::MO_Immediate:
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000122 O << (int)MO.getImm();
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000123 return;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000124
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000125 case MachineOperand::MO_GlobalAddress:
126 O << Mang->getValueName(MO.getGlobal());
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000127 break;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000128
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000129 case MachineOperand::MO_ExternalSymbol:
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000130 O << MO.getSymbolName();
131 break;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000132
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000133 default:
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000134 assert(0 && " Operand type not supported.");
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000135 }
136}
137
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000138bool PIC16AsmPrinter::doInitialization (Module &M) {
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000139 bool Result = AsmPrinter::doInitialization(M);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000140 // FIXME:: This is temporary solution to generate the include file.
141 // The processor should be passed to llc as in input and the header file
142 // should be generated accordingly.
143 O << "\t#include P16F1937.INC\n";
Sanjiv Gupta8f78fa82008-11-26 10:53:50 +0000144 EmitExternsAndGlobals (M);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000145 EmitInitData (M);
146 EmitUnInitData(M);
147 EmitRomData(M);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000148 return Result;
149}
150
Sanjiv Gupta8f78fa82008-11-26 10:53:50 +0000151void PIC16AsmPrinter::EmitExternsAndGlobals (Module &M) {
152 // Emit declarations for external functions.
153 O << "section.0" <<"\n";
154 for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) {
155 std::string Name = Mang->getValueName(I);
156 if (Name.compare("abort") == 0)
157 continue;
158 if (I->isDeclaration()) {
159 O << "\textern " <<Name << "\n";
160 O << "\textern " << Name << ".retval\n";
161 O << "\textern " << Name << ".args\n";
162 }
163 else if (I->hasExternalLinkage()) {
164 O << "\tglobal " << Name << "\n";
165 O << "\tglobal " << Name << ".retval\n";
166 O << "\tglobal " << Name << ".args\n";
167 }
168 }
169 // Emit declarations for external globals.
170 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
171 I != E; I++) {
172 std::string Name = Mang->getValueName(I);
173 if (I->isDeclaration())
174 O << "\textern "<< Name << "\n";
175 else if (I->getLinkage() == GlobalValue::CommonLinkage)
176 O << "\tglobal "<< Name << "\n";
177 }
178}
179void PIC16AsmPrinter::EmitInitData (Module &M) {
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000180 std::string iDataSection = "idata.#";
181 SwitchToDataSection(iDataSection.c_str());
182 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
183 I != E; ++I) {
184 if (!I->hasInitializer()) // External global require no code.
185 continue;
186
187 Constant *C = I->getInitializer();
188 const PointerType *PtrTy = I->getType();
189 int AddrSpace = PtrTy->getAddressSpace();
190
191 if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::RAM_SPACE)) {
192
193 if (EmitSpecialLLVMGlobal(I))
194 continue;
195
196 // Any variables reaching here with "." in its name is a local scope
197 // variable and should not be printed in global data section.
198 std::string name = Mang->getValueName(I);
199 if (name.find(".") != std::string::npos)
200 continue;
201
202 O << name;
203 EmitGlobalConstant(C);
204 }
205 }
206}
207
208void PIC16AsmPrinter::EmitConstantValueOnly(const Constant* CV) {
209 if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
210 unsigned BitWidth = CI->getBitWidth();
211 int Val = CI->getZExtValue();
212 if (BitWidth == 8) {
213 // Expecting db directive here. In case of romdata we need to pad the
214 // word with zeros.
215 if (IsRomData)
216 O << 0 <<", ";
217 O << Val;
218 }
219 else if (BitWidth == 16) {
220 unsigned Element1, Element2;
221 Element1 = 0x00ff & Val;
222 Element2 = 0x00ff & (Val >> 8);
223 if (IsRomData)
224 O << 0 <<", "<<Element1 <<", "<< 0 <<", "<< Element2;
225 else
226 O << Element1 <<", "<< Element2;
227 }
228 else if (BitWidth == 32) {
229 unsigned Element1, Element2, Element3, Element4;
230 Element1 = 0x00ff & Val;
231 Element2 = 0x00ff & (Val >> 8);
232 Element3 = 0x00ff & (Val >> 16);
233 Element4 = 0x00ff & (Val >> 24);
234 if (IsRomData)
235 O << 0 <<", "<< Element1 <<", "<< 0 <<", "<< Element2 <<", "<< 0
236 <<", "<< Element3 <<", "<< 0 <<", "<< Element4;
237 else
238 O << Element1 <<", "<< Element2 <<", "<< Element3 <<", "<< Element4;
239 }
240 return;
241 }
242 AsmPrinter::EmitConstantValueOnly(CV);
243}
244
245void PIC16AsmPrinter::EmitRomData (Module &M)
246{
247 std::string romDataSection = "romdata.#";
248 SwitchToRomDataSection(romDataSection.c_str());
249 IsRomData = true;
250 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
251 I != E; ++I) {
252 if (!I->hasInitializer()) // External global require no code.
253 continue;
254
255 Constant *C = I->getInitializer();
256 const PointerType *PtrTy = I->getType();
257 int AddrSpace = PtrTy->getAddressSpace();
258 if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::ROM_SPACE)) {
259
260 if (EmitSpecialLLVMGlobal(I))
261 continue;
262
263 // Any variables reaching here with "." in its name is a local scope
264 // variable and should not be printed in global data section.
265 std::string name = Mang->getValueName(I);
266 if (name.find(".") != std::string::npos)
267 continue;
268
269 O << name;
270 EmitGlobalConstant(C);
271 O << "\n";
272 }
273 }
274 IsRomData = false;
275}
276
277
278void PIC16AsmPrinter::EmitUnInitData (Module &M)
279{
280 std::string uDataSection = "udata.#";
281 SwitchToUDataSection(uDataSection.c_str());
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000282 const TargetData *TD = TM.getTargetData();
283
284 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
285 I != E; ++I) {
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000286 if (!I->hasInitializer()) // External global require no code.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000287 continue;
288
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000289 Constant *C = I->getInitializer();
290 if (C->isNullValue()) {
291
292 if (EmitSpecialLLVMGlobal(I))
293 continue;
294
295 // Any variables reaching here with "." in its name is a local scope
296 // variable and should not be printed in global data section.
297 std::string name = Mang->getValueName(I);
298 if (name.find(".") != std::string::npos)
299 continue;
300
301 const Type *Ty = C->getType();
Duncan Sandsceb4d1a2009-01-12 20:38:59 +0000302 unsigned Size = TD->getTypePaddedSize(Ty);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000303 O << name << " " <<"RES"<< " " << Size ;
304 O << "\n";
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000305 }
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000306 }
307}
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000308
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000309bool PIC16AsmPrinter::doFinalization(Module &M) {
310 O << "\t" << "END\n";
311 bool Result = AsmPrinter::doFinalization(M);
312 return Result;
313}
314
315void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
316 const Function *F = MF.getFunction();
317 std::string FuncName = Mang->getValueName(F);
318 const Module *M = F->getParent();
319 const TargetData *TD = TM.getTargetData();
320
321 // Emit the data section name.
322 O << "\n";
323 std::string fDataSection = "fdata." + CurrentFnName + ".#";
324 SwitchToUDataSection(fDataSection.c_str(), F);
Sanjiv Gupta8f78fa82008-11-26 10:53:50 +0000325
326 //Emit function return value.
327 O << CurrentFnName << ".retval:\n";
328 const Type *RetType = F->getReturnType();
329 if (RetType->getTypeID() != Type::VoidTyID) {
Duncan Sandsceb4d1a2009-01-12 20:38:59 +0000330 unsigned RetSize = TD->getTypePaddedSize(RetType);
Sanjiv Gupta8f78fa82008-11-26 10:53:50 +0000331 if (RetSize > 0)
332 O << CurrentFnName << ".retval" << " RES " << RetSize;
333 }
334 // Emit function arguments.
335 O << CurrentFnName << ".args:\n";
336 for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
337 AI != AE; ++AI) {
338 std::string ArgName = Mang->getValueName(AI);
339 const Type *ArgTy = AI->getType();
Duncan Sandsceb4d1a2009-01-12 20:38:59 +0000340 unsigned ArgSize = TD->getTypePaddedSize(ArgTy);
Sanjiv Gupta8f78fa82008-11-26 10:53:50 +0000341 O << CurrentFnName << ".args." << ArgName << " RES " << ArgSize;
342 }
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000343 // Emit the function variables.
344
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000345 // In PIC16 all the function arguments and local variables are global.
346 // Therefore to get the variable belonging to this function entire
347 // global list will be traversed and variables belonging to this function
348 // will be emitted in the current data section.
349 for (Module::const_global_iterator I = M->global_begin(), E = M->global_end();
350 I != E; ++I) {
351 std::string VarName = Mang->getValueName(I);
352
353 // The variables of a function are of form FuncName.* . If this variable
354 // does not belong to this function then continue.
355 if (!(VarName.find(FuncName + ".") == 0 ? true : false))
356 continue;
357
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000358 Constant *C = I->getInitializer();
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000359 const Type *Ty = C->getType();
Duncan Sandsceb4d1a2009-01-12 20:38:59 +0000360 unsigned Size = TD->getTypePaddedSize(Ty);
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000361 // Emit memory reserve directive.
362 O << VarName << " RES " << Size << "\n";
363 }
364 emitFunctionTempData(MF);
365}
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000366
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000367void PIC16AsmPrinter::emitFunctionTempData(MachineFunction &MF) {
368 // Emit temporary variables.
369 MachineFrameInfo *FrameInfo = MF.getFrameInfo();
370 if (FrameInfo->hasStackObjects()) {
371 int indexBegin = FrameInfo->getObjectIndexBegin();
372 int indexEnd = FrameInfo->getObjectIndexEnd();
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000373
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000374 if (indexBegin < indexEnd)
375 O << CurrentFnName << ".tmp RES"<< " "
376 <<indexEnd - indexBegin <<"\n";
377 /*
378 while (indexBegin < indexEnd) {
379 O << CurrentFnName << "_tmp_" << indexBegin << " " << "RES"<< " "
380 << 1 << "\n" ;
381 indexBegin++;
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000382 }
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000383 */
384 }
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000385}
386
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000387/// The function is same as AsmPrinter::SwitchtoDataSection except the call
388/// to getUDataSectionStartSuffix.
389void PIC16AsmPrinter::SwitchToUDataSection(const char *NewSection,
390 const GlobalValue *GV) {
391 std::string NS;
392 if (GV && GV->hasSection())
393 NS = TAI->getSwitchToSectionDirective() + GV->getSection();
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000394 else
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000395 NS = NewSection;
396
397 // If we're already in this section, we're done.
398 if (CurrentSection == NS) return;
399
400 // Close the current section, if applicable.
401 if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
402 O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
403
404 CurrentSection = NS;
405
406 if (!CurrentSection.empty()){}
407 O << CurrentSection << (static_cast<const PIC16TargetAsmInfo *>(TAI))->
408 getUDataSectionStartSuffix() << '\n';
409
410 IsInTextSection = false;
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000411}
412
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000413/// The function is same as AsmPrinter::SwitchtoDataSection except the call
414/// to getRomDataSectionStartSuffix.
415void PIC16AsmPrinter::SwitchToRomDataSection(const char *NewSection,
416 const GlobalValue *GV) {
417 std::string NS;
418 if (GV && GV->hasSection())
419 NS = TAI->getSwitchToSectionDirective() + GV->getSection();
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000420 else
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000421 NS = NewSection;
422
423 // If we're already in this section, we're done.
424 if (CurrentSection == NS) return;
425
426 // Close the current section, if applicable.
427 if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty())
428 O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n';
429
430 CurrentSection = NS;
431
432 if (!CurrentSection.empty()) {}
433 O << CurrentSection << (static_cast< const PIC16TargetAsmInfo *>(TAI))->
434 getRomDataSectionStartSuffix() << '\n';
435
436 IsInTextSection = false;
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000437}
Sanjiv Guptab1b5ffd2008-11-19 11:00:54 +0000438