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