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