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