* src/pic16/glue.c (pic16_print(G)PointerType): do not flush
[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                 assert(0);
1327               }
1328             }
1329   
1330         } else {
1331 //              fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1332 //                      __FILE__, __LINE__, sym->name);
1333
1334                 
1335           /* if it has an initial value */
1336           if (sym->ival) {
1337               pBlock *pb;
1338
1339               /* symbol doesn't have absolute address but has initial value */
1340               fprintf (code->oFile, "%s:\n", sym->rname);
1341               noAlloc++;
1342               resolveIvalSym (sym->ival, sym->type);
1343
1344               pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
1345               pic16_addpBlock(pb);
1346
1347               if(!didcode) {
1348                 /* make sure that 'code' directive is emitted before, once */
1349                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
1350                 
1351                 didcode++;
1352               }
1353
1354               pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1355               //fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1356               pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1357               pic16_flushDB('p', (void *)pb);
1358               noAlloc--;
1359             } else {
1360
1361               /* symbol doesn't have absolute address and no initial value */
1362               /* allocate space */
1363 //            fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1364               fprintf (code->oFile, "%s:\n", sym->rname);
1365               /* special case for character strings */
1366               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1367                   SPEC_CVAL (sym->etype).v_char) {
1368                 
1369 //              fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1370
1371                 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1372               } else {
1373                 assert(0);
1374               }
1375             }
1376         }
1377     }
1378
1379 }
1380
1381
1382 /*-----------------------------------------------------------------*/
1383 /* pic16_emitConfigRegs - emits the configuration registers              */
1384 /*-----------------------------------------------------------------*/
1385 void pic16_emitConfigRegs(FILE *of)
1386 {
1387   int i;
1388
1389         for(i=0;i<pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart;i++)
1390                 if(pic16->cwInfo.crInfo[i].emit)        //mask != -1)
1391                         fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1392                                 pic16->cwInfo.confAddrStart+i,
1393                                 pic16->cwInfo.crInfo[i].value);
1394 }
1395
1396 void pic16_emitIDRegs(FILE *of)
1397 {
1398   int i;
1399
1400         for(i=0;i<pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart;i++)
1401                 if(pic16->idInfo.irInfo[i].emit)
1402                         fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1403                                 pic16->idInfo.idAddrStart+i,
1404                                 pic16->idInfo.irInfo[i].value);
1405 }
1406
1407
1408 static void
1409 pic16emitMaps ()
1410 {
1411   /* no special considerations for the following
1412      data, idata & bit & xdata */
1413   pic16emitRegularMap (data, TRUE, TRUE);
1414   pic16emitRegularMap (idata, TRUE, TRUE);
1415   pic16emitRegularMap (bit, TRUE, FALSE);
1416   pic16emitRegularMap (xdata, TRUE, TRUE);
1417   pic16emitRegularMap (sfr, FALSE, FALSE);
1418   pic16emitRegularMap (sfrbit, FALSE, FALSE);
1419   pic16emitRegularMap (code, TRUE, FALSE);
1420   pic16emitStaticSeg (statsg);
1421 }
1422
1423 /*-----------------------------------------------------------------*/
1424 /* createInterruptVect - creates the interrupt vector              */
1425 /*-----------------------------------------------------------------*/
1426 static void
1427 pic16createInterruptVect (FILE * vFile)
1428 {
1429         /* if the main is only a prototype ie. no body then do nothing */
1430 #if 0
1431         if (!IFFUNC_HASBODY(mainf->type)) {
1432                 /* if ! compile only then main function should be present */
1433                 if (!options.cc_only)
1434                         werror (E_NO_MAIN);
1435                 return;
1436         }
1437 #endif
1438 #if 0
1439         if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1440                 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
1441                 fprintf(vFile, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1442
1443                 /* this is an overkill since WE are the port,
1444                  * and we know if we have a genIVT function! */
1445                 if(port->genIVT) {
1446                         port->genIVT(vFile, interrupts, maxInterrupts);
1447                 }
1448         }
1449 #endif
1450         
1451 }
1452
1453
1454 /*-----------------------------------------------------------------*/
1455 /* pic16initialComments - puts in some initial comments            */
1456 /*-----------------------------------------------------------------*/
1457 static void
1458 pic16initialComments (FILE * afile)
1459 {
1460         initialComments (afile);
1461         fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1462         if(pic16_mplab_comp)
1463                 fprintf(afile, "; MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1464         fprintf (afile, iComments2);
1465
1466         if(options.debug) {
1467                 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]\"\n",
1468                                 SDCC_VERSION_STR, getBuildNumber() );
1469         }
1470 }
1471
1472 /*-----------------------------------------------------------------*/
1473 /* printPublics - generates global declarations for publics        */
1474 /*-----------------------------------------------------------------*/
1475 static void
1476 pic16printPublics (FILE *afile)
1477 {
1478   symbol *sym;
1479
1480         fprintf (afile, "\n%s", iComments2);
1481         fprintf (afile, "; public variables in this module\n");
1482         fprintf (afile, "%s", iComments2);
1483
1484         for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1485           /* sanity check */
1486           if(!IS_STATIC(sym->etype))
1487                 fprintf(afile, "\tglobal %s\n", sym->rname);
1488 }
1489
1490 /*-----------------------------------------------------------------*/
1491 /* printExterns - generates extern declarations for externs        */
1492 /*-----------------------------------------------------------------*/
1493 static void
1494 pic16_printExterns(FILE *afile)
1495 {
1496   symbol *sym;
1497
1498         /* print nothing if no externs to declare */
1499         if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1500                 return;
1501
1502         fprintf(afile, "\n%s", iComments2);
1503         fprintf(afile, "; extern variables in this module\n");
1504         fprintf(afile, "%s", iComments2);
1505         
1506         for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1507                 fprintf(afile, "\textern %s\n", sym->rname);
1508
1509         for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1510                 fprintf(afile, "\textern _%s\n", sym->name);
1511 }
1512
1513 /*-----------------------------------------------------------------*/
1514 /* emitOverlay - will emit code for the overlay stuff              */
1515 /*-----------------------------------------------------------------*/
1516 static void
1517 pic16emitOverlay (FILE * afile)
1518 {
1519   set *ovrset;
1520
1521   if (!elementsInSet (ovrSetSets))
1522     fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
1523
1524   /* for each of the sets in the overlay segment do */
1525   for (ovrset = setFirstItem (ovrSetSets); ovrset;
1526        ovrset = setNextItem (ovrSetSets))
1527     {
1528
1529       symbol *sym;
1530
1531       if (elementsInSet (ovrset))
1532         {
1533           /* this dummy area is used to fool the assembler
1534              otherwise the assembler will append each of these
1535              declarations into one chunk and will not overlay
1536              sad but true */
1537           fprintf (afile, ";\t.area _DUMMY\n");
1538           /* output the area informtion */
1539           fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);    /* MOF */
1540         }
1541
1542       for (sym = setFirstItem (ovrset); sym;
1543            sym = setNextItem (ovrset))
1544         {
1545
1546           /* if extern then do nothing */
1547           if (IS_EXTERN (sym->etype))
1548             continue;
1549
1550           /* if allocation required check is needed
1551              then check if the symbol really requires
1552              allocation only for local variables */
1553           if (!IS_AGGREGATE (sym->type) &&
1554               !(sym->_isparm && !IS_REGPARM (sym->etype))
1555               && !sym->allocreq && sym->level)
1556             continue;
1557
1558           /* if global variable & not static or extern
1559              and addPublics allowed then add it to the public set */
1560           if ((sym->_isparm && !IS_REGPARM (sym->etype))
1561               && !IS_STATIC (sym->etype)) {
1562 //            fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1563               checkAddSym(&publics, sym);
1564 //          addSetHead (&publics, sym);
1565           }
1566
1567           /* if extern then do nothing or is a function
1568              then do nothing */
1569           if (IS_FUNC (sym->type))
1570             continue;
1571
1572
1573           /* if is has an absolute address then generate
1574              an equate for this no need to allocate space */
1575           if (SPEC_ABSA (sym->etype))
1576             {
1577
1578               if (options.debug || sym->level == 0)
1579                 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1580
1581               fprintf (afile, "%s\t=\t0x%04x\n",
1582                        sym->rname,
1583                        SPEC_ADDR (sym->etype));
1584             }
1585           else
1586             {
1587               if (options.debug || sym->level == 0)
1588                 fprintf (afile, "==.\n");
1589
1590               /* allocate space */
1591               fprintf (afile, "%s:\n", sym->rname);
1592               fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1593             }
1594
1595         }
1596     }
1597 }
1598
1599 void emitStatistics(FILE *asmFile)
1600 {
1601   unsigned long isize, udsize, ramsize;
1602   statistics.isize = pic16_countInstructions();
1603   isize = (statistics.isize >= 0) ? statistics.isize : 0;
1604   udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1605   ramsize = pic16 ? pic16->RAMsize : 0x200;
1606   ramsize -= 256; /* ignore access bank and SFRs */
1607   if (ramsize == 0) ramsize = 64; /* prevent division by zero (below) */
1608         
1609   fprintf (asmFile, "\n\n; Statistics:\n");
1610   fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n;           \t%5ld (0x%04lx) words\n",
1611     isize, isize, (isize*100.0)/(128UL << 10),
1612     isize>>1, isize>>1);
1613   fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n",
1614     udsize, udsize, (udsize*100.0) / (1.0 * ramsize));
1615   fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1616     statistics.intsize, statistics.intsize);
1617
1618   fprintf (asmFile, "\n\n");
1619 }
1620
1621
1622
1623 /*-----------------------------------------------------------------*/
1624 /* glue - the final glue that hold the whole thing together        */
1625 /*-----------------------------------------------------------------*/
1626 void
1627 pic16glue ()
1628 {
1629   FILE *vFile;
1630   FILE *asmFile;
1631   FILE *ovrFile = tempfile();
1632
1633     mainf = newSymbol ("main", 0);
1634     mainf->block = 0;
1635
1636     mainf = findSymWithLevel(SymbolTab, mainf);
1637
1638     addSetHead(&tmpfileSet,ovrFile);
1639     pic16_pCodeInitRegisters();
1640
1641     if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1642       pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1643
1644         pic16_addpBlock(pb);
1645
1646         /* entry point @ start of CSEG */
1647         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1648
1649         if(initsfpnt) {
1650           pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1651                   pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1652           pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1653                   pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1654         }
1655
1656         /* put in the call to main */
1657         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1658
1659         if (options.mainreturn) {
1660           pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1661           pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1662         } else {
1663           pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1664           pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1665         }
1666     }
1667
1668     /* At this point we've got all the code in the form of pCode structures */
1669     /* Now it needs to be rearranged into the order it should be placed in the */
1670     /* code space */
1671
1672     pic16_movepBlock2Head('P');              // Last
1673     pic16_movepBlock2Head(code->dbName);
1674     pic16_movepBlock2Head('X');
1675     pic16_movepBlock2Head(statsg->dbName);   // First
1676
1677     /* print the global struct definitions */
1678
1679     vFile = tempfile();
1680     /* PENDING: this isnt the best place but it will do */
1681     if (port->general.glue_up_main) {
1682       /* create the interrupt vector table */
1683       pic16createInterruptVect (vFile);
1684     }
1685
1686     addSetHead(&tmpfileSet,vFile);
1687     
1688     /* emit code for the all the variables declared */
1689     pic16emitMaps ();
1690
1691     /* do the overlay segments */
1692     pic16emitOverlay(ovrFile);
1693     pic16_AnalyzepCode('*');
1694
1695 #if 1
1696     if(pic16_options.dumpcalltree) {
1697       FILE *cFile;
1698         
1699         sprintf(buffer, dstFileName);
1700         strcat(buffer, ".calltree");
1701         cFile = fopen(buffer, "w");
1702         pic16_printCallTree( cFile );
1703         fclose(cFile);
1704     }
1705 #endif
1706
1707     pic16_InlinepCode();
1708     pic16_AnalyzepCode('*');
1709
1710
1711     if(pic16_debug_verbose)
1712       pic16_pcode_test();
1713
1714     /* now put it all together into the assembler file */
1715     /* create the assembler file name */
1716     if((noAssemble || options.c1mode)  && fullDstFileName) {
1717       sprintf (buffer, fullDstFileName);
1718     } else {
1719       sprintf (buffer, dstFileName);
1720       strcat (buffer, ".asm");
1721     }
1722
1723     if(!(asmFile = fopen (buffer, "w"))) {
1724       werror (E_FILE_OPEN_ERR, buffer);
1725       exit (1);
1726     }
1727     
1728     /* initial comments */
1729     pic16initialComments (asmFile);
1730
1731     /* print module name */
1732     if(options.debug)
1733       fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1734
1735     /* Let the port generate any global directives, etc. */
1736     if(port->genAssemblerPreamble) {
1737       port->genAssemblerPreamble(asmFile);
1738     }
1739         
1740     /* Put all variables into a cblock */
1741     pic16_AnalyzeBanking();
1742
1743 #if 0
1744     if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1745       pic16_OptimizeLocalRegs();
1746     }
1747 #endif
1748
1749     /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1750     if(pic16_options.opt_banksel > 1) {
1751       pic16_OptimizeBanksel();
1752     }
1753             
1754     /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1755     if(pic16_options.opt_flags & OF_OPTIMIZE_GOTO) {
1756       pic16_OptimizeJumps();
1757     }
1758
1759     /* print the extern variables to this module */
1760     pic16_printExterns(asmFile);
1761         
1762     /* print the global variables in this module */
1763     pic16printPublics (asmFile);
1764
1765     pic16_writeUsedRegs(asmFile);
1766
1767 #if 0
1768     /* no xdata in pic */
1769     /* if external stack then reserve space of it */
1770     if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1771       fprintf (asmFile, "%s", iComments2);
1772       fprintf (asmFile, "; external stack \n");
1773       fprintf (asmFile, "%s", iComments2);
1774       fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1775       fprintf (asmFile,";\t.ds 256\n");
1776     }
1777 #endif
1778
1779 #if 0   
1780     /* no xdata in pic */
1781     /* copy xtern ram data */
1782     fprintf (asmFile, "%s", iComments2);
1783     fprintf (asmFile, "; external ram data\n");
1784     fprintf (asmFile, "%s", iComments2);
1785     copyFile (asmFile, xdata->oFile);
1786 #endif
1787
1788 #if 0
1789     /* copy the bit segment */
1790     fprintf (asmFile, "%s", iComments2);
1791     fprintf (asmFile, "; bit data\n");
1792     fprintf (asmFile, "%s", iComments2);
1793     copyFile (asmFile, bit->oFile);
1794 #endif
1795
1796     /* copy the interrupt vector table */
1797     if(mainf && IFFUNC_HASBODY(mainf->type)) {
1798       fprintf (asmFile, "\n%s", iComments2);
1799       fprintf (asmFile, "; interrupt vector \n");
1800       fprintf (asmFile, "%s", iComments2);
1801       copyFile (asmFile, vFile);
1802     }
1803     
1804     /* copy global & static initialisations */
1805     fprintf (asmFile, "\n%s", iComments2);
1806     fprintf (asmFile, "; global & static initialisations\n");
1807     fprintf (asmFile, "%s", iComments2);
1808     
1809     if(pic16_debug_verbose)
1810       fprintf(asmFile, "; A code from now on!\n");
1811     
1812     pic16_copypCode(asmFile, 'A');
1813
1814     if(pic16_options.no_crt) {
1815       if(mainf && IFFUNC_HASBODY(mainf->type)) {
1816         fprintf(asmFile, "\tcode\n");
1817         fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1818       }
1819     }
1820
1821 //    copyFile (stderr, code->oFile);
1822
1823     fprintf(asmFile, "; I code from now on!\n");
1824     pic16_copypCode(asmFile, 'I');
1825
1826     if(pic16_debug_verbose)
1827       fprintf(asmFile, "; dbName from now on!\n");
1828     
1829     pic16_copypCode(asmFile, statsg->dbName);
1830
1831     if(pic16_options.no_crt) {
1832       if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1833         fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1834       }
1835     }
1836         
1837     if(pic16_debug_verbose)
1838       fprintf(asmFile, "; X code from now on!\n");
1839
1840     pic16_copypCode(asmFile, 'X');
1841
1842     if(pic16_debug_verbose)
1843       fprintf(asmFile, "; M code from now on!\n");
1844
1845     pic16_copypCode(asmFile, 'M');
1846
1847     pic16_copypCode(asmFile, code->dbName);
1848     
1849     pic16_copypCode(asmFile, 'P');
1850
1851     emitStatistics(asmFile);
1852
1853     fprintf (asmFile,"\tend\n");
1854     fclose (asmFile);
1855     
1856     rm_tmpfiles();
1857 }