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