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