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