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