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