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