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