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