2004-10-16 Vangelis Rokas <vrokas AT otenet.gr>
[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               strcpy(abSym->name, 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         if(options.debug) {
1455                 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]\"\n",
1456                                 SDCC_VERSION_STR, getBuildNumber() );
1457         }
1458 }
1459
1460 /*-----------------------------------------------------------------*/
1461 /* printPublics - generates global declarations for publics        */
1462 /*-----------------------------------------------------------------*/
1463 static void
1464 pic16printPublics (FILE *afile)
1465 {
1466   symbol *sym;
1467
1468         fprintf (afile, "\n%s", iComments2);
1469         fprintf (afile, "; public variables in this module\n");
1470         fprintf (afile, "%s", iComments2);
1471
1472         for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1473                 fprintf(afile, "\tglobal %s\n", sym->rname);
1474 }
1475
1476 /*-----------------------------------------------------------------*/
1477 /* printExterns - generates extern declarations for externs        */
1478 /*-----------------------------------------------------------------*/
1479 static void
1480 pic16_printExterns(FILE *afile)
1481 {
1482   symbol *sym;
1483
1484         /* print nothing if no externs to declare */
1485         if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1486                 return;
1487
1488         fprintf(afile, "\n%s", iComments2);
1489         fprintf(afile, "; extern variables in this module\n");
1490         fprintf(afile, "%s", iComments2);
1491         
1492         for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1493                 fprintf(afile, "\textern %s\n", sym->rname);
1494
1495         for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1496                 fprintf(afile, "\textern _%s\n", sym->name);
1497 }
1498
1499 /*-----------------------------------------------------------------*/
1500 /* emitOverlay - will emit code for the overlay stuff              */
1501 /*-----------------------------------------------------------------*/
1502 static void
1503 pic16emitOverlay (FILE * afile)
1504 {
1505   set *ovrset;
1506
1507   if (!elementsInSet (ovrSetSets))
1508     fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
1509
1510   /* for each of the sets in the overlay segment do */
1511   for (ovrset = setFirstItem (ovrSetSets); ovrset;
1512        ovrset = setNextItem (ovrSetSets))
1513     {
1514
1515       symbol *sym;
1516
1517       if (elementsInSet (ovrset))
1518         {
1519           /* this dummy area is used to fool the assembler
1520              otherwise the assembler will append each of these
1521              declarations into one chunk and will not overlay
1522              sad but true */
1523           fprintf (afile, ";\t.area _DUMMY\n");
1524           /* output the area informtion */
1525           fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);    /* MOF */
1526         }
1527
1528       for (sym = setFirstItem (ovrset); sym;
1529            sym = setNextItem (ovrset))
1530         {
1531
1532           /* if extern then do nothing */
1533           if (IS_EXTERN (sym->etype))
1534             continue;
1535
1536           /* if allocation required check is needed
1537              then check if the symbol really requires
1538              allocation only for local variables */
1539           if (!IS_AGGREGATE (sym->type) &&
1540               !(sym->_isparm && !IS_REGPARM (sym->etype))
1541               && !sym->allocreq && sym->level)
1542             continue;
1543
1544           /* if global variable & not static or extern
1545              and addPublics allowed then add it to the public set */
1546           if ((sym->_isparm && !IS_REGPARM (sym->etype))
1547               && !IS_STATIC (sym->etype)) {
1548 //            fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1549               checkAddSym(&publics, sym);
1550 //          addSetHead (&publics, sym);
1551           }
1552
1553           /* if extern then do nothing or is a function
1554              then do nothing */
1555           if (IS_FUNC (sym->type))
1556             continue;
1557
1558 #if 0
1559           /* print extra debug info if required */
1560           if (options.debug || sym->level == 0)
1561             {
1562
1563               cdbSymbol (sym, cdbFile, FALSE, FALSE);
1564
1565               if (!sym->level)
1566                 {               /* global */
1567                   if (IS_STATIC (sym->etype))
1568                     fprintf (afile, "F%s_", moduleName);        /* scope is file */
1569                   else
1570                     fprintf (afile, "G_");      /* scope is global */
1571                 }
1572               else
1573                 /* symbol is local */
1574                 fprintf (afile, "L%s_",
1575                          (sym->localof ? sym->localof->name : "-null-"));
1576               fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
1577             }
1578 #endif
1579
1580           /* if is has an absolute address then generate
1581              an equate for this no need to allocate space */
1582           if (SPEC_ABSA (sym->etype))
1583             {
1584
1585               if (options.debug || sym->level == 0)
1586                 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1587
1588               fprintf (afile, "%s\t=\t0x%04x\n",
1589                        sym->rname,
1590                        SPEC_ADDR (sym->etype));
1591             }
1592           else
1593             {
1594               if (options.debug || sym->level == 0)
1595                 fprintf (afile, "==.\n");
1596
1597               /* allocate space */
1598               fprintf (afile, "%s:\n", sym->rname);
1599               fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1600             }
1601
1602         }
1603     }
1604 }
1605
1606
1607 /*-----------------------------------------------------------------*/
1608 /* glue - the final glue that hold the whole thing together        */
1609 /*-----------------------------------------------------------------*/
1610 void
1611 pic16glue ()
1612 {
1613
1614   FILE *vFile;
1615   FILE *asmFile;
1616   FILE *ovrFile = tempfile();
1617
1618
1619         mainf = newSymbol ("main", 0);
1620         mainf->block = 0;
1621
1622         mainf = findSymWithLevel(SymbolTab, mainf);
1623 #if 0
1624         /* only if the main function exists */
1625         if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
1626                 if (!options.cc_only)
1627                         werror (E_NO_MAIN);
1628                 return;
1629         }
1630 #endif
1631
1632 //      fprintf(stderr, "main function= %p (%s)\thas body= %d\n", mainf, (mainf?mainf->name:NULL), mainf?IFFUNC_HASBODY(mainf->type):-1);
1633
1634         addSetHead(&tmpfileSet,ovrFile);
1635         pic16_pCodeInitRegisters();
1636
1637
1638         if (pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1639           pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1640
1641                 pic16_addpBlock(pb);
1642
1643                 /* entry point @ start of CSEG */
1644                 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1645
1646                 if(initsfpnt) {
1647                         pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1648                                 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1649                         pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1650                                 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1651                 }
1652
1653                 /* put in the call to main */
1654                 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1655
1656                 if (options.mainreturn) {
1657                         pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1658                         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1659                 } else {
1660                         pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1661                         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1662                 }
1663         }
1664
1665         /* At this point we've got all the code in the form of pCode structures */
1666         /* Now it needs to be rearranged into the order it should be placed in the */
1667         /* code space */
1668
1669         pic16_movepBlock2Head('P');              // Last
1670         pic16_movepBlock2Head(code->dbName);
1671         pic16_movepBlock2Head('X');
1672         pic16_movepBlock2Head(statsg->dbName);   // First
1673
1674         /* print the global struct definitions */
1675 //      if (options.debug)
1676 //              cdbStructBlock (0);     //,cdbFile);
1677
1678         vFile = tempfile();
1679         /* PENDING: this isnt the best place but it will do */
1680         if (port->general.glue_up_main) {
1681                 /* create the interrupt vector table */
1682                 pic16createInterruptVect (vFile);
1683         }
1684
1685         addSetHead(&tmpfileSet,vFile);
1686     
1687         /* emit code for the all the variables declared */
1688         pic16emitMaps ();
1689         /* do the overlay segments */
1690         pic16emitOverlay(ovrFile);
1691         pic16_AnalyzepCode('*');
1692
1693 #if 1
1694         if(pic16_options.dumpcalltree) {
1695           FILE *cFile;
1696                 sprintf(buffer, dstFileName);
1697                 strcat(buffer, ".calltree");
1698                 cFile = fopen(buffer, "w");
1699                 pic16_printCallTree( cFile );
1700                 fclose(cFile);
1701         }
1702 #endif
1703
1704         pic16_InlinepCode();
1705         pic16_AnalyzepCode('*');
1706
1707         if(pic16_debug_verbose)
1708                 pic16_pcode_test();
1709
1710         /* now put it all together into the assembler file */
1711         /* create the assembler file name */
1712         if ((noAssemble || options.c1mode)  && fullDstFileName) {
1713                 sprintf (buffer, fullDstFileName);
1714         } else {
1715                 sprintf (buffer, dstFileName);
1716                 strcat (buffer, ".asm");
1717         }
1718
1719         if (!(asmFile = fopen (buffer, "w"))) {
1720                 werror (E_FILE_OPEN_ERR, buffer);
1721                 exit (1);
1722         }
1723     
1724         /* initial comments */
1725         pic16initialComments (asmFile);
1726
1727         /* print module name */
1728         if(options.debug)
1729                 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1730
1731         /* Let the port generate any global directives, etc. */
1732         if (port->genAssemblerPreamble) {
1733                 port->genAssemblerPreamble(asmFile);
1734         }
1735         
1736         /* print the extern variables to this module */
1737         pic16_printExterns(asmFile);
1738         
1739         /* print the global variables in this module */
1740         pic16printPublics (asmFile);
1741
1742 #if 0
1743         /* copy the sfr segment */
1744         fprintf (asmFile, "%s", iComments2);
1745         fprintf (asmFile, "; special function registers\n");
1746         fprintf (asmFile, "%s", iComments2);
1747         copyFile (asmFile, sfr->oFile);
1748 #endif
1749
1750         /* Put all variables into a cblock */
1751         pic16_AnalyzeBanking();
1752         pic16_writeUsedRegs(asmFile);
1753
1754 #if 0
1755         /* no xdata in pic */
1756         /* if external stack then reserve space of it */
1757         if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1758                 fprintf (asmFile, "%s", iComments2);
1759                 fprintf (asmFile, "; external stack \n");
1760                 fprintf (asmFile, "%s", iComments2);
1761                 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1762                 fprintf (asmFile,";\t.ds 256\n");
1763         }
1764 #endif
1765
1766 #if 0   
1767         /* no xdata in pic */
1768         /* copy xtern ram data */
1769         fprintf (asmFile, "%s", iComments2);
1770         fprintf (asmFile, "; external ram data\n");
1771         fprintf (asmFile, "%s", iComments2);
1772         copyFile (asmFile, xdata->oFile);
1773 #endif
1774
1775 #if 0
1776         /* copy the bit segment */
1777         fprintf (asmFile, "%s", iComments2);
1778         fprintf (asmFile, "; bit data\n");
1779         fprintf (asmFile, "%s", iComments2);
1780         copyFile (asmFile, bit->oFile);
1781 #endif
1782
1783         /* copy the interrupt vector table */
1784         if(mainf && IFFUNC_HASBODY(mainf->type)) {
1785                 fprintf (asmFile, "\n%s", iComments2);
1786                 fprintf (asmFile, "; interrupt vector \n");
1787                 fprintf (asmFile, "%s", iComments2);
1788                 copyFile (asmFile, vFile);
1789         }
1790     
1791         /* copy global & static initialisations */
1792         fprintf (asmFile, "\n%s", iComments2);
1793         fprintf (asmFile, "; global & static initialisations\n");
1794         fprintf (asmFile, "%s", iComments2);
1795     
1796         if(pic16_debug_verbose)
1797                 fprintf(asmFile, "; A code from now on!\n");
1798         pic16_copypCode(asmFile, 'A');
1799
1800
1801         if(pic16_options.no_crt) {
1802                 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1803                         fprintf(asmFile, "\tcode\n");
1804                         fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1805                 }
1806         }
1807
1808 //      copyFile (stderr, code->oFile);
1809
1810         fprintf(asmFile, "; I code from now on!\n");
1811         pic16_copypCode(asmFile, 'I');
1812
1813         if(pic16_debug_verbose)
1814                 fprintf(asmFile, "; dbName from now on!\n");
1815         pic16_copypCode(asmFile, statsg->dbName);
1816
1817
1818         if(pic16_options.no_crt) {
1819                 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1820                         fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1821                 }
1822         }
1823         
1824
1825         if(pic16_debug_verbose)
1826                 fprintf(asmFile, "; X code from now on!\n");
1827         pic16_copypCode(asmFile, 'X');
1828
1829         if(pic16_debug_verbose)
1830                 fprintf(asmFile, "; M code from now on!\n");
1831         pic16_copypCode(asmFile, 'M');
1832
1833
1834         pic16_copypCode(asmFile, code->dbName);
1835
1836         pic16_copypCode(asmFile, 'P');
1837
1838         fprintf (asmFile,"\tend\n");
1839         fclose (asmFile);
1840
1841         rm_tmpfiles();
1842 }