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