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