* src/port.h (PORT structure): added hook initPaths, now each
[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         printf("\n");
618 #endif
619
620
621       /* if it is "extern" then do nothing */
622       if (IS_EXTERN (sym->etype)) {
623         checkAddSym(&externs, sym);
624 //      addSetHead(&externs, sym);
625         continue;
626       }
627
628       /* if it is not static add it to the public
629          table */
630       if (!IS_STATIC (sym->etype)) {
631         checkAddSym(&publics, sym);
632 //      addSetHead (&publics, sym);
633       }
634
635 #if 0
636       /* print extra debug info if required */
637       if (options.debug || sym->level == 0)
638         {
639           /* NOTE to me - cdbFile may be null in which case,
640            * the sym name will be printed to stdout. oh well */
641           if(cdbFile)
642             cdbSymbol (sym, cdbFile, FALSE, FALSE);
643
644           if (!sym->level)
645             {                   /* global */
646               if (IS_STATIC (sym->etype))
647                 fprintf (code->oFile, "F%s_", moduleName);      /* scope is file */
648               else
649                 fprintf (code->oFile, "G_");    /* scope is global */
650             }
651           else
652             /* symbol is local */
653             fprintf (code->oFile, "L%s_",
654                      (sym->localof ? sym->localof->name : "-null-"));
655           fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
656
657         }
658 #endif
659
660       /* if it has an absolute address */
661       if (SPEC_ABSA (sym->etype))
662         {
663           if (options.debug || sym->level == 0)
664             fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
665
666           fprintf (code->oFile, "%s\t=\t0x%04x\n",
667                    sym->rname,
668                    SPEC_ADDR (sym->etype));
669         }
670       else
671         {
672           if (options.debug || sym->level == 0)
673             fprintf (code->oFile, " == .\n");
674
675           /* if it has an initial value */
676           if (sym->ival)
677             {
678               pBlock *pb;
679
680               fprintf (code->oFile, "%s:\n", sym->rname);
681               noAlloc++;
682               resolveIvalSym (sym->ival, sym->type);
683               //printIval (sym, sym->type, sym->ival, code->oFile);
684               pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
685               pic16_addpBlock(pb);
686               pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
687
688               printIval (sym, sym->type, sym->ival, pb);
689               pic16_flushDB(pb);
690               noAlloc--;
691             }
692           else
693             {
694
695               /* allocate space */
696               fprintf (code->oFile, "%s:\n", sym->rname);
697               /* special case for character strings */
698               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
699                   SPEC_CVAL (sym->etype).v_char)
700                 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
701                 /*printChar (code->oFile,
702                            SPEC_CVAL (sym->etype).v_char,
703                            strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
704               else
705                 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
706             }
707         }
708     }
709
710 }
711
712
713 /*-----------------------------------------------------------------*/
714 /* emitMaps - emits the code for the data portion the code         */
715 /*-----------------------------------------------------------------*/
716 static void
717 pic16emitMaps ()
718 {
719   /* no special considerations for the following
720      data, idata & bit & xdata */
721   pic16emitRegularMap (data, TRUE, TRUE);
722   pic16emitRegularMap (idata, TRUE, TRUE);
723   pic16emitRegularMap (bit, TRUE, FALSE);
724   pic16emitRegularMap (xdata, TRUE, TRUE);
725   pic16emitRegularMap (sfr, FALSE, FALSE);
726   pic16emitRegularMap (sfrbit, FALSE, FALSE);
727   pic16emitRegularMap (code, TRUE, FALSE);
728   pic16emitStaticSeg (statsg);
729 }
730
731 /*-----------------------------------------------------------------*/
732 /* createInterruptVect - creates the interrupt vector              */
733 /*-----------------------------------------------------------------*/
734 static void
735 pic16createInterruptVect (FILE * vFile)
736 {
737         /* if the main is only a prototype ie. no body then do nothing */
738 #if 0
739         if (!IFFUNC_HASBODY(mainf->type)) {
740                 /* if ! compile only then main function should be present */
741                 if (!options.cc_only)
742                         werror (E_NO_MAIN);
743                 return;
744         }
745 #endif
746
747         if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
748                 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
749                 fprintf(vFile, ".intvecs\tcode\t0x0000\n");
750                 fprintf (vFile, "__interrupt_vect:\n");
751
752                 /* this is an overkill since WE are the port,
753                  * and we know if we have a genIVT function! */
754                 if(port->genIVT) {
755                         port->genIVT(vFile, interrupts, maxInterrupts);
756                 }
757         }
758         
759 }
760
761
762 /*-----------------------------------------------------------------*/
763 /* initialComments - puts in some initial comments                 */
764 /*-----------------------------------------------------------------*/
765 static void
766 pic16initialComments (FILE * afile)
767 {
768   initialComments (afile);
769   fprintf (afile, "; PIC port for the 16-bit core\n");
770   fprintf (afile, iComments2);
771
772 }
773
774 /*-----------------------------------------------------------------*/
775 /* printPublics - generates global declarations for publics        */
776 /*-----------------------------------------------------------------*/
777 static void
778 pic16printPublics (FILE *afile)
779 {
780   symbol *sym;
781
782         fprintf (afile, "%s", iComments2);
783         fprintf (afile, "; public variables in this module\n");
784         fprintf (afile, "%s", iComments2);
785
786         for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
787                 fprintf(afile, "\tglobal %s\n", sym->rname);
788 }
789
790 /*-----------------------------------------------------------------*/
791 /* printExterns - generates extern declarations for externs        */
792 /*-----------------------------------------------------------------*/
793 static void
794 pic16_printExterns(FILE *afile)
795 {
796   symbol *sym;
797
798         fprintf(afile, "%s", iComments2);
799         fprintf(afile, "; extern variables in this module\n");
800         fprintf(afile, "%s", iComments2);
801         
802         for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
803                 fprintf(afile, "\textern %s\n", sym->rname);
804
805         for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
806                 fprintf(afile, "\textern _%s\n", sym->name);
807 }
808
809 /*-----------------------------------------------------------------*/
810 /* emitOverlay - will emit code for the overlay stuff              */
811 /*-----------------------------------------------------------------*/
812 static void
813 pic16emitOverlay (FILE * afile)
814 {
815   set *ovrset;
816
817   if (!elementsInSet (ovrSetSets))
818     fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
819
820   /* for each of the sets in the overlay segment do */
821   for (ovrset = setFirstItem (ovrSetSets); ovrset;
822        ovrset = setNextItem (ovrSetSets))
823     {
824
825       symbol *sym;
826
827       if (elementsInSet (ovrset))
828         {
829           /* this dummy area is used to fool the assembler
830              otherwise the assembler will append each of these
831              declarations into one chunk and will not overlay
832              sad but true */
833           fprintf (afile, ";\t.area _DUMMY\n");
834           /* output the area informtion */
835           fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);    /* MOF */
836         }
837
838       for (sym = setFirstItem (ovrset); sym;
839            sym = setNextItem (ovrset))
840         {
841
842           /* if extern then do nothing */
843           if (IS_EXTERN (sym->etype))
844             continue;
845
846           /* if allocation required check is needed
847              then check if the symbol really requires
848              allocation only for local variables */
849           if (!IS_AGGREGATE (sym->type) &&
850               !(sym->_isparm && !IS_REGPARM (sym->etype))
851               && !sym->allocreq && sym->level)
852             continue;
853
854           /* if global variable & not static or extern
855              and addPublics allowed then add it to the public set */
856           if ((sym->_isparm && !IS_REGPARM (sym->etype))
857               && !IS_STATIC (sym->etype)) {
858               checkAddSym(&publics, sym);
859 //          addSetHead (&publics, sym);
860           }
861
862           /* if extern then do nothing or is a function
863              then do nothing */
864           if (IS_FUNC (sym->type))
865             continue;
866
867 #if 0
868           /* print extra debug info if required */
869           if (options.debug || sym->level == 0)
870             {
871
872               cdbSymbol (sym, cdbFile, FALSE, FALSE);
873
874               if (!sym->level)
875                 {               /* global */
876                   if (IS_STATIC (sym->etype))
877                     fprintf (afile, "F%s_", moduleName);        /* scope is file */
878                   else
879                     fprintf (afile, "G_");      /* scope is global */
880                 }
881               else
882                 /* symbol is local */
883                 fprintf (afile, "L%s_",
884                          (sym->localof ? sym->localof->name : "-null-"));
885               fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
886             }
887 #endif
888
889           /* if is has an absolute address then generate
890              an equate for this no need to allocate space */
891           if (SPEC_ABSA (sym->etype))
892             {
893
894               if (options.debug || sym->level == 0)
895                 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
896
897               fprintf (afile, "%s\t=\t0x%04x\n",
898                        sym->rname,
899                        SPEC_ADDR (sym->etype));
900             }
901           else
902             {
903               if (options.debug || sym->level == 0)
904                 fprintf (afile, "==.\n");
905
906               /* allocate space */
907               fprintf (afile, "%s:\n", sym->rname);
908               fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
909             }
910
911         }
912     }
913 }
914
915
916 /*-----------------------------------------------------------------*/
917 /* glue - the final glue that hold the whole thing together        */
918 /*-----------------------------------------------------------------*/
919 void
920 pic16glue ()
921 {
922
923   FILE *vFile;
924   FILE *asmFile;
925   FILE *ovrFile = tempfile();
926
927
928         mainf = newSymbol ("main", 0);
929         mainf->block = 0;
930
931         mainf = findSymWithLevel(SymbolTab, mainf);
932 #if 0
933         /* only if the main function exists */
934         if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
935                 if (!options.cc_only)
936                         werror (E_NO_MAIN);
937                 return;
938         }
939 #endif
940
941 //      fprintf(stderr, "main function= %p (%s)\thas body= %d\n", mainf, (mainf?mainf->name:NULL), mainf?IFFUNC_HASBODY(mainf->type):-1);
942
943         addSetHead(&tmpfileSet,ovrFile);
944         pic16_pCodeInitRegisters();
945
946         if (mainf && IFFUNC_HASBODY(mainf->type)) {
947           pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
948
949                 pic16_addpBlock(pb);
950
951                 /* entry point @ start of CSEG */
952                 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup\t;VR1",-1));
953
954                 if(initsfpnt) {
955                         pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
956                                 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("stack"))));
957                         pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
958                                 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("stack"))));
959                 }
960
961                 /* put in the call to main */
962                 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
963
964                 if (options.mainreturn) {
965                         pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
966                         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
967                 } else {
968                         pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
969                         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
970                 }
971         }
972
973         /* At this point we've got all the code in the form of pCode structures */
974         /* Now it needs to be rearranged into the order it should be placed in the */
975         /* code space */
976
977         pic16_movepBlock2Head('P');              // Last
978         pic16_movepBlock2Head(code->dbName);
979         pic16_movepBlock2Head('X');
980         pic16_movepBlock2Head(statsg->dbName);   // First
981
982         /* print the global struct definitions */
983 //      if (options.debug)
984 //              cdbStructBlock (0);     //,cdbFile);
985
986         vFile = tempfile();
987         /* PENDING: this isnt the best place but it will do */
988         if (port->general.glue_up_main) {
989                 /* create the interrupt vector table */
990                 pic16createInterruptVect (vFile);
991         }
992
993         addSetHead(&tmpfileSet,vFile);
994     
995         /* emit code for the all the variables declared */
996         pic16emitMaps ();
997         /* do the overlay segments */
998         pic16emitOverlay(ovrFile);
999         pic16_AnalyzepCode('*');
1000
1001 #if 0
1002         {
1003           FILE *cFile;
1004                 sprintf(buffer, dstFileName);
1005                 strcat(buffer, ".calltree");
1006                 cFile = fopen(buffer, "w");
1007                 pic16_printCallTree( cFile );
1008                 fclose(cFile);
1009         }
1010 #endif
1011
1012         pic16_InlinepCode();
1013         pic16_AnalyzepCode('*');
1014
1015         if(pic16_debug_verbose)
1016                 pic16_pcode_test();
1017
1018         /* now put it all together into the assembler file */
1019         /* create the assembler file name */
1020         if ((noAssemble || options.c1mode)  && fullDstFileName) {
1021                 sprintf (buffer, fullDstFileName);
1022         } else {
1023                 sprintf (buffer, dstFileName);
1024                 strcat (buffer, ".asm");
1025         }
1026
1027         if (!(asmFile = fopen (buffer, "w"))) {
1028                 werror (E_FILE_OPEN_ERR, buffer);
1029                 exit (1);
1030         }
1031     
1032         /* initial comments */
1033         pic16initialComments (asmFile);
1034     
1035         /* print module name */
1036         fprintf (asmFile, ";\t.module %s\n", moduleName);
1037     
1038         /* Let the port generate any global directives, etc. */
1039         if (port->genAssemblerPreamble) {
1040                 port->genAssemblerPreamble(asmFile);
1041         }
1042     
1043         /* print the extern variables to this module */
1044         pic16_printExterns(asmFile);
1045   
1046         /* print the global variables in this module */
1047         pic16printPublics (asmFile);
1048
1049 #if 0
1050         /* copy the sfr segment */
1051         fprintf (asmFile, "%s", iComments2);
1052         fprintf (asmFile, "; special function registers\n");
1053         fprintf (asmFile, "%s", iComments2);
1054         copyFile (asmFile, sfr->oFile);
1055 #endif
1056     
1057
1058         /* Put all variables into a cblock */
1059         pic16_AnalyzeBanking();
1060         pic16_writeUsedRegs(asmFile);
1061
1062         /* create the overlay segments */
1063         fprintf (asmFile, "%s", iComments2);
1064         fprintf (asmFile, "; overlayable items in internal ram \n");
1065         fprintf (asmFile, "%s", iComments2);    
1066         copyFile (asmFile, ovrFile);
1067
1068         /* create the stack segment MOF */
1069         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1070                 fprintf (asmFile, "%s", iComments2);
1071                 fprintf (asmFile, "; Stack segment in internal ram \n");
1072                 fprintf (asmFile, "%s", iComments2);    
1073                 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1074                         ";__start__stack:\n;\t.ds\t1\n\n");
1075         }
1076
1077 #if 0
1078         /* no indirect data in pic */
1079         /* create the idata segment */
1080         fprintf (asmFile, "%s", iComments2);
1081         fprintf (asmFile, "; indirectly addressable internal ram data\n");
1082         fprintf (asmFile, "%s", iComments2);
1083         copyFile (asmFile, idata->oFile);
1084 #endif
1085
1086
1087 #if 0
1088         /* no xdata in pic */
1089         /* if external stack then reserve space of it */
1090         if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1091                 fprintf (asmFile, "%s", iComments2);
1092                 fprintf (asmFile, "; external stack \n");
1093                 fprintf (asmFile, "%s", iComments2);
1094                 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1095                 fprintf (asmFile,";\t.ds 256\n");
1096         }
1097 #endif
1098
1099 #if 0   
1100         /* no xdata in pic */
1101         /* copy xtern ram data */
1102         fprintf (asmFile, "%s", iComments2);
1103         fprintf (asmFile, "; external ram data\n");
1104         fprintf (asmFile, "%s", iComments2);
1105         copyFile (asmFile, xdata->oFile);
1106 #endif
1107
1108         /* copy the bit segment */
1109         fprintf (asmFile, "%s", iComments2);
1110         fprintf (asmFile, "; bit data\n");
1111         fprintf (asmFile, "%s", iComments2);
1112         copyFile (asmFile, bit->oFile);
1113
1114
1115         /* copy the interrupt vector table */
1116         if(mainf && IFFUNC_HASBODY(mainf->type)) {
1117                 fprintf (asmFile, "%s", iComments2);
1118                 fprintf (asmFile, "; interrupt vector \n");
1119                 fprintf (asmFile, "%s", iComments2);
1120                 copyFile (asmFile, vFile);
1121         }
1122     
1123         /* copy global & static initialisations */
1124         fprintf (asmFile, "%s", iComments2);
1125         fprintf (asmFile, "; global & static initialisations\n");
1126         fprintf (asmFile, "%s", iComments2);
1127     
1128 #if 0
1129         /* FIXME 8051 Legacy -- VR */
1130         /* Everywhere we generate a reference to the static_name area, 
1131         * (which is currently only here), we immediately follow it with a 
1132         * definition of the post_static_name area. This guarantees that
1133         * the post_static_name area will immediately follow the static_name
1134         * area.
1135         */
1136         fprintf (asmFile, ";\t.area %s\n", port->mem.static_name); /* MOF */
1137         fprintf (asmFile, ";\t.area %s\n", port->mem.post_static_name);
1138         fprintf (asmFile, ";\t.area %s\n", port->mem.static_name);
1139 #endif
1140
1141 #if 0
1142         /* copy over code */
1143         fprintf (asmFile, "%s", iComments2);
1144         fprintf (asmFile, "\tcode\n");
1145         fprintf (asmFile, "%s", iComments2);
1146 #endif
1147
1148         fprintf(asmFile, "; A code from now on!\n");
1149         pic16_copypCode(asmFile, 'A');
1150
1151
1152         if(mainf && IFFUNC_HASBODY(mainf->type)) {
1153                 fprintf(asmFile, "\tcode\n");
1154                 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1155
1156 #if 0
1157                 /* FIXME 8051 legacy (?!) - VR 20-Jun-2003 */
1158                 /* if external stack is specified then the
1159                  * higher order byte of the xdatalocation is
1160                  * going into P2 and the lower order going into */
1161         
1162                 if (options.useXstack) {
1163                         fprintf(asmFile,";\tmov\tP2,#0x%02x\n",
1164                                         (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1165                         fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
1166                                         (unsigned int)options.xdata_loc & 0xff);
1167                 }
1168 #endif
1169         }
1170
1171 //      copyFile (stderr, code->oFile);
1172
1173         fprintf(asmFile, "; I code from now on!\n");
1174         pic16_copypCode(asmFile, 'I');
1175
1176 //      if(pic16_debug_verbose)
1177                 fprintf(asmFile, "; dbName from now on!\n");
1178         pic16_copypCode(asmFile, statsg->dbName);
1179
1180
1181         if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1182                 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\t;VR2\n");
1183         }
1184         
1185
1186 //      if(pic16_debug_verbose)
1187                 fprintf(asmFile, "; X code from now on!\n");
1188         pic16_copypCode(asmFile, 'X');
1189
1190 //      if(pic16_debug_verbose)
1191                 fprintf(asmFile, "; M code from now on!\n");
1192         pic16_copypCode(asmFile, 'M');
1193
1194
1195         pic16_copypCode(asmFile, code->dbName);
1196
1197         pic16_copypCode(asmFile, 'P');
1198
1199         fprintf (asmFile,"\tend\n");
1200         fclose (asmFile);
1201
1202         rm_tmpfiles();
1203 }