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