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