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