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