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