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