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