* src/pic16/glue.c (printIvalChar): bug introduced by previous patch fixed
[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 #ifdef WORDS_BIGENDIAN
39   #define _ENDIAN(x)  (3-x)
40 #else
41   #define _ENDIAN(x)  (x)
42 #endif
43
44 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
45
46 extern symbol *interrupts[256];
47 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p);
48 extern int noAlloc;
49 extern set *publics;
50 extern set *externs;
51 extern unsigned maxInterrupts;
52 extern int maxRegBank;
53 extern symbol *mainf;
54 extern char *VersionString;
55 extern FILE *codeOutFile;
56 extern set *tmpfileSet;
57 extern set *tmpfileNameSet;
58 extern char *iComments1;
59 extern char *iComments2;
60
61 extern int initsfpnt;
62 extern unsigned long pFile_isize;
63
64 extern unsigned long pic16_countInstructions();
65 set *rel_idataSymSet=NULL;
66 set *fix_idataSymSet=NULL;
67
68 extern DEFSETFUNC (closeTmpFiles);
69 extern DEFSETFUNC (rmTmpFiles);
70
71 extern void pic16_AnalyzeBanking (void);
72 extern void pic16_OptimizeJumps ();
73 extern void pic16_OptimizeBanksel ();
74 extern void copyFile (FILE * dest, FILE * src);
75 extern void pic16_InlinepCode(void);
76 extern void pic16_writeUsedRegs(FILE *);
77
78 extern void initialComments (FILE * afile);
79 extern void printPublics (FILE * afile);
80
81 void  pic16_pCodeInitRegisters(void);
82 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
83 extern void pic16_pCodeConstString(char *name, char *value);
84
85
86 /*-----------------------------------------------------------------*/
87 /* aopLiteral - string from a literal value                        */
88 /*-----------------------------------------------------------------*/
89 int pic16aopLiteral (value *val, int offset)
90 {
91   union {
92     float f;
93     unsigned char c[4];
94   } fl;
95
96   /* if it is a float then it gets tricky */
97   /* otherwise it is fairly simple */
98   if (!IS_FLOAT(val->type)) {
99     unsigned long v = (unsigned long) 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 = copyValue (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);
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 FUNCTION:
558         {
559           sprintf(buf, "UPPER(%s)", iname);
560           pic16_emitDS(buf, ptype, p);
561         }; break;
562       case POINTER:
563       case IPOINTER:
564         sprintf(buf, "0x80");
565         pic16_emitDS(buf, ptype, p);
566         break;
567       default:
568         debugf("itype = %d\n", itype );
569         assert( 0 );
570     }
571
572     pic16_flushDB(ptype, p);
573 }
574
575
576 /* set to 0 to disable debug messages */
577 #define DEBUG_PRINTIVAL 0
578
579 /*-----------------------------------------------------------------*/
580 /* pic16_printIvalType - generates ival for int/char               */
581 /*-----------------------------------------------------------------*/
582 static void 
583 pic16_printIvalType (symbol *sym, sym_link * type, initList * ilist, char ptype, void *p)
584 {
585   value *val;
586
587 //  fprintf(stderr, "%s for symbol %s\n",__FUNCTION__, sym->rname);
588
589 #if DEBUG_PRINTIVAL
590   fprintf(stderr, "%s\n",__FUNCTION__);
591 #endif
592
593
594   /* if initList is deep */
595   if (ilist && ilist->type == INIT_DEEP)
596     ilist = ilist->init.deep;
597
598   if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
599     werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
600   }
601
602   if (!(val = list2val (ilist))) {
603     // assuming a warning has been thrown
604     val=constVal("0");
605   }
606
607   if (val->type != type) {
608     val = valCastLiteral(type, floatFromVal(val));
609   }
610
611   switch (getSize (type)) {
612   case 1:
613     pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
614     break;
615
616   case 2:
617     pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
618     pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
619     break;
620   case 3:
621     pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
622     pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
623     pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
624   case 4:
625     pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
626     pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
627     pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
628     pic16_emitDB(pic16aopLiteral(val, 3), ptype, p);
629     break;
630   }
631 }
632
633 /*--------------------------------------------------------------------*/
634 /* pic16_printIvalChar - generates initital value for character array */
635 /*--------------------------------------------------------------------*/
636 static int 
637 pic16_printIvalChar (symbol *sym, sym_link * type, initList * ilist, char *s, char ptype, void *p)
638 {
639   value *val;
640   int remain, len;
641
642   if(!p)
643     return 0;
644
645 #if DEBUG_PRINTIVAL
646   fprintf(stderr, "%s\n",__FUNCTION__);
647 #endif
648
649   if(!s) {
650     val = list2val (ilist);
651     /* if the value is a character string  */
652     if(IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
653       if(!DCL_ELEM (type))
654         DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
655
656       /* len is 0 if declartion equals initializer,
657        * >0 if declaration greater than initializer
658        * <0 if declaration less than initializer
659        * Strategy: if >0 emit 0x00 for the rest of the length,
660        * if <0 then emit only the length of declaration elements
661        * and warn user
662        */
663       len = DCL_ELEM (type) - (strlen (SPEC_CVAL (val->etype).v_char)+1);
664
665 //      fprintf(stderr, "%s:%d len = %i DCL_ELEM(type) = %i SPEC_CVAL-len = %i\n", __FILE__, __LINE__,
666 //        len, DCL_ELEM(type), strlen(SPEC_CVAL(val->etype).v_char));
667
668       remain=0;
669       if(len >= 0) {
670         for(remain=0; remain<strlen(SPEC_CVAL(val->etype).v_char)+1; remain++)
671           pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
672
673         if(len>0) {
674           len -= remain;
675           while(len--) {
676             pic16_emitDB(0x00, ptype, p);
677           }
678         }
679
680       } else {
681         werror (W_EXCESS_INITIALIZERS, "array of chars", sym->name, sym->lineDef);
682
683         for(remain=0; remain<DCL_ELEM (type); remain++)
684           pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
685       }
686       
687
688 //      if((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
689 //      }
690       return 1;
691     } else return 0;
692   } else {
693     for(remain=0; remain<strlen(s); remain++) {
694         pic16_emitDB(s[remain], ptype, p);
695     }
696   }
697   return 1;
698 }
699
700 /*-----------------------------------------------------------------*/
701 /* pic16_printIvalArray - generates code for array initialization        */
702 /*-----------------------------------------------------------------*/
703 static void 
704 pic16_printIvalArray (symbol * sym, sym_link * type, initList * ilist,
705                 char ptype, void *p)
706 {
707   initList *iloop;
708   int lcnt = 0, size = 0;
709
710   if(!p)
711     return;
712
713
714 #if DEBUG_PRINTIVAL
715   fprintf(stderr, "%s\n",__FUNCTION__);
716 #endif
717   /* take care of the special   case  */
718   /* array of characters can be init  */
719   /* by a string                      */
720   if (IS_CHAR (type->next)) {
721     if (!IS_LITERAL(list2val(ilist)->etype)) {
722       werror (W_INIT_WRONG);
723       return;
724     }
725
726     if(pic16_printIvalChar (sym, type,
727                        (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
728                        SPEC_CVAL (sym->etype).v_char, ptype, p))
729       return;
730   }
731   /* not the special case             */
732   if (ilist && ilist->type != INIT_DEEP)
733     {
734       werror (E_INIT_STRUCT, sym->name);
735       return;
736     }
737
738   iloop = ilist->init.deep;
739   lcnt = DCL_ELEM (type);
740
741   for (;;)
742     {
743       size++;
744       pic16_printIval (sym, type->next, iloop, ptype, p);
745       iloop = (iloop ? iloop->next : NULL);
746
747
748       /* if not array limits given & we */
749       /* are out of initialisers then   */
750       if (!DCL_ELEM (type) && !iloop)
751         break;
752
753       /* no of elements given and we    */
754       /* have generated for all of them */
755       if (!--lcnt) {
756         /* if initializers left */
757         if (iloop) {
758           werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
759         }
760         break;
761       }
762     }
763
764   /* if we have not been given a size  */
765   if (!DCL_ELEM (type))
766     DCL_ELEM (type) = size;
767
768   return;
769 }
770
771 /*-----------------------------------------------------------------*/
772 /* pic16_printIvalBitFields - generate initializer for bitfields   */
773 /*-----------------------------------------------------------------*/
774 void pic16_printIvalBitFields(symbol **sym, initList **ilist, char ptype, void *p)
775 {
776   value *val ;
777   symbol *lsym = *sym;
778   initList *lilist = *ilist ;
779   unsigned long ival = 0;
780   int size =0;
781
782
783 #if DEBUG_PRINTIVAL
784   fprintf(stderr, "%s\n",__FUNCTION__);
785 #endif
786
787
788   do {
789     unsigned long i;
790     val = list2val(lilist);
791     if (size) {
792       if (SPEC_BLEN(lsym->etype) > 8) {
793         size += ((SPEC_BLEN (lsym->etype) / 8) +
794                  (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
795       }
796     } else {
797       size = ((SPEC_BLEN (lsym->etype) / 8) +
798               (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
799     }
800     i = (unsigned long)floatFromVal(val);
801     i <<= SPEC_BSTR (lsym->etype);
802     ival |= i;
803     if (! ( lsym->next &&
804           (IS_BITFIELD(lsym->next->type)) &&
805           (SPEC_BSTR(lsym->next->etype)))) break;
806     lsym = lsym->next;
807     lilist = lilist->next;
808   } while (1);
809   switch (size) {
810   case 1:
811         pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
812         break;
813
814   case 2:
815         pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
816         pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
817         break;
818
819   case 4: /* EEP: why is this db and not dw? */
820         pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
821         pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
822         pic16_emitDB(BYTE_IN_LONG(ival, 2), ptype, p);
823         pic16_emitDB(BYTE_IN_LONG(ival, 3), ptype, p);
824         break;
825   default:
826         /* VR - only 1,2,4 size long can be handled???? Why? */
827         fprintf(stderr, "%s:%d: unhandled case. Contact author.\n", __FILE__, __LINE__);
828         assert(0);
829   }
830   *sym = lsym;
831   *ilist = lilist;
832 }
833  
834
835 /*-----------------------------------------------------------------*/
836 /* printIvalStruct - generates initial value for structures        */
837 /*-----------------------------------------------------------------*/
838 void pic16_printIvalStruct (symbol * sym, sym_link * type,
839                  initList * ilist, char ptype, void *p)
840 {
841   symbol *sflds;
842   initList *iloop = NULL;
843
844
845 #if DEBUG_PRINTIVAL
846   fprintf(stderr, "%s\n",__FUNCTION__);
847 #endif
848
849   sflds = SPEC_STRUCT (type)->fields;
850
851   if (ilist) {
852     if (ilist->type != INIT_DEEP) {
853       werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
854       return;
855     }
856
857     iloop = ilist->init.deep;
858   }
859
860   for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
861 //    fprintf(stderr, "%s:%d sflds: %p\tiloop = %p\n", __FILE__, __LINE__, sflds, iloop);
862     if (IS_BITFIELD(sflds->type)) {
863       pic16_printIvalBitFields(&sflds, &iloop, ptype, p);
864     } else {
865       pic16_printIval (sym, sflds->type, iloop, ptype, p);
866     }
867   }
868   if (iloop) {
869     werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
870   }
871   return;
872 }
873
874 /*--------------------------------------------------------------------------*/
875 /* pic16_printIvalCharPtr - generates initial values for character pointers */
876 /*--------------------------------------------------------------------------*/
877 int pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
878 {
879   int size = 0;
880
881   /* PENDING: this is _very_ mcs51 specific, including a magic
882      number...
883      It's also endin specific.
884
885      VR - Attempting to port this function to pic16 port - 8-Jun-2004
886    */
887
888
889 #if DEBUG_PRINTIVAL
890   fprintf(stderr, "%s\n",__FUNCTION__);
891 #endif
892
893   size = getSize (type);
894
895   if (val->name && strlen (val->name))
896     {
897       if (size == 1)            /* This appears to be Z80 specific?? */
898         {
899           pic16_emitDS(val->name, ptype, p);
900         }
901       else if (size == 2)
902         {
903           pic16_printPointerType (val->name, ptype, p);
904         }
905       else if (size == 3)
906         {
907           int type;
908           if (IS_PTR (val->type)) {
909             type = DCL_TYPE (val->type);
910           } else {
911             type = PTR_TYPE (SPEC_OCLS (val->etype));
912           }
913           if (val->sym && val->sym->isstrlit) {
914             // this is a literal string
915             type=CPOINTER;
916           }
917           pic16_printGPointerType(val->name, type, ptype, p);
918         }
919       else
920         {
921           fprintf (stderr, "*** internal error: unknown size in "
922                    "printIvalCharPtr.\n");
923           assert(0);
924         }
925     }
926   else
927     {
928       // these are literals assigned to pointers
929       switch (size)
930         {
931         case 1:
932           pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
933           break;
934         case 2:
935           pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
936           pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
937           break;
938         case 3:
939           pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
940           pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
941           pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
942           break;
943
944         default:
945           assert (0);
946         }
947     }
948
949   if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
950         if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
951         else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
952   }
953
954   return 1;
955 }
956
957 /*-----------------------------------------------------------------------*/
958 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
959 /*-----------------------------------------------------------------------*/
960 void pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
961 {
962   value *val;
963   int dLvl = 0;
964
965
966 #if DEBUG_PRINTIVAL
967   fprintf(stderr, "%s\n",__FUNCTION__);
968 #endif
969
970   if (ilist)
971     val = list2val (ilist);
972   else
973     val = valCastLiteral(type, 0.0);
974
975   if (!val) {
976     // an error has been thrown already
977     val=constVal("0");
978   }
979
980   if (IS_LITERAL(val->etype)) {
981     if (compareType(type, val->etype) == 0) {
982       werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
983       printFromToType (val->type, type);
984     }
985     pic16_printIvalCharPtr (NULL, type, val, ptype, p);
986     return;
987   }
988
989   /* check the types   */
990   if ((dLvl = compareType (val->type, type->next)) <= 0)
991     {
992       pic16_emitDB(0x00, ptype, p);
993       return;
994     }
995
996   /* now generate the name */
997   if (!val->sym) {
998       pic16_printGPointerType (val->name, DCL_TYPE(val->type), ptype, p);
999   } else {
1000       pic16_printGPointerType (val->sym->rname, DCL_TYPE(val->type), ptype, p);
1001
1002       if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
1003         
1004         if(!checkSym(publics, val->sym))
1005           if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
1006             /* this has not been declared as extern
1007              * so declare it as a 'late extern' just after the symbol */
1008             fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
1009             fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
1010             fprintf((FILE *)p, ";\tcontinue variable declaration\n");
1011           }
1012       }
1013   }
1014
1015   return;
1016 }
1017
1018
1019 /*-----------------------------------------------------------------*/
1020 /* pic16_printIvalPtr - generates initial value for pointers       */
1021 /*-----------------------------------------------------------------*/
1022 void pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1023 {
1024   value *val;
1025   int size;
1026
1027 #if 0
1028         fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1029                 sym->rname, getSize(sym->type));
1030 #endif
1031
1032   /* if deep then   */
1033   if (ilist && (ilist->type == INIT_DEEP))
1034     ilist = ilist->init.deep;
1035
1036   /* function pointer     */
1037   if (IS_FUNC (type->next))
1038     {
1039       pic16_printIvalFuncPtr (type, ilist, ptype, p);
1040       return;
1041     }
1042
1043   if (!(val = pic16_initPointer (ilist, type)))
1044     return;
1045
1046   /* if character pointer */
1047   if (IS_CHAR (type->next))
1048     if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1049       return;
1050
1051   /* check the type      */
1052   if (compareType (type, val->type) == 0) {
1053     werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1054     printFromToType (val->type, type);
1055   }
1056
1057   /* if val is literal */
1058   if (IS_LITERAL (val->etype))
1059     {
1060       switch (getSize (type))
1061         {
1062         case 1:
1063             pic16_emitDB((unsigned int)floatFromVal(val) & 0xff, ptype, p);
1064             break;
1065         case 2:
1066             pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1067             pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1068             break;
1069         case 3:
1070             pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1071             pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1072             pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
1073             break;
1074         default:
1075                 fprintf(stderr, "%s:%d size = %d\n", __FILE__, __LINE__, getSize(type));
1076                 assert(0);
1077         }
1078       return;
1079     }
1080
1081
1082   size = getSize (type);
1083
1084   if (size == 1)                /* Z80 specific?? */
1085     {
1086       pic16_emitDS(val->name, ptype, p);
1087     }
1088   else if (size == 2)
1089     {
1090         pic16_printPointerType (val->name, ptype, p);
1091     }
1092   else if (size == 3)
1093     {
1094       pic16_printGPointerType (val->name, (IS_PTR(type)?DCL_TYPE(type):PTR_TYPE(SPEC_OCLS(sym->etype))),
1095                           ptype, p);
1096     } else
1097         assert(0);
1098   return;
1099 }
1100
1101
1102
1103 /*-----------------------------------------------------------------*/
1104 /* pic16_printIval - generates code for initial value                    */
1105 /*-----------------------------------------------------------------*/
1106 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1107 {
1108 //  sym_link *itype;
1109   
1110   if (!p)
1111     return;
1112
1113 #if 0
1114         fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
1115         fprintf(stderr, "%s: IS_STRUCT: %d  IS_ARRAY: %d  IS_PTR: %d  IS_SPEC: %d\n", sym->name,
1116                 IS_STRUCT(type), IS_ARRAY(type), IS_PTR(type), IS_SPEC(type));
1117 #endif
1118         
1119   /* if structure then */
1120   if (IS_STRUCT (type))
1121     {
1122 //      fprintf(stderr,"%s struct\n",__FUNCTION__);
1123       pic16_printIvalStruct (sym, type, ilist, ptype, p);
1124       return;
1125     }
1126
1127   /* if this is an array */
1128   if (IS_ARRAY (type))
1129     {
1130 //      fprintf(stderr,"%s array\n",__FUNCTION__);
1131       pic16_printIvalArray (sym, type, ilist, ptype, p);
1132       return;
1133     }
1134
1135 #if 0
1136   if (ilist)
1137     {
1138       // not an aggregate, ilist must be a node
1139       if (ilist->type!=INIT_NODE) {
1140           // or a 1-element list
1141         if (ilist->init.deep->next) {
1142           werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1143                   sym->name);
1144         } else {
1145           ilist=ilist->init.deep;
1146         }
1147       }
1148
1149 #if 0
1150       // and the type must match
1151       itype=ilist->init.node->ftype;
1152
1153       if (compareType(type, itype)==0) {
1154         // special case for literal strings
1155         if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1156             // which are really code pointers
1157             IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1158           // no sweat
1159         } else {
1160 //          werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1161 //          printFromToType(itype, type);
1162         }
1163       }
1164 #endif
1165     }
1166 #endif
1167
1168   /* if this is a pointer */
1169   if (IS_PTR (type))
1170     {
1171 //      fprintf(stderr,"%s pointer\n",__FUNCTION__);
1172       pic16_printIvalPtr (sym, type, ilist, ptype, p);
1173       return;
1174     }
1175
1176
1177   /* if type is SPECIFIER */
1178   if (IS_SPEC (type))
1179     {
1180 //      fprintf(stderr,"%s spec\n",__FUNCTION__);
1181       pic16_printIvalType (sym, type, ilist, ptype, p);
1182       return;
1183     }
1184 }
1185
1186 int PIC16_IS_CONFIG_ADDRESS(int address)
1187 {
1188   return ((address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd));
1189 }
1190
1191 int PIC16_IS_IDLOC_ADDRESS(int address)
1192 {
1193    return ((address >= pic16->idInfo.idAddrStart && address <= pic16->idInfo.idAddrEnd));
1194 }
1195
1196 /* wrapper function for the above */
1197 int PIC16_IS_HWREG_ADDRESS(int address)
1198 {
1199   return (PIC16_IS_CONFIG_ADDRESS(address) || PIC16_IS_IDLOC_ADDRESS(address));
1200 }
1201
1202
1203 /*-----------------------------------------------------------------*/
1204 /* emitStaticSeg - emitcode for the static segment                 */
1205 /*-----------------------------------------------------------------*/
1206 static void
1207 pic16emitStaticSeg (memmap * map)
1208 {
1209   symbol *sym;
1210   static int didcode=0;
1211
1212   //fprintf(stderr, "%s\n",__FUNCTION__);
1213
1214   pic16_initDB();
1215
1216   /* for all variables in this segment do */
1217   for (sym = setFirstItem (map->syms); sym;
1218        sym = setNextItem (map->syms))
1219     {
1220
1221 #if 0
1222         fprintf(stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1223 CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__,
1224                 map->sname, sym->name, sym->used, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type),
1225                 IS_CODE(sym->etype), IN_CODESPACE( SPEC_OCLS(sym->etype)), IS_CONSTANT(sym->etype),
1226                 IS_PTR_CONST(sym->etype), SPEC_CONST(sym->etype));
1227         printTypeChain( sym->type, stderr );
1228         fprintf(stderr, "\n");
1229 #endif
1230
1231         if(SPEC_ABSA(sym->etype) && PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))) {
1232                 pic16_assignConfigWordValue(SPEC_ADDR(sym->etype),
1233                         (int) floatFromVal(list2val(sym->ival)));
1234
1235                 continue;
1236         }
1237
1238         if(SPEC_ABSA(sym->etype) && PIC16_IS_IDLOC_ADDRESS(SPEC_ADDR(sym->etype))) {
1239                 pic16_assignIdByteValue(SPEC_ADDR(sym->etype),
1240                         (char) floatFromVal(list2val(sym->ival)));
1241
1242                 continue;
1243         }
1244
1245         /* if it is "extern" then do nothing */
1246         if (IS_EXTERN (sym->etype) && !SPEC_ABSA(sym->etype)) {
1247                 checkAddSym(&externs, sym);
1248           continue;
1249         }
1250
1251         /* if it is not static add it to the public
1252            table */
1253         if (!IS_STATIC (sym->etype)) {
1254                 /* do not emit if it is a config word declaration */
1255                 checkAddSym(&publics, sym);
1256         }
1257
1258       /* print extra debug info if required */
1259       if (options.debug || sym->level == 0) {
1260           /* NOTE to me - cdbFile may be null in which case,
1261            * the sym name will be printed to stdout. oh well */
1262            debugFile->writeSymbol(sym);
1263       }
1264          
1265       /* if it has an absolute address */
1266       if (SPEC_ABSA (sym->etype)) {
1267 //              fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1268 //                      __FILE__, __LINE__, sym->name);
1269                         
1270           /* if it has an initial value */
1271           if (sym->ival)
1272             {
1273               pBlock *pb;
1274               symbol *asym;
1275               absSym *abSym;
1276               pCode *pcf;
1277               
1278               /* symbol has absolute address and initial value */
1279               noAlloc++;
1280               resolveIvalSym (sym->ival, sym->type);
1281               asym = newSymbol(sym->rname, 0);
1282               abSym = Safe_calloc(1, sizeof(absSym));
1283               strcpy(abSym->name, sym->rname);
1284               abSym->address = SPEC_ADDR( sym->etype );
1285               addSet(&absSymSet, abSym);
1286               
1287               pb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
1288               pic16_addpBlock(pb);
1289
1290               pcf = pic16_newpCodeFunction(moduleName, asym->name);
1291               PCF(pcf)->absblock = 1;
1292               
1293               pic16_addpCode2pBlock(pb,pcf);
1294               pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1295 //            fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1296               pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1297               pic16_flushDB('p', (void *)pb);
1298
1299               pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(NULL, NULL));
1300               noAlloc--;
1301             }
1302           else
1303             {
1304
1305               /* symbol has absolute address but no initial value */
1306               
1307               /* allocate space */
1308               fprintf (code->oFile, "%s:\n", sym->rname);
1309
1310               /* special case for character strings */
1311               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1312                   SPEC_CVAL (sym->etype).v_char) {
1313
1314 //              fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1315
1316                 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1317               } else {
1318                 assert(0);
1319               }
1320             }
1321   
1322         } else {
1323 //              fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1324 //                      __FILE__, __LINE__, sym->name);
1325
1326                 
1327           /* if it has an initial value */
1328           if (sym->ival) {
1329               pBlock *pb;
1330
1331               /* symbol doesn't have absolute address but has initial value */
1332               fprintf (code->oFile, "%s:\n", sym->rname);
1333               noAlloc++;
1334               resolveIvalSym (sym->ival, sym->type);
1335
1336               pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
1337               pic16_addpBlock(pb);
1338
1339               if(!didcode) {
1340                 /* make sure that 'code' directive is emitted before, once */
1341                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
1342                 
1343                 didcode++;
1344               }
1345                             
1346 //            fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1347
1348               pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1349               pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1350               pic16_flushDB('p', (void *)pb);
1351               noAlloc--;
1352             } else {
1353
1354               /* symbol doesn't have absolute address and no initial value */
1355               /* allocate space */
1356 //            fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1357               fprintf (code->oFile, "%s:\n", sym->rname);
1358               /* special case for character strings */
1359               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1360                   SPEC_CVAL (sym->etype).v_char) {
1361                 
1362 //              fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1363
1364                 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1365               } else {
1366                 assert(0);
1367               }
1368             }
1369         }
1370     }
1371
1372 }
1373
1374
1375 /*-----------------------------------------------------------------*/
1376 /* pic16_emitConfigRegs - emits the configuration registers              */
1377 /*-----------------------------------------------------------------*/
1378 void pic16_emitConfigRegs(FILE *of)
1379 {
1380   int i;
1381
1382         for(i=0;i<pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart;i++)
1383                 if(pic16->cwInfo.crInfo[i].emit)        //mask != -1)
1384                         fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1385                                 pic16->cwInfo.confAddrStart+i,
1386                                 pic16->cwInfo.crInfo[i].value);
1387 }
1388
1389 void pic16_emitIDRegs(FILE *of)
1390 {
1391   int i;
1392
1393         for(i=0;i<pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart;i++)
1394                 if(pic16->idInfo.irInfo[i].emit)
1395                         fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1396                                 pic16->idInfo.idAddrStart+i,
1397                                 pic16->idInfo.irInfo[i].value);
1398 }
1399
1400
1401 static void
1402 pic16emitMaps ()
1403 {
1404   /* no special considerations for the following
1405      data, idata & bit & xdata */
1406   pic16emitRegularMap (data, TRUE, TRUE);
1407   pic16emitRegularMap (idata, TRUE, TRUE);
1408   pic16emitRegularMap (bit, TRUE, FALSE);
1409   pic16emitRegularMap (xdata, TRUE, TRUE);
1410   pic16emitRegularMap (sfr, FALSE, FALSE);
1411   pic16emitRegularMap (sfrbit, FALSE, FALSE);
1412   pic16emitRegularMap (code, TRUE, FALSE);
1413   pic16emitStaticSeg (statsg);
1414 }
1415
1416 /*-----------------------------------------------------------------*/
1417 /* createInterruptVect - creates the interrupt vector              */
1418 /*-----------------------------------------------------------------*/
1419 static void
1420 pic16createInterruptVect (FILE * vFile)
1421 {
1422         /* if the main is only a prototype ie. no body then do nothing */
1423 #if 0
1424         if (!IFFUNC_HASBODY(mainf->type)) {
1425                 /* if ! compile only then main function should be present */
1426                 if (!options.cc_only)
1427                         werror (E_NO_MAIN);
1428                 return;
1429         }
1430 #endif
1431 #if 0
1432         if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1433                 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
1434                 fprintf(vFile, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1435
1436                 /* this is an overkill since WE are the port,
1437                  * and we know if we have a genIVT function! */
1438                 if(port->genIVT) {
1439                         port->genIVT(vFile, interrupts, maxInterrupts);
1440                 }
1441         }
1442 #endif
1443         
1444 }
1445
1446
1447 /*-----------------------------------------------------------------*/
1448 /* pic16initialComments - puts in some initial comments            */
1449 /*-----------------------------------------------------------------*/
1450 static void
1451 pic16initialComments (FILE * afile)
1452 {
1453         initialComments (afile);
1454         fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1455         if(pic16_mplab_comp)
1456                 fprintf(afile, "; MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1457         fprintf (afile, iComments2);
1458
1459         if(options.debug) {
1460                 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]\"\n",
1461                                 SDCC_VERSION_STR, getBuildNumber() );
1462         }
1463 }
1464
1465 /*-----------------------------------------------------------------*/
1466 /* printPublics - generates global declarations for publics        */
1467 /*-----------------------------------------------------------------*/
1468 static void
1469 pic16printPublics (FILE *afile)
1470 {
1471   symbol *sym;
1472
1473         fprintf (afile, "\n%s", iComments2);
1474         fprintf (afile, "; public variables in this module\n");
1475         fprintf (afile, "%s", iComments2);
1476
1477         for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1478           /* sanity check */
1479           if(!IS_STATIC(sym->etype))
1480                 fprintf(afile, "\tglobal %s\n", sym->rname);
1481 }
1482
1483 /*-----------------------------------------------------------------*/
1484 /* printExterns - generates extern declarations for externs        */
1485 /*-----------------------------------------------------------------*/
1486 static void
1487 pic16_printExterns(FILE *afile)
1488 {
1489   symbol *sym;
1490
1491         /* print nothing if no externs to declare */
1492         if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1493                 return;
1494
1495         fprintf(afile, "\n%s", iComments2);
1496         fprintf(afile, "; extern variables in this module\n");
1497         fprintf(afile, "%s", iComments2);
1498         
1499         for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1500                 fprintf(afile, "\textern %s\n", sym->rname);
1501
1502         for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1503                 fprintf(afile, "\textern _%s\n", sym->name);
1504 }
1505
1506 /*-----------------------------------------------------------------*/
1507 /* emitOverlay - will emit code for the overlay stuff              */
1508 /*-----------------------------------------------------------------*/
1509 static void
1510 pic16emitOverlay (FILE * afile)
1511 {
1512   set *ovrset;
1513
1514   if (!elementsInSet (ovrSetSets))
1515     fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
1516
1517   /* for each of the sets in the overlay segment do */
1518   for (ovrset = setFirstItem (ovrSetSets); ovrset;
1519        ovrset = setNextItem (ovrSetSets))
1520     {
1521
1522       symbol *sym;
1523
1524       if (elementsInSet (ovrset))
1525         {
1526           /* this dummy area is used to fool the assembler
1527              otherwise the assembler will append each of these
1528              declarations into one chunk and will not overlay
1529              sad but true */
1530           fprintf (afile, ";\t.area _DUMMY\n");
1531           /* output the area informtion */
1532           fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);    /* MOF */
1533         }
1534
1535       for (sym = setFirstItem (ovrset); sym;
1536            sym = setNextItem (ovrset))
1537         {
1538
1539           /* if extern then do nothing */
1540           if (IS_EXTERN (sym->etype))
1541             continue;
1542
1543           /* if allocation required check is needed
1544              then check if the symbol really requires
1545              allocation only for local variables */
1546           if (!IS_AGGREGATE (sym->type) &&
1547               !(sym->_isparm && !IS_REGPARM (sym->etype))
1548               && !sym->allocreq && sym->level)
1549             continue;
1550
1551           /* if global variable & not static or extern
1552              and addPublics allowed then add it to the public set */
1553           if ((sym->_isparm && !IS_REGPARM (sym->etype))
1554               && !IS_STATIC (sym->etype)) {
1555 //            fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1556               checkAddSym(&publics, sym);
1557 //          addSetHead (&publics, sym);
1558           }
1559
1560           /* if extern then do nothing or is a function
1561              then do nothing */
1562           if (IS_FUNC (sym->type))
1563             continue;
1564
1565
1566           /* if is has an absolute address then generate
1567              an equate for this no need to allocate space */
1568           if (SPEC_ABSA (sym->etype))
1569             {
1570
1571               if (options.debug || sym->level == 0)
1572                 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1573
1574               fprintf (afile, "%s\t=\t0x%04x\n",
1575                        sym->rname,
1576                        SPEC_ADDR (sym->etype));
1577             }
1578           else
1579             {
1580               if (options.debug || sym->level == 0)
1581                 fprintf (afile, "==.\n");
1582
1583               /* allocate space */
1584               fprintf (afile, "%s:\n", sym->rname);
1585               fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1586             }
1587
1588         }
1589     }
1590 }
1591
1592 void emitStatistics(FILE *asmFile)
1593 {
1594   unsigned long isize, udsize;
1595   statistics.isize = pic16_countInstructions();
1596   isize = (statistics.isize >= 0) ? statistics.isize : 0;
1597   udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1598         
1599   fprintf (asmFile, "\n\n; Statistics:\n");
1600   fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%3.2f%%)\n;           \t%5ld (0x%04lx) words\n",
1601     isize, isize, (isize*100.0)/(128 << 10),
1602     isize>>1, isize>>1);
1603   fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%3.2f%%)\n",
1604     udsize, udsize, (udsize*100.0) / ((pic16 ? pic16->RAMsize : 0x200) -256));
1605   fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1606     statistics.intsize, statistics.intsize);
1607
1608   fprintf (asmFile, "\n\n");
1609 }
1610
1611
1612
1613 /*-----------------------------------------------------------------*/
1614 /* glue - the final glue that hold the whole thing together        */
1615 /*-----------------------------------------------------------------*/
1616 void
1617 pic16glue ()
1618 {
1619   FILE *vFile;
1620   FILE *asmFile;
1621   FILE *ovrFile = tempfile();
1622
1623     mainf = newSymbol ("main", 0);
1624     mainf->block = 0;
1625
1626     mainf = findSymWithLevel(SymbolTab, mainf);
1627
1628     addSetHead(&tmpfileSet,ovrFile);
1629     pic16_pCodeInitRegisters();
1630
1631     if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1632       pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1633
1634         pic16_addpBlock(pb);
1635
1636         /* entry point @ start of CSEG */
1637         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1638
1639         if(initsfpnt) {
1640           pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1641                   pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1642           pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1643                   pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1644         }
1645
1646         /* put in the call to main */
1647         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1648
1649         if (options.mainreturn) {
1650           pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1651           pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1652         } else {
1653           pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1654           pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1655         }
1656     }
1657
1658     /* At this point we've got all the code in the form of pCode structures */
1659     /* Now it needs to be rearranged into the order it should be placed in the */
1660     /* code space */
1661
1662     pic16_movepBlock2Head('P');              // Last
1663     pic16_movepBlock2Head(code->dbName);
1664     pic16_movepBlock2Head('X');
1665     pic16_movepBlock2Head(statsg->dbName);   // First
1666
1667     /* print the global struct definitions */
1668
1669     vFile = tempfile();
1670     /* PENDING: this isnt the best place but it will do */
1671     if (port->general.glue_up_main) {
1672       /* create the interrupt vector table */
1673       pic16createInterruptVect (vFile);
1674     }
1675
1676     addSetHead(&tmpfileSet,vFile);
1677     
1678     /* emit code for the all the variables declared */
1679     pic16emitMaps ();
1680
1681     /* do the overlay segments */
1682     pic16emitOverlay(ovrFile);
1683     pic16_AnalyzepCode('*');
1684
1685 #if 1
1686     if(pic16_options.dumpcalltree) {
1687       FILE *cFile;
1688         
1689         sprintf(buffer, dstFileName);
1690         strcat(buffer, ".calltree");
1691         cFile = fopen(buffer, "w");
1692         pic16_printCallTree( cFile );
1693         fclose(cFile);
1694     }
1695 #endif
1696
1697     pic16_InlinepCode();
1698     pic16_AnalyzepCode('*');
1699
1700
1701     if(pic16_debug_verbose)
1702       pic16_pcode_test();
1703
1704     /* now put it all together into the assembler file */
1705     /* create the assembler file name */
1706     if((noAssemble || options.c1mode)  && fullDstFileName) {
1707       sprintf (buffer, fullDstFileName);
1708     } else {
1709       sprintf (buffer, dstFileName);
1710       strcat (buffer, ".asm");
1711     }
1712
1713     if(!(asmFile = fopen (buffer, "w"))) {
1714       werror (E_FILE_OPEN_ERR, buffer);
1715       exit (1);
1716     }
1717     
1718     /* initial comments */
1719     pic16initialComments (asmFile);
1720
1721     /* print module name */
1722     if(options.debug)
1723       fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1724
1725     /* Let the port generate any global directives, etc. */
1726     if(port->genAssemblerPreamble) {
1727       port->genAssemblerPreamble(asmFile);
1728     }
1729         
1730     /* Put all variables into a cblock */
1731     pic16_AnalyzeBanking();
1732
1733 #if 0
1734     if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1735       pic16_OptimizeLocalRegs();
1736     }
1737 #endif
1738
1739     /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1740     if(pic16_options.opt_banksel > 1) {
1741       pic16_OptimizeBanksel();
1742     }
1743             
1744     /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1745     if(pic16_options.opt_flags & OF_OPTIMIZE_GOTO) {
1746       pic16_OptimizeJumps();
1747     }
1748
1749     /* print the extern variables to this module */
1750     pic16_printExterns(asmFile);
1751         
1752     /* print the global variables in this module */
1753     pic16printPublics (asmFile);
1754
1755     pic16_writeUsedRegs(asmFile);
1756
1757 #if 0
1758     /* no xdata in pic */
1759     /* if external stack then reserve space of it */
1760     if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1761       fprintf (asmFile, "%s", iComments2);
1762       fprintf (asmFile, "; external stack \n");
1763       fprintf (asmFile, "%s", iComments2);
1764       fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1765       fprintf (asmFile,";\t.ds 256\n");
1766     }
1767 #endif
1768
1769 #if 0   
1770     /* no xdata in pic */
1771     /* copy xtern ram data */
1772     fprintf (asmFile, "%s", iComments2);
1773     fprintf (asmFile, "; external ram data\n");
1774     fprintf (asmFile, "%s", iComments2);
1775     copyFile (asmFile, xdata->oFile);
1776 #endif
1777
1778 #if 0
1779     /* copy the bit segment */
1780     fprintf (asmFile, "%s", iComments2);
1781     fprintf (asmFile, "; bit data\n");
1782     fprintf (asmFile, "%s", iComments2);
1783     copyFile (asmFile, bit->oFile);
1784 #endif
1785
1786     /* copy the interrupt vector table */
1787     if(mainf && IFFUNC_HASBODY(mainf->type)) {
1788       fprintf (asmFile, "\n%s", iComments2);
1789       fprintf (asmFile, "; interrupt vector \n");
1790       fprintf (asmFile, "%s", iComments2);
1791       copyFile (asmFile, vFile);
1792     }
1793     
1794     /* copy global & static initialisations */
1795     fprintf (asmFile, "\n%s", iComments2);
1796     fprintf (asmFile, "; global & static initialisations\n");
1797     fprintf (asmFile, "%s", iComments2);
1798     
1799     if(pic16_debug_verbose)
1800       fprintf(asmFile, "; A code from now on!\n");
1801     
1802     pic16_copypCode(asmFile, 'A');
1803
1804     if(pic16_options.no_crt) {
1805       if(mainf && IFFUNC_HASBODY(mainf->type)) {
1806         fprintf(asmFile, "\tcode\n");
1807         fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1808       }
1809     }
1810
1811 //    copyFile (stderr, code->oFile);
1812
1813     fprintf(asmFile, "; I code from now on!\n");
1814     pic16_copypCode(asmFile, 'I');
1815
1816     if(pic16_debug_verbose)
1817       fprintf(asmFile, "; dbName from now on!\n");
1818     
1819     pic16_copypCode(asmFile, statsg->dbName);
1820
1821     if(pic16_options.no_crt) {
1822       if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1823         fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1824       }
1825     }
1826         
1827     if(pic16_debug_verbose)
1828       fprintf(asmFile, "; X code from now on!\n");
1829
1830     pic16_copypCode(asmFile, 'X');
1831
1832     if(pic16_debug_verbose)
1833       fprintf(asmFile, "; M code from now on!\n");
1834
1835     pic16_copypCode(asmFile, 'M');
1836
1837     pic16_copypCode(asmFile, code->dbName);
1838     
1839     pic16_copypCode(asmFile, 'P');
1840
1841     emitStatistics(asmFile);
1842
1843     fprintf (asmFile,"\tend\n");
1844     fclose (asmFile);
1845     
1846     rm_tmpfiles();
1847 }