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