Large cummulative patch for pic16 port.
[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 copyFile (FILE * dest, FILE * src);
73 extern void pic16_InlinepCode(void);
74 extern void pic16_writeUsedRegs(FILE *);
75
76 extern void initialComments (FILE * afile);
77 extern void printPublics (FILE * afile);
78
79 void  pic16_pCodeInitRegisters(void);
80 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
81 extern void pic16_pCodeConstString(char *name, char *value);
82
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 0
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) == S_REGISTER), 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                         /* reduce overhead while linking by not declaring
146                          * extern unused external functions (usually declared
147                          * in header files) */
148                         if(IS_FUNC(sym->type) && !sym->used)continue;
149                         
150                         /* make sure symbol is not in publics section */
151                         if(!checkSym(publics, sym))
152                                 checkAddSym(&externs, sym);
153                         continue;
154                 }
155                 
156                 /* if allocation required check is needed
157                  * then check if the symbol really requires
158                  * allocation only for local variables */
159                  if (arFlag && !IS_AGGREGATE (sym->type) &&
160                         !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
161                         !sym->allocreq && sym->level) {
162
163 //                      fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
164
165                         continue;
166                 }
167
168                 /* if global variable & not static or extern
169                  * and addPublics allowed then add it to the public set */
170                 if ((sym->used) && (sym->level == 0 ||
171                         (sym->_isparm && !IS_REGPARM (sym->etype))) &&
172                         addPublics &&
173                         !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
174                   
175                         checkAddSym(&publics, sym);
176                 } else
177                         if(IS_STATIC(sym->etype)
178                                 && !(sym->ival && !sym->level)
179                         ) {
180                           regs *reg;
181                           sectSym *ssym;
182                           int found=0;
183 #define SET_IMPLICIT    1
184
185 #if SET_IMPLICIT
186                                 if(IS_STRUCT(sym->type))
187                                         sym->implicit = 1;
188 #endif
189
190                                 reg = pic16_allocDirReg( operandFromSymbol( sym ));
191                                 
192                                 if(reg) {
193 #if 1
194                                   for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
195                                     if(!strcmp(ssym->name, reg->name))found=1;
196                                   }
197 #endif
198                                   if(!found)
199                                     checkAddReg(&pic16_rel_udata, reg);
200                                   else
201                                     checkAddSym(&publics, sym);
202
203                                 }
204                         }
205
206                 /* if extern then do nothing or is a function
207                  * then do nothing */
208                 if (IS_FUNC (sym->type) && !IS_STATIC(sym->etype)) {
209                         if(SPEC_OCLS(sym->etype) == code) {
210 //                              fprintf(stderr, "%s:%d: symbol added: %s\n", __FILE__, __LINE__, sym->rname);
211                                 checkAddSym(&publics, sym);
212                         }
213                         continue;
214                 }
215
216 #if 0
217                 /* print extra debug info if required */
218                 if (options.debug || sym->level == 0) {
219                         cdbWriteSymbol (sym);   //, cdbFile, FALSE, FALSE);
220
221                         if (!sym->level)        /* global */
222                                 if (IS_STATIC (sym->etype))
223                                         fprintf (map->oFile, "F%s_", moduleName);               /* scope is file */
224                                 else
225                                         fprintf (map->oFile, "G_");     /* scope is global */
226                         else
227                                 /* symbol is local */
228                                 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
229                         fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
230                 }
231 #endif
232
233
234                 /* if is has an absolute address then generate
235                 an equate for this no need to allocate space */
236                 if (SPEC_ABSA (sym->etype)) {
237 //                      if (options.debug || sym->level == 0)
238 //                              fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
239 //                                      sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
240
241                         fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
242                                 sym->rname,
243                                 SPEC_ADDR (sym->etype));
244
245                         /* emit only if it is global */
246                         if(sym->level == 0) {
247                           regs *reg;
248
249                                 reg = pic16_dirregWithName( sym->name );
250                                 if(!reg) {
251                                         /* here */
252 //                                      fprintf(stderr, "%s:%d: implicit add of symbol = %s\n",
253 //                                                      __FUNCTION__, __LINE__, sym->name);
254
255                                         /* if IS_STRUCT is omitted the following
256                                          * fixes structures but break char/int etc */
257 #if SET_IMPLICIT
258                                         if(IS_STRUCT(sym->type))
259                                                 sym->implicit = 1;              // mark as implicit
260 #endif
261                                         if(!sym->ival) {
262                                                 reg = pic16_allocDirReg( operandFromSymbol(sym) );
263                                                 if(reg) {
264                                                         if(checkAddReg(&pic16_fix_udata, reg)) {
265                                                                 /* and add to globals list if not exist */
266                                                                 addSet(&publics, sym);
267                                                         }
268                                                 }
269                                         } else
270                                                 addSet(&publics, sym);
271                                 }
272                         }
273                 } else {
274                         if(!sym->used && (sym->level == 0)) {
275                           regs *reg;
276
277                                 /* symbol not used, just declared probably, but its in
278                                  * level 0, so we must declare it fine as global */
279                                 
280 //                              fprintf(stderr, "EXTRA symbol declaration sym= %s\n", sym->name);
281
282 #if SET_IMPLICIT
283                                 if(IS_STRUCT(sym->type))
284                                         sym->implicit = 1;              // mark as implicit
285 #endif
286                                 if(!sym->ival) {
287                                         if(IS_AGGREGATE(sym->type)) {
288                                                 reg=pic16_allocRegByName(sym->rname, getSize( sym->type ), NULL);
289                                         } else {
290                                                 reg = pic16_allocDirReg( operandFromSymbol( sym ) );
291                                         }
292
293                                         {
294                                           sectSym *ssym;
295                                           int found=0;
296                                   
297 #if 0
298                                                 fprintf(stderr, "%s:%d sym->rname: %s reg: %p reg->name: %s\n", __FILE__, __LINE__,
299                                                         sym->rname, reg, (reg?reg->name:"<<NULL>>"));
300 #endif
301
302                                                 if(reg) {
303                                                   for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
304                                                     if(!strcmp(ssym->name, reg->name))found=1;
305                                                   }
306
307                                                   if(!found)
308                                                     if(checkAddReg(&pic16_rel_udata, reg)) {
309                                                       addSetHead(&publics, sym);
310                                                     }
311                                                 }
312                                         }
313
314
315                 
316                                 } else
317
318                                         addSetHead(&publics, sym);
319                         }
320
321 #if 0
322                         /* allocate space */
323                         /* If this is a bit variable, then allocate storage after 8 bits have been declared */
324                         /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
325                         /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
326                         if (IS_BITVAR (sym->etype)) {
327                                 bitvars++;
328                         } else {
329                                 fprintf (map->oFile, "\t%s\n", sym->rname);
330                                 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
331                                         for (i = 1; i < size; i++)
332                                                 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
333                                 }
334                         }
335                         fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
336 #endif
337                 }
338         
339                 /* FIXME -- VR Fix the following, so that syms to be placed
340                  * in the idata section and let linker decide about their fate */
341
342                 /* if it has an initial value then do it only if
343                         it is a global variable */
344
345                 if (sym->ival && sym->level == 0) {
346                   ast *ival = NULL;
347
348 #if 0
349                         if(SPEC_OCLS(sym->etype)==data) {
350                                 fprintf(stderr, "%s: sym %s placed in data segment\n", map->sname, sym->name);
351                         }
352
353                         if(SPEC_OCLS(sym->etype)==code) {
354                                 fprintf(stderr, "%s: sym %s placed in code segment\n", map->sname, sym->name);
355                         }
356 #endif
357
358 #if 0
359                         fprintf(stderr, "'%s': sym '%s' has initial value SPEC_ABSA: %d, IS_AGGREGATE: %d\n",
360                                 map->sname, sym->name, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type));
361 #endif
362
363                         if (IS_AGGREGATE (sym->type)) {
364                                 if(SPEC_ABSA(sym->etype))
365                                         addSet(&fix_idataSymSet, copySymbol(sym));
366                                 else
367                                         addSet(&rel_idataSymSet, copySymbol(sym));
368 //                              ival = initAggregates (sym, sym->ival, NULL);
369                         } else {
370                                 if(SPEC_ABSA(sym->etype))
371                                         addSet(&fix_idataSymSet, copySymbol(sym));
372                                 else
373                                         addSet(&rel_idataSymSet, copySymbol(sym));
374
375 //                                      ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
376 //                                              decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
377                         }
378
379                         if(ival) {
380                                 setAstLineno(ival, sym->lineDef);
381                                 codeOutFile = statsg->oFile;
382                                 GcurMemmap = statsg;
383                                 eBBlockFromiCode (iCodeFromAst (ival));
384                                 sym->ival = NULL;
385                         }
386                 }
387         }
388 }
389
390
391 /*-----------------------------------------------------------------*/
392 /* pic16_initPointer - pointer initialization code massaging       */
393 /*-----------------------------------------------------------------*/
394 value *pic16_initPointer (initList * ilist, sym_link *toType)
395 {
396   value *val;
397   ast *expr;
398
399   if (!ilist) {
400       return valCastLiteral(toType, 0.0);
401   }
402
403   expr = decorateType(resolveSymbols( list2expr (ilist) ), FALSE);
404 //  expr = list2expr( ilist );
405   
406   if (!expr)
407     goto wrong;
408   
409   /* try it the old way first */
410   if ((val = constExprValue (expr, FALSE)))
411     return val;
412   
413   /* ( ptr + constant ) */
414   if (IS_AST_OP (expr) &&
415       (expr->opval.op == '+' || expr->opval.op == '-') &&
416       IS_AST_SYM_VALUE (expr->left) &&
417       (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
418       compareType(toType, expr->left->ftype) &&
419       IS_AST_LIT_VALUE (expr->right)) {
420     return valForCastAggr (expr->left, expr->left->ftype,
421                            expr->right,
422                            expr->opval.op);
423   }
424   
425   /* (char *)&a */
426   if (IS_AST_OP(expr) && expr->opval.op==CAST &&
427       IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
428     if (compareType(toType, expr->left->ftype)!=1) {
429       werror (W_INIT_WRONG);
430       printFromToType(expr->left->ftype, toType);
431     }
432     // skip the cast ???
433     expr=expr->right;
434   }
435
436   /* no then we have to do these cludgy checks */
437   /* pointers can be initialized with address of
438      a variable or address of an array element */
439   if (IS_AST_OP (expr) && expr->opval.op == '&') {
440     /* address of symbol */
441     if (IS_AST_SYM_VALUE (expr->left)) {
442       val = copyValue (AST_VALUE (expr->left));
443       val->type = newLink (DECLARATOR);
444       if(SPEC_SCLS (expr->left->etype) == S_CODE) {
445         DCL_TYPE (val->type) = CPOINTER;
446         DCL_PTR_CONST (val->type) = port->mem.code_ro;
447       }
448       else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
449         DCL_TYPE (val->type) = FPOINTER;
450       else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
451         DCL_TYPE (val->type) = PPOINTER;
452       else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
453         DCL_TYPE (val->type) = IPOINTER;
454       else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
455         DCL_TYPE (val->type) = EEPPOINTER;
456       else
457         DCL_TYPE (val->type) = POINTER;
458
459       val->type->next = expr->left->ftype;
460       val->etype = getSpec (val->type);
461       return val;
462     }
463
464     /* if address of indexed array */
465     if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
466       return valForArray (expr->left);
467
468     /* if address of structure element then
469        case 1. a.b ; */
470     if (IS_AST_OP (expr->left) &&
471         expr->left->opval.op == '.') {
472       return valForStructElem (expr->left->left,
473                                expr->left->right);
474     }
475
476     /* case 2. (&a)->b ;
477        (&some_struct)->element */
478     if (IS_AST_OP (expr->left) &&
479         expr->left->opval.op == PTR_OP &&
480         IS_ADDRESS_OF_OP (expr->left->left)) {
481       return valForStructElem (expr->left->left->left,
482                                expr->left->right);
483     }
484   }
485   /* case 3. (((char *) &a) +/- constant) */
486   if (IS_AST_OP (expr) &&
487       (expr->opval.op == '+' || expr->opval.op == '-') &&
488       IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
489       IS_AST_OP (expr->left->right) &&
490       expr->left->right->opval.op == '&' &&
491       IS_AST_LIT_VALUE (expr->right)) {
492
493     return valForCastAggr (expr->left->right->left,
494                            expr->left->left->opval.lnk,
495                            expr->right, expr->opval.op);
496
497   }
498   /* case 4. (char *)(array type) */
499   if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
500       IS_ARRAY(expr->right->ftype)) {
501
502     val = copyValue (AST_VALUE (expr->right));
503     val->type = newLink (DECLARATOR);
504     if (SPEC_SCLS (expr->right->etype) == S_CODE) {
505       DCL_TYPE (val->type) = CPOINTER;
506       DCL_PTR_CONST (val->type) = port->mem.code_ro;
507     }
508     else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
509       DCL_TYPE (val->type) = FPOINTER;
510     else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
511       DCL_TYPE (val->type) = PPOINTER;
512     else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
513       DCL_TYPE (val->type) = IPOINTER;
514     else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
515       DCL_TYPE (val->type) = EEPPOINTER;
516     else
517       DCL_TYPE (val->type) = POINTER;
518     val->type->next = expr->right->ftype->next;
519     val->etype = getSpec (val->type);
520     return val;
521   }
522
523  wrong:
524   if (expr)
525     werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES);
526   else
527     werror (E_INCOMPAT_PTYPES);
528   return NULL;
529
530 }
531
532
533 /*-----------------------------------------------------------------*/
534 /* printPointerType - generates ival for pointer type              */
535 /*-----------------------------------------------------------------*/
536 void _pic16_printPointerType (const char *name, char ptype, void *p)
537 {
538   char buf[256];
539
540         sprintf(buf, "LOW(%s)", name);
541         pic16_emitDS(buf, ptype, p);
542         sprintf(buf, "HIGH(%s)", name);
543         pic16_emitDS(buf, ptype, p);
544 }
545
546 /*-----------------------------------------------------------------*/
547 /* printPointerType - generates ival for pointer type              */
548 /*-----------------------------------------------------------------*/
549 void pic16_printPointerType (const char *name, char ptype, void *p)
550 {
551   _pic16_printPointerType (name, ptype, p);
552   pic16_flushDB(ptype, p);
553 }
554
555 /*-----------------------------------------------------------------*/
556 /* printGPointerType - generates ival for generic pointer type     */
557 /*-----------------------------------------------------------------*/
558 void pic16_printGPointerType (const char *iname, const unsigned int itype,
559   char ptype, void *p)
560 {
561   char buf[256];
562   
563     _pic16_printPointerType (iname, ptype, p);
564
565     switch( itype ) {
566       case FPOINTER:
567       case CPOINTER:
568       case FUNCTION:
569         {
570           sprintf(buf, "UPPER(%s)", iname);
571           pic16_emitDS(buf, ptype, p);
572         }; break;
573       case POINTER:
574       case IPOINTER:
575         sprintf(buf, "0x80");
576         pic16_emitDS(buf, ptype, p);
577         break;
578       default:
579         debugf("itype = %d\n", itype );
580         assert( 0 );
581     }
582
583     pic16_flushDB(ptype, p);
584 }
585
586
587 /* set to 0 to disable debug messages */
588 #define DEBUG_PRINTIVAL 0
589
590 /*-----------------------------------------------------------------*/
591 /* pic16_printIvalType - generates ival for int/char               */
592 /*-----------------------------------------------------------------*/
593 static void 
594 pic16_printIvalType (symbol *sym, sym_link * type, initList * ilist, char ptype, void *p)
595 {
596   value *val;
597
598 //  fprintf(stderr, "%s for symbol %s\n",__FUNCTION__, sym->rname);
599
600 #if DEBUG_PRINTIVAL
601   fprintf(stderr, "%s\n",__FUNCTION__);
602 #endif
603
604
605   /* if initList is deep */
606   if (ilist && ilist->type == INIT_DEEP)
607     ilist = ilist->init.deep;
608
609   if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
610     werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
611   }
612
613   if (!(val = list2val (ilist))) {
614     // assuming a warning has been thrown
615     val=constVal("0");
616   }
617
618   if (val->type != type) {
619     val = valCastLiteral(type, floatFromVal(val));
620   }
621
622   switch (getSize (type)) {
623   case 1:
624     pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
625     break;
626
627   case 2:
628     pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
629     pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
630     break;
631   case 3:
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   case 4:
636     pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
637     pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
638     pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
639     pic16_emitDB(pic16aopLiteral(val, 3), ptype, p);
640     break;
641   }
642 }
643
644 /*--------------------------------------------------------------------*/
645 /* pic16_printIvalChar - generates initital value for character array */
646 /*--------------------------------------------------------------------*/
647 static int 
648 pic16_printIvalChar (sym_link * type, initList * ilist, char *s, char ptype, void *p)
649 {
650   value *val;
651   unsigned int remain;
652
653   if(!p)
654     return 0;
655
656 #if DEBUG_PRINTIVAL
657   fprintf(stderr, "%s\n",__FUNCTION__);
658 #endif
659
660   if(!s) {
661     val = list2val (ilist);
662     /* if the value is a character string  */
663     if(IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
664       if(!DCL_ELEM (type))
665         DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
666
667       for(remain=0; remain<strlen(SPEC_CVAL(val->etype).v_char)+1; remain++)
668         pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
669       
670       if((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
671         while(remain--) {
672           pic16_emitDB(0x00, ptype, p);
673         }
674       }
675       return 1;
676     } else return 0;
677   } else {
678     for(remain=0; remain<strlen(s); remain++) {
679         pic16_emitDB(s[remain], ptype, p);
680     }
681   }
682   return 1;
683 }
684
685 /*-----------------------------------------------------------------*/
686 /* pic16_printIvalArray - generates code for array initialization        */
687 /*-----------------------------------------------------------------*/
688 static void 
689 pic16_printIvalArray (symbol * sym, sym_link * type, initList * ilist,
690                 char ptype, void *p)
691 {
692   initList *iloop;
693   int lcnt = 0, size = 0;
694
695   if(!p)
696     return;
697
698
699 #if DEBUG_PRINTIVAL
700   fprintf(stderr, "%s\n",__FUNCTION__);
701 #endif
702   /* take care of the special   case  */
703   /* array of characters can be init  */
704   /* by a string                      */
705   if (IS_CHAR (type->next)) {
706     if (!IS_LITERAL(list2val(ilist)->etype)) {
707       werror (W_INIT_WRONG);
708       return;
709     }
710
711     if(pic16_printIvalChar (type,
712                        (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
713                        SPEC_CVAL (sym->etype).v_char, ptype, p))
714       return;
715   }
716   /* not the special case             */
717   if (ilist && ilist->type != INIT_DEEP)
718     {
719       werror (E_INIT_STRUCT, sym->name);
720       return;
721     }
722
723   iloop = ilist->init.deep;
724   lcnt = DCL_ELEM (type);
725
726   for (;;)
727     {
728       size++;
729       pic16_printIval (sym, type->next, iloop, ptype, p);
730       iloop = (iloop ? iloop->next : NULL);
731
732
733       /* if not array limits given & we */
734       /* are out of initialisers then   */
735       if (!DCL_ELEM (type) && !iloop)
736         break;
737
738       /* no of elements given and we    */
739       /* have generated for all of them */
740       if (!--lcnt) {
741         /* if initializers left */
742         if (iloop) {
743           werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
744         }
745         break;
746       }
747     }
748
749   /* if we have not been given a size  */
750   if (!DCL_ELEM (type))
751     DCL_ELEM (type) = size;
752
753   return;
754 }
755
756 /*-----------------------------------------------------------------*/
757 /* pic16_printIvalBitFields - generate initializer for bitfields   */
758 /*-----------------------------------------------------------------*/
759 void pic16_printIvalBitFields(symbol **sym, initList **ilist, char ptype, void *p)
760 {
761   value *val ;
762   symbol *lsym = *sym;
763   initList *lilist = *ilist ;
764   unsigned long ival = 0;
765   int size =0;
766
767
768 #if DEBUG_PRINTIVAL
769   fprintf(stderr, "%s\n",__FUNCTION__);
770 #endif
771
772
773   do {
774     unsigned long i;
775     val = list2val(lilist);
776     if (size) {
777       if (SPEC_BLEN(lsym->etype) > 8) {
778         size += ((SPEC_BLEN (lsym->etype) / 8) +
779                  (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
780       }
781     } else {
782       size = ((SPEC_BLEN (lsym->etype) / 8) +
783               (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
784     }
785     i = (unsigned long)floatFromVal(val);
786     i <<= SPEC_BSTR (lsym->etype);
787     ival |= i;
788     if (! ( lsym->next &&
789           (IS_BITFIELD(lsym->next->type)) &&
790           (SPEC_BSTR(lsym->next->etype)))) break;
791     lsym = lsym->next;
792     lilist = lilist->next;
793   } while (1);
794   switch (size) {
795   case 1:
796         pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
797         break;
798
799   case 2:
800         pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
801         pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
802         break;
803
804   case 4: /* EEP: why is this db and not dw? */
805         pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
806         pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
807         pic16_emitDB(BYTE_IN_LONG(ival, 2), ptype, p);
808         pic16_emitDB(BYTE_IN_LONG(ival, 3), ptype, p);
809         break;
810   default:
811         /* VR - only 1,2,4 size long can be handled???? Why? */
812         fprintf(stderr, "%s:%d: unhandled case. Contact author.\n", __FILE__, __LINE__);
813         assert(0);
814   }
815   *sym = lsym;
816   *ilist = lilist;
817 }
818  
819
820 /*-----------------------------------------------------------------*/
821 /* printIvalStruct - generates initial value for structures        */
822 /*-----------------------------------------------------------------*/
823 void pic16_printIvalStruct (symbol * sym, sym_link * type,
824                  initList * ilist, char ptype, void *p)
825 {
826   symbol *sflds;
827   initList *iloop = NULL;
828
829
830 #if DEBUG_PRINTIVAL
831   fprintf(stderr, "%s\n",__FUNCTION__);
832 #endif
833
834   sflds = SPEC_STRUCT (type)->fields;
835
836   if (ilist) {
837     if (ilist->type != INIT_DEEP) {
838       werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
839       return;
840     }
841
842     iloop = ilist->init.deep;
843   }
844
845   for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
846 //    fprintf(stderr, "%s:%d sflds: %p\tiloop = %p\n", __FILE__, __LINE__, sflds, iloop);
847     if (IS_BITFIELD(sflds->type)) {
848       pic16_printIvalBitFields(&sflds, &iloop, ptype, p);
849     } else {
850       pic16_printIval (sym, sflds->type, iloop, ptype, p);
851     }
852   }
853   if (iloop) {
854     werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
855   }
856   return;
857 }
858
859 /*--------------------------------------------------------------------------*/
860 /* pic16_printIvalCharPtr - generates initial values for character pointers */
861 /*--------------------------------------------------------------------------*/
862 int pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
863 {
864   int size = 0;
865
866   /* PENDING: this is _very_ mcs51 specific, including a magic
867      number...
868      It's also endin specific.
869
870      VR - Attempting to port this function to pic16 port - 8-Jun-2004
871    */
872
873
874 #if DEBUG_PRINTIVAL
875   fprintf(stderr, "%s\n",__FUNCTION__);
876 #endif
877
878   size = getSize (type);
879
880   if (val->name && strlen (val->name))
881     {
882       if (size == 1)            /* This appears to be Z80 specific?? */
883         {
884           pic16_emitDS(val->name, ptype, p);
885         }
886       else if (size == 2)
887         {
888           pic16_printPointerType (val->name, ptype, p);
889         }
890       else if (size == 3)
891         {
892           int type;
893           if (IS_PTR (val->type)) {
894             type = DCL_TYPE (val->type);
895           } else {
896             type = PTR_TYPE (SPEC_OCLS (val->etype));
897           }
898           if (val->sym && val->sym->isstrlit) {
899             // this is a literal string
900             type=CPOINTER;
901           }
902           pic16_printGPointerType(val->name, type, ptype, p);
903         }
904       else
905         {
906           fprintf (stderr, "*** internal error: unknown size in "
907                    "printIvalCharPtr.\n");
908           assert(0);
909         }
910     }
911   else
912     {
913       // these are literals assigned to pointers
914       switch (size)
915         {
916         case 1:
917           pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
918           break;
919         case 2:
920           pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
921           pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
922           break;
923         case 3:
924           pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
925           pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
926           pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
927           break;
928
929         default:
930           assert (0);
931         }
932     }
933
934   if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
935         if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
936         else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
937   }
938
939   return 1;
940 }
941
942 /*-----------------------------------------------------------------------*/
943 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
944 /*-----------------------------------------------------------------------*/
945 void pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
946 {
947   value *val;
948   int dLvl = 0;
949
950
951 #if DEBUG_PRINTIVAL
952   fprintf(stderr, "%s\n",__FUNCTION__);
953 #endif
954
955   if (ilist)
956     val = list2val (ilist);
957   else
958     val = valCastLiteral(type, 0.0);
959
960   if (!val) {
961     // an error has been thrown already
962     val=constVal("0");
963   }
964
965   if (IS_LITERAL(val->etype)) {
966     if (compareType(type, val->etype) == 0) {
967       werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
968       printFromToType (val->type, type);
969     }
970     pic16_printIvalCharPtr (NULL, type, val, ptype, p);
971     return;
972   }
973
974   /* check the types   */
975   if ((dLvl = compareType (val->type, type->next)) <= 0)
976     {
977       pic16_emitDB(0x00, ptype, p);
978       return;
979     }
980
981   /* now generate the name */
982   if (!val->sym) {
983       pic16_printGPointerType (val->name, DCL_TYPE(val->type), ptype, p);
984   } else {
985       pic16_printGPointerType (val->sym->rname, DCL_TYPE(val->type), ptype, p);
986
987       if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
988         
989         if(!checkSym(publics, val->sym))
990           if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
991             /* this has not been declared as extern
992              * so declare it as a 'late extern' just after the symbol */
993             fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
994             fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
995             fprintf((FILE *)p, ";\tcontinue variable declaration\n");
996           }
997       }
998   }
999
1000   return;
1001 }
1002
1003
1004 /*-----------------------------------------------------------------*/
1005 /* pic16_printIvalPtr - generates initial value for pointers       */
1006 /*-----------------------------------------------------------------*/
1007 void pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1008 {
1009   value *val;
1010   int size;
1011
1012 #if 0
1013         fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1014                 sym->rname, getSize(sym->type));
1015 #endif
1016
1017   /* if deep then   */
1018   if (ilist && (ilist->type == INIT_DEEP))
1019     ilist = ilist->init.deep;
1020
1021   /* function pointer     */
1022   if (IS_FUNC (type->next))
1023     {
1024       pic16_printIvalFuncPtr (type, ilist, ptype, p);
1025       return;
1026     }
1027
1028   if (!(val = pic16_initPointer (ilist, type)))
1029     return;
1030
1031   /* if character pointer */
1032   if (IS_CHAR (type->next))
1033     if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1034       return;
1035
1036   /* check the type      */
1037   if (compareType (type, val->type) == 0) {
1038     werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1039     printFromToType (val->type, type);
1040   }
1041
1042   /* if val is literal */
1043   if (IS_LITERAL (val->etype))
1044     {
1045       switch (getSize (type))
1046         {
1047         case 1:
1048             pic16_emitDB((unsigned int)floatFromVal(val) & 0xff, ptype, p);
1049             break;
1050         case 2:
1051             pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1052             pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1053             break;
1054         case 3:
1055             pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1056             pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1057             pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
1058             break;
1059         default:
1060                 fprintf(stderr, "%s:%d size = %d\n", __FILE__, __LINE__, getSize(type));
1061                 assert(0);
1062         }
1063       return;
1064     }
1065
1066
1067   size = getSize (type);
1068
1069   if (size == 1)                /* Z80 specific?? */
1070     {
1071       pic16_emitDS(val->name, ptype, p);
1072     }
1073   else if (size == 2)
1074     {
1075         pic16_printPointerType (val->name, ptype, p);
1076     }
1077   else if (size == 3)
1078     {
1079       pic16_printGPointerType (val->name, (IS_PTR(type)?DCL_TYPE(type):PTR_TYPE(SPEC_OCLS(sym->etype))),
1080                           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 0
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               strcpy(abSym->name, 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 for %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         if(options.debug) {
1444                 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]\"\n",
1445                                 SDCC_VERSION_STR, getBuildNumber() );
1446         }
1447 }
1448
1449 /*-----------------------------------------------------------------*/
1450 /* printPublics - generates global declarations for publics        */
1451 /*-----------------------------------------------------------------*/
1452 static void
1453 pic16printPublics (FILE *afile)
1454 {
1455   symbol *sym;
1456
1457         fprintf (afile, "\n%s", iComments2);
1458         fprintf (afile, "; public variables in this module\n");
1459         fprintf (afile, "%s", iComments2);
1460
1461         for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1462                 fprintf(afile, "\tglobal %s\n", sym->rname);
1463 }
1464
1465 /*-----------------------------------------------------------------*/
1466 /* printExterns - generates extern declarations for externs        */
1467 /*-----------------------------------------------------------------*/
1468 static void
1469 pic16_printExterns(FILE *afile)
1470 {
1471   symbol *sym;
1472
1473         /* print nothing if no externs to declare */
1474         if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1475                 return;
1476
1477         fprintf(afile, "\n%s", iComments2);
1478         fprintf(afile, "; extern variables in this module\n");
1479         fprintf(afile, "%s", iComments2);
1480         
1481         for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1482                 fprintf(afile, "\textern %s\n", sym->rname);
1483
1484         for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1485                 fprintf(afile, "\textern _%s\n", sym->name);
1486 }
1487
1488 /*-----------------------------------------------------------------*/
1489 /* emitOverlay - will emit code for the overlay stuff              */
1490 /*-----------------------------------------------------------------*/
1491 static void
1492 pic16emitOverlay (FILE * afile)
1493 {
1494   set *ovrset;
1495
1496   if (!elementsInSet (ovrSetSets))
1497     fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
1498
1499   /* for each of the sets in the overlay segment do */
1500   for (ovrset = setFirstItem (ovrSetSets); ovrset;
1501        ovrset = setNextItem (ovrSetSets))
1502     {
1503
1504       symbol *sym;
1505
1506       if (elementsInSet (ovrset))
1507         {
1508           /* this dummy area is used to fool the assembler
1509              otherwise the assembler will append each of these
1510              declarations into one chunk and will not overlay
1511              sad but true */
1512           fprintf (afile, ";\t.area _DUMMY\n");
1513           /* output the area informtion */
1514           fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);    /* MOF */
1515         }
1516
1517       for (sym = setFirstItem (ovrset); sym;
1518            sym = setNextItem (ovrset))
1519         {
1520
1521           /* if extern then do nothing */
1522           if (IS_EXTERN (sym->etype))
1523             continue;
1524
1525           /* if allocation required check is needed
1526              then check if the symbol really requires
1527              allocation only for local variables */
1528           if (!IS_AGGREGATE (sym->type) &&
1529               !(sym->_isparm && !IS_REGPARM (sym->etype))
1530               && !sym->allocreq && sym->level)
1531             continue;
1532
1533           /* if global variable & not static or extern
1534              and addPublics allowed then add it to the public set */
1535           if ((sym->_isparm && !IS_REGPARM (sym->etype))
1536               && !IS_STATIC (sym->etype)) {
1537 //            fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1538               checkAddSym(&publics, sym);
1539 //          addSetHead (&publics, sym);
1540           }
1541
1542           /* if extern then do nothing or is a function
1543              then do nothing */
1544           if (IS_FUNC (sym->type))
1545             continue;
1546
1547 #if 0
1548           /* print extra debug info if required */
1549           if (options.debug || sym->level == 0)
1550             {
1551
1552               cdbSymbol (sym, cdbFile, FALSE, FALSE);
1553
1554               if (!sym->level)
1555                 {               /* global */
1556                   if (IS_STATIC (sym->etype))
1557                     fprintf (afile, "F%s_", moduleName);        /* scope is file */
1558                   else
1559                     fprintf (afile, "G_");      /* scope is global */
1560                 }
1561               else
1562                 /* symbol is local */
1563                 fprintf (afile, "L%s_",
1564                          (sym->localof ? sym->localof->name : "-null-"));
1565               fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
1566             }
1567 #endif
1568
1569           /* if is has an absolute address then generate
1570              an equate for this no need to allocate space */
1571           if (SPEC_ABSA (sym->etype))
1572             {
1573
1574               if (options.debug || sym->level == 0)
1575                 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1576
1577               fprintf (afile, "%s\t=\t0x%04x\n",
1578                        sym->rname,
1579                        SPEC_ADDR (sym->etype));
1580             }
1581           else
1582             {
1583               if (options.debug || sym->level == 0)
1584                 fprintf (afile, "==.\n");
1585
1586               /* allocate space */
1587               fprintf (afile, "%s:\n", sym->rname);
1588               fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1589             }
1590
1591         }
1592     }
1593 }
1594
1595 void emitStatistics(FILE *asmFile)
1596 {
1597   statistics.isize = pic16_countInstructions();
1598         
1599   fprintf (asmFile, "\n\n; Statistics:\n");
1600   fprintf (asmFile, "; code size:\t%ld (0x%lx) bytes\n;\t\t%ld (0x%lx) words\n",
1601     statistics.isize, statistics.isize,
1602     statistics.isize>>1, statistics.isize>>1);
1603   fprintf (asmFile, "; udata size:\t%ld (0x%lx) bytes\n", 
1604     statistics.udsize, statistics.udsize);
1605   fprintf (asmFile, "; access size:\t%ld (0x%lx) bytes\n",
1606     statistics.intsize, statistics.intsize);
1607
1608   fprintf (asmFile, "\n\n");
1609 }
1610
1611
1612
1613 /*-----------------------------------------------------------------*/
1614 /* glue - the final glue that hold the whole thing together        */
1615 /*-----------------------------------------------------------------*/
1616 void
1617 pic16glue ()
1618 {
1619   FILE *vFile;
1620   FILE *asmFile;
1621   FILE *ovrFile = tempfile();
1622
1623     mainf = newSymbol ("main", 0);
1624     mainf->block = 0;
1625
1626     mainf = findSymWithLevel(SymbolTab, mainf);
1627
1628     addSetHead(&tmpfileSet,ovrFile);
1629     pic16_pCodeInitRegisters();
1630
1631     if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1632       pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1633
1634         pic16_addpBlock(pb);
1635
1636         /* entry point @ start of CSEG */
1637         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1638
1639         if(initsfpnt) {
1640           pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1641                   pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1642           pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1643                   pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1644         }
1645
1646         /* put in the call to main */
1647         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1648
1649         if (options.mainreturn) {
1650           pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1651           pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1652         } else {
1653           pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1654           pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1655         }
1656     }
1657
1658     /* At this point we've got all the code in the form of pCode structures */
1659     /* Now it needs to be rearranged into the order it should be placed in the */
1660     /* code space */
1661
1662     pic16_movepBlock2Head('P');              // Last
1663     pic16_movepBlock2Head(code->dbName);
1664     pic16_movepBlock2Head('X');
1665     pic16_movepBlock2Head(statsg->dbName);   // First
1666
1667     /* print the global struct definitions */
1668
1669     vFile = tempfile();
1670     /* PENDING: this isnt the best place but it will do */
1671     if (port->general.glue_up_main) {
1672       /* create the interrupt vector table */
1673       pic16createInterruptVect (vFile);
1674     }
1675
1676     addSetHead(&tmpfileSet,vFile);
1677     
1678     /* emit code for the all the variables declared */
1679     pic16emitMaps ();
1680
1681     /* do the overlay segments */
1682     pic16emitOverlay(ovrFile);
1683     pic16_AnalyzepCode('*');
1684
1685 #if 1
1686     if(pic16_options.dumpcalltree) {
1687       FILE *cFile;
1688         
1689         sprintf(buffer, dstFileName);
1690         strcat(buffer, ".calltree");
1691         cFile = fopen(buffer, "w");
1692         pic16_printCallTree( cFile );
1693         fclose(cFile);
1694     }
1695 #endif
1696
1697     pic16_InlinepCode();
1698     pic16_AnalyzepCode('*');
1699
1700
1701     if(pic16_debug_verbose)
1702       pic16_pcode_test();
1703
1704     /* now put it all together into the assembler file */
1705     /* create the assembler file name */
1706     if((noAssemble || options.c1mode)  && fullDstFileName) {
1707       sprintf (buffer, fullDstFileName);
1708     } else {
1709       sprintf (buffer, dstFileName);
1710       strcat (buffer, ".asm");
1711     }
1712
1713     if(!(asmFile = fopen (buffer, "w"))) {
1714       werror (E_FILE_OPEN_ERR, buffer);
1715       exit (1);
1716     }
1717     
1718     /* initial comments */
1719     pic16initialComments (asmFile);
1720
1721     /* print module name */
1722     if(options.debug)
1723       fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1724
1725     /* Let the port generate any global directives, etc. */
1726     if(port->genAssemblerPreamble) {
1727       port->genAssemblerPreamble(asmFile);
1728     }
1729         
1730     /* Put all variables into a cblock */
1731     pic16_AnalyzeBanking();
1732
1733     if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1734       pic16_OptimizeLocalRegs();
1735     }
1736
1737     /* print the extern variables to this module */
1738     pic16_printExterns(asmFile);
1739         
1740     /* print the global variables in this module */
1741     pic16printPublics (asmFile);
1742
1743     pic16_writeUsedRegs(asmFile);
1744
1745 #if 0
1746     /* no xdata in pic */
1747     /* if external stack then reserve space of it */
1748     if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1749       fprintf (asmFile, "%s", iComments2);
1750       fprintf (asmFile, "; external stack \n");
1751       fprintf (asmFile, "%s", iComments2);
1752       fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1753       fprintf (asmFile,";\t.ds 256\n");
1754     }
1755 #endif
1756
1757 #if 0   
1758     /* no xdata in pic */
1759     /* copy xtern ram data */
1760     fprintf (asmFile, "%s", iComments2);
1761     fprintf (asmFile, "; external ram data\n");
1762     fprintf (asmFile, "%s", iComments2);
1763     copyFile (asmFile, xdata->oFile);
1764 #endif
1765
1766 #if 0
1767     /* copy the bit segment */
1768     fprintf (asmFile, "%s", iComments2);
1769     fprintf (asmFile, "; bit data\n");
1770     fprintf (asmFile, "%s", iComments2);
1771     copyFile (asmFile, bit->oFile);
1772 #endif
1773
1774     /* copy the interrupt vector table */
1775     if(mainf && IFFUNC_HASBODY(mainf->type)) {
1776       fprintf (asmFile, "\n%s", iComments2);
1777       fprintf (asmFile, "; interrupt vector \n");
1778       fprintf (asmFile, "%s", iComments2);
1779       copyFile (asmFile, vFile);
1780     }
1781     
1782     /* copy global & static initialisations */
1783     fprintf (asmFile, "\n%s", iComments2);
1784     fprintf (asmFile, "; global & static initialisations\n");
1785     fprintf (asmFile, "%s", iComments2);
1786     
1787     if(pic16_debug_verbose)
1788       fprintf(asmFile, "; A code from now on!\n");
1789     
1790     pic16_copypCode(asmFile, 'A');
1791
1792     if(pic16_options.no_crt) {
1793       if(mainf && IFFUNC_HASBODY(mainf->type)) {
1794         fprintf(asmFile, "\tcode\n");
1795         fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1796       }
1797     }
1798
1799 //    copyFile (stderr, code->oFile);
1800
1801     fprintf(asmFile, "; I code from now on!\n");
1802     pic16_copypCode(asmFile, 'I');
1803
1804     if(pic16_debug_verbose)
1805       fprintf(asmFile, "; dbName from now on!\n");
1806     
1807     pic16_copypCode(asmFile, statsg->dbName);
1808
1809     if(pic16_options.no_crt) {
1810       if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1811         fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1812       }
1813     }
1814         
1815     if(pic16_debug_verbose)
1816       fprintf(asmFile, "; X code from now on!\n");
1817
1818     pic16_copypCode(asmFile, 'X');
1819
1820     if(pic16_debug_verbose)
1821       fprintf(asmFile, "; M code from now on!\n");
1822
1823     pic16_copypCode(asmFile, 'M');
1824
1825     pic16_copypCode(asmFile, code->dbName);
1826     
1827     pic16_copypCode(asmFile, 'P');
1828
1829     emitStatistics(asmFile);
1830
1831     fprintf (asmFile,"\tend\n");
1832     fclose (asmFile);
1833     
1834     rm_tmpfiles();
1835 }