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