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