* src/SDCCast.c (gatherAutoInit): allow pic16 to emit static
[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 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p);
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
61 extern int initsfpnt;
62 extern unsigned long pFile_isize;
63
64 extern unsigned long pic16_countInstructions();
65 set *rel_idataSymSet=NULL;
66 set *fix_idataSymSet=NULL;
67
68 extern DEFSETFUNC (closeTmpFiles);
69 extern DEFSETFUNC (rmTmpFiles);
70
71 extern void pic16_AnalyzeBanking (void);
72 extern void pic16_OptimizeJumps ();
73 extern void copyFile (FILE * dest, FILE * src);
74 extern void pic16_InlinepCode(void);
75 extern void pic16_writeUsedRegs(FILE *);
76
77 extern void initialComments (FILE * afile);
78 extern void printPublics (FILE * afile);
79
80 void  pic16_pCodeInitRegisters(void);
81 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
82 extern void pic16_pCodeConstString(char *name, char *value);
83
84
85 /*-----------------------------------------------------------------*/
86 /* aopLiteral - string from a literal value                        */
87 /*-----------------------------------------------------------------*/
88 int pic16aopLiteral (value *val, int offset)
89 {
90   union {
91     float f;
92     unsigned char c[4];
93   } fl;
94
95   /* if it is a float then it gets tricky */
96   /* otherwise it is fairly simple */
97   if (!IS_FLOAT(val->type)) {
98     unsigned long v = (unsigned long) floatFromVal(val);
99
100     return ( (v >> (offset * 8)) & 0xff);
101   }
102
103   /* it is type float */
104   fl.f = (float) floatFromVal(val);
105 #ifdef WORDS_BIGENDIAN
106   return fl.c[3-offset];
107 #else
108   return fl.c[offset];
109 #endif
110
111 }
112
113 iCode *tic;
114 symbol *nsym;
115 char tbuffer[512], *tbuf=tbuffer;;
116
117
118 /*-----------------------------------------------------------------*/
119 /* emitRegularMap - emit code for maps with no special cases       */
120 /*-----------------------------------------------------------------*/
121 static void
122 pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
123 {
124   symbol *sym;
125 //  int i, size, bitvars = 0;;
126
127 //      fprintf(stderr, "%s:%d map name= %s\n", __FUNCTION__, __LINE__, map->sname);
128         
129         if(addPublics)
130                 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
131                 /* print the area name */
132
133         for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) {
134
135 #if 0
136                 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\textern: %d\tstatic: %d\taggregate: %d\tregister: 0x%x\tfunction: %d\n",
137                         __FUNCTION__,
138                         map->sname, sym->name, sym->used, IS_EXTERN(sym->etype), IS_STATIC(sym->etype),
139                         IS_AGGREGATE(sym->type), (SPEC_SCLS(sym->etype) == S_REGISTER), IS_FUNC(sym->type));
140                 printTypeChain( sym->type, stderr );
141                 fprintf(stderr, "\n");
142 #endif
143
144                 /* if extern then add to externs */
145                 if (IS_EXTERN (sym->etype)) {
146                         /* reduce overhead while linking by not declaring
147                          * extern unused external functions (usually declared
148                          * in header files) */
149                         if(IS_FUNC(sym->type) && !sym->used)continue;
150                         
151                         /* make sure symbol is not in publics section */
152                         if(!checkSym(publics, sym))
153                                 checkAddSym(&externs, sym);
154                         continue;
155                 }
156                 
157                 /* if allocation required check is needed
158                  * then check if the symbol really requires
159                  * allocation only for local variables */
160                  if (arFlag && !IS_AGGREGATE (sym->type) &&
161                         !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
162                         !sym->allocreq && sym->level) {
163
164 //                      fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
165
166                         continue;
167                 }
168
169                 /* if global variable & not static or extern
170                  * and addPublics allowed then add it to the public set */
171                 if ((sym->used) && (sym->level == 0 ||
172                         (sym->_isparm && !IS_REGPARM (sym->etype))) &&
173                         addPublics &&
174                         !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
175                   
176                         checkAddSym(&publics, sym);
177                 } else
178 #if 1
179                         /* new version */
180                         if(IS_STATIC(sym->etype)
181                                 && !sym->ival) /* && !sym->level*/ {
182 #else
183                         /* old version */
184                         if(IS_STATIC(sym->etype)
185                                 && !(sym->ival && !sym->level)) {
186 #endif
187                           regs *reg;
188                           sectSym *ssym;
189                           int found=0;
190
191 //                            debugf("adding symbol %s\n", sym->name);
192 #define SET_IMPLICIT    1
193
194 #if SET_IMPLICIT
195                                 if(IS_STRUCT(sym->type))
196                                         sym->implicit = 1;
197 #endif
198
199                                 reg = pic16_allocDirReg( operandFromSymbol( sym ));
200                                 
201                                 if(reg) {
202                                   for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
203                                     if(!strcmp(ssym->name, reg->name))found=1;
204                                   }
205
206                                   if(!found)
207                                     checkAddReg(&pic16_rel_udata, reg);
208                                   else
209                                     debugf("Coudld not find %s in pic16_rel_udata. Check!\n", reg->name);
210 //                                  checkAddSym(&publics, sym);
211
212                                 }
213                         }
214
215                 /* if extern then do nothing or is a function
216                  * then do nothing */
217                 if (IS_FUNC (sym->type) && !IS_STATIC(sym->etype)) {
218                         if(SPEC_OCLS(sym->etype) == code) {
219 //                              fprintf(stderr, "%s:%d: symbol added: %s\n", __FILE__, __LINE__, sym->rname);
220                                 checkAddSym(&publics, sym);
221                         }
222                         continue;
223                 }
224
225                 /* if is has an absolute address then generate
226                 an equate for this no need to allocate space */
227                 if (SPEC_ABSA (sym->etype)) {
228 //                              fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
229 //                                      sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
230
231                         fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
232                                 sym->rname,
233                                 SPEC_ADDR (sym->etype));
234
235                         /* emit only if it is global */
236                         if(sym->level == 0) {
237                           regs *reg;
238
239                                 reg = pic16_dirregWithName( sym->name );
240                                 if(!reg) {
241                                         /* here */
242 //                                      fprintf(stderr, "%s:%d: implicit add of symbol = %s\n",
243 //                                                      __FUNCTION__, __LINE__, sym->name);
244
245                                         /* if IS_STRUCT is omitted the following
246                                          * fixes structures but break char/int etc */
247 #if SET_IMPLICIT
248                                         if(IS_STRUCT(sym->type))
249                                                 sym->implicit = 1;              // mark as implicit
250 #endif
251                                         if(!sym->ival) {
252                                                 reg = pic16_allocDirReg( operandFromSymbol(sym) );
253                                                 if(reg) {
254                                                         if(checkAddReg(&pic16_fix_udata, reg)) {
255                                                                 /* and add to globals list if not exist */
256                                                                 addSet(&publics, sym);
257                                                         }
258                                                 }
259                                         } else
260                                                 addSet(&publics, sym);
261                                 }
262                         }
263                 } else {
264                         if(!sym->used && (sym->level == 0)) {
265                           regs *reg;
266
267                                 /* symbol not used, just declared probably, but its in
268                                  * level 0, so we must declare it fine as global */
269                                 
270 //                              fprintf(stderr, "EXTRA symbol declaration sym= %s\n", sym->name);
271
272 #if SET_IMPLICIT
273                                 if(IS_STRUCT(sym->type))
274                                         sym->implicit = 1;              // mark as implicit
275 #endif
276                                 if(!sym->ival) {
277                                         if(IS_AGGREGATE(sym->type)) {
278                                                 reg=pic16_allocRegByName(sym->rname, getSize( sym->type ), NULL);
279                                         } else {
280                                                 reg = pic16_allocDirReg( operandFromSymbol( sym ) );
281                                         }
282
283                                         {
284                                           sectSym *ssym;
285                                           int found=0;
286                                   
287 #if 0
288                                                 fprintf(stderr, "%s:%d sym->rname: %s reg: %p reg->name: %s\n", __FILE__, __LINE__,
289                                                         sym->rname, reg, (reg?reg->name:"<<NULL>>"));
290 #endif
291
292                                                 if(reg) {
293                                                   for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
294                                                     if(!strcmp(ssym->name, reg->name))found=1;
295                                                   }
296
297                                                   if(!found)
298                                                     if(checkAddReg(&pic16_rel_udata, reg)) {
299                                                       addSetHead(&publics, sym);
300                                                     }
301                                                 }
302                                         }
303
304
305                 
306                                 } else
307
308                                         addSetHead(&publics, sym);
309                         }
310
311 #if 0
312                         /* allocate space */
313                         /* If this is a bit variable, then allocate storage after 8 bits have been declared */
314                         /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
315                         /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
316                         if (IS_BITVAR (sym->etype)) {
317                                 bitvars++;
318                         } else {
319                                 fprintf (map->oFile, "\t%s\n", sym->rname);
320                                 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
321                                         for (i = 1; i < size; i++)
322                                                 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
323                                 }
324                         }
325                         fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
326 #endif
327                 }
328         
329                 /* FIXME -- VR Fix the following, so that syms to be placed
330                  * in the idata section and let linker decide about their fate */
331
332                 /* if it has an initial value then do it only if
333                         it is a global variable */
334
335                 if (sym->ival
336                   && ((sym->level == 0)
337                       || IS_STATIC(sym->etype)) ) {
338                   ast *ival = NULL;
339
340 #if 0
341                         if(SPEC_OCLS(sym->etype)==data) {
342                                 fprintf(stderr, "%s: sym %s placed in data segment\n", map->sname, sym->name);
343                         }
344
345                         if(SPEC_OCLS(sym->etype)==code) {
346                                 fprintf(stderr, "%s: sym %s placed in code segment\n", map->sname, sym->name);
347                         }
348 #endif
349
350 #if 0
351                         fprintf(stderr, "'%s': sym '%s' has initial value SPEC_ABSA: %d, IS_AGGREGATE: %d\n",
352                                 map->sname, sym->name, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type));
353 #endif
354
355                         if (IS_AGGREGATE (sym->type)) {
356                                 if(SPEC_ABSA(sym->etype))
357                                         addSet(&fix_idataSymSet, copySymbol(sym));
358                                 else
359                                         addSet(&rel_idataSymSet, copySymbol(sym));
360 //                              ival = initAggregates (sym, sym->ival, NULL);
361                         } else {
362                                 if(SPEC_ABSA(sym->etype))
363                                         addSet(&fix_idataSymSet, copySymbol(sym));
364                                 else
365                                         addSet(&rel_idataSymSet, copySymbol(sym));
366
367 //                                      ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
368 //                                              decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
369                         }
370
371                         if(ival) {
372                                 setAstLineno(ival, sym->lineDef);
373                                 codeOutFile = statsg->oFile;
374                                 GcurMemmap = statsg;
375                                 eBBlockFromiCode (iCodeFromAst (ival));
376                                 sym->ival = NULL;
377                         }
378                 }
379         }
380 }
381
382
383 /*-----------------------------------------------------------------*/
384 /* pic16_initPointer - pointer initialization code massaging       */
385 /*-----------------------------------------------------------------*/
386 value *pic16_initPointer (initList * ilist, sym_link *toType)
387 {
388   value *val;
389   ast *expr;
390
391   if (!ilist) {
392       return valCastLiteral(toType, 0.0);
393   }
394
395   expr = decorateType(resolveSymbols( list2expr (ilist) ), FALSE);
396 //  expr = list2expr( ilist );
397   
398   if (!expr)
399     goto wrong;
400   
401   /* try it the old way first */
402   if ((val = constExprValue (expr, FALSE)))
403     return val;
404   
405   /* ( ptr + constant ) */
406   if (IS_AST_OP (expr) &&
407       (expr->opval.op == '+' || expr->opval.op == '-') &&
408       IS_AST_SYM_VALUE (expr->left) &&
409       (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
410       compareType(toType, expr->left->ftype) &&
411       IS_AST_LIT_VALUE (expr->right)) {
412     return valForCastAggr (expr->left, expr->left->ftype,
413                            expr->right,
414                            expr->opval.op);
415   }
416   
417   /* (char *)&a */
418   if (IS_AST_OP(expr) && expr->opval.op==CAST &&
419       IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
420     if (compareType(toType, expr->left->ftype)!=1) {
421       werror (W_INIT_WRONG);
422       printFromToType(expr->left->ftype, toType);
423     }
424     // skip the cast ???
425     expr=expr->right;
426   }
427
428   /* no then we have to do these cludgy checks */
429   /* pointers can be initialized with address of
430      a variable or address of an array element */
431   if (IS_AST_OP (expr) && expr->opval.op == '&') {
432     /* address of symbol */
433     if (IS_AST_SYM_VALUE (expr->left)) {
434       val = copyValue (AST_VALUE (expr->left));
435       val->type = newLink (DECLARATOR);
436       if(SPEC_SCLS (expr->left->etype) == S_CODE) {
437         DCL_TYPE (val->type) = CPOINTER;
438         DCL_PTR_CONST (val->type) = port->mem.code_ro;
439       }
440       else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
441         DCL_TYPE (val->type) = FPOINTER;
442       else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
443         DCL_TYPE (val->type) = PPOINTER;
444       else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
445         DCL_TYPE (val->type) = IPOINTER;
446       else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
447         DCL_TYPE (val->type) = EEPPOINTER;
448       else
449         DCL_TYPE (val->type) = POINTER;
450
451       val->type->next = expr->left->ftype;
452       val->etype = getSpec (val->type);
453       return val;
454     }
455
456     /* if address of indexed array */
457     if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
458       return valForArray (expr->left);
459
460     /* if address of structure element then
461        case 1. a.b ; */
462     if (IS_AST_OP (expr->left) &&
463         expr->left->opval.op == '.') {
464       return valForStructElem (expr->left->left,
465                                expr->left->right);
466     }
467
468     /* case 2. (&a)->b ;
469        (&some_struct)->element */
470     if (IS_AST_OP (expr->left) &&
471         expr->left->opval.op == PTR_OP &&
472         IS_ADDRESS_OF_OP (expr->left->left)) {
473       return valForStructElem (expr->left->left->left,
474                                expr->left->right);
475     }
476   }
477   /* case 3. (((char *) &a) +/- constant) */
478   if (IS_AST_OP (expr) &&
479       (expr->opval.op == '+' || expr->opval.op == '-') &&
480       IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
481       IS_AST_OP (expr->left->right) &&
482       expr->left->right->opval.op == '&' &&
483       IS_AST_LIT_VALUE (expr->right)) {
484
485     return valForCastAggr (expr->left->right->left,
486                            expr->left->left->opval.lnk,
487                            expr->right, expr->opval.op);
488
489   }
490   /* case 4. (char *)(array type) */
491   if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
492       IS_ARRAY(expr->right->ftype)) {
493
494     val = copyValue (AST_VALUE (expr->right));
495     val->type = newLink (DECLARATOR);
496     if (SPEC_SCLS (expr->right->etype) == S_CODE) {
497       DCL_TYPE (val->type) = CPOINTER;
498       DCL_PTR_CONST (val->type) = port->mem.code_ro;
499     }
500     else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
501       DCL_TYPE (val->type) = FPOINTER;
502     else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
503       DCL_TYPE (val->type) = PPOINTER;
504     else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
505       DCL_TYPE (val->type) = IPOINTER;
506     else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
507       DCL_TYPE (val->type) = EEPPOINTER;
508     else
509       DCL_TYPE (val->type) = POINTER;
510     val->type->next = expr->right->ftype->next;
511     val->etype = getSpec (val->type);
512     return val;
513   }
514
515  wrong:
516   if (expr)
517     werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES);
518   else
519     werror (E_INCOMPAT_PTYPES);
520   return NULL;
521
522 }
523
524
525 /*-----------------------------------------------------------------*/
526 /* printPointerType - generates ival for pointer type              */
527 /*-----------------------------------------------------------------*/
528 void _pic16_printPointerType (const char *name, char ptype, void *p)
529 {
530   char buf[256];
531
532         sprintf(buf, "LOW(%s)", name);
533         pic16_emitDS(buf, ptype, p);
534         sprintf(buf, "HIGH(%s)", name);
535         pic16_emitDS(buf, ptype, p);
536 }
537
538 /*-----------------------------------------------------------------*/
539 /* printPointerType - generates ival for pointer type              */
540 /*-----------------------------------------------------------------*/
541 void pic16_printPointerType (const char *name, char ptype, void *p)
542 {
543   _pic16_printPointerType (name, ptype, p);
544   pic16_flushDB(ptype, p);
545 }
546
547 /*-----------------------------------------------------------------*/
548 /* printGPointerType - generates ival for generic pointer type     */
549 /*-----------------------------------------------------------------*/
550 void pic16_printGPointerType (const char *iname, const unsigned int itype,
551   char ptype, void *p)
552 {
553   char buf[256];
554   
555     _pic16_printPointerType (iname, ptype, p);
556
557     switch( itype ) {
558       case FPOINTER:
559       case CPOINTER:
560       case FUNCTION:
561         {
562           sprintf(buf, "UPPER(%s)", iname);
563           pic16_emitDS(buf, ptype, p);
564         }; break;
565       case POINTER:
566       case IPOINTER:
567         sprintf(buf, "0x80");
568         pic16_emitDS(buf, ptype, p);
569         break;
570       default:
571         debugf("itype = %d\n", itype );
572         assert( 0 );
573     }
574
575     pic16_flushDB(ptype, p);
576 }
577
578
579 /* set to 0 to disable debug messages */
580 #define DEBUG_PRINTIVAL 0
581
582 /*-----------------------------------------------------------------*/
583 /* pic16_printIvalType - generates ival for int/char               */
584 /*-----------------------------------------------------------------*/
585 static void 
586 pic16_printIvalType (symbol *sym, sym_link * type, initList * ilist, char ptype, void *p)
587 {
588   value *val;
589
590 //  fprintf(stderr, "%s for symbol %s\n",__FUNCTION__, sym->rname);
591
592 #if DEBUG_PRINTIVAL
593   fprintf(stderr, "%s\n",__FUNCTION__);
594 #endif
595
596
597   /* if initList is deep */
598   if (ilist && ilist->type == INIT_DEEP)
599     ilist = ilist->init.deep;
600
601   if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
602     werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
603   }
604
605   if (!(val = list2val (ilist))) {
606     // assuming a warning has been thrown
607     val=constVal("0");
608   }
609
610   if (val->type != type) {
611     val = valCastLiteral(type, floatFromVal(val));
612   }
613
614   switch (getSize (type)) {
615   case 1:
616     pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
617     break;
618
619   case 2:
620     pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
621     pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
622     break;
623   case 3:
624     pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
625     pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
626     pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
627   case 4:
628     pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
629     pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
630     pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
631     pic16_emitDB(pic16aopLiteral(val, 3), ptype, p);
632     break;
633   }
634 }
635
636 /*--------------------------------------------------------------------*/
637 /* pic16_printIvalChar - generates initital value for character array */
638 /*--------------------------------------------------------------------*/
639 static int 
640 pic16_printIvalChar (sym_link * type, initList * ilist, char *s, char ptype, void *p)
641 {
642   value *val;
643   unsigned int remain;
644
645   if(!p)
646     return 0;
647
648 #if DEBUG_PRINTIVAL
649   fprintf(stderr, "%s\n",__FUNCTION__);
650 #endif
651
652   if(!s) {
653     val = list2val (ilist);
654     /* if the value is a character string  */
655     if(IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
656       if(!DCL_ELEM (type))
657         DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
658
659       for(remain=0; remain<strlen(SPEC_CVAL(val->etype).v_char)+1; remain++)
660         pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
661       
662       if((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
663         while(remain--) {
664           pic16_emitDB(0x00, ptype, p);
665         }
666       }
667       return 1;
668     } else return 0;
669   } else {
670     for(remain=0; remain<strlen(s); remain++) {
671         pic16_emitDB(s[remain], ptype, p);
672     }
673   }
674   return 1;
675 }
676
677 /*-----------------------------------------------------------------*/
678 /* pic16_printIvalArray - generates code for array initialization        */
679 /*-----------------------------------------------------------------*/
680 static void 
681 pic16_printIvalArray (symbol * sym, sym_link * type, initList * ilist,
682                 char ptype, void *p)
683 {
684   initList *iloop;
685   int lcnt = 0, size = 0;
686
687   if(!p)
688     return;
689
690
691 #if DEBUG_PRINTIVAL
692   fprintf(stderr, "%s\n",__FUNCTION__);
693 #endif
694   /* take care of the special   case  */
695   /* array of characters can be init  */
696   /* by a string                      */
697   if (IS_CHAR (type->next)) {
698     if (!IS_LITERAL(list2val(ilist)->etype)) {
699       werror (W_INIT_WRONG);
700       return;
701     }
702
703     if(pic16_printIvalChar (type,
704                        (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
705                        SPEC_CVAL (sym->etype).v_char, ptype, p))
706       return;
707   }
708   /* not the special case             */
709   if (ilist && ilist->type != INIT_DEEP)
710     {
711       werror (E_INIT_STRUCT, sym->name);
712       return;
713     }
714
715   iloop = ilist->init.deep;
716   lcnt = DCL_ELEM (type);
717
718   for (;;)
719     {
720       size++;
721       pic16_printIval (sym, type->next, iloop, ptype, p);
722       iloop = (iloop ? iloop->next : NULL);
723
724
725       /* if not array limits given & we */
726       /* are out of initialisers then   */
727       if (!DCL_ELEM (type) && !iloop)
728         break;
729
730       /* no of elements given and we    */
731       /* have generated for all of them */
732       if (!--lcnt) {
733         /* if initializers left */
734         if (iloop) {
735           werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
736         }
737         break;
738       }
739     }
740
741   /* if we have not been given a size  */
742   if (!DCL_ELEM (type))
743     DCL_ELEM (type) = size;
744
745   return;
746 }
747
748 /*-----------------------------------------------------------------*/
749 /* pic16_printIvalBitFields - generate initializer for bitfields   */
750 /*-----------------------------------------------------------------*/
751 void pic16_printIvalBitFields(symbol **sym, initList **ilist, char ptype, void *p)
752 {
753   value *val ;
754   symbol *lsym = *sym;
755   initList *lilist = *ilist ;
756   unsigned long ival = 0;
757   int size =0;
758
759
760 #if DEBUG_PRINTIVAL
761   fprintf(stderr, "%s\n",__FUNCTION__);
762 #endif
763
764
765   do {
766     unsigned long i;
767     val = list2val(lilist);
768     if (size) {
769       if (SPEC_BLEN(lsym->etype) > 8) {
770         size += ((SPEC_BLEN (lsym->etype) / 8) +
771                  (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
772       }
773     } else {
774       size = ((SPEC_BLEN (lsym->etype) / 8) +
775               (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
776     }
777     i = (unsigned long)floatFromVal(val);
778     i <<= SPEC_BSTR (lsym->etype);
779     ival |= i;
780     if (! ( lsym->next &&
781           (IS_BITFIELD(lsym->next->type)) &&
782           (SPEC_BSTR(lsym->next->etype)))) break;
783     lsym = lsym->next;
784     lilist = lilist->next;
785   } while (1);
786   switch (size) {
787   case 1:
788         pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
789         break;
790
791   case 2:
792         pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
793         pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
794         break;
795
796   case 4: /* EEP: why is this db and not dw? */
797         pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
798         pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
799         pic16_emitDB(BYTE_IN_LONG(ival, 2), ptype, p);
800         pic16_emitDB(BYTE_IN_LONG(ival, 3), ptype, p);
801         break;
802   default:
803         /* VR - only 1,2,4 size long can be handled???? Why? */
804         fprintf(stderr, "%s:%d: unhandled case. Contact author.\n", __FILE__, __LINE__);
805         assert(0);
806   }
807   *sym = lsym;
808   *ilist = lilist;
809 }
810  
811
812 /*-----------------------------------------------------------------*/
813 /* printIvalStruct - generates initial value for structures        */
814 /*-----------------------------------------------------------------*/
815 void pic16_printIvalStruct (symbol * sym, sym_link * type,
816                  initList * ilist, char ptype, void *p)
817 {
818   symbol *sflds;
819   initList *iloop = NULL;
820
821
822 #if DEBUG_PRINTIVAL
823   fprintf(stderr, "%s\n",__FUNCTION__);
824 #endif
825
826   sflds = SPEC_STRUCT (type)->fields;
827
828   if (ilist) {
829     if (ilist->type != INIT_DEEP) {
830       werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
831       return;
832     }
833
834     iloop = ilist->init.deep;
835   }
836
837   for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
838 //    fprintf(stderr, "%s:%d sflds: %p\tiloop = %p\n", __FILE__, __LINE__, sflds, iloop);
839     if (IS_BITFIELD(sflds->type)) {
840       pic16_printIvalBitFields(&sflds, &iloop, ptype, p);
841     } else {
842       pic16_printIval (sym, sflds->type, iloop, ptype, p);
843     }
844   }
845   if (iloop) {
846     werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
847   }
848   return;
849 }
850
851 /*--------------------------------------------------------------------------*/
852 /* pic16_printIvalCharPtr - generates initial values for character pointers */
853 /*--------------------------------------------------------------------------*/
854 int pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
855 {
856   int size = 0;
857
858   /* PENDING: this is _very_ mcs51 specific, including a magic
859      number...
860      It's also endin specific.
861
862      VR - Attempting to port this function to pic16 port - 8-Jun-2004
863    */
864
865
866 #if DEBUG_PRINTIVAL
867   fprintf(stderr, "%s\n",__FUNCTION__);
868 #endif
869
870   size = getSize (type);
871
872   if (val->name && strlen (val->name))
873     {
874       if (size == 1)            /* This appears to be Z80 specific?? */
875         {
876           pic16_emitDS(val->name, ptype, p);
877         }
878       else if (size == 2)
879         {
880           pic16_printPointerType (val->name, ptype, p);
881         }
882       else if (size == 3)
883         {
884           int type;
885           if (IS_PTR (val->type)) {
886             type = DCL_TYPE (val->type);
887           } else {
888             type = PTR_TYPE (SPEC_OCLS (val->etype));
889           }
890           if (val->sym && val->sym->isstrlit) {
891             // this is a literal string
892             type=CPOINTER;
893           }
894           pic16_printGPointerType(val->name, type, ptype, p);
895         }
896       else
897         {
898           fprintf (stderr, "*** internal error: unknown size in "
899                    "printIvalCharPtr.\n");
900           assert(0);
901         }
902     }
903   else
904     {
905       // these are literals assigned to pointers
906       switch (size)
907         {
908         case 1:
909           pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
910           break;
911         case 2:
912           pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
913           pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
914           break;
915         case 3:
916           pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
917           pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
918           pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
919           break;
920
921         default:
922           assert (0);
923         }
924     }
925
926   if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
927         if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
928         else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
929   }
930
931   return 1;
932 }
933
934 /*-----------------------------------------------------------------------*/
935 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
936 /*-----------------------------------------------------------------------*/
937 void pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
938 {
939   value *val;
940   int dLvl = 0;
941
942
943 #if DEBUG_PRINTIVAL
944   fprintf(stderr, "%s\n",__FUNCTION__);
945 #endif
946
947   if (ilist)
948     val = list2val (ilist);
949   else
950     val = valCastLiteral(type, 0.0);
951
952   if (!val) {
953     // an error has been thrown already
954     val=constVal("0");
955   }
956
957   if (IS_LITERAL(val->etype)) {
958     if (compareType(type, val->etype) == 0) {
959       werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
960       printFromToType (val->type, type);
961     }
962     pic16_printIvalCharPtr (NULL, type, val, ptype, p);
963     return;
964   }
965
966   /* check the types   */
967   if ((dLvl = compareType (val->type, type->next)) <= 0)
968     {
969       pic16_emitDB(0x00, ptype, p);
970       return;
971     }
972
973   /* now generate the name */
974   if (!val->sym) {
975       pic16_printGPointerType (val->name, DCL_TYPE(val->type), ptype, p);
976   } else {
977       pic16_printGPointerType (val->sym->rname, DCL_TYPE(val->type), ptype, p);
978
979       if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
980         
981         if(!checkSym(publics, val->sym))
982           if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
983             /* this has not been declared as extern
984              * so declare it as a 'late extern' just after the symbol */
985             fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
986             fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
987             fprintf((FILE *)p, ";\tcontinue variable declaration\n");
988           }
989       }
990   }
991
992   return;
993 }
994
995
996 /*-----------------------------------------------------------------*/
997 /* pic16_printIvalPtr - generates initial value for pointers       */
998 /*-----------------------------------------------------------------*/
999 void pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1000 {
1001   value *val;
1002   int size;
1003
1004 #if 0
1005         fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1006                 sym->rname, getSize(sym->type));
1007 #endif
1008
1009   /* if deep then   */
1010   if (ilist && (ilist->type == INIT_DEEP))
1011     ilist = ilist->init.deep;
1012
1013   /* function pointer     */
1014   if (IS_FUNC (type->next))
1015     {
1016       pic16_printIvalFuncPtr (type, ilist, ptype, p);
1017       return;
1018     }
1019
1020   if (!(val = pic16_initPointer (ilist, type)))
1021     return;
1022
1023   /* if character pointer */
1024   if (IS_CHAR (type->next))
1025     if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1026       return;
1027
1028   /* check the type      */
1029   if (compareType (type, val->type) == 0) {
1030     werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1031     printFromToType (val->type, type);
1032   }
1033
1034   /* if val is literal */
1035   if (IS_LITERAL (val->etype))
1036     {
1037       switch (getSize (type))
1038         {
1039         case 1:
1040             pic16_emitDB((unsigned int)floatFromVal(val) & 0xff, ptype, p);
1041             break;
1042         case 2:
1043             pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1044             pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1045             break;
1046         case 3:
1047             pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1048             pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1049             pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
1050             break;
1051         default:
1052                 fprintf(stderr, "%s:%d size = %d\n", __FILE__, __LINE__, getSize(type));
1053                 assert(0);
1054         }
1055       return;
1056     }
1057
1058
1059   size = getSize (type);
1060
1061   if (size == 1)                /* Z80 specific?? */
1062     {
1063       pic16_emitDS(val->name, ptype, p);
1064     }
1065   else if (size == 2)
1066     {
1067         pic16_printPointerType (val->name, ptype, p);
1068     }
1069   else if (size == 3)
1070     {
1071       pic16_printGPointerType (val->name, (IS_PTR(type)?DCL_TYPE(type):PTR_TYPE(SPEC_OCLS(sym->etype))),
1072                           ptype, p);
1073     } else
1074         assert(0);
1075   return;
1076 }
1077
1078
1079
1080 /*-----------------------------------------------------------------*/
1081 /* pic16_printIval - generates code for initial value                    */
1082 /*-----------------------------------------------------------------*/
1083 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1084 {
1085 //  sym_link *itype;
1086   
1087   if (!p)
1088     return;
1089
1090 #if 0
1091         fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
1092         fprintf(stderr, "%s: IS_STRUCT: %d  IS_ARRAY: %d  IS_PTR: %d  IS_SPEC: %d\n", sym->name,
1093                 IS_STRUCT(type), IS_ARRAY(type), IS_PTR(type), IS_SPEC(type));
1094 #endif
1095         
1096   /* if structure then */
1097   if (IS_STRUCT (type))
1098     {
1099 //      fprintf(stderr,"%s struct\n",__FUNCTION__);
1100       pic16_printIvalStruct (sym, type, ilist, ptype, p);
1101       return;
1102     }
1103
1104   /* if this is an array */
1105   if (IS_ARRAY (type))
1106     {
1107 //      fprintf(stderr,"%s array\n",__FUNCTION__);
1108       pic16_printIvalArray (sym, type, ilist, ptype, p);
1109       return;
1110     }
1111
1112 #if 0
1113   if (ilist)
1114     {
1115       // not an aggregate, ilist must be a node
1116       if (ilist->type!=INIT_NODE) {
1117           // or a 1-element list
1118         if (ilist->init.deep->next) {
1119           werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1120                   sym->name);
1121         } else {
1122           ilist=ilist->init.deep;
1123         }
1124       }
1125
1126 #if 0
1127       // and the type must match
1128       itype=ilist->init.node->ftype;
1129
1130       if (compareType(type, itype)==0) {
1131         // special case for literal strings
1132         if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1133             // which are really code pointers
1134             IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1135           // no sweat
1136         } else {
1137 //          werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1138 //          printFromToType(itype, type);
1139         }
1140       }
1141 #endif
1142     }
1143 #endif
1144
1145   /* if this is a pointer */
1146   if (IS_PTR (type))
1147     {
1148 //      fprintf(stderr,"%s pointer\n",__FUNCTION__);
1149       pic16_printIvalPtr (sym, type, ilist, ptype, p);
1150       return;
1151     }
1152
1153
1154   /* if type is SPECIFIER */
1155   if (IS_SPEC (type))
1156     {
1157 //      fprintf(stderr,"%s spec\n",__FUNCTION__);
1158       pic16_printIvalType (sym, type, ilist, ptype, p);
1159       return;
1160     }
1161 }
1162
1163 int PIC16_IS_CONFIG_ADDRESS(int address)
1164 {
1165   return ((address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd));
1166 }
1167
1168 int PIC16_IS_IDLOC_ADDRESS(int address)
1169 {
1170    return ((address >= pic16->idInfo.idAddrStart && address <= pic16->idInfo.idAddrEnd));
1171 }
1172
1173 /* wrapper function for the above */
1174 int PIC16_IS_HWREG_ADDRESS(int address)
1175 {
1176   return (PIC16_IS_CONFIG_ADDRESS(address) || PIC16_IS_IDLOC_ADDRESS(address));
1177 }
1178
1179
1180 /*-----------------------------------------------------------------*/
1181 /* emitStaticSeg - emitcode for the static segment                 */
1182 /*-----------------------------------------------------------------*/
1183 static void
1184 pic16emitStaticSeg (memmap * map)
1185 {
1186   symbol *sym;
1187   static int didcode=0;
1188
1189   //fprintf(stderr, "%s\n",__FUNCTION__);
1190
1191   pic16_initDB();
1192
1193   /* for all variables in this segment do */
1194   for (sym = setFirstItem (map->syms); sym;
1195        sym = setNextItem (map->syms))
1196     {
1197
1198 #if 0
1199         fprintf(stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1200 CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__,
1201                 map->sname, sym->name, sym->used, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type),
1202                 IS_CODE(sym->etype), IN_CODESPACE( SPEC_OCLS(sym->etype)), IS_CONSTANT(sym->etype),
1203                 IS_PTR_CONST(sym->etype), SPEC_CONST(sym->etype));
1204         printTypeChain( sym->type, stderr );
1205         fprintf(stderr, "\n");
1206 #endif
1207
1208         if(SPEC_ABSA(sym->etype) && PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))) {
1209                 pic16_assignConfigWordValue(SPEC_ADDR(sym->etype),
1210                         (int) floatFromVal(list2val(sym->ival)));
1211
1212                 continue;
1213         }
1214
1215         if(SPEC_ABSA(sym->etype) && PIC16_IS_IDLOC_ADDRESS(SPEC_ADDR(sym->etype))) {
1216                 pic16_assignIdByteValue(SPEC_ADDR(sym->etype),
1217                         (char) floatFromVal(list2val(sym->ival)));
1218
1219                 continue;
1220         }
1221
1222         /* if it is "extern" then do nothing */
1223         if (IS_EXTERN (sym->etype) && !SPEC_ABSA(sym->etype)) {
1224                 checkAddSym(&externs, sym);
1225           continue;
1226         }
1227
1228         /* if it is not static add it to the public
1229            table */
1230         if (!IS_STATIC (sym->etype)) {
1231                 /* do not emit if it is a config word declaration */
1232                 checkAddSym(&publics, sym);
1233         }
1234
1235       /* print extra debug info if required */
1236       if (options.debug || sym->level == 0) {
1237           /* NOTE to me - cdbFile may be null in which case,
1238            * the sym name will be printed to stdout. oh well */
1239            debugFile->writeSymbol(sym);
1240       }
1241          
1242       /* if it has an absolute address */
1243       if (SPEC_ABSA (sym->etype)) {
1244 //              fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1245 //                      __FILE__, __LINE__, sym->name);
1246                         
1247           /* if it has an initial value */
1248           if (sym->ival)
1249             {
1250               pBlock *pb;
1251               symbol *asym;
1252               absSym *abSym;
1253               pCode *pcf;
1254               
1255               /* symbol has absolute address and initial value */
1256               noAlloc++;
1257               resolveIvalSym (sym->ival, sym->type);
1258               asym = newSymbol(sym->rname, 0);
1259               abSym = Safe_calloc(1, sizeof(absSym));
1260               strcpy(abSym->name, sym->rname);
1261               abSym->address = SPEC_ADDR( sym->etype );
1262               addSet(&absSymSet, abSym);
1263               
1264               pb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
1265               pic16_addpBlock(pb);
1266
1267               pcf = pic16_newpCodeFunction(moduleName, asym->name);
1268               PCF(pcf)->absblock = 1;
1269               
1270               pic16_addpCode2pBlock(pb,pcf);
1271               pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1272 //            fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1273               pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1274               pic16_flushDB('p', (void *)pb);
1275
1276               pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(NULL, NULL));
1277               noAlloc--;
1278             }
1279           else
1280             {
1281
1282               /* symbol has absolute address but no initial value */
1283               
1284               /* allocate space */
1285               fprintf (code->oFile, "%s:\n", sym->rname);
1286
1287               /* special case for character strings */
1288               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1289                   SPEC_CVAL (sym->etype).v_char) {
1290
1291 //              fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1292
1293                 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1294               } else {
1295                 assert(0);
1296               }
1297             }
1298   
1299         } else {
1300 //              fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1301 //                      __FILE__, __LINE__, sym->name);
1302
1303                 
1304           /* if it has an initial value */
1305           if (sym->ival) {
1306               pBlock *pb;
1307
1308               /* symbol doesn't have absolute address but has initial value */
1309               fprintf (code->oFile, "%s:\n", sym->rname);
1310               noAlloc++;
1311               resolveIvalSym (sym->ival, sym->type);
1312
1313               pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
1314               pic16_addpBlock(pb);
1315
1316               if(!didcode) {
1317                 /* make sure that 'code' directive is emitted before, once */
1318                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
1319                 
1320                 didcode++;
1321               }
1322                             
1323 //            fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1324
1325               pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1326               pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1327               pic16_flushDB('p', (void *)pb);
1328               noAlloc--;
1329             } else {
1330
1331               /* symbol doesn't have absolute address and no initial value */
1332               /* allocate space */
1333 //            fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1334               fprintf (code->oFile, "%s:\n", sym->rname);
1335               /* special case for character strings */
1336               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1337                   SPEC_CVAL (sym->etype).v_char) {
1338                 
1339 //              fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1340
1341                 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1342               } else {
1343                 assert(0);
1344               }
1345             }
1346         }
1347     }
1348
1349 }
1350
1351
1352 /*-----------------------------------------------------------------*/
1353 /* pic16_emitConfigRegs - emits the configuration registers              */
1354 /*-----------------------------------------------------------------*/
1355 void pic16_emitConfigRegs(FILE *of)
1356 {
1357   int i;
1358
1359         for(i=0;i<pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart;i++)
1360                 if(pic16->cwInfo.crInfo[i].emit)        //mask != -1)
1361                         fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1362                                 pic16->cwInfo.confAddrStart+i,
1363                                 pic16->cwInfo.crInfo[i].value);
1364 }
1365
1366 void pic16_emitIDRegs(FILE *of)
1367 {
1368   int i;
1369
1370         for(i=0;i<pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart;i++)
1371                 if(pic16->idInfo.irInfo[i].emit)
1372                         fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1373                                 pic16->idInfo.idAddrStart+i,
1374                                 pic16->idInfo.irInfo[i].value);
1375 }
1376
1377
1378 static void
1379 pic16emitMaps ()
1380 {
1381   /* no special considerations for the following
1382      data, idata & bit & xdata */
1383   pic16emitRegularMap (data, TRUE, TRUE);
1384   pic16emitRegularMap (idata, TRUE, TRUE);
1385   pic16emitRegularMap (bit, TRUE, FALSE);
1386   pic16emitRegularMap (xdata, TRUE, TRUE);
1387   pic16emitRegularMap (sfr, FALSE, FALSE);
1388   pic16emitRegularMap (sfrbit, FALSE, FALSE);
1389   pic16emitRegularMap (code, TRUE, FALSE);
1390   pic16emitStaticSeg (statsg);
1391 }
1392
1393 /*-----------------------------------------------------------------*/
1394 /* createInterruptVect - creates the interrupt vector              */
1395 /*-----------------------------------------------------------------*/
1396 static void
1397 pic16createInterruptVect (FILE * vFile)
1398 {
1399         /* if the main is only a prototype ie. no body then do nothing */
1400 #if 0
1401         if (!IFFUNC_HASBODY(mainf->type)) {
1402                 /* if ! compile only then main function should be present */
1403                 if (!options.cc_only)
1404                         werror (E_NO_MAIN);
1405                 return;
1406         }
1407 #endif
1408
1409         if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1410                 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
1411                 fprintf(vFile, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1412
1413                 /* this is an overkill since WE are the port,
1414                  * and we know if we have a genIVT function! */
1415                 if(port->genIVT) {
1416                         port->genIVT(vFile, interrupts, maxInterrupts);
1417                 }
1418         }
1419         
1420 }
1421
1422
1423 /*-----------------------------------------------------------------*/
1424 /* pic16initialComments - puts in some initial comments            */
1425 /*-----------------------------------------------------------------*/
1426 static void
1427 pic16initialComments (FILE * afile)
1428 {
1429         initialComments (afile);
1430         fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1431         if(pic16_mplab_comp)
1432                 fprintf(afile, "; MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1433         fprintf (afile, iComments2);
1434
1435         if(options.debug) {
1436                 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]\"\n",
1437                                 SDCC_VERSION_STR, getBuildNumber() );
1438         }
1439 }
1440
1441 /*-----------------------------------------------------------------*/
1442 /* printPublics - generates global declarations for publics        */
1443 /*-----------------------------------------------------------------*/
1444 static void
1445 pic16printPublics (FILE *afile)
1446 {
1447   symbol *sym;
1448
1449         fprintf (afile, "\n%s", iComments2);
1450         fprintf (afile, "; public variables in this module\n");
1451         fprintf (afile, "%s", iComments2);
1452
1453         for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1454           /* sanity check */
1455           if(!IS_STATIC(sym->etype))
1456                 fprintf(afile, "\tglobal %s\n", sym->rname);
1457 }
1458
1459 /*-----------------------------------------------------------------*/
1460 /* printExterns - generates extern declarations for externs        */
1461 /*-----------------------------------------------------------------*/
1462 static void
1463 pic16_printExterns(FILE *afile)
1464 {
1465   symbol *sym;
1466
1467         /* print nothing if no externs to declare */
1468         if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1469                 return;
1470
1471         fprintf(afile, "\n%s", iComments2);
1472         fprintf(afile, "; extern variables in this module\n");
1473         fprintf(afile, "%s", iComments2);
1474         
1475         for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1476                 fprintf(afile, "\textern %s\n", sym->rname);
1477
1478         for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1479                 fprintf(afile, "\textern _%s\n", sym->name);
1480 }
1481
1482 /*-----------------------------------------------------------------*/
1483 /* emitOverlay - will emit code for the overlay stuff              */
1484 /*-----------------------------------------------------------------*/
1485 static void
1486 pic16emitOverlay (FILE * afile)
1487 {
1488   set *ovrset;
1489
1490   if (!elementsInSet (ovrSetSets))
1491     fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
1492
1493   /* for each of the sets in the overlay segment do */
1494   for (ovrset = setFirstItem (ovrSetSets); ovrset;
1495        ovrset = setNextItem (ovrSetSets))
1496     {
1497
1498       symbol *sym;
1499
1500       if (elementsInSet (ovrset))
1501         {
1502           /* this dummy area is used to fool the assembler
1503              otherwise the assembler will append each of these
1504              declarations into one chunk and will not overlay
1505              sad but true */
1506           fprintf (afile, ";\t.area _DUMMY\n");
1507           /* output the area informtion */
1508           fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);    /* MOF */
1509         }
1510
1511       for (sym = setFirstItem (ovrset); sym;
1512            sym = setNextItem (ovrset))
1513         {
1514
1515           /* if extern then do nothing */
1516           if (IS_EXTERN (sym->etype))
1517             continue;
1518
1519           /* if allocation required check is needed
1520              then check if the symbol really requires
1521              allocation only for local variables */
1522           if (!IS_AGGREGATE (sym->type) &&
1523               !(sym->_isparm && !IS_REGPARM (sym->etype))
1524               && !sym->allocreq && sym->level)
1525             continue;
1526
1527           /* if global variable & not static or extern
1528              and addPublics allowed then add it to the public set */
1529           if ((sym->_isparm && !IS_REGPARM (sym->etype))
1530               && !IS_STATIC (sym->etype)) {
1531 //            fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1532               checkAddSym(&publics, sym);
1533 //          addSetHead (&publics, sym);
1534           }
1535
1536           /* if extern then do nothing or is a function
1537              then do nothing */
1538           if (IS_FUNC (sym->type))
1539             continue;
1540
1541
1542           /* if is has an absolute address then generate
1543              an equate for this no need to allocate space */
1544           if (SPEC_ABSA (sym->etype))
1545             {
1546
1547               if (options.debug || sym->level == 0)
1548                 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1549
1550               fprintf (afile, "%s\t=\t0x%04x\n",
1551                        sym->rname,
1552                        SPEC_ADDR (sym->etype));
1553             }
1554           else
1555             {
1556               if (options.debug || sym->level == 0)
1557                 fprintf (afile, "==.\n");
1558
1559               /* allocate space */
1560               fprintf (afile, "%s:\n", sym->rname);
1561               fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1562             }
1563
1564         }
1565     }
1566 }
1567
1568 void emitStatistics(FILE *asmFile)
1569 {
1570   statistics.isize = pic16_countInstructions();
1571         
1572   fprintf (asmFile, "\n\n; Statistics:\n");
1573   fprintf (asmFile, "; code size:\t%ld (0x%lx) bytes\n;\t\t%ld (0x%lx) words\n",
1574     statistics.isize, statistics.isize,
1575     statistics.isize>>1, statistics.isize>>1);
1576   fprintf (asmFile, "; udata size:\t%ld (0x%lx) bytes\n", 
1577     statistics.udsize, statistics.udsize);
1578   fprintf (asmFile, "; access size:\t%ld (0x%lx) bytes\n",
1579     statistics.intsize, statistics.intsize);
1580
1581   fprintf (asmFile, "\n\n");
1582 }
1583
1584
1585
1586 /*-----------------------------------------------------------------*/
1587 /* glue - the final glue that hold the whole thing together        */
1588 /*-----------------------------------------------------------------*/
1589 void
1590 pic16glue ()
1591 {
1592   FILE *vFile;
1593   FILE *asmFile;
1594   FILE *ovrFile = tempfile();
1595
1596     mainf = newSymbol ("main", 0);
1597     mainf->block = 0;
1598
1599     mainf = findSymWithLevel(SymbolTab, mainf);
1600
1601     addSetHead(&tmpfileSet,ovrFile);
1602     pic16_pCodeInitRegisters();
1603
1604     if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1605       pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1606
1607         pic16_addpBlock(pb);
1608
1609         /* entry point @ start of CSEG */
1610         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1611
1612         if(initsfpnt) {
1613           pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1614                   pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1615           pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1616                   pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1617         }
1618
1619         /* put in the call to main */
1620         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1621
1622         if (options.mainreturn) {
1623           pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1624           pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1625         } else {
1626           pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1627           pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1628         }
1629     }
1630
1631     /* At this point we've got all the code in the form of pCode structures */
1632     /* Now it needs to be rearranged into the order it should be placed in the */
1633     /* code space */
1634
1635     pic16_movepBlock2Head('P');              // Last
1636     pic16_movepBlock2Head(code->dbName);
1637     pic16_movepBlock2Head('X');
1638     pic16_movepBlock2Head(statsg->dbName);   // First
1639
1640     /* print the global struct definitions */
1641
1642     vFile = tempfile();
1643     /* PENDING: this isnt the best place but it will do */
1644     if (port->general.glue_up_main) {
1645       /* create the interrupt vector table */
1646       pic16createInterruptVect (vFile);
1647     }
1648
1649     addSetHead(&tmpfileSet,vFile);
1650     
1651     /* emit code for the all the variables declared */
1652     pic16emitMaps ();
1653
1654     /* do the overlay segments */
1655     pic16emitOverlay(ovrFile);
1656     pic16_AnalyzepCode('*');
1657
1658 #if 1
1659     if(pic16_options.dumpcalltree) {
1660       FILE *cFile;
1661         
1662         sprintf(buffer, dstFileName);
1663         strcat(buffer, ".calltree");
1664         cFile = fopen(buffer, "w");
1665         pic16_printCallTree( cFile );
1666         fclose(cFile);
1667     }
1668 #endif
1669
1670     pic16_InlinepCode();
1671     pic16_AnalyzepCode('*');
1672
1673
1674     if(pic16_debug_verbose)
1675       pic16_pcode_test();
1676
1677     /* now put it all together into the assembler file */
1678     /* create the assembler file name */
1679     if((noAssemble || options.c1mode)  && fullDstFileName) {
1680       sprintf (buffer, fullDstFileName);
1681     } else {
1682       sprintf (buffer, dstFileName);
1683       strcat (buffer, ".asm");
1684     }
1685
1686     if(!(asmFile = fopen (buffer, "w"))) {
1687       werror (E_FILE_OPEN_ERR, buffer);
1688       exit (1);
1689     }
1690     
1691     /* initial comments */
1692     pic16initialComments (asmFile);
1693
1694     /* print module name */
1695     if(options.debug)
1696       fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1697
1698     /* Let the port generate any global directives, etc. */
1699     if(port->genAssemblerPreamble) {
1700       port->genAssemblerPreamble(asmFile);
1701     }
1702         
1703     /* Put all variables into a cblock */
1704     pic16_AnalyzeBanking();
1705
1706     if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1707       pic16_OptimizeLocalRegs();
1708     }
1709
1710     /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1711     if(pic16_options.opt_flags & OF_OPTIMIZE_GOTO) {
1712       pic16_OptimizeJumps();
1713     }
1714
1715     /* print the extern variables to this module */
1716     pic16_printExterns(asmFile);
1717         
1718     /* print the global variables in this module */
1719     pic16printPublics (asmFile);
1720
1721     pic16_writeUsedRegs(asmFile);
1722
1723 #if 0
1724     /* no xdata in pic */
1725     /* if external stack then reserve space of it */
1726     if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1727       fprintf (asmFile, "%s", iComments2);
1728       fprintf (asmFile, "; external stack \n");
1729       fprintf (asmFile, "%s", iComments2);
1730       fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1731       fprintf (asmFile,";\t.ds 256\n");
1732     }
1733 #endif
1734
1735 #if 0   
1736     /* no xdata in pic */
1737     /* copy xtern ram data */
1738     fprintf (asmFile, "%s", iComments2);
1739     fprintf (asmFile, "; external ram data\n");
1740     fprintf (asmFile, "%s", iComments2);
1741     copyFile (asmFile, xdata->oFile);
1742 #endif
1743
1744 #if 0
1745     /* copy the bit segment */
1746     fprintf (asmFile, "%s", iComments2);
1747     fprintf (asmFile, "; bit data\n");
1748     fprintf (asmFile, "%s", iComments2);
1749     copyFile (asmFile, bit->oFile);
1750 #endif
1751
1752     /* copy the interrupt vector table */
1753     if(mainf && IFFUNC_HASBODY(mainf->type)) {
1754       fprintf (asmFile, "\n%s", iComments2);
1755       fprintf (asmFile, "; interrupt vector \n");
1756       fprintf (asmFile, "%s", iComments2);
1757       copyFile (asmFile, vFile);
1758     }
1759     
1760     /* copy global & static initialisations */
1761     fprintf (asmFile, "\n%s", iComments2);
1762     fprintf (asmFile, "; global & static initialisations\n");
1763     fprintf (asmFile, "%s", iComments2);
1764     
1765     if(pic16_debug_verbose)
1766       fprintf(asmFile, "; A code from now on!\n");
1767     
1768     pic16_copypCode(asmFile, 'A');
1769
1770     if(pic16_options.no_crt) {
1771       if(mainf && IFFUNC_HASBODY(mainf->type)) {
1772         fprintf(asmFile, "\tcode\n");
1773         fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1774       }
1775     }
1776
1777 //    copyFile (stderr, code->oFile);
1778
1779     fprintf(asmFile, "; I code from now on!\n");
1780     pic16_copypCode(asmFile, 'I');
1781
1782     if(pic16_debug_verbose)
1783       fprintf(asmFile, "; dbName from now on!\n");
1784     
1785     pic16_copypCode(asmFile, statsg->dbName);
1786
1787     if(pic16_options.no_crt) {
1788       if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1789         fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1790       }
1791     }
1792         
1793     if(pic16_debug_verbose)
1794       fprintf(asmFile, "; X code from now on!\n");
1795
1796     pic16_copypCode(asmFile, 'X');
1797
1798     if(pic16_debug_verbose)
1799       fprintf(asmFile, "; M code from now on!\n");
1800
1801     pic16_copypCode(asmFile, 'M');
1802
1803     pic16_copypCode(asmFile, code->dbName);
1804     
1805     pic16_copypCode(asmFile, 'P');
1806
1807     emitStatistics(asmFile);
1808
1809     fprintf (asmFile,"\tend\n");
1810     fclose (asmFile);
1811     
1812     rm_tmpfiles();
1813 }