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