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