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