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