* src/pic/gen.c (genFunction,genCall): drop "same code page"
[fw/sdcc] / src / pic / glue.c
1 /*-------------------------------------------------------------------------
2
3   SDCCglue.c - glues everything we have done together into one file.
4                 Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
24
25 #include "../common.h"
26 #include <time.h>
27 #include "ralloc.h"
28 #include "pcode.h"
29 #include "newalloc.h"
30 #include "gen.h"
31 #include "main.h"
32 #include "device.h"
33
34
35 #ifdef WORDS_BIGENDIAN
36 #define _ENDIAN(x)  (3-x)
37 #else
38 #define _ENDIAN(x)  (x)
39 #endif
40
41 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
42
43 extern symbol *interrupts[256];
44 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
45 extern int noAlloc;
46 extern set *publics;
47 extern set *externs;
48 extern unsigned maxInterrupts;
49 extern int maxRegBank;
50 extern symbol *mainf;
51 extern char *VersionString;
52 extern FILE *codeOutFile;
53 extern set *tmpfileSet;
54 extern set *tmpfileNameSet;
55 extern char *iComments1;
56 extern char *iComments2;
57 //extern void emitStaticSeg (memmap * map);
58 set *pic14_localFunctions = NULL;
59
60 extern DEFSETFUNC (closeTmpFiles);
61 extern DEFSETFUNC (rmTmpFiles);
62
63 extern void AnalyzeBanking (void);
64 extern void copyFile (FILE * dest, FILE * src);
65 extern void ReuseReg(void);
66 extern void InlinepCode(void);
67 extern void writeUsedRegs(FILE *);
68
69 extern void initialComments (FILE * afile);
70 extern void printPublics (FILE * afile);
71
72 extern void printChar (FILE * ofile, char *s, int plen);
73 void  pCodeInitRegisters(void);
74 int getConfigWord(int address);
75 int getHasSecondConfigReg(void);
76 int pic14_getSharebankSize(void);
77 int pic14_getSharebankAddress(void);
78
79 char *udata_section_name=0;             // FIXME Temporary fix to change udata section name -- VR
80 int pic14_hasInterrupt = 0;             // Indicates whether to emit interrupt handler or not
81
82 /*-----------------------------------------------------------------*/
83 /* aopLiteral - string from a literal value                        */
84 /*-----------------------------------------------------------------*/
85 unsigned int pic14aopLiteral (value *val, int offset)
86 {
87         union {
88                 float f;
89                 unsigned char c[4];
90         } fl;
91         
92         /* if it is a float then it gets tricky */
93         /* otherwise it is fairly simple */
94         if (!IS_FLOAT(val->type)) {
95                 unsigned long v = (unsigned long) floatFromVal(val);
96                 
97                 return ( (v >> (offset * 8)) & 0xff);
98         }
99         
100         /* it is type float */
101         fl.f = (float) floatFromVal(val);
102 #ifdef WORDS_BIGENDIAN
103         return fl.c[3-offset];
104 #else
105         return fl.c[offset];
106 #endif
107         
108 }
109
110 /* Check whether the given reg is shared amongst all .o files of a project.
111  * This is true for the pseudo stack and WSAVE, SSAVE and PSAVE. */
112 static int
113 is_shared_address (int addr)
114 {
115   return ((addr > Gstack_base_addr - 18)
116         && (addr <= Gstack_base_addr));
117 }
118
119 int
120 pic14_is_shared (regs *reg)
121 {
122         if (!reg) return 0;
123         return is_shared_address (reg->address);
124 }
125
126 static int
127 is_valid_identifier( const char *name )
128 {
129   char a;
130   if (!name) return 0;
131   a = *name;
132   
133   /* only accept [a-zA-Z_][a-zA-Z0-9_] */
134   if (!((a >= 'a' && a <= 'z')
135         || (a >= 'A' && a <= 'z')
136         || (a == '_')))
137     return 0;
138
139   name++;
140   while ((a = *name++))
141   {
142     if (!((a >= 'a' && a <= 'z')
143         || (a >= 'A' && a <= 'Z')
144         || (a >= '0' && a <= '9')
145         || (a == '_')))
146       return 0;
147   } // while
148
149   /* valid identifier */
150   return 1;
151 }
152
153 /* set of already emitted symbols; we store only pointers to the emitted
154  * symbol names so these MUST NO BE CHANGED afterwards... */
155 static set *symbolsEmitted = NULL;
156
157 /*-------------------------------------------------------------------*/
158 /* emitSymbolToFile - write a symbol definition only if it is not    */
159 /*                    already present                                */
160 /*-------------------------------------------------------------------*/
161 void
162 emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
163 {
164         const char *sym;
165         static unsigned int sec_idx = 0;
166
167         /* workaround: variables declared via `sbit' result in a numeric
168          * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
169          * sbit is heavily used in the inc2h-generated header files!
170          */
171         if (!is_valid_identifier(name))
172         {
173           //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
174           return;
175         }
176         
177         /* check whether the symbol is already defined */
178         for (sym = (const char *) setFirstItem (symbolsEmitted);
179                 sym;
180                 sym = (const char *) setNextItem (symbolsEmitted))
181         {
182                 if (!strcmp (sym, name))
183                 {
184                         //fprintf (stderr, "%s: already emitted: %s\n", __FUNCTION__, name);
185                         return;
186                 }
187         } // for
188         
189         /* new symbol -- define it */
190         //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
191         if (useEQU)
192           fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
193         else
194         {
195           /* we place each symbol into a section of its own to allow the linker
196            * to distribute the data into all available memory banks */
197           if (!section_type) section_type = "udata";
198           if (addr != -1)
199           {
200             /* absolute symbols are handled in pic14_constructAbsMap */
201             /* do nothing */
202 #if 0
203             /* workaround gpasm bug with symbols being EQUated and placed in absolute sections */
204             if (1 || !is_shared_address (addr))
205             {
206               if (globalize) fprintf (of, "\tglobal\t%s\n", name);
207               fprintf (of, "udata_%s_%u\t%s\t0x%04x\n", moduleName,
208                   sec_idx++, "udata_ovr", addr);
209               fprintf (of, "%s\tres\t%d\n", name, size);
210             }
211             else
212             {
213               /* EQUs cannot be exported... */
214               fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
215             }
216 #endif
217           } else {
218             if (globalize) fprintf (of, "\tglobal\t%s\n", name);
219             fprintf (of, "udata_%s_%u\t%s\n", moduleName,
220                   sec_idx++, section_type);
221             fprintf (of, "%s\tres\t%d\n", name, size);
222           }
223         }
224
225         //if (options.verbose) fprintf (stderr, "%s: emitted %s\n", __FUNCTION__, name);
226         addSet (&symbolsEmitted, (void *) name);
227 }
228
229 #define IS_DEFINED_HERE(sym)    (!IS_EXTERN(sym->etype))
230 extern int IS_CONFIG_ADDRESS( int addr );
231 static void
232 pic14_constructAbsMap (FILE *ofile)
233 {
234   memmap *maps[] = { data, sfr, NULL };
235   int i;
236   hTab *ht = NULL;
237   symbol *sym;
238   set *aliases;
239   int addr, min=-1, max=-1;
240   int size;
241
242   for (i=0; maps[i] != NULL; i++)
243   {
244     for (sym = (symbol *)setFirstItem (maps[i]->syms);
245         sym; sym = setNextItem (maps[i]->syms))
246     {
247       if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
248       {
249         addr = SPEC_ADDR(sym->etype);
250
251         /* handle CONFIG words here */
252         if (IS_CONFIG_ADDRESS( addr ))
253         {
254           //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
255           //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
256           if (sym->ival) {
257             pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
258           } else {
259             fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
260           }
261           continue;
262         }
263         
264         if (max == -1 || addr > max) max = addr;
265         if (min == -1 || addr < min) min = addr;
266         //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
267         aliases = hTabItemWithKey (ht, addr);
268         if (aliases) {
269           /* May not use addSetHead, as we cannot update the
270            * list's head in the hastable `ht'. */
271           addSet (&aliases, sym);
272 #if 0
273           fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
274               __FUNCTION__, elementsInSet(aliases), sym->name, addr);
275 #endif
276         } else {
277           addSet (&aliases, sym);
278           hTabAddItem (&ht, addr, aliases);
279         } // if
280       } // if
281     } // for sym
282   } // for i
283
284   /* now emit definitions for all absolute symbols */
285   fprintf (ofile, "%s", iComments2);
286   fprintf (ofile, "; absolute symbol definitions\n");
287   fprintf (ofile, "%s", iComments2);
288   for (addr=min; addr <= max; addr++)
289   {
290     size = 1;
291     aliases = hTabItemWithKey (ht, addr);
292     if (aliases && elementsInSet(aliases)) {
293       fprintf (ofile, "udata_abs_%s_%x\tudata_ovr\t0x%04x",
294           moduleName, addr, addr);
295       for (sym = setFirstItem (aliases); sym;
296           sym = setNextItem (aliases))
297       {
298         /* emit STATUS as well as _STATUS, required for SFRs only */
299         fprintf (ofile, "\n%s", sym->name);
300         fprintf (ofile, "\n%s", sym->rname);
301         if (getSize(sym->type) > size) {
302           size = getSize(sym->type);
303         }
304         addSet (&symbolsEmitted, (void *) sym->name);
305         addSet (&symbolsEmitted, (void *) sym->rname);
306       } // for
307       fprintf (ofile, "\tres\t%d\n", size);
308     } // if
309   } // for i
310
311   /* also emit STK symbols
312    * XXX: This is ugly and fails as soon as devices start to get
313    *      differently sized sharebanks, since STK12 will be
314    *      required by larger devices but only up to STK03 might
315    *      be defined using smaller devices. */
316   fprintf (ofile, "\n");
317   if (!pic14_options.isLibrarySource)
318   {
319     fprintf (ofile, "\tglobal PSAVE\n");
320     fprintf (ofile, "\tglobal SSAVE\n");
321     fprintf (ofile, "\tglobal WSAVE\n");
322     for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
323       fprintf (ofile, "\tglobal STK%02d\n", i);
324     } // for i
325     fprintf (ofile, "sharebank udata_ovr 0x%04x\n",
326           pic14_getSharebankAddress() - pic14_getSharebankSize() + 1);
327     fprintf (ofile, "PSAVE\tres 1\n");
328     fprintf (ofile, "SSAVE\tres 1\n");
329     fprintf (ofile, "WSAVE\tres 1\n");
330     /* fill rest of sharebank with stack STKxx .. STK00 */
331     for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
332       fprintf (ofile, "STK%02d\tres 1\n", i);
333     } // for i
334   } else {
335     /* declare STKxx as extern for all files
336      * except the one containing main() */
337     fprintf (ofile, "\textern PSAVE\n");
338     fprintf (ofile, "\textern SSAVE\n");
339     fprintf (ofile, "\textern WSAVE\n");
340     for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
341       fprintf (ofile, "\textern STK%02d\n", i);
342     } // for i
343   }
344 }
345
346 /*-----------------------------------------------------------------*/
347 /* emitRegularMap - emit code for maps with no special cases       */
348 /*-----------------------------------------------------------------*/
349 static void
350 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
351 {
352         symbol *sym;
353         int bitvars = 0;;
354         
355         /* print the area name */
356         if (addPublics)
357                 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
358         
359         for (sym = setFirstItem (map->syms); sym;
360         sym = setNextItem (map->syms)) {
361                 
362                 //printf("%s\n",sym->name);
363
364                 /* ignore if config word */
365                 if (SPEC_ABSA(sym->etype)
366                     && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
367                         continue;
368                 
369                 /* if extern then add it into the extern list */
370                 if (IS_EXTERN (sym->etype)) {
371                         addSetHead (&externs, sym);
372                         continue;
373                 }
374                 
375                 /* if allocation required check is needed
376                 then check if the symbol really requires
377                 allocation only for local variables */
378                 if (arFlag && !IS_AGGREGATE (sym->type) &&
379                         !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
380                         !sym->allocreq && sym->level)
381                         continue;
382                 
383                 /* if global variable & not static or extern
384                 and addPublics allowed then add it to the public set */
385                 if ((sym->level == 0 ||
386                         (sym->_isparm && !IS_REGPARM (sym->etype))) &&
387                         addPublics &&
388                         !IS_STATIC (sym->etype))
389                 {
390                         //fprintf( stderr, "%s: made public %s\n", __FUNCTION__, sym->name );
391                         addSetHead (&publics, sym);
392                 }
393                 
394                 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
395                 if (sym->_isparm)
396                         continue;
397                         /* if extern then do nothing or is a function
398                 then do nothing */
399                 if (IS_FUNC (sym->type))
400                         continue;
401 #if 0
402                 /* print extra debug info if required */
403                 if (options.debug || sym->level == 0)
404                 {
405                         if (!sym->level)        /* global */
406                                 if (IS_STATIC (sym->etype))
407                                         fprintf (map->oFile, "F%s_", moduleName);               /* scope is file */
408                                 else
409                                         fprintf (map->oFile, "G_");     /* scope is global */
410                                 else
411                                         /* symbol is local */
412                                         fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
413                                 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
414                 }
415 #endif
416                 /* absolute symbols are handled in pic14_constructAbsMap */
417                 if (SPEC_ABSA(sym->etype) && IS_DEFINED_HERE(sym))
418                         continue;
419                 
420                 /* if it has an absolute address then generate
421                 an equate for this no need to allocate space */
422                 if (0 && SPEC_ABSA (sym->etype))
423                 {
424                         //if (options.debug || sym->level == 0)
425                         //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
426                         
427                         fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
428                                 sym->rname,
429                                 SPEC_ADDR (sym->etype));
430                 }
431                 else
432                 {
433                         /* allocate space */
434                         
435                         /* If this is a bit variable, then allocate storage after 8 bits have been declared */
436                         /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
437                         /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
438                         if (IS_BITVAR (sym->etype))
439                         {
440                                 bitvars++;
441                         }
442                         else
443                         {
444                                 emitSymbolToFile (map->oFile,
445                                         sym->rname, 
446                                         NULL,
447                                         getSize (sym->type) & 0xffff,
448                                         SPEC_ABSA(sym->etype)
449                                                 ? SPEC_ADDR(sym->etype)
450                                                 : -1,
451                                         0,
452                                         0);
453                                 /*
454                                 {
455                                 int i, size;
456                                 
457                                   if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
458                                   {
459                                   for (i = 1; i < size; i++)
460                                   fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
461                                   }
462                                   }
463                                 */
464                         }
465                         //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
466                 }
467                 
468                 /* if it has a initial value then do it only if
469                 it is a global variable */
470                 if (sym->ival && sym->level == 0) {
471                         ast *ival = NULL;
472                 
473                         if (IS_AGGREGATE (sym->type))
474                                 ival = initAggregates (sym, sym->ival, NULL);
475                         else
476                                 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
477                                 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
478                         codeOutFile = statsg->oFile;
479                         GcurMemmap = statsg;
480                         eBBlockFromiCode (iCodeFromAst (ival));
481                         sym->ival = NULL;
482                 }
483         }
484 }
485
486
487 /*-----------------------------------------------------------------*/
488 /* printIvalType - generates ival for int/char                     */
489 /*-----------------------------------------------------------------*/
490 static void 
491 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
492 {
493         value *val;
494         unsigned long ulval;
495         
496         //fprintf(stderr, "%s\n",__FUNCTION__);
497         
498         /* if initList is deep */
499         if (ilist->type == INIT_DEEP)
500                 ilist = ilist->init.deep;
501         
502         if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
503                 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
504         }
505         
506         if (!(val = list2val (ilist))) {
507                 // assuming a warning has been thrown
508                 val=constVal("0");
509         }
510         
511         if (val->type != type) {
512                 val = valCastLiteral(type, floatFromVal(val));
513         }
514         
515         if(val) 
516                 ulval = (unsigned long) floatFromVal (val);
517         else
518                 ulval =0;
519         
520         switch (getSize (type)) {
521         case 1:
522                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
523                 break;
524                 
525         case 2:
526                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
527                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
528                 break;
529                 
530         case 4:
531                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
532                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
533                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
534                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
535                 break;
536         }
537 }
538
539 /*-----------------------------------------------------------------*/
540 /* printIvalBitFields - generate initializer for bitfields         */
541 /*-----------------------------------------------------------------*/
542 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb ) 
543 {
544         value *val ;
545         symbol *lsym = *sym;
546         initList *lilist = *ilist ;
547         unsigned long ival = 0;
548         int size =0;
549         
550         
551         do {
552                 unsigned long i;
553                 val = list2val(lilist);
554                 if (size) {
555                         if (SPEC_BLEN(lsym->etype) > 8) {
556                                 size += ((SPEC_BLEN (lsym->etype) / 8) + 
557                                         (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
558                         }
559                 } else {
560                         size = ((SPEC_BLEN (lsym->etype) / 8) + 
561                                 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
562                 }
563                 i = (unsigned long)floatFromVal(val);
564                 i <<= SPEC_BSTR (lsym->etype);
565                 ival |= i;
566                 if (! ( lsym->next &&
567                         (IS_BITFIELD(lsym->next->type)) &&
568                         (SPEC_BSTR(lsym->next->etype)))) break;
569                 lsym = lsym->next;
570                 lilist = lilist->next;
571         } while (1);
572         switch (size) {
573         case 1:
574                 //tfprintf (oFile, "\t!db !constbyte\n",ival);
575                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
576                 break;
577                 
578         case 2:
579                 //tfprintf (oFile, "\t!dw !constword\n",ival);
580                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
581                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
582                 break;
583         case 4:
584                 //tfprintf (oFile, "\t!db  !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
585                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
586                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
587                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
588                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
589                 break;
590         }
591         *sym = lsym;
592         *ilist = lilist;
593 }
594
595 /*-----------------------------------------------------------------*/
596 /* printIvalStruct - generates initial value for structures        */
597 /*-----------------------------------------------------------------*/
598 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
599 {
600         symbol *sflds;
601         initList *iloop = NULL;
602         
603         sflds = SPEC_STRUCT (type)->fields;
604         
605         if (ilist) {
606                 if (ilist->type != INIT_DEEP) {
607                         werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
608                         return;
609                 }
610                 
611                 iloop = ilist->init.deep;
612         }
613         
614         for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
615                 if (IS_BITFIELD(sflds->type)) {
616                         printIvalBitFields(&sflds,&iloop,pb);
617                 } else {
618                         printIval (sym, sflds->type, iloop, pb);
619                 }
620         }
621         if (iloop) {
622                 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
623         }
624         return;
625 }
626
627 /*-----------------------------------------------------------------*/
628 /* printIvalChar - generates initital value for character array    */
629 /*-----------------------------------------------------------------*/
630 static int 
631 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
632 {
633         value *val;
634         int remain, ilen;
635         
636         if(!pb)
637                 return 0;
638         
639         //fprintf(stderr, "%s\n",__FUNCTION__);
640         if (!s)
641         {
642                 
643                 val = list2val (ilist);
644
645                 /* if the value is a character string  */
646                 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
647                 {
648                         ilen = DCL_ELEM(val->type);
649
650                         if (!DCL_ELEM (type))
651                                 DCL_ELEM (type) = ilen;
652                 
653                         /* emit string constant */
654                         for (remain = 0; remain < ilen; remain++) {
655                                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
656                         }
657                         
658                         /* fill array up to desired size */
659                         if ((remain = (DCL_ELEM (type) - ilen)) > 0)
660                                 while (remain--)
661                                         //tfprintf (oFile, "\t!db !constbyte\n", 0);
662                                         addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
663                                 return 1;
664                 }
665                 else
666                         return 0;
667         }
668         else {
669                 //printChar (oFile, s, strlen (s) + 1);
670                 
671                 for(remain=0; remain<(int)strlen(s); remain++) {
672                         addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
673                         //fprintf(stderr,"0x%02x ",s[remain]);
674                 }
675                 //fprintf(stderr,"\n");
676         }
677         return 1;
678 }
679
680 /*-----------------------------------------------------------------*/
681 /* printIvalArray - generates code for array initialization        */
682 /*-----------------------------------------------------------------*/
683 static void 
684 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
685                                 pBlock *pb)
686 {
687         initList *iloop;
688         unsigned size = 0;
689
690         if(!pb)
691                 return;
692         if (ilist) {
693                 /* take care of the special   case  */
694                 /* array of characters can be init  */
695                 /* by a string                      */
696                 if (IS_CHAR (type->next)) {
697                         //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
698                         if (!IS_LITERAL(list2val(ilist)->etype)) {
699                                 werror (W_INIT_WRONG);
700                                 return;
701                         }
702                         if (printIvalChar (type,
703                                 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
704                                 pb, SPEC_CVAL (sym->etype).v_char))
705                                 return;
706                 }
707                 /* not the special case */
708                 if (ilist->type != INIT_DEEP) {
709                         werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
710                         return;
711                 }
712
713                 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
714                         if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
715                                 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
716                                 break;
717                         }
718                         printIval (sym, type->next, iloop, pb);
719                 }
720         }
721
722         if (DCL_ELEM(type)) {
723                 // pad with zeros if needed
724                 if (size<DCL_ELEM(type)) {
725                         size = (DCL_ELEM(type) - size) * getSize(type->next);
726                         while (size--) {
727                                 //tfprintf (oFile, "\t!db !constbyte\n", 0);
728                                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
729                         }
730                 }
731         } else {
732                 // we have not been given a size, but we now know it
733                 DCL_ELEM (type) = size;
734         }
735
736         return;
737 }
738
739 /*-----------------------------------------------------------------*/
740 /* printIvalPtr - generates code for initial value of pointers     */
741 /*-----------------------------------------------------------------*/
742 extern value *initPointer (initList *, sym_link *toType);
743
744 static void 
745 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
746 {
747         value *val;
748         
749         if (!ilist || !pb)
750                 return;
751         
752         fprintf (stderr, "FIXME: initializers for pointers...\n");
753         printTypeChain (type, stderr);
754         
755         fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
756         fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
757
758         if (ilist && (ilist->type == INIT_DEEP))
759           ilist = ilist->init.deep;
760         
761         /* function pointers */
762         if (IS_FUNC (type->next))
763         {
764                 assert ( !"function pointers not yet handled" );
765                 //printIvalFuncPtr (type, ilist, pb);
766         }
767
768         if (!(val = initPointer (ilist, type)))
769                 return;
770         
771         if (IS_CHAR (type->next))
772         {
773                 if (printIvalChar (type, ilist, pb, NULL)) return;
774         }
775
776         /* check the type */
777         if (compareType (type, val->type) == 0)
778         {
779                 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
780                 printFromToType (val->type, type);
781         }
782
783         if (IS_LITERAL (val->etype))
784         {
785                 switch (getSize (type))
786                 {
787                 case 1:
788                         fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
789                         break;
790                 case 2:
791                         fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
792                         break;
793                 case 3: /* gneric pointers */
794                         assert ( !"generic pointers not yet handled" );
795                 case 4:
796                         fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
797                         break;
798                 default:
799                         assert ( !"invaild size of value -- aborting" );
800                 } // switch
801
802                 return;
803         } // if (IS_LITERAL)
804
805         /* now handle symbolic values */
806         switch (getSize (type))
807         {
808         case 1:
809                 fprintf (stderr, "BYTE: %s", val->name);
810                 break;
811         case 2:
812                 fprintf (stderr, "WORD: %s", val->name);
813                 break;
814         case 4:
815                 fprintf (stderr, "LONG: %s", val->name);
816                 break;
817         default:
818                 assert ( !"invalid size of (symbolic) value -- aborting" );
819         } // switch
820 }
821
822 /*-----------------------------------------------------------------*/
823 /* printIval - generates code for initial value                    */
824 /*-----------------------------------------------------------------*/
825 static void 
826 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
827 {
828         if (!ilist || !pb)
829                 return;
830         
831         /* if structure then    */
832         if (IS_STRUCT (type))
833         {
834                 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
835                 printIvalStruct (sym, type, ilist, pb);
836                 return;
837         }
838         
839         /* if this is an array   */
840         if (IS_ARRAY (type))
841         {
842                 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
843                 printIvalArray (sym, type, ilist, pb);
844                 return;
845         }
846         
847         /* if this is a pointer */
848         if (IS_PTR (type))
849         {
850                 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
851                 printIvalPtr (sym, type, ilist, pb);
852                 return;
853         }
854         
855         /* if type is SPECIFIER */
856         if (IS_SPEC (type))
857         {
858                 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
859                 printIvalType (sym, type, ilist, pb);
860                 return;
861         }
862 }
863
864 extern void pCodeConstString(char *name, char *value);
865 /*-----------------------------------------------------------------*/
866 /* emitStaticSeg - emitcode for the static segment                 */
867 /*-----------------------------------------------------------------*/
868 static void
869 pic14emitStaticSeg (memmap * map)
870 {
871         symbol *sym;
872         
873         fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
874         
875         //fprintf(stderr, "%s\n",__FUNCTION__);
876         
877         /* for all variables in this segment do */
878         for (sym = setFirstItem (map->syms); sym;
879         sym = setNextItem (map->syms))
880         {
881                 /* if extern then add it into the extern list */
882                 if (IS_EXTERN (sym->etype)) {
883                         addSetHead (&externs, sym);
884                         continue;
885                 }
886                 
887                 /* if it is not static add it to the public
888                 table */
889                 if (!IS_STATIC (sym->etype))
890                         addSetHead (&publics, sym);
891                 
892                 /* print extra debug info if required */
893                 if (options.debug || sym->level == 0)
894                 {
895                         if (!sym->level)
896                         {                       /* global */
897                                 if (IS_STATIC (sym->etype))
898                                         fprintf (code->oFile, "F%s_", moduleName);      /* scope is file */
899                                 else
900                                         fprintf (code->oFile, "G_");    /* scope is global */
901                         }
902                         else
903                                 /* symbol is local */
904                                 fprintf (code->oFile, "L%s_",
905                                 (sym->localof ? sym->localof->name : "-null-"));
906                         fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
907                         
908                 }
909                 
910                 /* if it has an absolute address */
911                 if (SPEC_ABSA (sym->etype))
912                 {
913                         if (options.debug || sym->level == 0)
914                                 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
915                         
916                         fprintf (code->oFile, "%s\t=\t0x%04x\n",
917                                 sym->rname,
918                                 SPEC_ADDR (sym->etype));
919                 }
920                 else
921                 {
922                         if (options.debug || sym->level == 0)
923                                 fprintf (code->oFile, " == .\n");
924                         
925                         /* if it has an initial value */
926                         if (sym->ival)
927                         {
928                                 pBlock *pb;
929                                 
930                                 fprintf (code->oFile, "%s:\n", sym->rname);
931                                 noAlloc++;
932                                 resolveIvalSym (sym->ival, sym->type);
933                                 //printIval (sym, sym->type, sym->ival, code->oFile);
934                                 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
935                                 addpBlock(pb);
936                                 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
937                                 
938                                 printIval (sym, sym->type, sym->ival, pb);
939                                 noAlloc--;
940                         }
941                         else
942                         {
943                                 
944                                 /* allocate space */
945                                 fprintf (code->oFile, "%s:\n", sym->rname);
946                                 /* special case for character strings */
947                                 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
948                                         SPEC_CVAL (sym->etype).v_char)
949                                         pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
950                                         /*printChar (code->oFile,
951                                         SPEC_CVAL (sym->etype).v_char,
952                                 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
953                                 else
954                                         fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
955                         }
956                 }
957         }
958         
959 }
960
961
962 /*-----------------------------------------------------------------*/
963 /* emitMaps - emits the code for the data portion the code         */
964 /*-----------------------------------------------------------------*/
965 static void
966 pic14emitMaps ()
967 {
968         pic14_constructAbsMap (sfr->oFile);
969 /* no special considerations for the following
970         data, idata & bit & xdata */
971         pic14emitRegularMap (data, TRUE, TRUE);
972         pic14emitRegularMap (idata, TRUE, TRUE);
973         pic14emitRegularMap (bit, TRUE, FALSE);
974         pic14emitRegularMap (xdata, TRUE, TRUE);
975         pic14emitRegularMap (sfr, TRUE, FALSE);
976         pic14emitRegularMap (sfrbit, FALSE, FALSE);
977         pic14emitRegularMap (code, TRUE, FALSE);
978         pic14emitStaticSeg (statsg);
979         pic14emitStaticSeg (c_abs);
980 }
981
982 /*-----------------------------------------------------------------*/
983 /* createInterruptVect - creates the interrupt vector              */
984 /*-----------------------------------------------------------------*/
985 static void
986 pic14createInterruptVect (FILE * vFile)
987 {
988         mainf = newSymbol ("main", 0);
989         mainf->block = 0;
990         
991         /* only if the main function exists */
992         if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
993         {
994                 struct options *op = &options;
995                 if (!(op->cc_only || noAssemble))
996                         //      werror (E_NO_MAIN);
997                         fprintf(stderr,"WARNING: function 'main' undefined\n");
998                 return;
999         }
1000         
1001         /* if the main is only a prototype ie. no body then do nothing */
1002         if (!IFFUNC_HASBODY(mainf->type))
1003         {
1004                 /* if ! compile only then main function should be present */
1005                 if (!(options.cc_only || noAssemble))
1006                         //      werror (E_NO_MAIN);
1007                         fprintf(stderr,"WARNING: function 'main' undefined\n");
1008                 return;
1009         }
1010         
1011         fprintf (vFile, "%s", iComments2);
1012         fprintf (vFile, "; reset vector \n");
1013         fprintf (vFile, "%s", iComments2);
1014         fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
1015         fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
1016         fprintf( vFile, "\tpagesel __sdcc_gsinit_startup\n");
1017         fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
1018 }
1019
1020
1021 /*-----------------------------------------------------------------*/
1022 /* initialComments - puts in some initial comments                 */
1023 /*-----------------------------------------------------------------*/
1024 static void
1025 pic14initialComments (FILE * afile)
1026 {
1027         initialComments (afile);
1028         fprintf (afile, "; PIC port for the 14-bit core\n");
1029         fprintf (afile, iComments2);
1030         
1031 }
1032
1033 int
1034 pic14_stringInSet(const char *str, set **world, int autoAdd)
1035 {
1036   char *s;
1037
1038   if (!str) return 1;
1039   assert(world);
1040
1041   for (s = setFirstItem(*world); s; s = setNextItem(*world))
1042   {
1043     /* found in set */
1044     if (0 == strcmp(s, str)) return 1;
1045   }
1046
1047   /* not found */
1048   if (autoAdd) addSet(world, Safe_strdup(str));
1049   return 0;
1050 }
1051
1052 static int
1053 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1054 {
1055   static set *emitted = NULL;
1056
1057   if (!pic14_stringInSet(sym, &emitted, 1)) {
1058     /* sym was not in emittedSymbols */
1059     if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
1060       /* sym is not a locally defined function---avoid bug #1443651 */
1061       fprintf( file, fmt, sym );
1062       return 0;
1063     }
1064   }
1065   return 1;
1066 }
1067
1068 /*-----------------------------------------------------------------*/
1069 /* printExterns - generates extern for external variables          */
1070 /*-----------------------------------------------------------------*/
1071 static void
1072 pic14printExterns (FILE * afile)
1073 {
1074         symbol *sym;
1075         
1076         fprintf (afile, "%s", iComments2);
1077         fprintf (afile, "; extern variables in this module\n");
1078         fprintf (afile, "%s", iComments2);
1079         
1080         for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1081                 pic14_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1082 }
1083
1084 /*-----------------------------------------------------------------*/
1085 /* printPublics - generates .global for publics                    */
1086 /*-----------------------------------------------------------------*/
1087 static void
1088 pic14printPublics (FILE * afile)
1089 {
1090   symbol *sym;
1091
1092   fprintf (afile, "%s", iComments2);
1093   fprintf (afile, "; publics variables in this module\n");
1094   fprintf (afile, "%s", iComments2);
1095
1096   for (sym = setFirstItem (publics); sym;
1097       sym = setNextItem (publics)) {
1098
1099     if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1100       if (!IS_BITVAR(sym->type))
1101         pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1102     } else {
1103       /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1104       /* Not any longer! */
1105       //if (!SPEC_ABSA (sym->etype))
1106       pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1107     }
1108   }
1109 }
1110
1111 /*-----------------------------------------------------------------*/
1112 /* emitOverlay - will emit code for the overlay stuff              */
1113 /*-----------------------------------------------------------------*/
1114 static void
1115 pic14emitOverlay (FILE * afile)
1116 {
1117         set *ovrset;
1118         
1119         /*  if (!elementsInSet (ovrSetSets))*/
1120         
1121         /* the hack below, fixes translates for devices which
1122         * only have udata_shr memory */
1123         fprintf (afile, "%s\t%s\n",
1124                 (elementsInSet(ovrSetSets)?"":";"),
1125                 port->mem.overlay_name);
1126         
1127         /* for each of the sets in the overlay segment do */
1128         for (ovrset = setFirstItem (ovrSetSets); ovrset;
1129         ovrset = setNextItem (ovrSetSets))
1130         {
1131                 
1132                 symbol *sym;
1133                 
1134                 if (elementsInSet (ovrset))
1135                 {
1136                 /* this dummy area is used to fool the assembler
1137                 otherwise the assembler will append each of these
1138                 declarations into one chunk and will not overlay
1139                         sad but true */
1140                         
1141                         /* I don't think this applies to us. We are using gpasm.  CRF */
1142                         
1143                         fprintf (afile, ";\t.area _DUMMY\n");
1144                         /* output the area informtion */
1145                         fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);      /* MOF */
1146                 }
1147                 
1148                 for (sym = setFirstItem (ovrset); sym;
1149                 sym = setNextItem (ovrset))
1150                 {
1151                         
1152                         /* if extern then do nothing */
1153                         if (IS_EXTERN (sym->etype))
1154                                 continue;
1155                         
1156                                 /* if allocation required check is needed
1157                                 then check if the symbol really requires
1158                         allocation only for local variables */
1159                         if (!IS_AGGREGATE (sym->type) &&
1160                                 !(sym->_isparm && !IS_REGPARM (sym->etype))
1161                                 && !sym->allocreq && sym->level)
1162                                 continue;
1163                         
1164                                 /* if global variable & not static or extern
1165                         and addPublics allowed then add it to the public set */
1166                         if ((sym->_isparm && !IS_REGPARM (sym->etype))
1167                                 && !IS_STATIC (sym->etype))
1168                                 addSetHead (&publics, sym);
1169                         
1170                                 /* if extern then do nothing or is a function
1171                         then do nothing */
1172                         if (IS_FUNC (sym->type))
1173                                 continue;
1174                         
1175                         /* print extra debug info if required */
1176                         if (options.debug || sym->level == 0)
1177                         {
1178                                 if (!sym->level)
1179                                 {               /* global */
1180                                         if (IS_STATIC (sym->etype))
1181                                                 fprintf (afile, "F%s_", moduleName);    /* scope is file */
1182                                         else
1183                                                 fprintf (afile, "G_");  /* scope is global */
1184                                 }
1185                                 else
1186                                         /* symbol is local */
1187                                         fprintf (afile, "L%s_",
1188                                         (sym->localof ? sym->localof->name : "-null-"));
1189                                 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
1190                         }
1191                         
1192                         /* if is has an absolute address then generate
1193                         an equate for this no need to allocate space */
1194                         if (SPEC_ABSA (sym->etype))
1195                         {
1196                                 
1197                                 if (options.debug || sym->level == 0)
1198                                         fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1199                                 
1200                                 fprintf (afile, "%s\t=\t0x%04x\n",
1201                                         sym->rname,
1202                                         SPEC_ADDR (sym->etype));
1203                         }
1204                         else
1205                         {
1206                                 if (options.debug || sym->level == 0)
1207                                         fprintf (afile, "==.\n");
1208                                 
1209                                 /* allocate space */
1210                                 fprintf (afile, "%s:\n", sym->rname);
1211                                 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1212                         }
1213                         
1214                 }
1215         }
1216 }
1217
1218
1219 void
1220 pic14_emitInterruptHandler (FILE * asmFile)
1221 {
1222         if (pic14_hasInterrupt)
1223         {
1224
1225                 fprintf (asmFile, "%s", iComments2);
1226                 fprintf (asmFile, "; interrupt and initialization code\n");
1227                 fprintf (asmFile, "%s", iComments2);
1228                 // Note - for mplink may have to enlarge section vectors in .lnk file
1229                 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1230                 //       source files's code segment (interrupt.c -> code_interrupt)
1231                 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1232                 
1233                 /* interrupt service routine */
1234                 fprintf (asmFile, "__sdcc_interrupt\n");
1235                 copypCode(asmFile, 'I');
1236         }       
1237 }
1238
1239 /*-----------------------------------------------------------------*/
1240 /* glue - the final glue that hold the whole thing together        */
1241 /*-----------------------------------------------------------------*/
1242 void
1243 picglue ()
1244 {
1245         char udata_name[80];
1246         FILE *vFile;
1247         FILE *asmFile;
1248         FILE *ovrFile = tempfile();
1249         
1250         addSetHead(&tmpfileSet,ovrFile);
1251         pCodeInitRegisters();
1252
1253         /* check for main() */
1254         mainf = newSymbol ("main", 0);
1255         mainf->block = 0;
1256         mainf = findSymWithLevel (SymbolTab, mainf);
1257
1258         if (!mainf || !IFFUNC_HASBODY(mainf->type))
1259         {
1260                 /* main missing -- import stack from main module */
1261                 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1262                 pic14_options.isLibrarySource = 1;
1263         }
1264
1265 #if 0
1266         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1267                 
1268                 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1269                 addpBlock(pb);
1270                 
1271                 /* entry point @ start of CSEG */
1272                 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1273                 /* put in the call to main */
1274                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1275                 
1276                 if (options.mainreturn) {
1277                         
1278                         addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1279                         addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1280                         
1281                 } else {
1282                         
1283                         addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1284                         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1285                         
1286                 }
1287         }
1288 #endif  
1289         
1290         /* At this point we've got all the code in the form of pCode structures */
1291         /* Now it needs to be rearranged into the order it should be placed in the */
1292         /* code space */
1293         
1294         movepBlock2Head('P');              // Last
1295         movepBlock2Head(code->dbName);
1296         movepBlock2Head('X');
1297         movepBlock2Head(statsg->dbName);   // First
1298         
1299         
1300         /* print the global struct definitions */
1301         if (options.debug)
1302                 cdbStructBlock (0);
1303         
1304         vFile = tempfile();
1305         
1306         addSetHead(&tmpfileSet,vFile);
1307         
1308         /* emit code for the all the variables declared */
1309         pic14emitMaps ();
1310         /* do the overlay segments */
1311         pic14emitOverlay(ovrFile);
1312         
1313         /* PENDING: this isnt the best place but it will do */
1314         if (port->general.glue_up_main) {
1315                 /* create the interrupt vector table */
1316                 pic14createInterruptVect (vFile);
1317         }
1318         
1319         AnalyzepCode('*');
1320         
1321         ReuseReg(); // ReuseReg where call tree permits
1322         
1323         InlinepCode();
1324         
1325         AnalyzepCode('*');
1326         
1327         pcode_test();
1328         
1329         
1330         /* now put it all together into the assembler file */
1331         /* create the assembler file name */
1332         
1333         if ((noAssemble || options.c1mode) && fullDstFileName)
1334         {
1335                 sprintf (buffer, fullDstFileName);
1336         }
1337         else
1338         {
1339                 sprintf (buffer, dstFileName);
1340                 strcat (buffer, ".asm");
1341         }
1342         
1343         if (!(asmFile = fopen (buffer, "w"))) {
1344                 werror (E_FILE_OPEN_ERR, buffer);
1345                 exit (1);
1346         }
1347
1348         /* prepare statistics */
1349         resetpCodeStatistics ();
1350         
1351         /* initial comments */
1352         pic14initialComments (asmFile);
1353         
1354         /* print module name */
1355         fprintf (asmFile, ";\t.module %s\n", moduleName);
1356         
1357         /* Let the port generate any global directives, etc. */
1358         if (port->genAssemblerPreamble)
1359         {
1360                 port->genAssemblerPreamble(asmFile);
1361         }
1362
1363         /* Emit the __config directive */
1364         pic14_emitConfigWord (asmFile);
1365         
1366         /* print the global variables in this module */
1367         pic14printPublics (asmFile);
1368         
1369         /* print the extern variables in this module */
1370         pic14printExterns (asmFile);
1371         
1372         /* copy the sfr segment */
1373         fprintf (asmFile, "%s", iComments2);
1374         fprintf (asmFile, "; special function registers\n");
1375         fprintf (asmFile, "%s", iComments2);
1376         copyFile (asmFile, sfr->oFile);
1377         
1378         
1379         if (udata_section_name) {
1380                 sprintf(udata_name,"%s",udata_section_name);
1381         } else {
1382                 sprintf(udata_name,"data_%s",moduleName);
1383         }
1384         fprintf (asmFile, "%s", iComments2);
1385         fprintf (asmFile, "; udata\n");
1386         fprintf (asmFile, "%s", iComments2);
1387         fprintf (asmFile, "%s\tudata\n", udata_name);
1388         copyFile (asmFile, data->oFile);
1389         
1390         /* Put all variables into a cblock */
1391         AnalyzeBanking();
1392         writeUsedRegs(asmFile);
1393         
1394         /* create the overlay segments */
1395         fprintf (asmFile, "%s", iComments2);
1396         fprintf (asmFile, "; overlayable items in internal ram \n");
1397         fprintf (asmFile, "%s", iComments2);    
1398         copyFile (asmFile, ovrFile);
1399         
1400 #if 0
1401         
1402         /* create the stack segment MOF */
1403         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1404                 fprintf (asmFile, "%s", iComments2);
1405                 fprintf (asmFile, "; Stack segment in internal ram \n");
1406                 fprintf (asmFile, "%s", iComments2);    
1407                 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1408                         ";__start__stack:\n;\t.ds\t1\n\n");
1409         }
1410         
1411         /* create the idata segment */
1412         fprintf (asmFile, "%s", iComments2);
1413         fprintf (asmFile, "; indirectly addressable internal ram data\n");
1414         fprintf (asmFile, "%s", iComments2);
1415         copyFile (asmFile, idata->oFile);
1416         
1417         /* if external stack then reserve space of it */
1418         if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1419                 fprintf (asmFile, "%s", iComments2);
1420                 fprintf (asmFile, "; external stack \n");
1421                 fprintf (asmFile, "%s", iComments2);
1422                 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1423                 fprintf (asmFile,";\t.ds 256\n");
1424         }
1425         
1426         /* copy xtern ram data */
1427         fprintf (asmFile, "%s", iComments2);
1428         fprintf (asmFile, "; external ram data\n");
1429         fprintf (asmFile, "%s", iComments2);
1430         copyFile (asmFile, xdata->oFile);
1431         
1432 #endif
1433         
1434         /* copy the bit segment */
1435         fprintf (asmFile, "%s", iComments2);
1436         fprintf (asmFile, "; bit data\n");
1437         fprintf (asmFile, "%s", iComments2);
1438         copyFile (asmFile, bit->oFile);
1439
1440         /* copy the interrupt vector table */
1441         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1442                 copyFile (asmFile, vFile);
1443         }
1444         
1445         /* create interupt ventor handler */
1446         pic14_emitInterruptHandler (asmFile);
1447         
1448         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1449                 /* initialize data memory */
1450                 fprintf (asmFile, "code_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1451                 fprintf (asmFile,"__sdcc_gsinit_startup\n");
1452                 /* FIXME: This is temporary.  The idata section should be used.  If 
1453                 not, we could add a special feature to the linker.  This will 
1454                 work in the mean time.  Put all initalized data in main.c */
1455                 copypCode(asmFile, statsg->dbName);
1456                 fprintf (asmFile,"\tpagesel _main\n");
1457                 fprintf (asmFile,"\tgoto _main\n");
1458         }
1459         
1460 #if 0    
1461         
1462         /* copy global & static initialisations */
1463         fprintf (asmFile, "%s", iComments2);
1464         fprintf (asmFile, "; global & static initialisations\n");
1465         fprintf (asmFile, "%s", iComments2);
1466         copypCode(asmFile, statsg->dbName);
1467         
1468 #endif
1469         
1470         /* copy over code */
1471         fprintf (asmFile, "%s", iComments2);
1472         fprintf (asmFile, "; code\n");
1473         fprintf (asmFile, "%s", iComments2);
1474         fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1475         
1476         /* unknown */
1477         copypCode(asmFile, 'X');
1478         
1479         /* _main function */
1480         copypCode(asmFile, 'M');
1481         
1482         /* other functions */
1483         copypCode(asmFile, code->dbName);
1484         
1485         /* unknown */
1486         copypCode(asmFile, 'P');
1487
1488         dumppCodeStatistics (asmFile);
1489         
1490         fprintf (asmFile,"\tend\n");
1491         
1492         fclose (asmFile);
1493         
1494         rm_tmpfiles();
1495 }