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