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