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