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