blob: 65309ea6750b68cf767f5e5556fd73c3452f050d [file] [log] [blame]
Sanjiv Gupta27806092009-08-13 16:37:05 +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
15#include "PIC16AsmPrinter.h"
Chris Lattnerc0776212009-08-15 06:13:40 +000016#include "MCSectionPIC16.h"
Sanjiv Gupta27806092009-08-13 16:37:05 +000017#include "PIC16TargetAsmInfo.h"
18#include "llvm/DerivedTypes.h"
19#include "llvm/Function.h"
20#include "llvm/Module.h"
21#include "llvm/CodeGen/DwarfWriter.h"
22#include "llvm/CodeGen/MachineFrameInfo.h"
23#include "llvm/CodeGen/DwarfWriter.h"
24#include "llvm/CodeGen/MachineModuleInfo.h"
Chris Lattner6c2f9e12009-08-19 05:49:37 +000025#include "llvm/MC/MCStreamer.h"
Sanjiv Gupta27806092009-08-13 16:37:05 +000026#include "llvm/Target/TargetRegistry.h"
27#include "llvm/Target/TargetLoweringObjectFile.h"
28#include "llvm/Support/ErrorHandling.h"
29#include "llvm/Support/FormattedStream.h"
30#include "llvm/Support/Mangler.h"
31#include <cstring>
32using namespace llvm;
33
34#include "PIC16GenAsmWriter.inc"
35
36PIC16AsmPrinter::PIC16AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
37 const TargetAsmInfo *T, bool V)
38: AsmPrinter(O, TM, T, V), DbgInfo(O, T) {
39 PTLI = static_cast<PIC16TargetLowering*>(TM.getTargetLowering());
40 PTAI = static_cast<const PIC16TargetAsmInfo*>(T);
41 PTOF = (PIC16TargetObjectFile*)&PTLI->getObjFileLowering();
Sanjiv Guptaeb01aba2009-08-20 19:28:24 +000042 CurrentFnPtr = NULL;
Sanjiv Gupta27806092009-08-13 16:37:05 +000043}
44
45bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
46 printInstruction(MI);
47 return true;
48}
49
50/// runOnMachineFunction - This emits the frame section, autos section and
51/// assembly for each instruction. Also takes care of function begin debug
52/// directive and file begin debug directive (if required) for the function.
53///
54bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
55 this->MF = &MF;
56
57 // This calls the base class function required to be called at beginning
58 // of runOnMachineFunction.
59 SetupMachineFunction(MF);
60
61 // Get the mangled name.
62 const Function *F = MF.getFunction();
63 CurrentFnName = Mang->getMangledName(F);
Sanjiv Guptaeb01aba2009-08-20 19:28:24 +000064 CurrentFnPtr = F;
65
66 // Current function name was mangled in llvm-ld for both
67 // MainLine and InterruptLine and should be demangled here
68 PAN::updateCallLineSymbol(CurrentFnName, CurrentFnPtr);
Sanjiv Gupta27806092009-08-13 16:37:05 +000069
70 // Emit the function frame (args and temps).
71 EmitFunctionFrame(MF);
72
73 DbgInfo.BeginFunction(MF);
74
75 // Emit the autos section of function.
Sanjiv Guptaeaa8b1f2009-08-21 15:22:33 +000076 EmitAutos(F);
Sanjiv Gupta27806092009-08-13 16:37:05 +000077
78 // Now emit the instructions of function in its code section.
79 const MCSection *fCodeSection =
Sanjiv Guptaeb01aba2009-08-20 19:28:24 +000080 getObjFileLowering().getSectionForFunction(CurrentFnName,
81 PAN::isISR(F));
Sanjiv Gupta27806092009-08-13 16:37:05 +000082 // Start the Code Section.
83 O << "\n";
Chris Lattner6c2f9e12009-08-19 05:49:37 +000084 OutStreamer.SwitchSection(fCodeSection);
Sanjiv Guptaeb01aba2009-08-20 19:28:24 +000085
86 // If it is not an interrupt function then emit the data address
87 // retrieval code in function code itself.
88 if (!(PAN::isISR(F))) {
89 // Emit the frame address of the function at the beginning of code.
90 O << "\tretlw low(" << PAN::getFrameLabel(CurrentFnName) << ")\n";
91 O << "\tretlw high(" << PAN::getFrameLabel(CurrentFnName) << ")\n";
92 }
Sanjiv Gupta27806092009-08-13 16:37:05 +000093
94 // Emit function start label.
95 O << CurrentFnName << ":\n";
Sanjiv Guptaeb01aba2009-08-20 19:28:24 +000096
Sanjiv Gupta27806092009-08-13 16:37:05 +000097 DebugLoc CurDL;
98 O << "\n";
99 // Print out code for the function.
100 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
101 I != E; ++I) {
102
103 // Print a label for the basic block.
104 if (I != MF.begin()) {
105 printBasicBlockLabel(I, true);
106 O << '\n';
107 }
108
109 // Print a basic block.
110 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
111 II != E; ++II) {
112
113 // Emit the line directive if source line changed.
114 const DebugLoc DL = II->getDebugLoc();
115 if (!DL.isUnknown() && DL != CurDL) {
116 DbgInfo.ChangeDebugLoc(MF, DL);
117 CurDL = DL;
118 }
119
120 // Print the assembly for the instruction.
121 printMachineInstruction(II);
122 }
123 }
124
125 // Emit function end debug directives.
126 DbgInfo.EndFunction(MF);
127
128 return false; // we didn't modify anything.
129}
130
131
132// printOperand - print operand of insn.
133void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
134 const MachineOperand &MO = MI->getOperand(opNum);
135
136 switch (MO.getType()) {
137 case MachineOperand::MO_Register:
138 if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
139 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
140 else
141 llvm_unreachable("not implemented");
142 return;
143
144 case MachineOperand::MO_Immediate:
145 O << (int)MO.getImm();
146 return;
147
148 case MachineOperand::MO_GlobalAddress: {
149 std::string Sname = Mang->getMangledName(MO.getGlobal());
150 // FIXME: currently we do not have a memcpy def coming in the module
151 // by any chance, as we do not link in those as .bc lib. So these calls
152 // are always external and it is safe to emit an extern.
153 if (PAN::isMemIntrinsic(Sname)) {
154 LibcallDecls.push_back(createESName(Sname));
155 }
Sanjiv Guptaeb01aba2009-08-20 19:28:24 +0000156 // All the call sites were mangled in llvm-ld pass hence the
157 // operands for call instructions should be demangled here.
158 PAN::updateCallLineSymbol(Sname, CurrentFnPtr);
Sanjiv Gupta27806092009-08-13 16:37:05 +0000159 O << Sname;
160 break;
161 }
162 case MachineOperand::MO_ExternalSymbol: {
163 const char *Sname = MO.getSymbolName();
164
165 // If its a libcall name, record it to decls section.
166 if (PAN::getSymbolTag(Sname) == PAN::LIBCALL) {
Sanjiv Guptaeb01aba2009-08-20 19:28:24 +0000167 // LibCallDecls for InterruptLine functions should have ".IL" suffix
168 const char *NewName= PAN::getUpdatedLibCallDecl(Sname, CurrentFnPtr);
169 LibcallDecls.push_back(NewName);
Sanjiv Gupta27806092009-08-13 16:37:05 +0000170 }
171
172 // Record a call to intrinsic to print the extern declaration for it.
173 std::string Sym = Sname;
174 if (PAN::isMemIntrinsic(Sym)) {
175 Sym = PAN::addPrefix(Sym);
176 LibcallDecls.push_back(createESName(Sym));
177 }
Sanjiv Guptaeb01aba2009-08-20 19:28:24 +0000178 // Update the library call symbols. Library calls to InterruptLine
179 // functions are different. (They have ".IL" in their names)
180 // Also other symbols (frame and temp) for the cloned function
181 // should be updated here.
182 PAN::updateCallLineSymbol(Sym, CurrentFnPtr);
183 O << Sym;
184 break;
Sanjiv Gupta27806092009-08-13 16:37:05 +0000185 }
186 case MachineOperand::MO_MachineBasicBlock:
187 printBasicBlockLabel(MO.getMBB());
188 return;
189
190 default:
191 llvm_unreachable(" Operand type not supported.");
192 }
193}
194
195/// printCCOperand - Print the cond code operand.
196///
197void PIC16AsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
198 int CC = (int)MI->getOperand(opNum).getImm();
199 O << PIC16CondCodeToString((PIC16CC::CondCodes)CC);
200}
201
202// This function is used to sort the decls list.
203// should return true if s1 should come before s2.
204static bool is_before(const char *s1, const char *s2) {
205 return strcmp(s1, s2) <= 0;
206}
207
208// This is used by list::unique below.
209// unique will filter out duplicates if it knows them.
210static bool is_duplicate(const char *s1, const char *s2) {
211 return !strcmp(s1, s2);
212}
213
214/// printLibcallDecls - print the extern declarations for compiler
215/// intrinsics.
216///
217void PIC16AsmPrinter::printLibcallDecls() {
218 // If no libcalls used, return.
219 if (LibcallDecls.empty()) return;
220
221 O << TAI->getCommentString() << "External decls for libcalls - BEGIN." <<"\n";
222 // Remove duplicate entries.
223 LibcallDecls.sort(is_before);
224 LibcallDecls.unique(is_duplicate);
225
226 for (std::list<const char*>::const_iterator I = LibcallDecls.begin();
227 I != LibcallDecls.end(); I++) {
228 O << TAI->getExternDirective() << *I << "\n";
229 O << TAI->getExternDirective() << PAN::getArgsLabel(*I) << "\n";
230 O << TAI->getExternDirective() << PAN::getRetvalLabel(*I) << "\n";
231 }
232 O << TAI->getCommentString() << "External decls for libcalls - END." <<"\n";
233}
234
235/// doInitialization - Perfrom Module level initializations here.
236/// One task that we do here is to sectionize all global variables.
237/// The MemSelOptimizer pass depends on the sectionizing.
238///
239bool PIC16AsmPrinter::doInitialization(Module &M) {
240 bool Result = AsmPrinter::doInitialization(M);
241
242 // FIXME:: This is temporary solution to generate the include file.
243 // The processor should be passed to llc as in input and the header file
244 // should be generated accordingly.
245 O << "\n\t#include P16F1937.INC\n";
246
247 // Set the section names for all globals.
248 for (Module::global_iterator I = M.global_begin(), E = M.global_end();
249 I != E; ++I)
250 if (!I->isDeclaration() && !I->hasAvailableExternallyLinkage()) {
251 const MCSection *S = getObjFileLowering().SectionForGlobal(I, Mang, TM);
252
253 I->setSection(((const MCSectionPIC16*)S)->getName());
254 }
255
256 DbgInfo.BeginModule(M);
257 EmitFunctionDecls(M);
258 EmitUndefinedVars(M);
259 EmitDefinedVars(M);
260 EmitIData(M);
261 EmitUData(M);
262 EmitRomData(M);
263 return Result;
264}
265
266/// Emit extern decls for functions imported from other modules, and emit
267/// global declarations for function defined in this module and which are
268/// available to other modules.
269///
270void PIC16AsmPrinter::EmitFunctionDecls(Module &M) {
271 // Emit declarations for external functions.
272 O <<"\n"<<TAI->getCommentString() << "Function Declarations - BEGIN." <<"\n";
273 for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) {
274 if (I->isIntrinsic())
275 continue;
276
277 std::string Name = Mang->getMangledName(I);
278 if (Name.compare("@abort") == 0)
279 continue;
280
281 if (!I->isDeclaration() && !I->hasExternalLinkage())
282 continue;
283
284 // Do not emit memcpy, memset, and memmove here.
285 // Calls to these routines can be generated in two ways,
286 // 1. User calling the standard lib function
287 // 2. Codegen generating these calls for llvm intrinsics.
288 // In the first case a prototype is alread availale, while in
289 // second case the call is via and externalsym and the prototype is missing.
290 // So declarations for these are currently always getting printing by
291 // tracking both kind of references in printInstrunction.
292 if (I->isDeclaration() && PAN::isMemIntrinsic(Name)) continue;
293
294 const char *directive = I->isDeclaration() ? TAI->getExternDirective() :
295 TAI->getGlobalDirective();
Sanjiv Guptaeb01aba2009-08-20 19:28:24 +0000296
297 // This is called in initialization. Hence information of the current
298 // function line is not available. Hence UnspecifiedLine. UnspecifiedLine
299 // will be treated as MainLine.
300 PAN::updateCallLineSymbol(Name, PAN::UnspecifiedLine);
Sanjiv Gupta27806092009-08-13 16:37:05 +0000301 O << directive << Name << "\n";
302 O << directive << PAN::getRetvalLabel(Name) << "\n";
303 O << directive << PAN::getArgsLabel(Name) << "\n";
304 }
305
306 O << TAI->getCommentString() << "Function Declarations - END." <<"\n";
307}
308
309// Emit variables imported from other Modules.
310void PIC16AsmPrinter::EmitUndefinedVars(Module &M) {
311 std::vector<const GlobalVariable*> Items = PTOF->ExternalVarDecls->Items;
312 if (!Items.size()) return;
313
314 O << "\n" << TAI->getCommentString() << "Imported Variables - BEGIN" << "\n";
315 for (unsigned j = 0; j < Items.size(); j++) {
316 O << TAI->getExternDirective() << Mang->getMangledName(Items[j]) << "\n";
317 }
318 O << TAI->getCommentString() << "Imported Variables - END" << "\n";
319}
320
321// Emit variables defined in this module and are available to other modules.
322void PIC16AsmPrinter::EmitDefinedVars(Module &M) {
323 std::vector<const GlobalVariable*> Items = PTOF->ExternalVarDefs->Items;
324 if (!Items.size()) return;
325
326 O << "\n" << TAI->getCommentString() << "Exported Variables - BEGIN" << "\n";
327 for (unsigned j = 0; j < Items.size(); j++) {
328 O << TAI->getGlobalDirective() << Mang->getMangledName(Items[j]) << "\n";
329 }
330 O << TAI->getCommentString() << "Exported Variables - END" << "\n";
331}
332
333// Emit initialized data placed in ROM.
334void PIC16AsmPrinter::EmitRomData(Module &M) {
335 // Print ROM Data section.
336 const std::vector<PIC16Section*> &ROSections = PTOF->ROSections;
337 for (unsigned i = 0; i < ROSections.size(); i++) {
338 const std::vector<const GlobalVariable*> &Items = ROSections[i]->Items;
339 if (!Items.size()) continue;
340 O << "\n";
Chris Lattner6c2f9e12009-08-19 05:49:37 +0000341 OutStreamer.SwitchSection(PTOF->ROSections[i]->S_);
Sanjiv Gupta27806092009-08-13 16:37:05 +0000342 for (unsigned j = 0; j < Items.size(); j++) {
343 O << Mang->getMangledName(Items[j]);
344 Constant *C = Items[j]->getInitializer();
345 int AddrSpace = Items[j]->getType()->getAddressSpace();
346 EmitGlobalConstant(C, AddrSpace);
347 }
348 }
349}
350
351bool PIC16AsmPrinter::doFinalization(Module &M) {
352 printLibcallDecls();
353 EmitRemainingAutos();
354 DbgInfo.EndModule(M);
355 O << "\n\t" << "END\n";
356 return AsmPrinter::doFinalization(M);
357}
358
359void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) {
360 const Function *F = MF.getFunction();
361 std::string FuncName = Mang->getMangledName(F);
362 const TargetData *TD = TM.getTargetData();
363 // Emit the data section name.
364 O << "\n";
Sanjiv Guptaeaa8b1f2009-08-21 15:22:33 +0000365
366 std::string SectionName = getObjFileLowering().getNameForFunctFrame(F);
Sanjiv Gupta27806092009-08-13 16:37:05 +0000367 const MCSection *fPDataSection =
Sanjiv Guptaeaa8b1f2009-08-21 15:22:33 +0000368 getObjFileLowering().getSectionForFunctionFrame(SectionName);
Chris Lattner6c2f9e12009-08-19 05:49:37 +0000369 OutStreamer.SwitchSection(fPDataSection);
Sanjiv Gupta27806092009-08-13 16:37:05 +0000370
371 // Emit function frame label
372 O << PAN::getFrameLabel(CurrentFnName) << ":\n";
373
374 const Type *RetType = F->getReturnType();
375 unsigned RetSize = 0;
376 if (RetType->getTypeID() != Type::VoidTyID)
377 RetSize = TD->getTypeAllocSize(RetType);
378
379 //Emit function return value space
380 // FIXME: Do not emit RetvalLable when retsize is zero. To do this
381 // we will need to avoid printing a global directive for Retval label
382 // in emitExternandGloblas.
383 if(RetSize > 0)
384 O << PAN::getRetvalLabel(CurrentFnName) << " RES " << RetSize << "\n";
385 else
386 O << PAN::getRetvalLabel(CurrentFnName) << ": \n";
387
388 // Emit variable to hold the space for function arguments
389 unsigned ArgSize = 0;
390 for (Function::const_arg_iterator argi = F->arg_begin(),
391 arge = F->arg_end(); argi != arge ; ++argi) {
392 const Type *Ty = argi->getType();
393 ArgSize += TD->getTypeAllocSize(Ty);
394 }
395
396 O << PAN::getArgsLabel(CurrentFnName) << " RES " << ArgSize << "\n";
397
398 // Emit temporary space
399 int TempSize = PTLI->GetTmpSize();
400 if (TempSize > 0)
401 O << PAN::getTempdataLabel(CurrentFnName) << " RES " << TempSize << '\n';
402}
403
404void PIC16AsmPrinter::EmitIData(Module &M) {
405
406 // Print all IDATA sections.
407 const std::vector<PIC16Section*> &IDATASections = PTOF->IDATASections;
408 for (unsigned i = 0; i < IDATASections.size(); i++) {
409 O << "\n";
410 if (IDATASections[i]->S_->getName().find("llvm.") != std::string::npos)
411 continue;
Chris Lattner6c2f9e12009-08-19 05:49:37 +0000412 OutStreamer.SwitchSection(IDATASections[i]->S_);
Sanjiv Gupta27806092009-08-13 16:37:05 +0000413 std::vector<const GlobalVariable*> Items = IDATASections[i]->Items;
414 for (unsigned j = 0; j < Items.size(); j++) {
415 std::string Name = Mang->getMangledName(Items[j]);
416 Constant *C = Items[j]->getInitializer();
417 int AddrSpace = Items[j]->getType()->getAddressSpace();
418 O << Name;
419 EmitGlobalConstant(C, AddrSpace);
420 }
421 }
422}
423
424void PIC16AsmPrinter::EmitUData(Module &M) {
425 const TargetData *TD = TM.getTargetData();
426
427 // Print all BSS sections.
428 const std::vector<PIC16Section*> &BSSSections = PTOF->BSSSections;
429 for (unsigned i = 0; i < BSSSections.size(); i++) {
430 O << "\n";
Chris Lattner6c2f9e12009-08-19 05:49:37 +0000431 OutStreamer.SwitchSection(BSSSections[i]->S_);
Sanjiv Gupta27806092009-08-13 16:37:05 +0000432 std::vector<const GlobalVariable*> Items = BSSSections[i]->Items;
433 for (unsigned j = 0; j < Items.size(); j++) {
434 std::string Name = Mang->getMangledName(Items[j]);
435 Constant *C = Items[j]->getInitializer();
436 const Type *Ty = C->getType();
437 unsigned Size = TD->getTypeAllocSize(Ty);
438
439 O << Name << " RES " << Size << "\n";
440 }
441 }
442}
443
Sanjiv Guptaeaa8b1f2009-08-21 15:22:33 +0000444void PIC16AsmPrinter::EmitAutos(const Function *F) {
Sanjiv Gupta27806092009-08-13 16:37:05 +0000445 // Section names for all globals are already set.
446 const TargetData *TD = TM.getTargetData();
447
448 // Now print Autos section for this function.
Sanjiv Guptaeaa8b1f2009-08-21 15:22:33 +0000449 std::string SectionName = PAN::getAutosSectionName(CurrentFnName);
Sanjiv Guptaeb01aba2009-08-20 19:28:24 +0000450
451 // If this function is a cloned function then the name of auto section
452 // will not be present in the list of existing section. Hence this section
453 // should be cloned.
454 // This function will check and clone
455 PTOF->createClonedSectionForAutos(SectionName);
456
Sanjiv Gupta27806092009-08-13 16:37:05 +0000457 const std::vector<PIC16Section*> &AutosSections = PTOF->AutosSections;
458 for (unsigned i = 0; i < AutosSections.size(); i++) {
459 O << "\n";
460 if (AutosSections[i]->S_->getName() == SectionName) {
461 // Set the printing status to true
462 AutosSections[i]->setPrintedStatus(true);
Sanjiv Guptaeaa8b1f2009-08-21 15:22:33 +0000463 // Overlay auto sections with same function color.
464 std::string BaseSectionName = getObjFileLowering().
465 getNameForFunctFrame(F, true);
466 if (BaseSectionName != F->getName()) {
467 std::string NewSectionName = PAN::getAutosSectionName(BaseSectionName);
468 const_cast<MCSectionPIC16 *>(AutosSections[i]->S_)->setName(
469 NewSectionName);
470 }
471
Chris Lattner6c2f9e12009-08-19 05:49:37 +0000472 OutStreamer.SwitchSection(AutosSections[i]->S_);
Sanjiv Gupta27806092009-08-13 16:37:05 +0000473 const std::vector<const GlobalVariable*> &Items = AutosSections[i]->Items;
474 for (unsigned j = 0; j < Items.size(); j++) {
475 std::string VarName = Mang->getMangledName(Items[j]);
476 Constant *C = Items[j]->getInitializer();
477 const Type *Ty = C->getType();
478 unsigned Size = TD->getTypeAllocSize(Ty);
Sanjiv Guptaeb01aba2009-08-20 19:28:24 +0000479 // Auto variables should be cloned for the cloned function
480 PAN::updateCallLineAutos(VarName, CurrentFnName);
Sanjiv Gupta27806092009-08-13 16:37:05 +0000481 // Emit memory reserve directive.
482 O << VarName << " RES " << Size << "\n";
483 }
484 break;
485 }
486 }
487}
488
489// Print autos that were not printed during the code printing of functions.
490// As the functions might themselves would have got deleted by the optimizer.
491void PIC16AsmPrinter::EmitRemainingAutos() {
492 const TargetData *TD = TM.getTargetData();
493
494 // Now print Autos section for this function.
495 std::vector <PIC16Section *>AutosSections = PTOF->AutosSections;
496 for (unsigned i = 0; i < AutosSections.size(); i++) {
497
498 // if the section is already printed then don't print again
499 if (AutosSections[i]->isPrinted())
500 continue;
501
502 // Set status as printed
503 AutosSections[i]->setPrintedStatus(true);
504
505 O << "\n";
Chris Lattner6c2f9e12009-08-19 05:49:37 +0000506 OutStreamer.SwitchSection(AutosSections[i]->S_);
Sanjiv Gupta27806092009-08-13 16:37:05 +0000507 const std::vector<const GlobalVariable*> &Items = AutosSections[i]->Items;
508 for (unsigned j = 0; j < Items.size(); j++) {
509 std::string VarName = Mang->getMangledName(Items[j]);
510 Constant *C = Items[j]->getInitializer();
511 const Type *Ty = C->getType();
512 unsigned Size = TD->getTypeAllocSize(Ty);
513 // Emit memory reserve directive.
514 O << VarName << " RES " << Size << "\n";
515 }
516 }
517}
518
519
520extern "C" void LLVMInitializePIC16AsmPrinter() {
521 RegisterAsmPrinter<PIC16AsmPrinter> X(ThePIC16Target);
522}
523
524