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