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