* src/pic/glue.c (pic14emitRegularMap): fixed warning
[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
31
32 #ifdef WORDS_BIGENDIAN
33   #define _ENDIAN(x)  (3-x)
34 #else
35   #define _ENDIAN(x)  (x)
36 #endif
37
38 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
39
40 extern symbol *interrupts[256];
41 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
42 extern int noAlloc;
43 extern set *publics;
44 extern set *externs;
45 extern unsigned maxInterrupts;
46 extern int maxRegBank;
47 extern symbol *mainf;
48 extern char *VersionString;
49 extern FILE *codeOutFile;
50 extern set *tmpfileSet;
51 extern set *tmpfileNameSet;
52 extern char *iComments1;
53 extern char *iComments2;
54 //extern void emitStaticSeg (memmap * map);
55
56 extern DEFSETFUNC (closeTmpFiles);
57 extern DEFSETFUNC (rmTmpFiles);
58
59 extern void AnalyzeBanking (void);
60 extern void copyFile (FILE * dest, FILE * src);
61 extern void InlinepCode(void);
62 extern void writeUsedRegs(FILE *);
63
64 extern void initialComments (FILE * afile);
65 extern void printPublics (FILE * afile);
66
67 extern void printChar (FILE * ofile, char *s, int plen);
68 void  pCodeInitRegisters(void);
69 int getConfigWord(int address);
70
71 /*-----------------------------------------------------------------*/
72 /* aopLiteral - string from a literal value                        */
73 /*-----------------------------------------------------------------*/
74 int pic14aopLiteral (value *val, int offset)
75 {
76   union {
77     float f;
78     unsigned char c[4];
79   } fl;
80
81   /* if it is a float then it gets tricky */
82   /* otherwise it is fairly simple */
83   if (!IS_FLOAT(val->type)) {
84     unsigned long v = (unsigned long) floatFromVal(val);
85
86     return ( (v >> (offset * 8)) & 0xff);
87   }
88
89   /* it is type float */
90   fl.f = (float) floatFromVal(val);
91 #ifdef WORDS_BIGENDIAN
92   return fl.c[3-offset];
93 #else
94   return fl.c[offset];
95 #endif
96
97 }
98
99
100 /*-----------------------------------------------------------------*/
101 /* emitRegularMap - emit code for maps with no special cases       */
102 /*-----------------------------------------------------------------*/
103 static void
104 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
105 {
106   symbol *sym;
107   int bitvars = 0;;
108
109   if (addPublics)
110     fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
111
112   /* print the area name */
113   for (sym = setFirstItem (map->syms); sym;
114        sym = setNextItem (map->syms)) {
115
116     printf("%s\n",sym->name);
117
118     /* if extern then add it into the extern list */
119     if (IS_EXTERN (sym->etype)) {
120       addSetHead (&externs, sym);
121       continue;
122     }
123
124     /* if allocation required check is needed
125        then check if the symbol really requires
126        allocation only for local variables */
127     if (arFlag && !IS_AGGREGATE (sym->type) &&
128         !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
129         !sym->allocreq && sym->level)
130       continue;
131
132     /* if global variable & not static or extern
133        and addPublics allowed then add it to the public set */
134     if ((sym->level == 0 ||
135          (sym->_isparm && !IS_REGPARM (sym->etype))) &&
136         addPublics &&
137         !IS_STATIC (sym->etype))
138       addSetHead (&publics, sym);
139
140     /* if extern then do nothing or is a function
141        then do nothing */
142     if (IS_FUNC (sym->type))
143       continue;
144 #if 0
145     /* print extra debug info if required */
146     if (options.debug || sym->level == 0)
147       {
148         if (!sym->level)        /* global */
149           if (IS_STATIC (sym->etype))
150             fprintf (map->oFile, "F%s_", moduleName);           /* scope is file */
151           else
152             fprintf (map->oFile, "G_"); /* scope is global */
153         else
154           /* symbol is local */
155           fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
156         fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
157       }
158 #endif
159
160     /* if it has an absolute address then generate
161        an equate for this no need to allocate space */
162     if (SPEC_ABSA (sym->etype))
163       {
164         //if (options.debug || sym->level == 0)
165         //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
166
167         fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
168                  sym->rname,
169                  SPEC_ADDR (sym->etype));
170       }
171      else
172        {
173          /* allocate space */
174
175          /* If this is a bit variable, then allocate storage after 8 bits have been declared */
176          /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
177          /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
178          if (IS_BITVAR (sym->etype))
179            {
180              bitvars++;
181            }
182          else
183            {
184              fprintf (map->oFile, "%s\tres\t%d\n", sym->rname,getSize (sym->type) & 0xffff);
185              /*
186              {
187                int i, size;
188
189                if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
190                  {
191                    for (i = 1; i < size; i++)
192                      fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
193                  }
194              }
195              */
196            }
197          //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
198        }
199
200     /* if it has a initial value then do it only if
201        it is a global variable */
202     if (sym->ival && sym->level == 0) {
203       ast *ival = NULL;
204             
205       if (IS_AGGREGATE (sym->type))
206         ival = initAggregates (sym, sym->ival, NULL);
207       else
208         ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
209                         decorateType (resolveSymbols (list2expr (sym->ival))));
210       codeOutFile = statsg->oFile;
211       GcurMemmap = statsg;
212       eBBlockFromiCode (iCodeFromAst (ival));
213       sym->ival = NULL;
214     }
215   }
216 }
217
218
219 /*-----------------------------------------------------------------*/
220 /* printIvalType - generates ival for int/char                     */
221 /*-----------------------------------------------------------------*/
222 static void 
223 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
224 {
225   value *val;
226   unsigned long ulval;
227
228   //fprintf(stderr, "%s\n",__FUNCTION__);
229
230   /* if initList is deep */
231   if (ilist->type == INIT_DEEP)
232     ilist = ilist->init.deep;
233
234   if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
235     werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
236   }
237
238   if (!(val = list2val (ilist))) {
239     // assuming a warning has been thrown
240     val=constVal("0");
241   }
242
243   if (val->type != type) {
244     val = valCastLiteral(type, floatFromVal(val));
245   }
246
247   if(val) 
248     ulval = (unsigned long) floatFromVal (val);
249   else
250     ulval =0;
251
252   switch (getSize (type)) {
253   case 1:
254     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
255     break;
256
257   case 2:
258     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
259     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
260     break;
261
262   case 4:
263     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
264     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
265     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
266     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
267     break;
268   }
269 }
270
271 /*-----------------------------------------------------------------*/
272 /* printIvalChar - generates initital value for character array    */
273 /*-----------------------------------------------------------------*/
274 static int 
275 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
276 {
277   value *val;
278   int remain;
279
280   if(!pb)
281     return 0;
282
283   fprintf(stderr, "%s\n",__FUNCTION__);
284   if (!s)
285     {
286
287       val = list2val (ilist);
288       /* if the value is a character string  */
289       if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
290         {
291           if (!DCL_ELEM (type))
292             DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
293
294           //printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
295           //fprintf(stderr, "%s omitting call to printChar\n",__FUNCTION__);
296           addpCode2pBlock(pb,newpCodeCharP(";omitting call to printChar"));
297
298           if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
299             while (remain--)
300               //tfprintf (oFile, "\t!db !constbyte\n", 0);
301               addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
302           return 1;
303         }
304       else
305         return 0;
306     }
307   else {
308     //printChar (oFile, s, strlen (s) + 1);
309
310     for(remain=0; remain<strlen(s); remain++) {
311       addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
312       //fprintf(stderr,"0x%02x ",s[remain]);
313     }
314     //fprintf(stderr,"\n");
315   }
316   return 1;
317 }
318
319 /*-----------------------------------------------------------------*/
320 /* printIvalArray - generates code for array initialization        */
321 /*-----------------------------------------------------------------*/
322 static void 
323 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
324                 pBlock *pb)
325 {
326   initList *iloop;
327   int lcnt = 0, size = 0;
328
329   if(!pb)
330     return;
331
332   /* take care of the special   case  */
333   /* array of characters can be init  */
334   /* by a string                      */
335   if (IS_CHAR (type->next)) {
336     //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
337     if (!IS_LITERAL(list2val(ilist)->etype)) {
338       werror (W_INIT_WRONG);
339       return;
340     }
341     if (printIvalChar (type,
342                        (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
343                        pb, SPEC_CVAL (sym->etype).v_char))
344       return;
345   }
346   /* not the special case             */
347   if (ilist->type != INIT_DEEP)
348     {
349       werror (E_INIT_STRUCT, sym->name);
350       return;
351     }
352
353   iloop = ilist->init.deep;
354   lcnt = DCL_ELEM (type);
355
356   for (;;)
357     {
358       //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
359       size++;
360       printIval (sym, type->next, iloop, pb);
361       iloop = (iloop ? iloop->next : NULL);
362
363
364       /* if not array limits given & we */
365       /* are out of initialisers then   */
366       if (!DCL_ELEM (type) && !iloop)
367         break;
368
369       /* no of elements given and we    */
370       /* have generated for all of them */
371       if (!--lcnt) {
372         /* if initializers left */
373         if (iloop) {
374           werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
375         }
376         break;
377       }
378     }
379
380   /* if we have not been given a size  */
381   if (!DCL_ELEM (type))
382     DCL_ELEM (type) = size;
383
384   return;
385 }
386
387 /*-----------------------------------------------------------------*/
388 /* printIval - generates code for initial value                    */
389 /*-----------------------------------------------------------------*/
390 static void 
391 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
392 {
393   if (!ilist || !pb)
394     return;
395
396   /* if structure then    */
397   if (IS_STRUCT (type))
398     {
399       //fprintf(stderr,"%s struct\n",__FUNCTION__);
400       //printIvalStruct (sym, type, ilist, oFile);
401       return;
402     }
403
404   /* if this is a pointer */
405   if (IS_PTR (type))
406     {
407       //fprintf(stderr,"%s pointer\n",__FUNCTION__);
408       //printIvalPtr (sym, type, ilist, oFile);
409       return;
410     }
411
412   /* if this is an array   */
413   if (IS_ARRAY (type))
414     {
415       //fprintf(stderr,"%s array\n",__FUNCTION__);
416       printIvalArray (sym, type, ilist, pb);
417       return;
418     }
419
420   /* if type is SPECIFIER */
421   if (IS_SPEC (type))
422     {
423       //fprintf(stderr,"%s spec\n",__FUNCTION__);
424       printIvalType (sym, type, ilist, pb);
425       return;
426     }
427 }
428
429 extern void pCodeConstString(char *name, char *value);
430 /*-----------------------------------------------------------------*/
431 /* emitStaticSeg - emitcode for the static segment                 */
432 /*-----------------------------------------------------------------*/
433 static void
434 pic14emitStaticSeg (memmap * map)
435 {
436   symbol *sym;
437
438   fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
439
440   //fprintf(stderr, "%s\n",__FUNCTION__);
441
442   /* for all variables in this segment do */
443   for (sym = setFirstItem (map->syms); sym;
444        sym = setNextItem (map->syms))
445     {
446       /* if it is "extern" then do nothing */
447       if (IS_EXTERN (sym->etype))
448         continue;
449
450       /* if it is not static add it to the public
451          table */
452       if (!IS_STATIC (sym->etype))
453         addSetHead (&publics, sym);
454
455       /* print extra debug info if required */
456       if (options.debug || sym->level == 0)
457         {
458           if (!sym->level)
459             {                   /* global */
460               if (IS_STATIC (sym->etype))
461                 fprintf (code->oFile, "F%s_", moduleName);      /* scope is file */
462               else
463                 fprintf (code->oFile, "G_");    /* scope is global */
464             }
465           else
466             /* symbol is local */
467             fprintf (code->oFile, "L%s_",
468                      (sym->localof ? sym->localof->name : "-null-"));
469           fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
470
471         }
472
473       /* if it has an absolute address */
474       if (SPEC_ABSA (sym->etype))
475         {
476           if (options.debug || sym->level == 0)
477             fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
478
479           fprintf (code->oFile, "%s\t=\t0x%04x\n",
480                    sym->rname,
481                    SPEC_ADDR (sym->etype));
482         }
483       else
484         {
485           if (options.debug || sym->level == 0)
486             fprintf (code->oFile, " == .\n");
487
488           /* if it has an initial value */
489           if (sym->ival)
490             {
491               pBlock *pb;
492
493               fprintf (code->oFile, "%s:\n", sym->rname);
494               noAlloc++;
495               resolveIvalSym (sym->ival);
496               //printIval (sym, sym->type, sym->ival, code->oFile);
497               pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
498               addpBlock(pb);
499               addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
500
501               printIval (sym, sym->type, sym->ival, pb);
502               noAlloc--;
503             }
504           else
505             {
506
507               /* allocate space */
508               fprintf (code->oFile, "%s:\n", sym->rname);
509               /* special case for character strings */
510               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
511                   SPEC_CVAL (sym->etype).v_char)
512                 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
513                 /*printChar (code->oFile,
514                            SPEC_CVAL (sym->etype).v_char,
515                            strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
516               else
517                 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
518             }
519         }
520     }
521
522 }
523
524
525 /*-----------------------------------------------------------------*/
526 /* emitMaps - emits the code for the data portion the code         */
527 /*-----------------------------------------------------------------*/
528 static void
529 pic14emitMaps ()
530 {
531   /* no special considerations for the following
532      data, idata & bit & xdata */
533   pic14emitRegularMap (data, TRUE, TRUE);
534   pic14emitRegularMap (idata, TRUE, TRUE);
535   pic14emitRegularMap (bit, TRUE, FALSE);
536   pic14emitRegularMap (xdata, TRUE, TRUE);
537   pic14emitRegularMap (sfr, FALSE, FALSE);
538   pic14emitRegularMap (sfrbit, FALSE, FALSE);
539   pic14emitRegularMap (code, TRUE, FALSE);
540   pic14emitStaticSeg (statsg);
541 }
542
543 /*-----------------------------------------------------------------*/
544 /* createInterruptVect - creates the interrupt vector              */
545 /*-----------------------------------------------------------------*/
546 static void
547 pic14createInterruptVect (FILE * vFile)
548 {
549   mainf = newSymbol ("main", 0);
550   mainf->block = 0;
551
552   /* only if the main function exists */
553   if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
554     {
555       if (!options.cc_only)
556         werror (E_NO_MAIN);
557       return;
558     }
559
560   /* if the main is only a prototype ie. no body then do nothing */
561   if (!IFFUNC_HASBODY(mainf->type))
562     {
563       /* if ! compile only then main function should be present */
564       if (!options.cc_only)
565         werror (E_NO_MAIN);
566       return;
567     }
568
569   fprintf (vFile, "%s", iComments2);
570   fprintf (vFile, "; config word \n");
571   fprintf (vFile, "%s", iComments2);
572   fprintf (vFile, "\t__config 0x%x\n", getConfigWord(0x2007));
573
574   fprintf (vFile, "%s", iComments2);
575   fprintf (vFile, "; reset and interrupt vectors \n");
576   fprintf (vFile, "%s", iComments2);
577   fprintf (vFile, "STARTUP\t%s\n", CODE_NAME);
578   fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
579   fprintf (vFile, "\tnop\n");
580   fprintf (vFile, "\tnop\n");
581   fprintf (vFile, "\tgoto\t__sdcc_interrupt\n");
582
583 }
584
585
586 /*-----------------------------------------------------------------*/
587 /* initialComments - puts in some initial comments                 */
588 /*-----------------------------------------------------------------*/
589 static void
590 pic14initialComments (FILE * afile)
591 {
592   initialComments (afile);
593   fprintf (afile, "; PIC port for the 14-bit core\n");
594   fprintf (afile, iComments2);
595
596 }
597
598 /*-----------------------------------------------------------------*/
599 /* printExterns - generates extern for external variables          */
600 /*-----------------------------------------------------------------*/
601 static void
602 pic14printExterns (FILE * afile)
603 {
604   symbol *sym;
605
606   fprintf (afile, "%s", iComments2);
607   fprintf (afile, "; extern variables in this module\n");
608   fprintf (afile, "%s", iComments2);
609
610   for (sym = setFirstItem (externs); sym;
611        sym = setNextItem (externs))
612     fprintf (afile, "\textern %s\n", sym->rname);
613 }
614
615 /*-----------------------------------------------------------------*/
616 /* printPublics - generates .global for publics                    */
617 /*-----------------------------------------------------------------*/
618 static void
619 pic14printPublics (FILE * afile)
620 {
621   symbol *sym;
622
623   fprintf (afile, "%s", iComments2);
624   fprintf (afile, "; publics variables in this module\n");
625   fprintf (afile, "%s", iComments2);
626
627   for (sym = setFirstItem (publics); sym;
628        sym = setNextItem (publics)) {
629     if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq)))
630       fprintf (afile, "\tglobal %s\n", sym->rname);
631     else
632       fprintf (afile, ";\tglobal %s\n", sym->rname);
633   }
634 }
635
636 /*-----------------------------------------------------------------*/
637 /* emitOverlay - will emit code for the overlay stuff              */
638 /*-----------------------------------------------------------------*/
639 static void
640 pic14emitOverlay (FILE * afile)
641 {
642   set *ovrset;
643
644   if (!elementsInSet (ovrSetSets))
645     fprintf (afile, "\t%s\n", port->mem.overlay_name);
646
647   /* for each of the sets in the overlay segment do */
648   for (ovrset = setFirstItem (ovrSetSets); ovrset;
649        ovrset = setNextItem (ovrSetSets))
650     {
651
652       symbol *sym;
653
654       if (elementsInSet (ovrset))
655         {
656           /* this dummy area is used to fool the assembler
657              otherwise the assembler will append each of these
658              declarations into one chunk and will not overlay
659              sad but true */
660              
661           /* I don't think this applies to us. We are using gpasm.  CRF */
662           
663           fprintf (afile, ";\t.area _DUMMY\n");
664           /* output the area informtion */
665           fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);    /* MOF */
666         }
667
668       for (sym = setFirstItem (ovrset); sym;
669            sym = setNextItem (ovrset))
670         {
671
672           /* if extern then do nothing */
673           if (IS_EXTERN (sym->etype))
674             continue;
675
676           /* if allocation required check is needed
677              then check if the symbol really requires
678              allocation only for local variables */
679           if (!IS_AGGREGATE (sym->type) &&
680               !(sym->_isparm && !IS_REGPARM (sym->etype))
681               && !sym->allocreq && sym->level)
682             continue;
683
684           /* if global variable & not static or extern
685              and addPublics allowed then add it to the public set */
686           if ((sym->_isparm && !IS_REGPARM (sym->etype))
687               && !IS_STATIC (sym->etype))
688             addSetHead (&publics, sym);
689
690           /* if extern then do nothing or is a function
691              then do nothing */
692           if (IS_FUNC (sym->type))
693             continue;
694
695           /* print extra debug info if required */
696           if (options.debug || sym->level == 0)
697             {
698               if (!sym->level)
699                 {               /* global */
700                   if (IS_STATIC (sym->etype))
701                     fprintf (afile, "F%s_", moduleName);        /* scope is file */
702                   else
703                     fprintf (afile, "G_");      /* scope is global */
704                 }
705               else
706                 /* symbol is local */
707                 fprintf (afile, "L%s_",
708                          (sym->localof ? sym->localof->name : "-null-"));
709               fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
710             }
711
712           /* if is has an absolute address then generate
713              an equate for this no need to allocate space */
714           if (SPEC_ABSA (sym->etype))
715             {
716
717               if (options.debug || sym->level == 0)
718                 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
719
720               fprintf (afile, "%s\t=\t0x%04x\n",
721                        sym->rname,
722                        SPEC_ADDR (sym->etype));
723             }
724           else
725             {
726               if (options.debug || sym->level == 0)
727                 fprintf (afile, "==.\n");
728
729               /* allocate space */
730               fprintf (afile, "%s:\n", sym->rname);
731               fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
732             }
733
734         }
735     }
736 }
737
738
739 /*-----------------------------------------------------------------*/
740 /* glue - the final glue that hold the whole thing together        */
741 /*-----------------------------------------------------------------*/
742 void
743 picglue ()
744 {
745
746   FILE *vFile;
747   FILE *asmFile;
748   FILE *ovrFile = tempfile();
749
750   addSetHead(&tmpfileSet,ovrFile);
751   pCodeInitRegisters();
752
753   if (mainf && IFFUNC_HASBODY(mainf->type)) {
754
755     pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
756     addpBlock(pb);
757
758     /* entry point @ start of CSEG */
759     addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
760     /* put in the call to main */
761     addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
762
763     if (options.mainreturn) {
764
765       addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
766       addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
767
768     } else {
769
770       addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
771       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
772
773     }
774   }
775
776
777   /* At this point we've got all the code in the form of pCode structures */
778   /* Now it needs to be rearranged into the order it should be placed in the */
779   /* code space */
780
781   movepBlock2Head('P');              // Last
782   movepBlock2Head(code->dbName);
783   movepBlock2Head('X');
784   movepBlock2Head(statsg->dbName);   // First
785
786
787   /* print the global struct definitions */
788   if (options.debug)
789     cdbStructBlock (0);
790
791   vFile = tempfile();
792   /* PENDING: this isnt the best place but it will do */
793   if (port->general.glue_up_main) {
794     /* create the interrupt vector table */
795     pic14createInterruptVect (vFile);
796   }
797
798   addSetHead(&tmpfileSet,vFile);
799     
800   /* emit code for the all the variables declared */
801   pic14emitMaps ();
802   /* do the overlay segments */
803   pic14emitOverlay(ovrFile);
804
805
806   AnalyzepCode('*');
807
808   //#ifdef PCODE_DEBUG
809   //printCallTree(stderr);
810   //#endif
811
812   InlinepCode();
813
814   AnalyzepCode('*');
815
816   pcode_test();
817
818
819   /* now put it all together into the assembler file */
820   /* create the assembler file name */
821     
822   if ((noAssemble || options.c1mode) && fullDstFileName)
823     {
824       sprintf (buffer, fullDstFileName);
825     }
826   else
827     {
828       sprintf (buffer, dstFileName);
829       strcat (buffer, ".asm");
830     }
831
832   if (!(asmFile = fopen (buffer, "w"))) {
833     werror (E_FILE_OPEN_ERR, buffer);
834     exit (1);
835   }
836     
837   /* initial comments */
838   pic14initialComments (asmFile);
839     
840   /* print module name */
841   fprintf (asmFile, ";\t.module %s\n", moduleName);
842     
843   /* Let the port generate any global directives, etc. */
844   if (port->genAssemblerPreamble)
845     {
846       port->genAssemblerPreamble(asmFile);
847     }
848     
849   /* print the extern variables in this module */
850   pic14printExterns (asmFile);
851
852   /* print the global variables in this module */
853   pic14printPublics (asmFile);
854
855   /* copy the sfr segment */
856   fprintf (asmFile, "%s", iComments2);
857   fprintf (asmFile, "; special function registers\n");
858   fprintf (asmFile, "%s", iComments2);
859   copyFile (asmFile, sfr->oFile);
860
861   fprintf (asmFile, "%s", iComments2);
862   fprintf (asmFile, "; udata\n");
863   fprintf (asmFile, "%s", iComments2);
864   fprintf (asmFile, "\tudata\n");
865   copyFile (asmFile, data->oFile);
866
867   /* Put all variables into a cblock */
868   AnalyzeBanking();
869   writeUsedRegs(asmFile);
870
871   /* create the overlay segments */
872   fprintf (asmFile, "%s", iComments2);
873   fprintf (asmFile, "; overlayable items in internal ram \n");
874   fprintf (asmFile, "%s", iComments2);    
875   copyFile (asmFile, ovrFile);
876
877 #if 0
878
879   /* create the stack segment MOF */
880   if (mainf && IFFUNC_HASBODY(mainf->type)) {
881     fprintf (asmFile, "%s", iComments2);
882     fprintf (asmFile, "; Stack segment in internal ram \n");
883     fprintf (asmFile, "%s", iComments2);    
884     fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
885              ";__start__stack:\n;\t.ds\t1\n\n");
886   }
887
888   /* create the idata segment */
889   fprintf (asmFile, "%s", iComments2);
890   fprintf (asmFile, "; indirectly addressable internal ram data\n");
891   fprintf (asmFile, "%s", iComments2);
892   copyFile (asmFile, idata->oFile);
893     
894   /* if external stack then reserve space of it */
895   if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
896     fprintf (asmFile, "%s", iComments2);
897     fprintf (asmFile, "; external stack \n");
898     fprintf (asmFile, "%s", iComments2);
899     fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
900     fprintf (asmFile,";\t.ds 256\n");
901   }
902
903   /* copy xtern ram data */
904   fprintf (asmFile, "%s", iComments2);
905   fprintf (asmFile, "; external ram data\n");
906   fprintf (asmFile, "%s", iComments2);
907   copyFile (asmFile, xdata->oFile);
908
909 #endif
910
911   /* copy the bit segment */
912   fprintf (asmFile, "%s", iComments2);
913   fprintf (asmFile, "; bit data\n");
914   fprintf (asmFile, "%s", iComments2);
915   copyFile (asmFile, bit->oFile);
916
917   /* copy the interrupt vector table */
918   if (mainf && IFFUNC_HASBODY(mainf->type)) {
919     copyFile (asmFile, vFile);
920     
921     fprintf (asmFile, "%s", iComments2);
922     fprintf (asmFile, "; initialization and interrupt code \n");
923     fprintf (asmFile, "%s", iComments2);
924
925     /* initialize data memory */
926     fprintf (asmFile, "code_init\t%s\t0x10\n", CODE_NAME);
927     fprintf (asmFile,"__sdcc_gsinit_startup:\n");
928     /* FIXME: This is temporary.  The idata section should be used.  If 
929        not, we could add a special feature to the linker.  This will 
930        work in the mean time.  Put all initalized data in main.c */
931     copypCode(asmFile, statsg->dbName);
932     fprintf (asmFile,"\tpagesel _main\n");
933     fprintf (asmFile,"\tgoto _main\n");
934
935     /* interrupt service routine */
936     fprintf (asmFile, "__sdcc_interrupt:\n");
937     copypCode(asmFile, 'I');
938     fprintf (asmFile,"\tgoto $\n");
939   }
940
941 #if 0    
942
943   /* copy global & static initialisations */
944   fprintf (asmFile, "%s", iComments2);
945   fprintf (asmFile, "; global & static initialisations\n");
946   fprintf (asmFile, "%s", iComments2);
947   copypCode(asmFile, statsg->dbName);
948
949 #endif
950
951   /* copy over code */
952   fprintf (asmFile, "%s", iComments2);
953   fprintf (asmFile, "; code\n");
954   fprintf (asmFile, "%s", iComments2);
955   fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
956
957   /* unknown */
958   copypCode(asmFile, 'X');
959   
960   /* _main function */
961   copypCode(asmFile, 'M');
962
963   /* other functions */
964   copypCode(asmFile, code->dbName);
965
966   /* unknown */
967   copypCode(asmFile, 'P');
968
969   fprintf (asmFile,"\tend\n");
970
971   fclose (asmFile);
972
973   rm_tmpfiles();
974 }