76a883c608b21a733621c81a96d06ba5d77c3710
[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 "dbuf_string.h"
34 #include <string.h>
35
36
37 extern symbol *interrupts[256];
38 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p);
39 extern int noAlloc;
40 extern set *publics;
41 extern set *externs;
42 extern unsigned maxInterrupts;
43 extern symbol *mainf;
44 extern char *VersionString;
45 extern struct dbuf_s *codeOutBuf;
46 extern char *iComments1;
47 extern char *iComments2;
48
49 extern int initsfpnt;
50 extern unsigned long pFile_isize;
51
52 extern unsigned long pic16_countInstructions();
53 set *pic16_localFunctions = NULL;
54 set *rel_idataSymSet=NULL;
55 set *fix_idataSymSet=NULL;
56
57 extern DEFSETFUNC (closeTmpFiles);
58 extern DEFSETFUNC (rmTmpFiles);
59
60 extern void pic16_AnalyzeBanking (void);
61 extern void pic16_OptimizeJumps ();
62 extern void pic16_OptimizeBanksel ();
63 extern void pic16_InlinepCode(void);
64 extern void pic16_writeUsedRegs(FILE *);
65
66 extern void initialComments (FILE * afile);
67 extern void printPublics (FILE * afile);
68
69 void  pic16_pCodeInitRegisters(void);
70 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
71 extern void pic16_pCodeConstString(char *name, char *value);
72
73
74 /*-----------------------------------------------------------------*/
75 /* aopLiteral - string from a literal value                        */
76 /*-----------------------------------------------------------------*/
77 unsigned int pic16aopLiteral (value *val, int offset)
78 {
79   union {
80     float f;
81     unsigned char c[4];
82   } fl;
83
84   /* if it is a float then it gets tricky */
85   /* otherwise it is fairly simple */
86   if (!(IS_FLOAT(val->type) || IS_FIXED(val->type))) {
87     unsigned long v = ulFromVal (val);
88
89     return ( (v >> (offset * 8)) & 0xff);
90   }
91
92   if(IS_FIXED16X16(val->type)) {
93     unsigned long v = (unsigned long)fixed16x16FromDouble( floatFromVal( val ) );
94
95     return ( (v >> (offset * 8)) & 0xff);
96   }
97
98   /* it is type float */
99   fl.f = (float) floatFromVal(val);
100 #ifdef WORDS_BIGENDIAN
101   return fl.c[3-offset];
102 #else
103   return fl.c[offset];
104 #endif
105
106 }
107
108 iCode *tic;
109 symbol *nsym;
110 char tbuffer[512], *tbuf=tbuffer;;
111
112
113 /*-----------------------------------------------------------------*/
114 /* emitRegularMap - emit code for maps with no special cases       */
115 /*-----------------------------------------------------------------*/
116 static void
117 pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
118 {
119   symbol *sym;
120 //  int i, size, bitvars = 0;;
121
122 //      fprintf(stderr, "%s:%d map name= %s\n", __FUNCTION__, __LINE__, map->sname);
123
124         if(addPublics)
125                 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
126                 /* print the area name */
127
128         for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) {
129
130 #if 0
131                 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\textern: %d\tstatic: %d\taggregate: %d\tregister: 0x%x\tfunction: %d\n",
132                         __FUNCTION__,
133                         map->sname, sym->name, sym->used, IS_EXTERN(sym->etype), IS_STATIC(sym->etype),
134                         IS_AGGREGATE(sym->type), (SPEC_SCLS(sym->etype) == S_REGISTER), IS_FUNC(sym->type));
135                 printTypeChain( sym->type, stderr );
136                 fprintf(stderr, "\n");
137 #endif
138
139                 /* if extern then add to externs */
140                 if (IS_EXTERN (sym->etype)) {
141                         /* reduce overhead while linking by not declaring
142                          * extern unused external functions (usually declared
143                          * in header files) */
144                         if(IS_FUNC(sym->type) && !sym->used)continue;
145
146                         /* make sure symbol is not in publics section */
147                         if(!checkSym(publics, sym))
148                                 checkAddSym(&externs, sym);
149                         continue;
150                 }
151
152                 /* if allocation required check is needed
153                  * then check if the symbol really requires
154                  * allocation only for local variables */
155                  if (arFlag && !IS_AGGREGATE (sym->type) &&
156                         !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
157                         !sym->allocreq && sym->level) {
158
159 //                      fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
160
161                         continue;
162                 }
163
164                 /* if global variable & not static or extern
165                  * and addPublics allowed then add it to the public set */
166                 if ((sym->used) && (sym->level == 0 ||
167                         (sym->_isparm && !IS_REGPARM (sym->etype))) &&
168                         addPublics &&
169                         !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
170
171                         checkAddSym(&publics, sym);
172                 } else
173                         /* new version */
174                         if(IS_STATIC(sym->etype)
175                                 && !sym->ival) /* && !sym->level*/ {
176                           regs *reg;
177                           sectSym *ssym;
178                           int found=0;
179
180 //                            debugf("adding symbol %s\n", sym->name);
181 #define SET_IMPLICIT    1
182
183 #if SET_IMPLICIT
184                                 if(IS_STRUCT(sym->type))
185                                         sym->implicit = 1;
186 #endif
187
188                                 reg = pic16_allocDirReg( operandFromSymbol( sym ));
189
190                                 if(reg) {
191                                   for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
192                                     if(!strcmp(ssym->name, reg->name))found=1;
193                                   }
194
195                                   if(!found)
196                                     checkAddReg(&pic16_rel_udata, reg);
197 #if 0
198                                   else
199                                     debugf("Did find %s in pic16_rel_udata already. Check!\n", reg->name);
200 //                                  checkAddSym(&publics, sym);
201 #endif
202
203                                 }
204                         }
205
206                 /* if extern then do nothing or is a function
207                  * then do nothing */
208                 if (IS_FUNC (sym->type) && !IS_STATIC(sym->etype)) {
209                         if(SPEC_OCLS(sym->etype) == code) {
210 //                              fprintf(stderr, "%s:%d: symbol added: %s\n", __FILE__, __LINE__, sym->rname);
211                                 checkAddSym(&publics, sym);
212                         }
213                         continue;
214                 }
215
216                 /* if is has an absolute address then generate
217                 an equate for this no need to allocate space */
218                 if (SPEC_ABSA (sym->etype)) {
219 //                              fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
220 //                                      sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
221
222                         dbuf_printf (&map->oBuf, "%s\tEQU\t0x%04x\n",
223                                 sym->rname,
224                                 SPEC_ADDR (sym->etype));
225
226                         /* emit only if it is global */
227                         if(sym->level == 0) {
228                           regs *reg;
229
230                                 reg = pic16_dirregWithName( sym->name );
231                                 if(!reg) {
232                                         /* here */
233 //                                      fprintf(stderr, "%s:%d: implicit add of symbol = %s\n",
234 //                                                      __FUNCTION__, __LINE__, sym->name);
235
236                                         /* if IS_STRUCT is omitted the following
237                                          * fixes structures but break char/int etc */
238 #if SET_IMPLICIT
239                                         if(IS_STRUCT(sym->type))
240                                                 sym->implicit = 1;              // mark as implicit
241 #endif
242                                         if(!sym->ival) {
243                                                 reg = pic16_allocDirReg( operandFromSymbol(sym) );
244                                                 if(reg) {
245                                                         if(checkAddReg(&pic16_fix_udata, reg)) {
246                                                                 /* and add to globals list if not exist */
247                                                                 addSet(&publics, sym);
248                                                         }
249                                                 }
250                                         } else
251                                                 addSet(&publics, sym);
252                                 }
253                         }
254                 } else {
255                         if(!sym->used && (sym->level == 0)) {
256                           regs *reg;
257
258                                 /* symbol not used, just declared probably, but its in
259                                  * level 0, so we must declare it fine as global */
260
261 //                              fprintf(stderr, "EXTRA symbol declaration sym= %s\n", sym->name);
262
263 #if SET_IMPLICIT
264                                 if(IS_STRUCT(sym->type))
265                                         sym->implicit = 1;              // mark as implicit
266 #endif
267                                 if(!sym->ival) {
268                                         if(IS_AGGREGATE(sym->type)) {
269                                                 reg=pic16_allocRegByName(sym->rname, getSize( sym->type ), NULL);
270                                         } else {
271                                                 reg = pic16_allocDirReg( operandFromSymbol( sym ) );
272                                         }
273
274                                         {
275                                           sectSym *ssym;
276                                           int found=0;
277
278 #if 0
279                                                 fprintf(stderr, "%s:%d sym->rname: %s reg: %p reg->name: %s\n", __FILE__, __LINE__,
280                                                         sym->rname, reg, (reg?reg->name:"<<NULL>>"));
281 #endif
282
283                                                 if(reg) {
284                                                   for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
285                                                     if(!strcmp(ssym->name, reg->name))found=1;
286                                                   }
287
288                                                   if(!found)
289                                                     if(checkAddReg(&pic16_rel_udata, reg)) {
290                                                       addSetHead(&publics, sym);
291                                                     }
292                                                 }
293                                         }
294
295
296
297                                 } else
298
299                                         addSetHead(&publics, sym);
300                         }
301
302 #if 0
303                         /* allocate space */
304                         /* If this is a bit variable, then allocate storage after 8 bits have been declared */
305                         /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
306                         /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
307                         if (IS_BITVAR (sym->etype)) {
308                                 bitvars++;
309                         } else {
310                                 dbuf_printf (map->oBuf, "\t%s\n", sym->rname);
311                                 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
312                                         for (i = 1; i < size; i++)
313                                                 dbuf_printf (map->oBuf, "\t%s_%d\n", sym->rname, i);
314                                 }
315                         }
316                         dbuf_printf (map->oBuf, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
317 #endif
318                 }
319
320                 /* FIXME -- VR Fix the following, so that syms to be placed
321                  * in the idata section and let linker decide about their fate */
322
323                 /* if it has an initial value then do it only if
324                         it is a global variable */
325
326                 if (sym->ival
327                   && ((sym->level == 0)
328                       || IS_STATIC(sym->etype)) ) {
329                   ast *ival = NULL;
330
331 #if 0
332                         if(SPEC_OCLS(sym->etype)==data) {
333                                 fprintf(stderr, "%s: sym %s placed in data segment\n", map->sname, sym->name);
334                         }
335
336                         if(SPEC_OCLS(sym->etype)==code) {
337                                 fprintf(stderr, "%s: sym %s placed in code segment\n", map->sname, sym->name);
338                         }
339 #endif
340
341 #if 0
342                         fprintf(stderr, "'%s': sym '%s' has initial value SPEC_ABSA: %d, IS_AGGREGATE: %d\n",
343                                 map->sname, sym->name, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type));
344 #endif
345
346                         if (IS_AGGREGATE (sym->type)) {
347                                 if(SPEC_ABSA(sym->etype))
348                                         addSet(&fix_idataSymSet, copySymbol(sym));
349                                 else
350                                         addSet(&rel_idataSymSet, copySymbol(sym));
351 //                              ival = initAggregates (sym, sym->ival, NULL);
352                         } else {
353                                 if(SPEC_ABSA(sym->etype))
354                                         addSet(&fix_idataSymSet, copySymbol(sym));
355                                 else
356                                         addSet(&rel_idataSymSet, copySymbol(sym));
357
358 //                                      ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
359 //                                              decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
360                         }
361
362                         if(ival) {
363                                 setAstFileLine (ival, sym->fileDef, sym->lineDef);
364                                 codeOutBuf = &statsg->oBuf;
365                                 GcurMemmap = statsg;
366                                 eBBlockFromiCode (iCodeFromAst (ival));
367                                 sym->ival = NULL;
368                         }
369                 }
370         }
371 }
372
373
374 /*-----------------------------------------------------------------*/
375 /* pic16_initPointer - pointer initialization code massaging       */
376 /*-----------------------------------------------------------------*/
377 value *pic16_initPointer (initList * ilist, sym_link *toType)
378 {
379   value *val;
380   ast *expr;
381
382   if (!ilist) {
383       return valCastLiteral(toType, 0.0);
384   }
385
386   expr = decorateType(resolveSymbols( list2expr (ilist) ), FALSE);
387 //  expr = list2expr( ilist );
388
389   if (!expr)
390     goto wrong;
391
392   /* try it the old way first */
393   if (expr->etype && (val = constExprValue (expr, FALSE)))
394     return val;
395
396   /* ( ptr + constant ) */
397   if (IS_AST_OP (expr) &&
398       (expr->opval.op == '+' || expr->opval.op == '-') &&
399       IS_AST_SYM_VALUE (expr->left) &&
400       (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
401       compareType(toType, expr->left->ftype) &&
402       IS_AST_LIT_VALUE (expr->right)) {
403     return valForCastAggr (expr->left, expr->left->ftype,
404                            expr->right,
405                            expr->opval.op);
406   }
407
408   /* (char *)&a */
409   if (IS_AST_OP(expr) && expr->opval.op==CAST &&
410       IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
411     if (compareType(toType, expr->left->ftype)!=1) {
412       werror (W_INIT_WRONG);
413       printFromToType(expr->left->ftype, toType);
414     }
415     // skip the cast ???
416     expr=expr->right;
417   }
418
419   /* no then we have to do these cludgy checks */
420   /* pointers can be initialized with address of
421      a variable or address of an array element */
422   if (IS_AST_OP (expr) && expr->opval.op == '&') {
423     /* address of symbol */
424     if (IS_AST_SYM_VALUE (expr->left) && expr->left->etype) {
425       val = AST_VALUE (expr->left);
426       val->type = newLink (DECLARATOR);
427       if(SPEC_SCLS (expr->left->etype) == S_CODE) {
428         DCL_TYPE (val->type) = CPOINTER;
429         DCL_PTR_CONST (val->type) = port->mem.code_ro;
430       }
431       else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
432         DCL_TYPE (val->type) = FPOINTER;
433       else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
434         DCL_TYPE (val->type) = PPOINTER;
435       else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
436         DCL_TYPE (val->type) = IPOINTER;
437       else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
438         DCL_TYPE (val->type) = EEPPOINTER;
439       else
440         DCL_TYPE (val->type) = POINTER;
441
442       val->type->next = expr->left->ftype;
443       val->etype = getSpec (val->type);
444       return val;
445     }
446
447     /* if address of indexed array */
448     if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
449       return valForArray (expr->left);
450
451     /* if address of structure element then
452        case 1. a.b ; */
453     if (IS_AST_OP (expr->left) &&
454         expr->left->opval.op == '.') {
455       return valForStructElem (expr->left->left,
456                                expr->left->right);
457     }
458
459     /* case 2. (&a)->b ;
460        (&some_struct)->element */
461     if (IS_AST_OP (expr->left) &&
462         expr->left->opval.op == PTR_OP &&
463         IS_ADDRESS_OF_OP (expr->left->left)) {
464       return valForStructElem (expr->left->left->left,
465                                expr->left->right);
466     }
467   }
468   /* case 3. (((char *) &a) +/- constant) */
469   if (IS_AST_OP (expr) &&
470       (expr->opval.op == '+' || expr->opval.op == '-') &&
471       IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
472       IS_AST_OP (expr->left->right) &&
473       expr->left->right->opval.op == '&' &&
474       IS_AST_LIT_VALUE (expr->right)) {
475
476     return valForCastAggr (expr->left->right->left,
477                            expr->left->left->opval.lnk,
478                            expr->right, expr->opval.op);
479
480   }
481   /* case 4. (char *)(array type) */
482   if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
483       IS_ARRAY(expr->right->ftype)) {
484
485     val = copyValue (AST_VALUE (expr->right));
486     val->type = newLink (DECLARATOR);
487     if (SPEC_SCLS (expr->right->etype) == S_CODE) {
488       DCL_TYPE (val->type) = CPOINTER;
489       DCL_PTR_CONST (val->type) = port->mem.code_ro;
490     }
491     else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
492       DCL_TYPE (val->type) = FPOINTER;
493     else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
494       DCL_TYPE (val->type) = PPOINTER;
495     else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
496       DCL_TYPE (val->type) = IPOINTER;
497     else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
498       DCL_TYPE (val->type) = EEPPOINTER;
499     else
500       DCL_TYPE (val->type) = POINTER;
501     val->type->next = expr->right->ftype->next;
502     val->etype = getSpec (val->type);
503     return val;
504   }
505
506  wrong:
507   if (expr)
508     werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES);
509   else
510     werror (E_INCOMPAT_PTYPES);
511   return NULL;
512
513 }
514
515
516 /*-----------------------------------------------------------------*/
517 /* printPointerType - generates ival for pointer type              */
518 /*-----------------------------------------------------------------*/
519 void _pic16_printPointerType (const char *name, char ptype, void *p)
520 {
521   char buf[256];
522
523   sprintf (buf, "LOW(%s)", name);
524   pic16_emitDS (buf, ptype, p);
525   sprintf (buf, "HIGH(%s)", name);
526   pic16_emitDS (buf, ptype, p);
527 }
528
529 /*-----------------------------------------------------------------*/
530 /* printPointerType - generates ival for pointer type              */
531 /*-----------------------------------------------------------------*/
532 void pic16_printPointerType (const char *name, char ptype, void *p)
533 {
534   _pic16_printPointerType (name, ptype, p);
535   //pic16_flushDB(ptype, p); /* breaks char* const arr[] = {&c, &c, &c}; */
536 }
537
538 /*-----------------------------------------------------------------*/
539 /* printGPointerType - generates ival for generic pointer type     */
540 /*-----------------------------------------------------------------*/
541 void pic16_printGPointerType (const char *iname, const unsigned int itype,
542   char ptype, void *p)
543 {
544   char buf[256];
545
546   _pic16_printPointerType (iname, ptype, p);
547
548   switch (itype)
549     {
550     case CPOINTER:
551     case FUNCTION:
552       sprintf (buf, "UPPER(%s)", iname);
553       pic16_emitDS (buf, ptype, p);
554       break;
555
556     case GPOINTER:
557     case POINTER:
558       sprintf (buf, "0x80");
559       pic16_emitDS (buf, ptype, p);
560       break;
561
562     /*
563      * FPOINTER and IPOINTER are not used in pic16 port
564       case FPOINTER:
565       case IPOINTER:
566      */
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 = constCharVal (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 = ulFromVal (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 = ulFromVal (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 = constCharVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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               dbuf_printf (&code->oBuf, "%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               dbuf_printf (&code->oBuf, "%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               dbuf_printf (&code->oBuf, "%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   pic16emitStaticSeg (c_abs);
1472 }
1473
1474 /*-----------------------------------------------------------------*/
1475 /* createInterruptVect - creates the interrupt vector              */
1476 /*-----------------------------------------------------------------*/
1477 static void
1478 pic16createInterruptVect (struct dbuf_s * vBuf)
1479 {
1480         /* if the main is only a prototype ie. no body then do nothing */
1481 #if 0
1482         if (!IFFUNC_HASBODY(mainf->type)) {
1483                 /* if ! compile only then main function should be present */
1484                 if (!options.cc_only)
1485                         werror (E_NO_MAIN);
1486                 return;
1487         }
1488 #endif
1489 #if 0
1490         if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1491                 dbuf_printf (vBuf, ";\t.area\t%s\n", CODE_NAME);
1492                 dbuf_printf (vBuf, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1493
1494                 /* this is an overkill since WE are the port,
1495                  * and we know if we have a genIVT function! */
1496                 if(port->genIVT) {
1497                         port->genIVT(vFile, interrupts, maxInterrupts);
1498                 }
1499         }
1500 #endif
1501
1502 }
1503
1504
1505 /*-----------------------------------------------------------------*/
1506 /* pic16initialComments - puts in some initial comments            */
1507 /*-----------------------------------------------------------------*/
1508 static void
1509 pic16initialComments (FILE * afile)
1510 {
1511     initialComments (afile);
1512     fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1513     if (pic16_options.xinst) {
1514         fprintf (afile, "; * Extended Instruction Set\n");
1515     } // if
1516
1517     if (pic16_mplab_comp) {
1518         fprintf(afile, "; * MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1519     } // if
1520     fprintf (afile, iComments2);
1521
1522     if (options.debug) {
1523         fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]%s\"\n",
1524                 SDCC_VERSION_STR, getBuildNumber(), (!pic16_options.xinst?"":" {extended}") );
1525     } // if
1526 }
1527
1528 int
1529 pic16_stringInSet(const char *str, set **world, int autoAdd)
1530 {
1531   char *s;
1532
1533   if (!str) return 1;
1534   assert(world);
1535
1536   for (s = setFirstItem(*world); s; s = setNextItem(*world))
1537   {
1538     /* found in set */
1539     if (0 == strcmp(s, str)) return 1;
1540   }
1541
1542   /* not found */
1543   if (autoAdd) addSet(world, Safe_strdup(str));
1544   return 0;
1545 }
1546
1547 static int
1548 pic16_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1549 {
1550   static set *emitted = NULL;
1551
1552   if (!pic16_stringInSet(sym, &emitted, 1)) {
1553     /* sym was not in emittedSymbols */
1554     if (!checkLocals || !pic16_stringInSet(sym, &pic16_localFunctions, 0)) {
1555       /* sym is not a locally defined function---avoid bug #1443651 */
1556       fprintf( file, fmt, sym );
1557       return 0;
1558     }
1559   }
1560   return 1;
1561 }
1562
1563 /*-----------------------------------------------------------------*/
1564 /* printPublics - generates global declarations for publics        */
1565 /*-----------------------------------------------------------------*/
1566 static void
1567 pic16printPublics (FILE *afile)
1568 {
1569   symbol *sym;
1570
1571         fprintf (afile, "\n%s", iComments2);
1572         fprintf (afile, "; public variables in this module\n");
1573         fprintf (afile, "%s", iComments2);
1574
1575         for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1576           /* sanity check */
1577           if(!IS_STATIC(sym->etype))
1578                 pic16_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1579 }
1580
1581 /*-----------------------------------------------------------------*/
1582 /* printExterns - generates extern declarations for externs        */
1583 /*-----------------------------------------------------------------*/
1584 static void
1585 pic16_printExterns(FILE *afile)
1586 {
1587   symbol *sym;
1588
1589         /* print nothing if no externs to declare */
1590         if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1591                 return;
1592
1593         fprintf(afile, "\n%s", iComments2);
1594         fprintf(afile, "; extern variables in this module\n");
1595         fprintf(afile, "%s", iComments2);
1596
1597         for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1598                 pic16_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1599
1600         for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1601                 pic16_emitSymbolIfNew(afile, "\textern _%s\n", sym->name, 1);
1602 }
1603
1604 /*-----------------------------------------------------------------*/
1605 /* emitOverlay - will emit code for the overlay stuff              */
1606 /*-----------------------------------------------------------------*/
1607 static void
1608 pic16emitOverlay (struct dbuf_s *aBuf)
1609 {
1610   set *ovrset;
1611
1612   if (!elementsInSet (ovrSetSets))
1613     dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name);
1614
1615   /* for each of the sets in the overlay segment do */
1616   for (ovrset = setFirstItem (ovrSetSets); ovrset;
1617        ovrset = setNextItem (ovrSetSets))
1618     {
1619
1620       symbol *sym;
1621
1622       if (elementsInSet (ovrset))
1623         {
1624           /* this dummy area is used to fool the assembler
1625              otherwise the assembler will append each of these
1626              declarations into one chunk and will not overlay
1627              sad but true */
1628           dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1629           /* output the area informtion */
1630           dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1631         }
1632
1633       for (sym = setFirstItem (ovrset); sym;
1634            sym = setNextItem (ovrset))
1635         {
1636
1637           /* if extern then do nothing */
1638           if (IS_EXTERN (sym->etype))
1639             continue;
1640
1641           /* if allocation required check is needed
1642              then check if the symbol really requires
1643              allocation only for local variables */
1644           if (!IS_AGGREGATE (sym->type) &&
1645               !(sym->_isparm && !IS_REGPARM (sym->etype))
1646               && !sym->allocreq && sym->level)
1647             continue;
1648
1649           /* if global variable & not static or extern
1650              and addPublics allowed then add it to the public set */
1651           if ((sym->_isparm && !IS_REGPARM (sym->etype))
1652               && !IS_STATIC (sym->etype)) {
1653 //            fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1654               checkAddSym(&publics, sym);
1655 //          addSetHead (&publics, sym);
1656           }
1657
1658           /* if extern then do nothing or is a function
1659              then do nothing */
1660           if (IS_FUNC (sym->type))
1661             continue;
1662
1663
1664           /* if is has an absolute address then generate
1665              an equate for this no need to allocate space */
1666           if (SPEC_ABSA (sym->etype))
1667             {
1668
1669               if (options.debug || sym->level == 0)
1670                 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1671
1672               dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1673                        sym->rname,
1674                        SPEC_ADDR (sym->etype));
1675             }
1676           else
1677             {
1678               if (options.debug || sym->level == 0)
1679                 dbuf_printf (aBuf, "==.\n");
1680
1681               /* allocate space */
1682               dbuf_printf (aBuf, "%s:\n", sym->rname);
1683               dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1684             }
1685
1686         }
1687     }
1688 }
1689
1690 void emitStatistics(FILE *asmFile)
1691 {
1692   unsigned long isize, udsize, ramsize;
1693   statistics.isize = pic16_countInstructions();
1694   isize = (statistics.isize >= 0) ? statistics.isize : 0;
1695   udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1696   ramsize = pic16 ? pic16->RAMsize : 0x200;
1697   ramsize -= 256; /* ignore access bank and SFRs */
1698   if (ramsize == 0) ramsize = 64; /* prevent division by zero (below) */
1699
1700   fprintf (asmFile, "\n\n; Statistics:\n");
1701   fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n;           \t%5ld (0x%04lx) words\n",
1702     isize, isize, (isize*100.0)/(128UL << 10),
1703     isize>>1, isize>>1);
1704   fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n",
1705     udsize, udsize, (udsize*100.0) / (1.0 * ramsize));
1706   fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1707     statistics.intsize, statistics.intsize);
1708
1709   fprintf (asmFile, "\n\n");
1710 }
1711
1712
1713
1714 /*-----------------------------------------------------------------*/
1715 /* glue - the final glue that hold the whole thing together        */
1716 /*-----------------------------------------------------------------*/
1717 void
1718 pic16glue ()
1719 {
1720   FILE *asmFile;
1721   struct dbuf_s ovrBuf;
1722   struct dbuf_s vBuf;
1723
1724     dbuf_init(&ovrBuf, 4096);
1725     dbuf_init(&vBuf, 4096);
1726
1727     mainf = newSymbol ("main", 0);
1728     mainf->block = 0;
1729
1730     mainf = findSymWithLevel(SymbolTab, mainf);
1731
1732     pic16_pCodeInitRegisters();
1733
1734     if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1735       pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1736
1737         pic16_addpBlock(pb);
1738
1739         /* entry point @ start of CSEG */
1740         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1741
1742         if(initsfpnt) {
1743           pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1744                   pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1745           pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1746                   pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1747         }
1748
1749         /* put in the call to main */
1750         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1751
1752         if (options.mainreturn) {
1753           pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1754           pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1755         } else {
1756           pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1757           pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1758         }
1759     }
1760
1761     /* At this point we've got all the code in the form of pCode structures */
1762     /* Now it needs to be rearranged into the order it should be placed in the */
1763     /* code space */
1764
1765     pic16_movepBlock2Head('P');              // Last
1766     pic16_movepBlock2Head(code->dbName);
1767     pic16_movepBlock2Head('X');
1768     pic16_movepBlock2Head(statsg->dbName);   // First
1769
1770     /* print the global struct definitions */
1771
1772     /* PENDING: this isnt the best place but it will do */
1773     if (port->general.glue_up_main) {
1774       /* create the interrupt vector table */
1775       pic16createInterruptVect (&vBuf);
1776     }
1777
1778     /* emit code for the all the variables declared */
1779     pic16emitMaps ();
1780
1781     /* do the overlay segments */
1782     pic16emitOverlay(&ovrBuf);
1783     pic16_AnalyzepCode('*');
1784
1785 #if 1
1786     if(pic16_options.dumpcalltree) {
1787       FILE *cFile;
1788
1789         sprintf(buffer, dstFileName);
1790         strcat(buffer, ".calltree");
1791         cFile = fopen(buffer, "w");
1792         pic16_printCallTree( cFile );
1793         fclose(cFile);
1794     }
1795 #endif
1796
1797     pic16_InlinepCode();
1798     pic16_AnalyzepCode('*');
1799
1800
1801     if(pic16_debug_verbose)
1802       pic16_pcode_test();
1803
1804     /* now put it all together into the assembler file */
1805     /* create the assembler file name */
1806     if((noAssemble || options.c1mode)  && fullDstFileName) {
1807       sprintf (buffer, fullDstFileName);
1808     } else {
1809       sprintf (buffer, dstFileName);
1810       strcat (buffer, ".asm");
1811     }
1812
1813     if(!(asmFile = fopen (buffer, "w"))) {
1814       werror (E_FILE_OPEN_ERR, buffer);
1815       exit (1);
1816     }
1817
1818     /* initial comments */
1819     pic16initialComments (asmFile);
1820
1821     /* print module name */
1822     if(options.debug)
1823       fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1824
1825     /* Let the port generate any global directives, etc. */
1826     if(port->genAssemblerPreamble) {
1827       port->genAssemblerPreamble(asmFile);
1828     }
1829
1830     /* Put all variables into a cblock */
1831     pic16_AnalyzeBanking();
1832
1833 #if 0
1834     if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1835       pic16_OptimizeLocalRegs();
1836     }
1837 #endif
1838
1839     /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1840     if(pic16_options.opt_banksel > 1) {
1841       pic16_OptimizeBanksel();
1842     }
1843
1844     /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1845     if(pic16_options.opt_flags & OF_OPTIMIZE_GOTO) {
1846       pic16_OptimizeJumps();
1847     }
1848
1849     /* print the global variables in this module */
1850     pic16printPublics (asmFile);
1851
1852     /* print the extern variables to this module */
1853     pic16_printExterns(asmFile);
1854
1855     pic16_writeUsedRegs(asmFile);
1856
1857 #if 0
1858     /* no xdata in pic */
1859     /* if external stack then reserve space of it */
1860     if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1861       fprintf (asmFile, "%s", iComments2);
1862       fprintf (asmFile, "; external stack \n");
1863       fprintf (asmFile, "%s", iComments2);
1864       fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1865       fprintf (asmFile,";\t.ds 256\n");
1866     }
1867 #endif
1868
1869 #if 0
1870     /* no xdata in pic */
1871     /* copy xtern ram data */
1872     fprintf (asmFile, "%s", iComments2);
1873     fprintf (asmFile, "; external ram data\n");
1874     fprintf (asmFile, "%s", iComments2);
1875     dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1876 #endif
1877
1878 #if 0
1879     /* copy the bit segment */
1880     fprintf (asmFile, "%s", iComments2);
1881     fprintf (asmFile, "; bit data\n");
1882     fprintf (asmFile, "%s", iComments2);
1883     dbuf_write_and_destroy (&bit->oBuf, asmFile);
1884 #endif
1885
1886     /* copy the interrupt vector table */
1887     if(mainf && IFFUNC_HASBODY(mainf->type)) {
1888       fprintf (asmFile, "\n%s", iComments2);
1889       fprintf (asmFile, "; interrupt vector \n");
1890       fprintf (asmFile, "%s", iComments2);
1891       dbuf_write_and_destroy (&vBuf, asmFile);
1892     }
1893
1894     /* copy global & static initialisations */
1895     fprintf (asmFile, "\n%s", iComments2);
1896     fprintf (asmFile, "; global & static initialisations\n");
1897     fprintf (asmFile, "%s", iComments2);
1898
1899     if(pic16_debug_verbose)
1900       fprintf(asmFile, "; A code from now on!\n");
1901
1902     pic16_copypCode(asmFile, 'A');
1903
1904     if(pic16_options.no_crt) {
1905       if(mainf && IFFUNC_HASBODY(mainf->type)) {
1906         fprintf(asmFile, "\tcode\n");
1907         fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1908       }
1909     }
1910
1911 //    dbuf_write_and_destroy (&code->oBuf, stderr);
1912
1913     fprintf(asmFile, "; I code from now on!\n");
1914     pic16_copypCode(asmFile, 'I');
1915
1916     if(pic16_debug_verbose)
1917       fprintf(asmFile, "; dbName from now on!\n");
1918
1919     pic16_copypCode(asmFile, statsg->dbName);
1920
1921     if(pic16_options.no_crt) {
1922       if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1923         fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1924       }
1925     }
1926
1927     if(pic16_debug_verbose)
1928       fprintf(asmFile, "; X code from now on!\n");
1929
1930     pic16_copypCode(asmFile, 'X');
1931
1932     if(pic16_debug_verbose)
1933       fprintf(asmFile, "; M code from now on!\n");
1934
1935     pic16_copypCode(asmFile, 'M');
1936
1937     pic16_copypCode(asmFile, code->dbName);
1938
1939     pic16_copypCode(asmFile, 'P');
1940
1941     emitStatistics(asmFile);
1942
1943     fprintf (asmFile,"\tend\n");
1944     fclose (asmFile);
1945 }