d75dd6d6a9d77ddc19f9b11b60e4dfc46e15c9c4
[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;
1232        sym = setNextItem (map->syms))
1233     {
1234
1235 #if 0
1236         fprintf(stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1237 CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__,
1238                 map->sname, sym->name, sym->used, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type),
1239                 IS_CODE(sym->etype), IN_CODESPACE( SPEC_OCLS(sym->etype)), IS_CONSTANT(sym->etype),
1240                 IS_PTR_CONST(sym->etype), SPEC_CONST(sym->etype));
1241         printTypeChain( sym->type, stderr );
1242         fprintf(stderr, "\n");
1243 #endif
1244
1245         if(SPEC_ABSA(sym->etype) && PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))) {
1246                 pic16_assignConfigWordValue(SPEC_ADDR(sym->etype),
1247                         (int) ulFromVal (list2val(sym->ival)));
1248
1249                 continue;
1250         }
1251
1252         if(SPEC_ABSA(sym->etype) && PIC16_IS_IDLOC_ADDRESS(SPEC_ADDR(sym->etype))) {
1253                 pic16_assignIdByteValue(SPEC_ADDR(sym->etype),
1254                         (char) ulFromVal (list2val(sym->ival)));
1255
1256                 continue;
1257         }
1258
1259         /* if it is "extern" then do nothing */
1260         if (IS_EXTERN (sym->etype)/* && !SPEC_ABSA(sym->etype)*/) {
1261                 checkAddSym(&externs, sym);
1262           continue;
1263         }
1264
1265         /* if it is not static add it to the public
1266            table */
1267         if (!IS_STATIC (sym->etype)) {
1268                 /* do not emit if it is a config word declaration */
1269                 checkAddSym(&publics, sym);
1270         }
1271
1272       /* print extra debug info if required */
1273       if (options.debug || sym->level == 0) {
1274           /* NOTE to me - cdbFile may be null in which case,
1275            * the sym name will be printed to stdout. oh well */
1276            debugFile->writeSymbol(sym);
1277       }
1278
1279       /* if it has an absolute address */
1280       if (SPEC_ABSA (sym->etype)) {
1281 //              fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1282 //                      __FILE__, __LINE__, sym->name);
1283
1284           /* if it has an initial value */
1285           if (sym->ival)
1286             {
1287               pBlock *pb;
1288               symbol *asym;
1289               absSym *abSym;
1290               pCode *pcf;
1291
1292               /* symbol has absolute address and initial value */
1293               noAlloc++;
1294               resolveIvalSym (sym->ival, sym->type);
1295               asym = newSymbol(sym->rname, 0);
1296               abSym = Safe_calloc(1, sizeof(absSym));
1297               strcpy(abSym->name, sym->rname);
1298               abSym->address = SPEC_ADDR( sym->etype );
1299               addSet(&absSymSet, abSym);
1300
1301               pb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
1302               pic16_addpBlock(pb);
1303
1304               pcf = pic16_newpCodeFunction(moduleName, asym->name);
1305               PCF(pcf)->absblock = 1;
1306
1307               pic16_addpCode2pBlock(pb,pcf);
1308               pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1309               //fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1310               pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1311               pic16_flushDB('p', (void *)pb);
1312
1313               pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(NULL, NULL));
1314               noAlloc--;
1315             }
1316           else
1317             {
1318
1319               /* symbol has absolute address but no initial value */
1320
1321               /* allocate space */
1322               dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1323
1324               /* special case for character strings */
1325               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1326                   SPEC_CVAL (sym->etype).v_char) {
1327
1328 //              fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1329
1330                 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char, getSize(sym->type));
1331               } else {
1332                 fprintf (stderr, "%s:%u(%s): do not know how to intialize symbol %s\n", __FILE__, __LINE__, __FUNCTION__, sym->rname);
1333                 assert(0);
1334               }
1335             }
1336
1337         } else {
1338 //              fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1339 //                      __FILE__, __LINE__, sym->name);
1340
1341
1342           /* if it has an initial value */
1343           if (sym->ival) {
1344               pBlock *pb;
1345
1346               /* symbol doesn't have absolute address but has initial value */
1347               dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1348               ++noAlloc;
1349               resolveIvalSym (sym->ival, sym->type);
1350
1351               pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
1352               pic16_addpBlock(pb);
1353
1354               if(!didcode) {
1355                 /* make sure that 'code' directive is emitted before, once */
1356                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
1357
1358                 didcode++;
1359               }
1360
1361               pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1362               //fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1363               pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1364               pic16_flushDB('p', (void *)pb);
1365               --noAlloc;
1366             } else {
1367
1368               /* symbol doesn't have absolute address and no initial value */
1369               /* allocate space */
1370 //            fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1371               dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1372               /* special case for character strings */
1373               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1374                   SPEC_CVAL (sym->etype).v_char) {
1375
1376 //              fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1377
1378                 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char, getSize(sym->type));
1379               } else {
1380                 assert(0);
1381               }
1382             }
1383         }
1384     }
1385
1386 }
1387
1388
1389 /*-----------------------------------------------------------------*/
1390 /* pic16_emitConfigRegs - emits the configuration registers              */
1391 /*-----------------------------------------------------------------*/
1392 void pic16_emitConfigRegs(FILE *of)
1393 {
1394   int i;
1395
1396         for(i=0;i<=(pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart);i++)
1397                 if(pic16->cwInfo.crInfo[i].emit)        //mask != -1)
1398                         fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1399                                 pic16->cwInfo.confAddrStart+i,
1400                                 pic16->cwInfo.crInfo[i].value);
1401 }
1402
1403 void pic16_emitIDRegs(FILE *of)
1404 {
1405   int i;
1406
1407         for(i=0;i<=(pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart);i++)
1408                 if(pic16->idInfo.irInfo[i].emit)
1409                         fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1410                                 pic16->idInfo.idAddrStart+i,
1411                                 pic16->idInfo.irInfo[i].value);
1412 }
1413
1414
1415 static void
1416 pic16emitMaps ()
1417 {
1418   /* no special considerations for the following
1419      data, idata & bit & xdata */
1420   pic16emitRegularMap (data, TRUE, TRUE);
1421   pic16emitRegularMap (idata, TRUE, TRUE);
1422   pic16emitRegularMap (bit, TRUE, FALSE);
1423   pic16emitRegularMap (xdata, TRUE, TRUE);
1424   pic16emitRegularMap (sfr, FALSE, FALSE);
1425   pic16emitRegularMap (sfrbit, FALSE, FALSE);
1426   pic16emitRegularMap (code, TRUE, FALSE);
1427   pic16emitStaticSeg (statsg);
1428   pic16emitStaticSeg (c_abs);
1429 }
1430
1431 /*-----------------------------------------------------------------*/
1432 /* createInterruptVect - creates the interrupt vector              */
1433 /*-----------------------------------------------------------------*/
1434 static void
1435 pic16createInterruptVect (struct dbuf_s * vBuf)
1436 {
1437         /* if the main is only a prototype ie. no body then do nothing */
1438 #if 0
1439         if (!IFFUNC_HASBODY(mainf->type)) {
1440                 /* if ! compile only then main function should be present */
1441                 if (!options.cc_only)
1442                         werror (E_NO_MAIN);
1443                 return;
1444         }
1445 #endif
1446 #if 0
1447         if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1448                 dbuf_printf (vBuf, ";\t.area\t%s\n", CODE_NAME);
1449                 dbuf_printf (vBuf, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1450
1451                 /* this is an overkill since WE are the port,
1452                  * and we know if we have a genIVT function! */
1453                 if(port->genIVT) {
1454                         port->genIVT(vFile, interrupts, maxInterrupts);
1455                 }
1456         }
1457 #endif
1458
1459 }
1460
1461
1462 /*-----------------------------------------------------------------*/
1463 /* pic16initialComments - puts in some initial comments            */
1464 /*-----------------------------------------------------------------*/
1465 static void
1466 pic16initialComments (FILE * afile)
1467 {
1468     initialComments (afile);
1469     fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1470     if (pic16_options.xinst) {
1471         fprintf (afile, "; * Extended Instruction Set\n");
1472     } // if
1473
1474     if (pic16_mplab_comp) {
1475         fprintf(afile, "; * MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1476     } // if
1477     fprintf (afile, iComments2);
1478
1479     if (options.debug) {
1480         fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]%s\"\n",
1481                 SDCC_VERSION_STR, getBuildNumber(), (!pic16_options.xinst?"":" {extended}") );
1482     } // if
1483 }
1484
1485 int
1486 pic16_stringInSet(const char *str, set **world, int autoAdd)
1487 {
1488   char *s;
1489
1490   if (!str) return 1;
1491   assert(world);
1492
1493   for (s = setFirstItem(*world); s; s = setNextItem(*world))
1494   {
1495     /* found in set */
1496     if (0 == strcmp(s, str)) return 1;
1497   }
1498
1499   /* not found */
1500   if (autoAdd) addSet(world, Safe_strdup(str));
1501   return 0;
1502 }
1503
1504 static int
1505 pic16_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1506 {
1507   static set *emitted = NULL;
1508
1509   if (!pic16_stringInSet(sym, &emitted, 1)) {
1510     /* sym was not in emittedSymbols */
1511     if (!checkLocals || !pic16_stringInSet(sym, &pic16_localFunctions, 0)) {
1512       /* sym is not a locally defined function---avoid bug #1443651 */
1513       fprintf( file, fmt, sym );
1514       return 0;
1515     }
1516   }
1517   return 1;
1518 }
1519
1520 /*-----------------------------------------------------------------*/
1521 /* printPublics - generates global declarations for publics        */
1522 /*-----------------------------------------------------------------*/
1523 static void
1524 pic16printPublics (FILE *afile)
1525 {
1526   symbol *sym;
1527
1528         fprintf (afile, "\n%s", iComments2);
1529         fprintf (afile, "; public variables in this module\n");
1530         fprintf (afile, "%s", iComments2);
1531
1532         for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1533           /* sanity check */
1534           if(!IS_STATIC(sym->etype))
1535                 pic16_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1536 }
1537
1538 /*-----------------------------------------------------------------*/
1539 /* printExterns - generates extern declarations for externs        */
1540 /*-----------------------------------------------------------------*/
1541 static void
1542 pic16_printExterns(FILE *afile)
1543 {
1544   symbol *sym;
1545
1546         /* print nothing if no externs to declare */
1547         if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1548                 return;
1549
1550         fprintf(afile, "\n%s", iComments2);
1551         fprintf(afile, "; extern variables in this module\n");
1552         fprintf(afile, "%s", iComments2);
1553
1554         for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1555                 pic16_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1556
1557         for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1558                 pic16_emitSymbolIfNew(afile, "\textern _%s\n", sym->name, 1);
1559 }
1560
1561 /*-----------------------------------------------------------------*/
1562 /* emitOverlay - will emit code for the overlay stuff              */
1563 /*-----------------------------------------------------------------*/
1564 static void
1565 pic16emitOverlay (struct dbuf_s *aBuf)
1566 {
1567   set *ovrset;
1568
1569   if (!elementsInSet (ovrSetSets))
1570     dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name);
1571
1572   /* for each of the sets in the overlay segment do */
1573   for (ovrset = setFirstItem (ovrSetSets); ovrset;
1574        ovrset = setNextItem (ovrSetSets))
1575     {
1576
1577       symbol *sym;
1578
1579       if (elementsInSet (ovrset))
1580         {
1581           /* this dummy area is used to fool the assembler
1582              otherwise the assembler will append each of these
1583              declarations into one chunk and will not overlay
1584              sad but true */
1585           dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1586           /* output the area informtion */
1587           dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1588         }
1589
1590       for (sym = setFirstItem (ovrset); sym;
1591            sym = setNextItem (ovrset))
1592         {
1593
1594           /* if extern then do nothing */
1595           if (IS_EXTERN (sym->etype))
1596             continue;
1597
1598           /* if allocation required check is needed
1599              then check if the symbol really requires
1600              allocation only for local variables */
1601           if (!IS_AGGREGATE (sym->type) &&
1602               !(sym->_isparm && !IS_REGPARM (sym->etype))
1603               && !sym->allocreq && sym->level)
1604             continue;
1605
1606           /* if global variable & not static or extern
1607              and addPublics allowed then add it to the public set */
1608           if ((sym->_isparm && !IS_REGPARM (sym->etype))
1609               && !IS_STATIC (sym->etype)) {
1610 //            fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1611               checkAddSym(&publics, sym);
1612 //          addSetHead (&publics, sym);
1613           }
1614
1615           /* if extern then do nothing or is a function
1616              then do nothing */
1617           if (IS_FUNC (sym->type))
1618             continue;
1619
1620
1621           /* if is has an absolute address then generate
1622              an equate for this no need to allocate space */
1623           if (SPEC_ABSA (sym->etype))
1624             {
1625
1626               if (options.debug || sym->level == 0)
1627                 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1628
1629               dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1630                        sym->rname,
1631                        SPEC_ADDR (sym->etype));
1632             }
1633           else
1634             {
1635               if (options.debug || sym->level == 0)
1636                 dbuf_printf (aBuf, "==.\n");
1637
1638               /* allocate space */
1639               dbuf_printf (aBuf, "%s:\n", sym->rname);
1640               dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1641             }
1642
1643         }
1644     }
1645 }
1646
1647 static void
1648 emitStatistics(FILE *asmFile)
1649 {
1650   unsigned long isize, udsize, ramsize;
1651   statistics.isize = pic16_countInstructions();
1652   isize = (statistics.isize >= 0) ? statistics.isize : 0;
1653   udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1654   ramsize = pic16 ? pic16->RAMsize : 0x200;
1655   ramsize -= 256; /* ignore access bank and SFRs */
1656   if (ramsize == 0) ramsize = 64; /* prevent division by zero (below) */
1657
1658   fprintf (asmFile, "\n\n; Statistics:\n");
1659   fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n;           \t%5ld (0x%04lx) words\n",
1660     isize, isize, (isize*100.0)/(128UL << 10),
1661     isize>>1, isize>>1);
1662   fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n",
1663     udsize, udsize, (udsize*100.0) / (1.0 * ramsize));
1664   fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1665     statistics.intsize, statistics.intsize);
1666
1667   fprintf (asmFile, "\n\n");
1668 }
1669
1670
1671
1672 /*-----------------------------------------------------------------*/
1673 /* glue - the final glue that hold the whole thing together        */
1674 /*-----------------------------------------------------------------*/
1675 void
1676 pic16glue ()
1677 {
1678   FILE *asmFile;
1679   struct dbuf_s ovrBuf;
1680   struct dbuf_s vBuf;
1681
1682     dbuf_init(&ovrBuf, 4096);
1683     dbuf_init(&vBuf, 4096);
1684
1685     mainf = newSymbol ("main", 0);
1686     mainf->block = 0;
1687
1688     mainf = findSymWithLevel(SymbolTab, mainf);
1689
1690     pic16_pCodeInitRegisters();
1691
1692     if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1693       pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1694
1695         pic16_addpBlock(pb);
1696
1697         /* entry point @ start of CSEG */
1698         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1699
1700         if(initsfpnt) {
1701           pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1702                   pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1703           pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1704                   pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1705         }
1706
1707         /* put in the call to main */
1708         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1709
1710         if (options.mainreturn) {
1711           pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1712           pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1713         } else {
1714           pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1715           pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1716         }
1717     }
1718
1719     /* At this point we've got all the code in the form of pCode structures */
1720     /* Now it needs to be rearranged into the order it should be placed in the */
1721     /* code space */
1722
1723     pic16_movepBlock2Head('P');              // Last
1724     pic16_movepBlock2Head(code->dbName);
1725     pic16_movepBlock2Head('X');
1726     pic16_movepBlock2Head(statsg->dbName);   // First
1727
1728     /* print the global struct definitions */
1729
1730     /* PENDING: this isnt the best place but it will do */
1731     if (port->general.glue_up_main) {
1732       /* create the interrupt vector table */
1733       pic16createInterruptVect (&vBuf);
1734     }
1735
1736     /* emit code for the all the variables declared */
1737     pic16emitMaps ();
1738
1739     /* do the overlay segments */
1740     pic16emitOverlay(&ovrBuf);
1741     pic16_AnalyzepCode('*');
1742
1743 #if 1
1744     if(pic16_options.dumpcalltree) {
1745       FILE *cFile;
1746
1747         sprintf(buffer, dstFileName);
1748         strcat(buffer, ".calltree");
1749         cFile = fopen(buffer, "w");
1750         pic16_printCallTree( cFile );
1751         fclose(cFile);
1752     }
1753 #endif
1754
1755     pic16_InlinepCode();
1756     pic16_AnalyzepCode('*');
1757
1758
1759     if(pic16_debug_verbose)
1760       pic16_pcode_test();
1761
1762     /* now put it all together into the assembler file */
1763     /* create the assembler file name */
1764     if((noAssemble || options.c1mode)  && fullDstFileName) {
1765       sprintf (buffer, fullDstFileName);
1766     } else {
1767       sprintf (buffer, dstFileName);
1768       strcat (buffer, ".asm");
1769     }
1770
1771     if(!(asmFile = fopen (buffer, "w"))) {
1772       werror (E_FILE_OPEN_ERR, buffer);
1773       exit (1);
1774     }
1775
1776     /* initial comments */
1777     pic16initialComments (asmFile);
1778
1779     /* print module name */
1780     if(options.debug)
1781       fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1782
1783     /* Let the port generate any global directives, etc. */
1784     if(port->genAssemblerPreamble) {
1785       port->genAssemblerPreamble(asmFile);
1786     }
1787
1788     /* Put all variables into a cblock */
1789     pic16_AnalyzeBanking();
1790
1791 #if 0
1792     if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1793       pic16_OptimizeLocalRegs();
1794     }
1795 #endif
1796
1797     /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1798     if(pic16_options.opt_banksel > 1) {
1799       pic16_OptimizeBanksel();
1800     }
1801
1802     /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1803     if(!(pic16_options.opt_flags & OF_NO_OPTIMIZE_GOTO)) {
1804       pic16_OptimizeJumps();
1805     }
1806
1807     /* print the global variables in this module */
1808     pic16printPublics (asmFile);
1809
1810     /* print the extern variables to this module */
1811     pic16_printExterns(asmFile);
1812
1813     pic16_writeUsedRegs(asmFile);
1814
1815 #if 0
1816     /* no xdata in pic */
1817     /* if external stack then reserve space of it */
1818     if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1819       fprintf (asmFile, "%s", iComments2);
1820       fprintf (asmFile, "; external stack \n");
1821       fprintf (asmFile, "%s", iComments2);
1822       fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1823       fprintf (asmFile,";\t.ds 256\n");
1824     }
1825 #endif
1826
1827 #if 0
1828     /* no xdata in pic */
1829     /* copy xtern ram data */
1830     fprintf (asmFile, "%s", iComments2);
1831     fprintf (asmFile, "; external ram data\n");
1832     fprintf (asmFile, "%s", iComments2);
1833     dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1834 #endif
1835
1836 #if 0
1837     /* copy the bit segment */
1838     fprintf (asmFile, "%s", iComments2);
1839     fprintf (asmFile, "; bit data\n");
1840     fprintf (asmFile, "%s", iComments2);
1841     dbuf_write_and_destroy (&bit->oBuf, asmFile);
1842 #endif
1843
1844     /* copy the interrupt vector table */
1845     if(mainf && IFFUNC_HASBODY(mainf->type)) {
1846       fprintf (asmFile, "\n%s", iComments2);
1847       fprintf (asmFile, "; interrupt vector \n");
1848       fprintf (asmFile, "%s", iComments2);
1849       dbuf_write_and_destroy (&vBuf, asmFile);
1850     }
1851
1852     /* copy global & static initialisations */
1853     fprintf (asmFile, "\n%s", iComments2);
1854     fprintf (asmFile, "; global & static initialisations\n");
1855     fprintf (asmFile, "%s", iComments2);
1856
1857     if(pic16_debug_verbose)
1858       fprintf(asmFile, "; A code from now on!\n");
1859
1860     pic16_copypCode(asmFile, 'A');
1861
1862     if(pic16_options.no_crt) {
1863       if(mainf && IFFUNC_HASBODY(mainf->type)) {
1864         fprintf(asmFile, "\tcode\n");
1865         fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1866       }
1867     }
1868
1869 //    dbuf_write_and_destroy (&code->oBuf, stderr);
1870
1871     fprintf(asmFile, "; I code from now on!\n");
1872     pic16_copypCode(asmFile, 'I');
1873
1874     if(pic16_debug_verbose)
1875       fprintf(asmFile, "; dbName from now on!\n");
1876
1877     pic16_copypCode(asmFile, statsg->dbName);
1878
1879     if(pic16_options.no_crt) {
1880       if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1881         fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1882       }
1883     }
1884
1885     if(pic16_debug_verbose)
1886       fprintf(asmFile, "; X code from now on!\n");
1887
1888     pic16_copypCode(asmFile, 'X');
1889
1890     if(pic16_debug_verbose)
1891       fprintf(asmFile, "; M code from now on!\n");
1892
1893     pic16_copypCode(asmFile, 'M');
1894
1895     pic16_copypCode(asmFile, code->dbName);
1896
1897     pic16_copypCode(asmFile, 'P');
1898
1899     emitStatistics(asmFile);
1900
1901     fprintf (asmFile,"\tend\n");
1902     fclose (asmFile);
1903 }