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