* device/lib/pic16/libsdcc/Makefile.rules: fixed bug concerning
[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
63 set *rel_idataSymSet=NULL;
64 set *fix_idataSymSet=NULL;
65
66 extern DEFSETFUNC (closeTmpFiles);
67 extern DEFSETFUNC (rmTmpFiles);
68
69 extern void pic16_AnalyzeBanking (void);
70 extern void copyFile (FILE * dest, FILE * src);
71 extern void pic16_InlinepCode(void);
72 extern void pic16_writeUsedRegs(FILE *);
73
74 extern void initialComments (FILE * afile);
75 extern void printPublics (FILE * afile);
76
77 void  pic16_pCodeInitRegisters(void);
78 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
79 extern void pic16_pCodeConstString(char *name, char *value);
80
81 /*-----------------------------------------------------------------*/
82 /* aopLiteral - string from a literal value                        */
83 /*-----------------------------------------------------------------*/
84 int pic16aopLiteral (value *val, int offset)
85 {
86   union {
87     float f;
88     unsigned char c[4];
89   } fl;
90
91   /* if it is a float then it gets tricky */
92   /* otherwise it is fairly simple */
93   if (!IS_FLOAT(val->type)) {
94     unsigned long v = (unsigned long) floatFromVal(val);
95
96     return ( (v >> (offset * 8)) & 0xff);
97   }
98
99   /* it is type float */
100   fl.f = (float) floatFromVal(val);
101 #ifdef WORDS_BIGENDIAN
102   return fl.c[3-offset];
103 #else
104   return fl.c[offset];
105 #endif
106
107 }
108
109 iCode *tic;
110 symbol *nsym;
111 char tbuffer[512], *tbuf=tbuffer;;
112
113
114 /*-----------------------------------------------------------------*/
115 /* emitRegularMap - emit code for maps with no special cases       */
116 /*-----------------------------------------------------------------*/
117 static void
118 pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
119 {
120   symbol *sym;
121 //  int i, size, bitvars = 0;;
122
123 //      fprintf(stderr, "%s:%d map name= %s\n", __FUNCTION__, __LINE__, map->sname);
124         
125         if(addPublics)
126                 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
127                 /* print the area name */
128
129         for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) {
130
131 #if 0
132                 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\textern: %d\tstatic: %d\taggregate: %d\tregister: 0x%x\tfunction: %d\n",
133                         __FUNCTION__,
134                         map->sname, sym->name, sym->used, IS_EXTERN(sym->etype), IS_STATIC(sym->etype),
135                         IS_AGGREGATE(sym->type), (SPEC_SCLS(sym->etype) == S_REGISTER), IS_FUNC(sym->type));
136                 printTypeChain( sym->type, stderr );
137                 fprintf(stderr, "\n");
138 #endif
139
140                 /* if extern then add to externs */
141                 if (IS_EXTERN (sym->etype)) {
142                         /* reduce overhead while linking by not declaring
143                          * extern unused external functions (usually declared
144                          * in header files) */
145                         if(IS_FUNC(sym->type) && !sym->used)continue;
146                         
147                         /* make sure symbol is not in publics section */
148                         if(!checkSym(publics, sym))
149                                 checkAddSym(&externs, sym);
150                         continue;
151                 }
152                 
153                 /* if allocation required check is needed
154                  * then check if the symbol really requires
155                  * allocation only for local variables */
156                  if (arFlag && !IS_AGGREGATE (sym->type) &&
157                         !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
158                         !sym->allocreq && sym->level) {
159
160 //                      fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
161
162                         continue;
163                 }
164
165                 /* if global variable & not static or extern
166                  * and addPublics allowed then add it to the public set */
167                 if ((sym->used) && (sym->level == 0 ||
168                         (sym->_isparm && !IS_REGPARM (sym->etype))) &&
169                         addPublics &&
170                         !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
171                   
172                         checkAddSym(&publics, sym);
173                 } else
174                         if(IS_STATIC(sym->etype)
175                                 && !(sym->ival && !sym->level)
176                         ) {
177                           regs *reg;
178                                 /* add it to udata list */
179
180 //                              fprintf(stderr, "%s:%d adding %s (%s) remat=%d\n", __FILE__, __LINE__,
181 //                                      sym->name, sym->rname, sym->remat);
182                                         
183                                                 //, OP_SYMBOL(operandFromSymbol(sym))->name);
184 #define SET_IMPLICIT    1
185
186 #if SET_IMPLICIT
187                                 if(IS_STRUCT(sym->type))
188                                         sym->implicit = 1;
189 #endif
190
191                                 reg = pic16_allocDirReg( operandFromSymbol( sym ));
192                                 
193                                 {
194                                   sectSym *ssym;
195                                   int found=0;
196                                   
197 #if 1
198                                         for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
199                                                 if(!strcmp(ssym->name, reg->name))found=1;
200                                         }
201 #endif
202
203                                         if(!found)checkAddReg(&pic16_rel_udata, reg);
204                                 }
205                         }
206
207                 /* if extern then do nothing or is a function
208                  * then do nothing */
209                 if (IS_FUNC (sym->type) && !IS_STATIC(sym->etype)) {
210                         if(SPEC_OCLS(sym->etype) == code) {
211 //                              fprintf(stderr, "%s:%d: symbol added: %s\n", __FILE__, __LINE__, sym->rname);
212                                 checkAddSym(&publics, sym);
213                         }
214                         continue;
215                 }
216
217 #if 0
218                 /* print extra debug info if required */
219                 if (options.debug || sym->level == 0) {
220                         cdbWriteSymbol (sym);   //, cdbFile, FALSE, FALSE);
221
222                         if (!sym->level)        /* global */
223                                 if (IS_STATIC (sym->etype))
224                                         fprintf (map->oFile, "F%s_", moduleName);               /* scope is file */
225                                 else
226                                         fprintf (map->oFile, "G_");     /* scope is global */
227                         else
228                                 /* symbol is local */
229                                 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
230                         fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
231                 }
232 #endif
233
234
235                 /* if is has an absolute address then generate
236                 an equate for this no need to allocate space */
237                 if (SPEC_ABSA (sym->etype)) {
238 //                      if (options.debug || sym->level == 0)
239 //                              fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
240 //                                      sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
241
242                         fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
243                                 sym->rname,
244                                 SPEC_ADDR (sym->etype));
245
246                         /* emit only if it is global */
247                         if(sym->level == 0) {
248                           regs *reg;
249
250                                 reg = pic16_dirregWithName( sym->name );
251                                 if(!reg) {
252                                         /* here */
253 //                                      fprintf(stderr, "%s:%d: implicit add of symbol = %s\n",
254 //                                                      __FUNCTION__, __LINE__, sym->name);
255
256                                         /* if IS_STRUCT is omitted the following
257                                          * fixes structures but break char/int etc */
258 #if SET_IMPLICIT
259                                         if(IS_STRUCT(sym->type))
260                                                 sym->implicit = 1;              // mark as implicit
261 #endif
262                                         if(!sym->ival) {
263                                                 reg = pic16_allocDirReg( operandFromSymbol(sym) );
264                                                 if(reg) {
265                                                         if(checkAddReg(&pic16_fix_udata, reg)) {
266                                                                 /* and add to globals list if not exist */
267                                                                 addSet(&publics, sym);
268                                                         }
269                                                 }
270                                         } else
271                                                 addSet(&publics, sym);
272                                 }
273                         }
274                 } else {
275                         if(!sym->used && (sym->level == 0)) {
276                           regs *reg;
277
278                                 /* symbol not used, just declared probably, but its in
279                                  * level 0, so we must declare it fine as global */
280                                 
281 //                              fprintf(stderr, "EXTRA symbol declaration sym= %s\n", sym->name);
282
283 #if SET_IMPLICIT
284                                 if(IS_STRUCT(sym->type))
285                                         sym->implicit = 1;              // mark as implicit
286 #endif
287                                 if(!sym->ival) {
288                                         if(IS_AGGREGATE(sym->type)) {
289                                                 reg=pic16_allocRegByName(sym->rname, getSize( sym->type ), NULL);
290                                         } else {
291                                                 reg = pic16_allocDirReg( operandFromSymbol( sym ) );
292                                         }
293
294                                         {
295                                           sectSym *ssym;
296                                           int found=0;
297                                   
298 #if 0
299                                                 fprintf(stderr, "%s:%d sym->rname: %s reg: %p reg->name: %s\n", __FILE__, __LINE__,
300                                                         sym->rname, reg, (reg?reg->name:"<<NULL>>"));
301 #endif
302
303 #if 1
304                                                 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
305                                                         if(!strcmp(ssym->name, reg->name))found=1;
306                                                 }
307 #endif
308
309                                                 if(!found)
310                                                         if(checkAddReg(&pic16_rel_udata, reg)) {
311                                                                 addSetHead(&publics, sym);
312                                                         }
313
314                                         }
315
316
317                 
318                                 } else
319
320                                         addSetHead(&publics, sym);
321                         }
322
323 #if 0
324                         /* allocate space */
325                         /* If this is a bit variable, then allocate storage after 8 bits have been declared */
326                         /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
327                         /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
328                         if (IS_BITVAR (sym->etype)) {
329                                 bitvars++;
330                         } else {
331                                 fprintf (map->oFile, "\t%s\n", sym->rname);
332                                 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
333                                         for (i = 1; i < size; i++)
334                                                 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
335                                 }
336                         }
337                         fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
338 #endif
339                 }
340         
341                 /* FIXME -- VR Fix the following, so that syms to be placed
342                  * in the idata section and let linker decide about their fate */
343
344                 /* if it has an initial value then do it only if
345                         it is a global variable */
346
347                 if (sym->ival && sym->level == 0) {
348                   ast *ival = NULL;
349
350 #if 0
351                         if(SPEC_OCLS(sym->etype)==data) {
352                                 fprintf(stderr, "%s: sym %s placed in data segment\n", map->sname, sym->name);
353                         }
354
355                         if(SPEC_OCLS(sym->etype)==code) {
356                                 fprintf(stderr, "%s: sym %s placed in code segment\n", map->sname, sym->name);
357                         }
358 #endif
359
360 #if 0
361                         fprintf(stderr, "'%s': sym '%s' has initial value SPEC_ABSA: %d, IS_AGGREGATE: %d\n",
362                                 map->sname, sym->name, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type));
363 #endif
364
365                         if (IS_AGGREGATE (sym->type)) {
366                                 if(SPEC_ABSA(sym->etype))
367                                         addSet(&fix_idataSymSet, copySymbol(sym));
368                                 else
369                                         addSet(&rel_idataSymSet, copySymbol(sym));
370 //                              ival = initAggregates (sym, sym->ival, NULL);
371                         } else {
372                                 if(SPEC_ABSA(sym->etype))
373                                         addSet(&fix_idataSymSet, copySymbol(sym));
374                                 else
375                                         addSet(&rel_idataSymSet, copySymbol(sym));
376
377 //                                      ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
378 //                                              decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
379                         }
380
381                         if(ival) {
382                                 setAstLineno(ival, sym->lineDef);
383                                 codeOutFile = statsg->oFile;
384                                 GcurMemmap = statsg;
385                                 eBBlockFromiCode (iCodeFromAst (ival));
386                                 sym->ival = NULL;
387                         }
388                 }
389         }
390 }
391
392
393 /*-----------------------------------------------------------------*/
394 /* pic16_initPointer - pointer initialization code massaging       */
395 /*-----------------------------------------------------------------*/
396 value *pic16_initPointer (initList * ilist, sym_link *toType)
397 {
398   value *val;
399   ast *expr;
400
401   if (!ilist) {
402       return valCastLiteral(toType, 0.0);
403   }
404
405   expr = decorateType(resolveSymbols( list2expr (ilist) ), FALSE);
406 //  expr = list2expr( ilist );
407   
408   if (!expr)
409     goto wrong;
410   
411   /* try it the old way first */
412   if ((val = constExprValue (expr, FALSE)))
413     return val;
414   
415   /* ( ptr + constant ) */
416   if (IS_AST_OP (expr) &&
417       (expr->opval.op == '+' || expr->opval.op == '-') &&
418       IS_AST_SYM_VALUE (expr->left) &&
419       (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
420       compareType(toType, expr->left->ftype) &&
421       IS_AST_LIT_VALUE (expr->right)) {
422     return valForCastAggr (expr->left, expr->left->ftype,
423                            expr->right,
424                            expr->opval.op);
425   }
426   
427   /* (char *)&a */
428   if (IS_AST_OP(expr) && expr->opval.op==CAST &&
429       IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
430     if (compareType(toType, expr->left->ftype)!=1) {
431       werror (W_INIT_WRONG);
432       printFromToType(expr->left->ftype, toType);
433     }
434     // skip the cast ???
435     expr=expr->right;
436   }
437
438   /* no then we have to do these cludgy checks */
439   /* pointers can be initialized with address of
440      a variable or address of an array element */
441   if (IS_AST_OP (expr) && expr->opval.op == '&') {
442     /* address of symbol */
443     if (IS_AST_SYM_VALUE (expr->left)) {
444       val = copyValue (AST_VALUE (expr->left));
445       val->type = newLink (DECLARATOR);
446       if(SPEC_SCLS (expr->left->etype) == S_CODE) {
447         DCL_TYPE (val->type) = CPOINTER;
448         DCL_PTR_CONST (val->type) = port->mem.code_ro;
449       }
450       else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
451         DCL_TYPE (val->type) = FPOINTER;
452       else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
453         DCL_TYPE (val->type) = PPOINTER;
454       else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
455         DCL_TYPE (val->type) = IPOINTER;
456       else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
457         DCL_TYPE (val->type) = EEPPOINTER;
458       else
459         DCL_TYPE (val->type) = POINTER;
460
461       val->type->next = expr->left->ftype;
462       val->etype = getSpec (val->type);
463       return val;
464     }
465
466     /* if address of indexed array */
467     if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
468       return valForArray (expr->left);
469
470     /* if address of structure element then
471        case 1. a.b ; */
472     if (IS_AST_OP (expr->left) &&
473         expr->left->opval.op == '.') {
474       return valForStructElem (expr->left->left,
475                                expr->left->right);
476     }
477
478     /* case 2. (&a)->b ;
479        (&some_struct)->element */
480     if (IS_AST_OP (expr->left) &&
481         expr->left->opval.op == PTR_OP &&
482         IS_ADDRESS_OF_OP (expr->left->left)) {
483       return valForStructElem (expr->left->left->left,
484                                expr->left->right);
485     }
486   }
487   /* case 3. (((char *) &a) +/- constant) */
488   if (IS_AST_OP (expr) &&
489       (expr->opval.op == '+' || expr->opval.op == '-') &&
490       IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
491       IS_AST_OP (expr->left->right) &&
492       expr->left->right->opval.op == '&' &&
493       IS_AST_LIT_VALUE (expr->right)) {
494
495     return valForCastAggr (expr->left->right->left,
496                            expr->left->left->opval.lnk,
497                            expr->right, expr->opval.op);
498
499   }
500   /* case 4. (char *)(array type) */
501   if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
502       IS_ARRAY(expr->right->ftype)) {
503
504     val = copyValue (AST_VALUE (expr->right));
505     val->type = newLink (DECLARATOR);
506     if (SPEC_SCLS (expr->right->etype) == S_CODE) {
507       DCL_TYPE (val->type) = CPOINTER;
508       DCL_PTR_CONST (val->type) = port->mem.code_ro;
509     }
510     else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
511       DCL_TYPE (val->type) = FPOINTER;
512     else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
513       DCL_TYPE (val->type) = PPOINTER;
514     else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
515       DCL_TYPE (val->type) = IPOINTER;
516     else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
517       DCL_TYPE (val->type) = EEPPOINTER;
518     else
519       DCL_TYPE (val->type) = POINTER;
520     val->type->next = expr->right->ftype->next;
521     val->etype = getSpec (val->type);
522     return val;
523   }
524
525  wrong:
526   if (expr)
527     werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES);
528   else
529     werror (E_INCOMPAT_PTYPES);
530   return NULL;
531
532 }
533
534
535 /*-----------------------------------------------------------------*/
536 /* printPointerType - generates ival for pointer type              */
537 /*-----------------------------------------------------------------*/
538 void _pic16_printPointerType (const char *name, char ptype, void *p)
539 {
540   char buf[256];
541
542         sprintf(buf, "LOW(%s)", name);
543         pic16_emitDS(buf, ptype, p);
544         sprintf(buf, "HIGH(%s)", name);
545         pic16_emitDS(buf, ptype, p);
546 }
547
548 /*-----------------------------------------------------------------*/
549 /* printPointerType - generates ival for pointer type              */
550 /*-----------------------------------------------------------------*/
551 void pic16_printPointerType (const char *name, char ptype, void *p)
552 {
553   _pic16_printPointerType (name, ptype, p);
554   pic16_flushDB(ptype, p);
555 }
556
557 /*-----------------------------------------------------------------*/
558 /* printGPointerType - generates ival for generic pointer type     */
559 /*-----------------------------------------------------------------*/
560 void pic16_printGPointerType (const char *iname, const char *oname, const unsigned int itype,
561   const unsigned int type, char ptype, void *p)
562 {
563   char buf[256];
564   
565     _pic16_printPointerType (iname, ptype, p);
566
567     switch( itype ) {
568       case FPOINTER:
569       case CPOINTER:
570         {
571           sprintf(buf, "UPPER(%s)", iname);
572           pic16_emitDS(buf, ptype, p);
573         }; break;
574       case POINTER:
575       case IPOINTER:
576         sprintf(buf, "0x80");
577         pic16_emitDS(buf, ptype, p);
578         break;
579     }
580
581     pic16_flushDB(ptype, p);
582 }
583
584
585 /* set to 0 to disable debug messages */
586 #define DEBUG_PRINTIVAL 0
587
588 /*-----------------------------------------------------------------*/
589 /* pic16_printIvalType - generates ival for int/char               */
590 /*-----------------------------------------------------------------*/
591 static void 
592 pic16_printIvalType (symbol *sym, sym_link * type, initList * ilist, char ptype, void *p)
593 {
594   value *val;
595   unsigned long ulval;
596
597 //  fprintf(stderr, "%s for symbol %s\n",__FUNCTION__, sym->rname);
598
599 #if DEBUG_PRINTIVAL
600   fprintf(stderr, "%s\n",__FUNCTION__);
601 #endif
602
603
604   /* if initList is deep */
605   if (ilist && ilist->type == INIT_DEEP)
606     ilist = ilist->init.deep;
607
608   if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
609     werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
610   }
611
612   if (!(val = list2val (ilist))) {
613     // assuming a warning has been thrown
614     val=constVal("0");
615   }
616
617   if (val->type != type) {
618     val = valCastLiteral(type, floatFromVal(val));
619   }
620
621   if(val) 
622     ulval = (unsigned long) floatFromVal (val);
623   else
624     ulval =0;
625
626   switch (getSize (type)) {
627   case 1:
628     pic16_emitDB(BYTE_IN_LONG(ulval,0), ptype, p);
629     break;
630
631   case 2:
632     pic16_emitDB(BYTE_IN_LONG(ulval,0), ptype, p);
633     pic16_emitDB(BYTE_IN_LONG(ulval,1), ptype, p);
634     break;
635
636   case 4:
637     pic16_emitDB(BYTE_IN_LONG(ulval,0), ptype, p);
638     pic16_emitDB(BYTE_IN_LONG(ulval,1), ptype, p);
639     pic16_emitDB(BYTE_IN_LONG(ulval,2), ptype, p);
640     pic16_emitDB(BYTE_IN_LONG(ulval,3), ptype, p);
641     break;
642   }
643 }
644
645 /*--------------------------------------------------------------------*/
646 /* pic16_printIvalChar - generates initital value for character array */
647 /*--------------------------------------------------------------------*/
648 static int 
649 pic16_printIvalChar (sym_link * type, initList * ilist, char *s, char ptype, void *p)
650 {
651   value *val;
652   unsigned int remain;
653
654   if(!p)
655     return 0;
656
657 #if DEBUG_PRINTIVAL
658   fprintf(stderr, "%s\n",__FUNCTION__);
659 #endif
660
661   if (!s)
662     {
663
664       val = list2val (ilist);
665       /* if the value is a character string  */
666       if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
667         {
668           if (!DCL_ELEM (type))
669             DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
670
671             for(remain=0; remain<DCL_ELEM(type); remain++)
672                 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
673                         
674           if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
675               while (remain--) {
676                   pic16_emitDB(0x00, ptype, p);
677               }
678           }
679           return 1;
680         }
681       else
682         return 0;
683     }
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               abSym->name = Safe_strdup( 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 from %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
1454 /*-----------------------------------------------------------------*/
1455 /* printPublics - generates global declarations for publics        */
1456 /*-----------------------------------------------------------------*/
1457 static void
1458 pic16printPublics (FILE *afile)
1459 {
1460   symbol *sym;
1461
1462         fprintf (afile, "\n%s", iComments2);
1463         fprintf (afile, "; public variables in this module\n");
1464         fprintf (afile, "%s", iComments2);
1465
1466         for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1467                 fprintf(afile, "\tglobal %s\n", sym->rname);
1468 }
1469
1470 /*-----------------------------------------------------------------*/
1471 /* printExterns - generates extern declarations for externs        */
1472 /*-----------------------------------------------------------------*/
1473 static void
1474 pic16_printExterns(FILE *afile)
1475 {
1476   symbol *sym;
1477
1478         /* print nothing if no externs to declare */
1479         if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1480                 return;
1481
1482         fprintf(afile, "\n%s", iComments2);
1483         fprintf(afile, "; extern variables in this module\n");
1484         fprintf(afile, "%s", iComments2);
1485         
1486         for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1487                 fprintf(afile, "\textern %s\n", sym->rname);
1488
1489         for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1490                 fprintf(afile, "\textern _%s\n", sym->name);
1491 }
1492
1493 /*-----------------------------------------------------------------*/
1494 /* emitOverlay - will emit code for the overlay stuff              */
1495 /*-----------------------------------------------------------------*/
1496 static void
1497 pic16emitOverlay (FILE * afile)
1498 {
1499   set *ovrset;
1500
1501   if (!elementsInSet (ovrSetSets))
1502     fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
1503
1504   /* for each of the sets in the overlay segment do */
1505   for (ovrset = setFirstItem (ovrSetSets); ovrset;
1506        ovrset = setNextItem (ovrSetSets))
1507     {
1508
1509       symbol *sym;
1510
1511       if (elementsInSet (ovrset))
1512         {
1513           /* this dummy area is used to fool the assembler
1514              otherwise the assembler will append each of these
1515              declarations into one chunk and will not overlay
1516              sad but true */
1517           fprintf (afile, ";\t.area _DUMMY\n");
1518           /* output the area informtion */
1519           fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);    /* MOF */
1520         }
1521
1522       for (sym = setFirstItem (ovrset); sym;
1523            sym = setNextItem (ovrset))
1524         {
1525
1526           /* if extern then do nothing */
1527           if (IS_EXTERN (sym->etype))
1528             continue;
1529
1530           /* if allocation required check is needed
1531              then check if the symbol really requires
1532              allocation only for local variables */
1533           if (!IS_AGGREGATE (sym->type) &&
1534               !(sym->_isparm && !IS_REGPARM (sym->etype))
1535               && !sym->allocreq && sym->level)
1536             continue;
1537
1538           /* if global variable & not static or extern
1539              and addPublics allowed then add it to the public set */
1540           if ((sym->_isparm && !IS_REGPARM (sym->etype))
1541               && !IS_STATIC (sym->etype)) {
1542 //            fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1543               checkAddSym(&publics, sym);
1544 //          addSetHead (&publics, sym);
1545           }
1546
1547           /* if extern then do nothing or is a function
1548              then do nothing */
1549           if (IS_FUNC (sym->type))
1550             continue;
1551
1552 #if 0
1553           /* print extra debug info if required */
1554           if (options.debug || sym->level == 0)
1555             {
1556
1557               cdbSymbol (sym, cdbFile, FALSE, FALSE);
1558
1559               if (!sym->level)
1560                 {               /* global */
1561                   if (IS_STATIC (sym->etype))
1562                     fprintf (afile, "F%s_", moduleName);        /* scope is file */
1563                   else
1564                     fprintf (afile, "G_");      /* scope is global */
1565                 }
1566               else
1567                 /* symbol is local */
1568                 fprintf (afile, "L%s_",
1569                          (sym->localof ? sym->localof->name : "-null-"));
1570               fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
1571             }
1572 #endif
1573
1574           /* if is has an absolute address then generate
1575              an equate for this no need to allocate space */
1576           if (SPEC_ABSA (sym->etype))
1577             {
1578
1579               if (options.debug || sym->level == 0)
1580                 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1581
1582               fprintf (afile, "%s\t=\t0x%04x\n",
1583                        sym->rname,
1584                        SPEC_ADDR (sym->etype));
1585             }
1586           else
1587             {
1588               if (options.debug || sym->level == 0)
1589                 fprintf (afile, "==.\n");
1590
1591               /* allocate space */
1592               fprintf (afile, "%s:\n", sym->rname);
1593               fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1594             }
1595
1596         }
1597     }
1598 }
1599
1600
1601 /*-----------------------------------------------------------------*/
1602 /* glue - the final glue that hold the whole thing together        */
1603 /*-----------------------------------------------------------------*/
1604 void
1605 pic16glue ()
1606 {
1607
1608   FILE *vFile;
1609   FILE *asmFile;
1610   FILE *ovrFile = tempfile();
1611
1612
1613         mainf = newSymbol ("main", 0);
1614         mainf->block = 0;
1615
1616         mainf = findSymWithLevel(SymbolTab, mainf);
1617 #if 0
1618         /* only if the main function exists */
1619         if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
1620                 if (!options.cc_only)
1621                         werror (E_NO_MAIN);
1622                 return;
1623         }
1624 #endif
1625
1626 //      fprintf(stderr, "main function= %p (%s)\thas body= %d\n", mainf, (mainf?mainf->name:NULL), mainf?IFFUNC_HASBODY(mainf->type):-1);
1627
1628         addSetHead(&tmpfileSet,ovrFile);
1629         pic16_pCodeInitRegisters();
1630
1631
1632         if (pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1633           pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1634
1635                 pic16_addpBlock(pb);
1636
1637                 /* entry point @ start of CSEG */
1638                 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1639
1640                 if(initsfpnt) {
1641                         pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1642                                 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1643                         pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1644                                 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1645                 }
1646
1647                 /* put in the call to main */
1648                 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1649
1650                 if (options.mainreturn) {
1651                         pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1652                         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1653                 } else {
1654                         pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1655                         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1656                 }
1657         }
1658
1659         /* At this point we've got all the code in the form of pCode structures */
1660         /* Now it needs to be rearranged into the order it should be placed in the */
1661         /* code space */
1662
1663         pic16_movepBlock2Head('P');              // Last
1664         pic16_movepBlock2Head(code->dbName);
1665         pic16_movepBlock2Head('X');
1666         pic16_movepBlock2Head(statsg->dbName);   // First
1667
1668         /* print the global struct definitions */
1669 //      if (options.debug)
1670 //              cdbStructBlock (0);     //,cdbFile);
1671
1672         vFile = tempfile();
1673         /* PENDING: this isnt the best place but it will do */
1674         if (port->general.glue_up_main) {
1675                 /* create the interrupt vector table */
1676                 pic16createInterruptVect (vFile);
1677         }
1678
1679         addSetHead(&tmpfileSet,vFile);
1680     
1681         /* emit code for the all the variables declared */
1682         pic16emitMaps ();
1683         /* do the overlay segments */
1684         pic16emitOverlay(ovrFile);
1685         pic16_AnalyzepCode('*');
1686
1687 #if 1
1688         if(pic16_options.dumpcalltree) {
1689           FILE *cFile;
1690                 sprintf(buffer, dstFileName);
1691                 strcat(buffer, ".calltree");
1692                 cFile = fopen(buffer, "w");
1693                 pic16_printCallTree( cFile );
1694                 fclose(cFile);
1695         }
1696 #endif
1697
1698         pic16_InlinepCode();
1699         pic16_AnalyzepCode('*');
1700
1701         if(pic16_debug_verbose)
1702                 pic16_pcode_test();
1703
1704         /* now put it all together into the assembler file */
1705         /* create the assembler file name */
1706         if ((noAssemble || options.c1mode)  && fullDstFileName) {
1707                 sprintf (buffer, fullDstFileName);
1708         } else {
1709                 sprintf (buffer, dstFileName);
1710                 strcat (buffer, ".asm");
1711         }
1712
1713         if (!(asmFile = fopen (buffer, "w"))) {
1714                 werror (E_FILE_OPEN_ERR, buffer);
1715                 exit (1);
1716         }
1717     
1718         /* initial comments */
1719         pic16initialComments (asmFile);
1720
1721         /* print module name */
1722         if(options.debug)
1723                 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1724
1725         /* Let the port generate any global directives, etc. */
1726         if (port->genAssemblerPreamble) {
1727                 port->genAssemblerPreamble(asmFile);
1728         }
1729         
1730         /* print the extern variables to this module */
1731         pic16_printExterns(asmFile);
1732         
1733         /* print the global variables in this module */
1734         pic16printPublics (asmFile);
1735
1736 #if 0
1737         /* copy the sfr segment */
1738         fprintf (asmFile, "%s", iComments2);
1739         fprintf (asmFile, "; special function registers\n");
1740         fprintf (asmFile, "%s", iComments2);
1741         copyFile (asmFile, sfr->oFile);
1742 #endif
1743
1744         /* Put all variables into a cblock */
1745         pic16_AnalyzeBanking();
1746         pic16_writeUsedRegs(asmFile);
1747
1748 #if 0
1749         /* no xdata in pic */
1750         /* if external stack then reserve space of it */
1751         if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1752                 fprintf (asmFile, "%s", iComments2);
1753                 fprintf (asmFile, "; external stack \n");
1754                 fprintf (asmFile, "%s", iComments2);
1755                 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1756                 fprintf (asmFile,";\t.ds 256\n");
1757         }
1758 #endif
1759
1760 #if 0   
1761         /* no xdata in pic */
1762         /* copy xtern ram data */
1763         fprintf (asmFile, "%s", iComments2);
1764         fprintf (asmFile, "; external ram data\n");
1765         fprintf (asmFile, "%s", iComments2);
1766         copyFile (asmFile, xdata->oFile);
1767 #endif
1768
1769 #if 0
1770         /* copy the bit segment */
1771         fprintf (asmFile, "%s", iComments2);
1772         fprintf (asmFile, "; bit data\n");
1773         fprintf (asmFile, "%s", iComments2);
1774         copyFile (asmFile, bit->oFile);
1775 #endif
1776
1777         /* copy the interrupt vector table */
1778         if(mainf && IFFUNC_HASBODY(mainf->type)) {
1779                 fprintf (asmFile, "\n%s", iComments2);
1780                 fprintf (asmFile, "; interrupt vector \n");
1781                 fprintf (asmFile, "%s", iComments2);
1782                 copyFile (asmFile, vFile);
1783         }
1784     
1785         /* copy global & static initialisations */
1786         fprintf (asmFile, "\n%s", iComments2);
1787         fprintf (asmFile, "; global & static initialisations\n");
1788         fprintf (asmFile, "%s", iComments2);
1789     
1790         if(pic16_debug_verbose)
1791                 fprintf(asmFile, "; A code from now on!\n");
1792         pic16_copypCode(asmFile, 'A');
1793
1794
1795         if(pic16_options.no_crt) {
1796                 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1797                         fprintf(asmFile, "\tcode\n");
1798                         fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1799                 }
1800         }
1801
1802 //      copyFile (stderr, code->oFile);
1803
1804         fprintf(asmFile, "; I code from now on!\n");
1805         pic16_copypCode(asmFile, 'I');
1806
1807         if(pic16_debug_verbose)
1808                 fprintf(asmFile, "; dbName from now on!\n");
1809         pic16_copypCode(asmFile, statsg->dbName);
1810
1811
1812         if(pic16_options.no_crt) {
1813                 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1814                         fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1815                 }
1816         }
1817         
1818
1819         if(pic16_debug_verbose)
1820                 fprintf(asmFile, "; X code from now on!\n");
1821         pic16_copypCode(asmFile, 'X');
1822
1823         if(pic16_debug_verbose)
1824                 fprintf(asmFile, "; M code from now on!\n");
1825         pic16_copypCode(asmFile, 'M');
1826
1827
1828         pic16_copypCode(asmFile, code->dbName);
1829
1830         pic16_copypCode(asmFile, 'P');
1831
1832         fprintf (asmFile,"\tend\n");
1833         fclose (asmFile);
1834
1835         rm_tmpfiles();
1836 }