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