* src/pic16/glue.c, src/SDCC.y, src/SDCCast.c, src/SDCCglue.c,
[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   symbol *lsym = *sym;
779   initList *lilist = *ilist;
780   unsigned long ival = 0;
781   int size = 0;
782   unsigned long i;
783
784
785 #if DEBUG_PRINTIVAL
786   fprintf(stderr, "%s\n",__FUNCTION__);
787 #endif
788
789
790   while (lsym)
791     {
792       if (0 == SPEC_BLEN (lsym->etype))
793         {
794           /* bit-field structure member with a width of 0 */
795           break;
796         }
797       else if (!SPEC_BUNNAMED (lsym->etype))
798         {
799           /* not an unnamed bit-field structure member */
800           value *val = list2val (lilist);
801           int bit_length = SPEC_BLEN (lsym->etype);
802
803           if (size)
804             {
805               if (bit_length > 8)
806                 size += (bit_length + 7) / 8;
807             }
808           else
809             size = (bit_length + 7) / 8;
810
811           ival |= (ulFromVal (val) & ((1ul << bit_length) - 1ul)) << SPEC_BSTR (lsym->etype);
812           lilist = lilist->next;
813         }
814       lsym = lsym->next;
815     }
816
817   for (i = 0; i < size; i++)
818     pic16_emitDB (BYTE_IN_LONG (ival, i), ptype, p);
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     {
844       if (ilist->type != INIT_DEEP)
845         {
846           werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
847           return;
848         }
849
850       iloop = ilist->init.deep;
851     }
852
853   while (sflds)
854     {
855 //      fprintf(stderr, "%s:%d sflds: %p\tiloop = %p\n", __FILE__, __LINE__, sflds, iloop);
856       if (IS_BITFIELD (sflds->type))
857         {
858           pic16_printIvalBitFields (&sflds, &iloop, ptype, p);
859         }
860       else
861         {
862           pic16_printIval (sym, sflds->type, iloop, ptype, p);
863           sflds = sflds->next;
864           iloop = iloop ? iloop->next : NULL;
865         }
866     }
867   if (iloop)
868     werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
869 }
870
871 /*-----------------------------------------------------------------*/
872 /* printIvalUnion - generates initial value for unions             */
873 /*-----------------------------------------------------------------*/
874 static void
875 pic16_printIvalUnion (symbol * sym, sym_link * type,
876                  initList * ilist, char ptype, void *p)
877 {
878   //symbol *sflds;
879   initList *iloop = NULL;
880   int size;
881   symbol *sflds = NULL;
882
883 #if DEBUG_PRINTIVAL
884   fprintf(stderr, "%s\n",__FUNCTION__);
885 #endif
886
887   assert (type);
888
889   sflds = SPEC_STRUCT (type)->fields;
890
891   if (ilist) {
892     if (ilist->type != INIT_DEEP) {
893       werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
894       return;
895     }
896
897     iloop = ilist->init.deep;
898   }
899
900   size = SPEC_STRUCT(type)->size;
901   sflds = SPEC_STRUCT(type)->fields;
902   pic16_printIval (sym, sflds->type, iloop, ptype, p);
903
904   /* if the first field is not the longest, fill with 0s */
905   while (size > getSize (sflds->type)) {
906       pic16_emitDB(0, ptype, p);
907       size--;
908   } // while
909 }
910
911 static int
912 pic16_isUnion( symbol *sym, sym_link *type )
913 {
914   if (type && SPEC_STRUCT(type)->type == UNION) return 1;
915   return 0;
916 }
917
918 /*--------------------------------------------------------------------------*/
919 /* pic16_printIvalCharPtr - generates initial values for character pointers */
920 /*--------------------------------------------------------------------------*/
921 static int
922 pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
923 {
924   int size = 0;
925   int i;
926
927   /* PENDING: this is _very_ mcs51 specific, including a magic
928      number...
929      It's also endin specific.
930
931      VR - Attempting to port this function to pic16 port - 8-Jun-2004
932    */
933
934
935 #if DEBUG_PRINTIVAL
936   fprintf(stderr, "%s\n",__FUNCTION__);
937 #endif
938
939   size = getSize (type);
940
941   if (val->name && strlen (val->name))
942     {
943       if (size == 1)            /* This appears to be Z80 specific?? */
944         {
945           pic16_emitDS(val->name, ptype, p);
946         }
947       else if (size == 2)
948         {
949           pic16_printPointerType (val->name, ptype, p);
950         }
951       else if (size == 3)
952         {
953           int type;
954           type = PTR_TYPE (SPEC_OCLS (val->etype));
955           if (val->sym && val->sym->isstrlit) {
956             // this is a literal string
957             type = CPOINTER;
958           }
959           pic16_printGPointerType(val->name, type, ptype, p);
960         }
961       else
962         {
963           fprintf (stderr, "*** internal error: unknown size in "
964                    "printIvalCharPtr.\n");
965           assert(0);
966         }
967     }
968   else
969     {
970       // these are literals assigned to pointers
971       for (i = 0; i < size; i++)
972         {
973           pic16_emitDB(pic16aopLiteral(val, i), ptype, p);
974         } // for
975     }
976
977   if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
978         if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
979         else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
980   }
981
982   return 1;
983 }
984
985 /*-----------------------------------------------------------------------*/
986 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
987 /*-----------------------------------------------------------------------*/
988 static void
989 pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
990 {
991   value *val;
992   int dLvl = 0;
993
994
995 #if DEBUG_PRINTIVAL
996   fprintf(stderr, "%s\n",__FUNCTION__);
997 #endif
998
999   if (ilist)
1000     val = list2val (ilist);
1001   else
1002     val = valCastLiteral(type, 0.0);
1003
1004   if (!val) {
1005     // an error has been thrown already
1006     val = constCharVal (0);
1007   }
1008
1009   if (IS_LITERAL(val->etype)) {
1010     if (0 && compareType(type, val->etype) == 0) {
1011       werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
1012       printFromToType (val->type, type);
1013     }
1014     pic16_printIvalCharPtr (NULL, type, val, ptype, p);
1015     return;
1016   }
1017
1018   /* check the types   */
1019   if ((dLvl = compareType (val->type, type->next)) <= 0)
1020     {
1021       pic16_emitDB(0x00, ptype, p);
1022       return;
1023     }
1024
1025   /* now generate the name */
1026   if (!val->sym) {
1027       pic16_printGPointerType (val->name, CPOINTER /*DCL_TYPE(val->type)*/, ptype, p);
1028   } else {
1029       pic16_printGPointerType (val->sym->rname, CPOINTER /*DCL_TYPE(val->type)*/, ptype, p);
1030
1031       if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
1032
1033         if(!checkSym(publics, val->sym))
1034           if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
1035             /* this has not been declared as extern
1036              * so declare it as a 'late extern' just after the symbol */
1037             fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
1038             fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
1039             fprintf((FILE *)p, ";\tcontinue variable declaration\n");
1040           }
1041       }
1042   }
1043
1044   return;
1045 }
1046
1047
1048 /*-----------------------------------------------------------------*/
1049 /* pic16_printIvalPtr - generates initial value for pointers       */
1050 /*-----------------------------------------------------------------*/
1051 static void
1052 pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1053 {
1054   value *val;
1055   int size;
1056   int i;
1057
1058 #if 0
1059         fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1060                 sym->rname, getSize(sym->type));
1061 #endif
1062
1063   /* if deep then   */
1064   if (ilist && (ilist->type == INIT_DEEP))
1065     ilist = ilist->init.deep;
1066
1067   /* function pointer     */
1068   if (IS_FUNC (type->next))
1069     {
1070       pic16_printIvalFuncPtr (type, ilist, ptype, p);
1071       return;
1072     }
1073
1074   if (!(val = pic16_initPointer (ilist, type)))
1075     return;
1076
1077   /* if character pointer */
1078   if (IS_CHAR (type->next))
1079     if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1080       return;
1081
1082   /* check the type      */
1083   if (compareType (type, val->type) == 0) {
1084     werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1085     printFromToType (val->type, type);
1086   }
1087
1088   size = getSize (type);
1089
1090   /* if val is literal */
1091   if (IS_LITERAL (val->etype))
1092     {
1093       for (i = 0; i < size; i++)
1094         {
1095           pic16_emitDB(pic16aopLiteral(val, i), ptype, p);
1096         } // for
1097       return;
1098     }
1099
1100   if (size == 1)                /* Z80 specific?? */
1101     {
1102       pic16_emitDS(val->name, ptype, p);
1103     }
1104   else if (size == 2)
1105     {
1106       pic16_printPointerType (val->name, ptype, p);
1107     }
1108   else if (size == 3)
1109     {
1110       int itype = 0;
1111       itype = PTR_TYPE (SPEC_OCLS (val->etype));
1112       pic16_printGPointerType (val->name, itype, ptype, p);
1113     }
1114   else
1115     {
1116       assert(0);
1117     }
1118 }
1119
1120
1121
1122 /*-----------------------------------------------------------------*/
1123 /* pic16_printIval - generates code for initial value                    */
1124 /*-----------------------------------------------------------------*/
1125 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1126 {
1127 //  sym_link *itype;
1128
1129   if (!p)
1130     return;
1131
1132 #if 0
1133         fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
1134         fprintf(stderr, "%s: IS_STRUCT: %d  IS_ARRAY: %d  IS_PTR: %d  IS_SPEC: %d\n", sym->name,
1135                 IS_STRUCT(type), IS_ARRAY(type), IS_PTR(type), IS_SPEC(type));
1136 #endif
1137
1138   /* if structure then */
1139   if (IS_STRUCT (type))
1140     {
1141       if (pic16_isUnion(sym, type))
1142         {
1143           //fprintf(stderr,"%s union\n",__FUNCTION__);
1144           pic16_printIvalUnion (sym, type, ilist, ptype, p);
1145         } else {
1146           //fprintf(stderr,"%s struct\n",__FUNCTION__);
1147           pic16_printIvalStruct (sym, type, ilist, ptype, p);
1148         }
1149       return;
1150     }
1151
1152   /* if this is an array */
1153   if (IS_ARRAY (type))
1154     {
1155 //      fprintf(stderr,"%s array\n",__FUNCTION__);
1156       pic16_printIvalArray (sym, type, ilist, ptype, p);
1157       return;
1158     }
1159
1160 #if 0
1161   if (ilist)
1162     {
1163       // not an aggregate, ilist must be a node
1164       if (ilist->type!=INIT_NODE) {
1165           // or a 1-element list
1166         if (ilist->init.deep->next) {
1167           werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1168                   sym->name);
1169         } else {
1170           ilist=ilist->init.deep;
1171         }
1172       }
1173
1174 #if 0
1175       // and the type must match
1176       itype=ilist->init.node->ftype;
1177
1178       if (compareType(type, itype)==0) {
1179         // special case for literal strings
1180         if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1181             // which are really code pointers
1182             IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1183           // no sweat
1184         } else {
1185 //          werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1186 //          printFromToType(itype, type);
1187         }
1188       }
1189 #endif
1190     }
1191 #endif
1192
1193   /* if this is a pointer */
1194   if (IS_PTR (type))
1195     {
1196 //      fprintf(stderr,"%s pointer\n",__FUNCTION__);
1197       pic16_printIvalPtr (sym, type, ilist, ptype, p);
1198       return;
1199     }
1200
1201
1202   /* if type is SPECIFIER */
1203   if (IS_SPEC (type))
1204     {
1205 //      fprintf(stderr,"%s spec\n",__FUNCTION__);
1206       pic16_printIvalType (sym, type, ilist, ptype, p);
1207       return;
1208     }
1209 }
1210
1211 static int
1212 PIC16_IS_CONFIG_ADDRESS(int address)
1213 {
1214   return ((address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd));
1215 }
1216
1217 static int
1218 PIC16_IS_IDLOC_ADDRESS(int address)
1219 {
1220    return ((address >= pic16->idInfo.idAddrStart && address <= pic16->idInfo.idAddrEnd));
1221 }
1222
1223 /*-----------------------------------------------------------------*/
1224 /* emitStaticSeg - emitcode for the static segment                 */
1225 /*-----------------------------------------------------------------*/
1226 static void
1227 pic16emitStaticSeg (memmap * map)
1228 {
1229   symbol *sym;
1230   static int didcode = 0;
1231
1232   //fprintf(stderr, "%s\n",__FUNCTION__);
1233
1234   pic16_initDB ();
1235
1236   /* for all variables in this segment do */
1237   for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms))
1238     {
1239
1240 #if 0
1241       fprintf (stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1242 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));
1243       printTypeChain (sym->type, stderr);
1244       fprintf (stderr, "\n");
1245 #endif
1246
1247       if (SPEC_ABSA (sym->etype) && PIC16_IS_CONFIG_ADDRESS (SPEC_ADDR (sym->etype)))
1248         {
1249           pic16_assignConfigWordValue (SPEC_ADDR (sym->etype), (int) ulFromVal (list2val (sym->ival)));
1250
1251           continue;
1252         }
1253
1254       if (SPEC_ABSA (sym->etype) && PIC16_IS_IDLOC_ADDRESS (SPEC_ADDR (sym->etype)))
1255         {
1256           pic16_assignIdByteValue (SPEC_ADDR (sym->etype), (char) ulFromVal (list2val (sym->ival)));
1257
1258           continue;
1259         }
1260
1261       /* if it is "extern" then do nothing */
1262       if (IS_EXTERN (sym->etype) /* && !SPEC_ABSA(sym->etype) */ )
1263         {
1264           checkAddSym (&externs, sym);
1265           continue;
1266         }
1267
1268       /* if it is not static add it to the public
1269          table */
1270       if (!IS_STATIC (sym->etype))
1271         {
1272           /* do not emit if it is a config word declaration */
1273           checkAddSym (&publics, sym);
1274         }
1275
1276       /* print extra debug info if required */
1277       if (options.debug || sym->level == 0)
1278         {
1279           /* NOTE to me - cdbFile may be null in which case,
1280            * the sym name will be printed to stdout. oh well */
1281           debugFile->writeSymbol (sym);
1282         }
1283
1284       /* if it has an absolute address */
1285       if (SPEC_ABSA (sym->etype))
1286         {
1287 //        fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1288 //                __FILE__, __LINE__, sym->name);
1289
1290           if (!sym->ival && IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) && SPEC_CVAL (sym->etype).v_char)
1291             {
1292               /* symbol has absolute address but no initial value */
1293               /* special case for character strings */
1294
1295 //            fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1296
1297               pic16_pCodeConstString (sym->rname, SPEC_CVAL (sym->etype).v_char, getSize (sym->type));
1298             }
1299           else
1300             {
1301               pBlock *pb;
1302               symbol *asym;
1303               absSym *abSym;
1304               pCode *pcf;
1305
1306               /* symbol has absolute address and initial value */
1307               ++noAlloc;
1308               resolveIvalSym (sym->ival, sym->type);
1309               asym = newSymbol (sym->rname, 0);
1310               abSym = Safe_calloc (1, sizeof (absSym));
1311               strcpy (abSym->name, sym->rname);
1312               abSym->address = SPEC_ADDR (sym->etype);
1313               addSet (&absSymSet, abSym);
1314
1315               pb = pic16_newpCodeChain (NULL, 'A', pic16_newpCodeCharP ("; Starting pCode block for absolute Ival"));
1316               pic16_addpBlock (pb);
1317
1318               pcf = pic16_newpCodeFunction (moduleName, asym->name);
1319               PCF (pcf)->absblock = 1;
1320
1321               pic16_addpCode2pBlock (pb, pcf);
1322               pic16_addpCode2pBlock (pb, pic16_newpCodeLabel (sym->rname, -1));
1323               //fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1324               /* if it has an initial value */
1325               if (sym->ival)
1326                 {
1327                   pic16_printIval (sym, sym->type, sym->ival, 'p', (void *) pb);
1328                   pic16_flushDB ('p', (void *) pb);
1329                 }
1330
1331               pic16_addpCode2pBlock (pb, pic16_newpCodeFunction (NULL, NULL));
1332               --noAlloc;
1333             }
1334         }
1335       else
1336         {
1337 //        fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1338 //               __FILE__, __LINE__, sym->name);
1339
1340
1341           /* if it has an initial value */
1342           if (sym->ival)
1343             {
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                 {
1356                   /* make sure that 'code' directive is emitted before, once */
1357                   pic16_addpCode2pBlock (pb, pic16_newpCodeAsmDir ("code", NULL));
1358
1359                   ++didcode;
1360                 }
1361
1362               pic16_addpCode2pBlock (pb, pic16_newpCodeLabel (sym->rname, -1));
1363               //fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1364               pic16_printIval (sym, sym->type, sym->ival, 'p', (void *) pb);
1365               pic16_flushDB ('p', (void *) pb);
1366               --noAlloc;
1367             }
1368           else
1369             {
1370
1371               /* symbol doesn't have absolute address and no initial value */
1372               /* allocate space */
1373 //            fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1374               dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1375               /* special case for character strings */
1376               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) && SPEC_CVAL (sym->etype).v_char)
1377                 {
1378
1379 //                fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1380
1381                   pic16_pCodeConstString (sym->rname, SPEC_CVAL (sym->etype).v_char, getSize (sym->type));
1382                 }
1383               else
1384                 {
1385                   assert (0);
1386                 }
1387             }
1388         }
1389     }
1390 }
1391
1392 /*-----------------------------------------------------------------*/
1393 /* pic16_emitConfigRegs - emits the configuration registers              */
1394 /*-----------------------------------------------------------------*/
1395 void pic16_emitConfigRegs(FILE *of)
1396 {
1397   int i;
1398
1399         for(i=0;i<=(pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart);i++)
1400                 if(pic16->cwInfo.crInfo[i].emit)        //mask != -1)
1401                         fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1402                                 pic16->cwInfo.confAddrStart+i,
1403                                 pic16->cwInfo.crInfo[i].value);
1404 }
1405
1406 void pic16_emitIDRegs(FILE *of)
1407 {
1408   int i;
1409
1410         for(i=0;i<=(pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart);i++)
1411                 if(pic16->idInfo.irInfo[i].emit)
1412                         fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1413                                 pic16->idInfo.idAddrStart+i,
1414                                 pic16->idInfo.irInfo[i].value);
1415 }
1416
1417
1418 static void
1419 pic16emitMaps ()
1420 {
1421   /* no special considerations for the following
1422      data, idata & bit & xdata */
1423   pic16emitRegularMap (data, TRUE, TRUE);
1424   pic16emitRegularMap (idata, TRUE, TRUE);
1425   pic16emitRegularMap (bit, TRUE, FALSE);
1426   pic16emitRegularMap (xdata, TRUE, TRUE);
1427   pic16emitRegularMap (sfr, FALSE, FALSE);
1428   pic16emitRegularMap (sfrbit, FALSE, FALSE);
1429   pic16emitRegularMap (code, TRUE, FALSE);
1430   pic16emitStaticSeg (statsg);
1431   pic16emitStaticSeg (c_abs);
1432 }
1433
1434 /*-----------------------------------------------------------------*/
1435 /* createInterruptVect - creates the interrupt vector              */
1436 /*-----------------------------------------------------------------*/
1437 static void
1438 pic16createInterruptVect (struct dbuf_s * vBuf)
1439 {
1440         /* if the main is only a prototype ie. no body then do nothing */
1441 #if 0
1442         if (!IFFUNC_HASBODY(mainf->type)) {
1443                 /* if ! compile only then main function should be present */
1444                 if (!options.cc_only)
1445                         werror (E_NO_MAIN);
1446                 return;
1447         }
1448 #endif
1449 #if 0
1450         if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1451                 dbuf_printf (vBuf, ";\t.area\t%s\n", CODE_NAME);
1452                 dbuf_printf (vBuf, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1453
1454                 /* this is an overkill since WE are the port,
1455                  * and we know if we have a genIVT function! */
1456                 if(port->genIVT) {
1457                         port->genIVT(vFile, interrupts, maxInterrupts);
1458                 }
1459         }
1460 #endif
1461
1462 }
1463
1464
1465 /*-----------------------------------------------------------------*/
1466 /* pic16initialComments - puts in some initial comments            */
1467 /*-----------------------------------------------------------------*/
1468 static void
1469 pic16initialComments (FILE * afile)
1470 {
1471     initialComments (afile);
1472     fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1473     if (pic16_options.xinst) {
1474         fprintf (afile, "; * Extended Instruction Set\n");
1475     } // if
1476
1477     if (pic16_mplab_comp) {
1478         fprintf(afile, "; * MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1479     } // if
1480     fprintf (afile, "%s", iComments2);
1481
1482     if (options.debug) {
1483         fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]%s\"\n",
1484                 SDCC_VERSION_STR, getBuildNumber(), (!pic16_options.xinst?"":" {extended}") );
1485     } // if
1486 }
1487
1488 int
1489 pic16_stringInSet(const char *str, set **world, int autoAdd)
1490 {
1491   char *s;
1492
1493   if (!str) return 1;
1494   assert(world);
1495
1496   for (s = setFirstItem(*world); s; s = setNextItem(*world))
1497   {
1498     /* found in set */
1499     if (0 == strcmp(s, str)) return 1;
1500   }
1501
1502   /* not found */
1503   if (autoAdd) addSet(world, Safe_strdup(str));
1504   return 0;
1505 }
1506
1507 static int
1508 pic16_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1509 {
1510   static set *emitted = NULL;
1511
1512   if (!pic16_stringInSet(sym, &emitted, 1)) {
1513     /* sym was not in emittedSymbols */
1514     if (!checkLocals || !pic16_stringInSet(sym, &pic16_localFunctions, 0)) {
1515       /* sym is not a locally defined function---avoid bug #1443651 */
1516       fprintf( file, fmt, sym );
1517       return 0;
1518     }
1519   }
1520   return 1;
1521 }
1522
1523 /*-----------------------------------------------------------------*/
1524 /* printPublics - generates global declarations for publics        */
1525 /*-----------------------------------------------------------------*/
1526 static void
1527 pic16printPublics (FILE *afile)
1528 {
1529   symbol *sym;
1530
1531         fprintf (afile, "\n%s", iComments2);
1532         fprintf (afile, "; public variables in this module\n");
1533         fprintf (afile, "%s", iComments2);
1534
1535         for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1536           /* sanity check */
1537           if(!IS_STATIC(sym->etype))
1538                 pic16_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1539 }
1540
1541 /*-----------------------------------------------------------------*/
1542 /* printExterns - generates extern declarations for externs        */
1543 /*-----------------------------------------------------------------*/
1544 static void
1545 pic16_printExterns(FILE *afile)
1546 {
1547   symbol *sym;
1548
1549         /* print nothing if no externs to declare */
1550         if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1551                 return;
1552
1553         fprintf(afile, "\n%s", iComments2);
1554         fprintf(afile, "; extern variables in this module\n");
1555         fprintf(afile, "%s", iComments2);
1556
1557         for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1558                 pic16_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1559
1560         for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1561                 pic16_emitSymbolIfNew(afile, "\textern _%s\n", sym->name, 1);
1562 }
1563
1564 /*-----------------------------------------------------------------*/
1565 /* emitOverlay - will emit code for the overlay stuff              */
1566 /*-----------------------------------------------------------------*/
1567 static void
1568 pic16emitOverlay (struct dbuf_s *aBuf)
1569 {
1570   set *ovrset;
1571
1572   if (!elementsInSet (ovrSetSets))
1573     dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name);
1574
1575   /* for each of the sets in the overlay segment do */
1576   for (ovrset = setFirstItem (ovrSetSets); ovrset;
1577        ovrset = setNextItem (ovrSetSets))
1578     {
1579
1580       symbol *sym;
1581
1582       if (elementsInSet (ovrset))
1583         {
1584           /* this dummy area is used to fool the assembler
1585              otherwise the assembler will append each of these
1586              declarations into one chunk and will not overlay
1587              sad but true */
1588           dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1589           /* output the area informtion */
1590           dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1591         }
1592
1593       for (sym = setFirstItem (ovrset); sym;
1594            sym = setNextItem (ovrset))
1595         {
1596
1597           /* if extern then do nothing */
1598           if (IS_EXTERN (sym->etype))
1599             continue;
1600
1601           /* if allocation required check is needed
1602              then check if the symbol really requires
1603              allocation only for local variables */
1604           if (!IS_AGGREGATE (sym->type) &&
1605               !(sym->_isparm && !IS_REGPARM (sym->etype))
1606               && !sym->allocreq && sym->level)
1607             continue;
1608
1609           /* if global variable & not static or extern
1610              and addPublics allowed then add it to the public set */
1611           if ((sym->_isparm && !IS_REGPARM (sym->etype))
1612               && !IS_STATIC (sym->etype)) {
1613 //            fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1614               checkAddSym(&publics, sym);
1615 //          addSetHead (&publics, sym);
1616           }
1617
1618           /* if extern then do nothing or is a function
1619              then do nothing */
1620           if (IS_FUNC (sym->type))
1621             continue;
1622
1623
1624           /* if is has an absolute address then generate
1625              an equate for this no need to allocate space */
1626           if (SPEC_ABSA (sym->etype))
1627             {
1628
1629               if (options.debug || sym->level == 0)
1630                 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1631
1632               dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1633                        sym->rname,
1634                        SPEC_ADDR (sym->etype));
1635             }
1636           else
1637             {
1638               if (options.debug || sym->level == 0)
1639                 dbuf_printf (aBuf, "==.\n");
1640
1641               /* allocate space */
1642               dbuf_printf (aBuf, "%s:\n", sym->rname);
1643               dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1644             }
1645
1646         }
1647     }
1648 }
1649
1650 static void
1651 emitStatistics(FILE *asmFile)
1652 {
1653   unsigned long isize, udsize, ramsize;
1654   statistics.isize = pic16_countInstructions();
1655   isize = (statistics.isize >= 0) ? statistics.isize : 0;
1656   udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1657   ramsize = pic16 ? pic16->RAMsize : 0x200;
1658   ramsize -= 256; /* ignore access bank and SFRs */
1659   if (ramsize == 0) ramsize = 64; /* prevent division by zero (below) */
1660
1661   fprintf (asmFile, "\n\n; Statistics:\n");
1662   fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n;           \t%5ld (0x%04lx) words\n",
1663     isize, isize, (isize*100.0)/(128UL << 10),
1664     isize>>1, isize>>1);
1665   fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n",
1666     udsize, udsize, (udsize*100.0) / (1.0 * ramsize));
1667   fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1668     statistics.intsize, statistics.intsize);
1669
1670   fprintf (asmFile, "\n\n");
1671 }
1672
1673
1674
1675 /*-----------------------------------------------------------------*/
1676 /* glue - the final glue that hold the whole thing together        */
1677 /*-----------------------------------------------------------------*/
1678 void
1679 pic16glue ()
1680 {
1681   FILE *asmFile;
1682   struct dbuf_s ovrBuf;
1683   struct dbuf_s vBuf;
1684
1685     dbuf_init(&ovrBuf, 4096);
1686     dbuf_init(&vBuf, 4096);
1687
1688     mainf = newSymbol ("main", 0);
1689     mainf->block = 0;
1690
1691     mainf = findSymWithLevel(SymbolTab, mainf);
1692
1693     pic16_pCodeInitRegisters();
1694
1695     if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1696       pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1697
1698         pic16_addpBlock(pb);
1699
1700         /* entry point @ start of CSEG */
1701         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1702
1703         if(initsfpnt) {
1704           pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1705                   pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1706           pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1707                   pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1708         }
1709
1710         /* put in the call to main */
1711         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1712
1713         if (options.mainreturn) {
1714           pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1715           pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1716         } else {
1717           pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1718           pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1719         }
1720     }
1721
1722     /* At this point we've got all the code in the form of pCode structures */
1723     /* Now it needs to be rearranged into the order it should be placed in the */
1724     /* code space */
1725
1726     pic16_movepBlock2Head('P');              // Last
1727     pic16_movepBlock2Head(code->dbName);
1728     pic16_movepBlock2Head('X');
1729     pic16_movepBlock2Head(statsg->dbName);   // First
1730
1731     /* print the global struct definitions */
1732
1733     /* PENDING: this isnt the best place but it will do */
1734     if (port->general.glue_up_main) {
1735       /* create the interrupt vector table */
1736       pic16createInterruptVect (&vBuf);
1737     }
1738
1739     /* emit code for the all the variables declared */
1740     pic16emitMaps ();
1741
1742     /* do the overlay segments */
1743     pic16emitOverlay(&ovrBuf);
1744     pic16_AnalyzepCode('*');
1745
1746 #if 1
1747     if(pic16_options.dumpcalltree) {
1748       FILE *cFile;
1749
1750         sprintf(buffer, "%s", dstFileName);
1751         strcat(buffer, ".calltree");
1752         cFile = fopen(buffer, "w");
1753         pic16_printCallTree( cFile );
1754         fclose(cFile);
1755     }
1756 #endif
1757
1758     pic16_InlinepCode();
1759     pic16_AnalyzepCode('*');
1760
1761
1762     if(pic16_debug_verbose)
1763       pic16_pcode_test();
1764
1765     /* now put it all together into the assembler file */
1766     /* create the assembler file name */
1767     if((noAssemble || options.c1mode)  && fullDstFileName) {
1768       sprintf (buffer, "%s", fullDstFileName);
1769     } else {
1770       sprintf (buffer, "%s", dstFileName);
1771       strcat (buffer, ".asm");
1772     }
1773
1774     if(!(asmFile = fopen (buffer, "w"))) {
1775       werror (E_FILE_OPEN_ERR, buffer);
1776       exit (1);
1777     }
1778
1779     /* initial comments */
1780     pic16initialComments (asmFile);
1781
1782     /* print module name */
1783     if(options.debug)
1784       fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1785
1786     /* Let the port generate any global directives, etc. */
1787     if(port->genAssemblerPreamble) {
1788       port->genAssemblerPreamble(asmFile);
1789     }
1790
1791     /* Put all variables into a cblock */
1792     pic16_AnalyzeBanking();
1793
1794 #if 0
1795     if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1796       pic16_OptimizeLocalRegs();
1797     }
1798 #endif
1799
1800     /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1801     if(pic16_options.opt_banksel > 1) {
1802       pic16_OptimizeBanksel();
1803     }
1804
1805     /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1806     if(!(pic16_options.opt_flags & OF_NO_OPTIMIZE_GOTO)) {
1807       pic16_OptimizeJumps();
1808     }
1809
1810     /* print the global variables in this module */
1811     pic16printPublics (asmFile);
1812
1813     /* print the extern variables to this module */
1814     pic16_printExterns(asmFile);
1815
1816     pic16_writeUsedRegs(asmFile);
1817
1818 #if 0
1819     /* no xdata in pic */
1820     /* if external stack then reserve space of it */
1821     if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1822       fprintf (asmFile, "%s", iComments2);
1823       fprintf (asmFile, "; external stack \n");
1824       fprintf (asmFile, "%s", iComments2);
1825       fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1826       fprintf (asmFile,";\t.ds 256\n");
1827     }
1828 #endif
1829
1830 #if 0
1831     /* no xdata in pic */
1832     /* copy xtern ram data */
1833     fprintf (asmFile, "%s", iComments2);
1834     fprintf (asmFile, "; external ram data\n");
1835     fprintf (asmFile, "%s", iComments2);
1836     dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1837 #endif
1838
1839 #if 0
1840     /* copy the bit segment */
1841     fprintf (asmFile, "%s", iComments2);
1842     fprintf (asmFile, "; bit data\n");
1843     fprintf (asmFile, "%s", iComments2);
1844     dbuf_write_and_destroy (&bit->oBuf, asmFile);
1845 #endif
1846
1847     /* copy the interrupt vector table */
1848     if(mainf && IFFUNC_HASBODY(mainf->type)) {
1849       fprintf (asmFile, "\n%s", iComments2);
1850       fprintf (asmFile, "; interrupt vector \n");
1851       fprintf (asmFile, "%s", iComments2);
1852       dbuf_write_and_destroy (&vBuf, asmFile);
1853     }
1854
1855     /* copy global & static initialisations */
1856     fprintf (asmFile, "\n%s", iComments2);
1857     fprintf (asmFile, "; global & static initialisations\n");
1858     fprintf (asmFile, "%s", iComments2);
1859
1860     if(pic16_debug_verbose)
1861       fprintf(asmFile, "; A code from now on!\n");
1862
1863     pic16_copypCode(asmFile, 'A');
1864
1865     if(pic16_options.no_crt) {
1866       if(mainf && IFFUNC_HASBODY(mainf->type)) {
1867         fprintf(asmFile, "\tcode\n");
1868         fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1869       }
1870     }
1871
1872 //    dbuf_write_and_destroy (&code->oBuf, stderr);
1873
1874     fprintf(asmFile, "; I code from now on!\n");
1875     pic16_copypCode(asmFile, 'I');
1876
1877     if(pic16_debug_verbose)
1878       fprintf(asmFile, "; dbName from now on!\n");
1879
1880     pic16_copypCode(asmFile, statsg->dbName);
1881
1882     if(pic16_options.no_crt) {
1883       if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1884         fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1885       }
1886     }
1887
1888     if(pic16_debug_verbose)
1889       fprintf(asmFile, "; X code from now on!\n");
1890
1891     pic16_copypCode(asmFile, 'X');
1892
1893     if(pic16_debug_verbose)
1894       fprintf(asmFile, "; M code from now on!\n");
1895
1896     pic16_copypCode(asmFile, 'M');
1897
1898     pic16_copypCode(asmFile, code->dbName);
1899
1900     pic16_copypCode(asmFile, 'P');
1901
1902     emitStatistics(asmFile);
1903
1904     fprintf (asmFile,"\tend\n");
1905     fclose (asmFile);
1906 }