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