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