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