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