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