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