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