* device/lib/Makefile.in: removed comment line with model-pic16,
[fw/sdcc] / src / pic16 / glue.c
1 /*-------------------------------------------------------------------------
2
3   glue.c - glues everything we have done together into one file.
4                 Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
24
25 #include "../common.h"
26 #include <time.h>
27 #include "ralloc.h"
28 #include "pcode.h"
29 #include "newalloc.h"
30 #include "gen.h"
31 #include "device.h"
32 #include "main.h"
33 #include <string.h>
34
35 #include <string.h>
36
37
38 #ifdef WORDS_BIGENDIAN
39   #define _ENDIAN(x)  (3-x)
40 #else
41   #define _ENDIAN(x)  (x)
42 #endif
43
44 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
45
46 extern symbol *interrupts[256];
47 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
48 extern int noAlloc;
49 extern set *publics;
50 extern set *externs;
51 extern unsigned maxInterrupts;
52 extern int maxRegBank;
53 extern symbol *mainf;
54 extern char *VersionString;
55 extern FILE *codeOutFile;
56 extern set *tmpfileSet;
57 extern set *tmpfileNameSet;
58 extern char *iComments1;
59 extern char *iComments2;
60 //extern void emitStaticSeg (memmap * map);
61
62 extern int initsfpnt;
63
64 set *rel_idataSymSet=NULL;
65 set *fix_idataSymSet=NULL;
66
67 extern DEFSETFUNC (closeTmpFiles);
68 extern DEFSETFUNC (rmTmpFiles);
69
70 extern void pic16_AnalyzeBanking (void);
71 extern void copyFile (FILE * dest, FILE * src);
72 extern void pic16_InlinepCode(void);
73 extern void pic16_writeUsedRegs(FILE *);
74
75 extern void initialComments (FILE * afile);
76 extern void printPublics (FILE * afile);
77
78 void  pic16_pCodeInitRegisters(void);
79 pCodeOp *pic16_popGetLit(unsigned int lit);
80 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2);
81 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
82 extern void pic16_pCodeConstString(char *name, char *value);
83
84 /*-----------------------------------------------------------------*/
85 /* aopLiteral - string from a literal value                        */
86 /*-----------------------------------------------------------------*/
87 int pic16aopLiteral (value *val, int offset)
88 {
89   union {
90     float f;
91     unsigned char c[4];
92   } fl;
93
94   /* if it is a float then it gets tricky */
95   /* otherwise it is fairly simple */
96   if (!IS_FLOAT(val->type)) {
97     unsigned long v = (unsigned long) floatFromVal(val);
98
99     return ( (v >> (offset * 8)) & 0xff);
100   }
101
102   /* it is type float */
103   fl.f = (float) floatFromVal(val);
104 #ifdef WORDS_BIGENDIAN
105   return fl.c[3-offset];
106 #else
107   return fl.c[offset];
108 #endif
109
110 }
111
112 iCode *tic;
113 symbol *nsym;
114 char tbuffer[512], *tbuf=tbuffer;;
115
116
117 /*-----------------------------------------------------------------*/
118 /* emitRegularMap - emit code for maps with no special cases       */
119 /*-----------------------------------------------------------------*/
120 static void
121 pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
122 {
123   symbol *sym;
124 //  int i, size, bitvars = 0;;
125
126 //      fprintf(stderr, "%s:%d map name= %s\n", __FUNCTION__, __LINE__, map->sname);
127         
128         if(addPublics)
129                 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
130                 /* print the area name */
131
132         for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) {
133
134 #if 0
135                 fprintf(stderr, "\t%s: sym: %s\tused: %d\textern: %d\tstatic: %d\n",
136                         map->sname, sym->name, sym->used, IS_EXTERN(sym->etype), IS_STATIC(sym->etype));
137                 printTypeChain( sym->type, stderr );
138                 fprintf(stderr, "\n");
139 #endif
140
141 //              if(PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
142 //                      continue;
143
144
145                 /* if extern then add to externs */
146                 if (IS_EXTERN (sym->etype)) {
147                         checkAddSym(&externs, sym);
148                         continue;
149                 }
150                 
151                 /* if allocation required check is needed
152                  *  then check if the symbol really requires
153                  * allocation only for local variables */
154                  if (arFlag && !IS_AGGREGATE (sym->type) &&
155                         !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
156                         !sym->allocreq && sym->level) {
157
158 //                      fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
159
160                         continue;
161                 }
162
163                 /* if global variable & not static or extern
164                  * and addPublics allowed then add it to the public set */
165                 if ((sym->used) && (sym->level == 0 ||
166                         (sym->_isparm && !IS_REGPARM (sym->etype))) &&
167                         addPublics &&
168                         !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
169                   
170                         checkAddSym(&publics, sym);
171 //                      addSetHead(&publics, sym);
172                 } else
173                         if(IS_STATIC(sym->etype)
174                                 && !(sym->ival && !sym->level)
175                         ) {
176                           regs *reg;
177                                 /* add it to udata list */
178
179 //                              fprintf(stderr, "%s:%d adding %s (%s) remat=%d\n", __FILE__, __LINE__,
180 //                                      sym->name, sym->rname, sym->remat);
181                                         
182                                                 //, OP_SYMBOL(operandFromSymbol(sym))->name);
183 #define SET_IMPLICIT    1
184
185 #if SET_IMPLICIT
186                                 if(IS_STRUCT(sym->type))
187                                         sym->implicit = 1;
188 #endif
189
190                                 reg = pic16_allocDirReg( operandFromSymbol( sym ));
191                                 checkAddReg(&pic16_rel_udata, reg);
192                         }
193
194                 /* if extern then do nothing or is a function
195                  * then do nothing */
196                 if (IS_FUNC (sym->type) && !IS_STATIC(sym->etype)) {
197                         if(SPEC_OCLS(sym->etype) == code) {
198 //                              fprintf(stderr, "%s:%d: symbol added: %s\n", __FILE__, __LINE__, sym->rname);
199                                 checkAddSym(&publics, sym);
200                         }
201                         continue;
202                 }
203
204 #if 0
205                 /* print extra debug info if required */
206                 if (options.debug || sym->level == 0) {
207                         cdbWriteSymbol (sym);   //, cdbFile, FALSE, FALSE);
208
209                         if (!sym->level)        /* global */
210                                 if (IS_STATIC (sym->etype))
211                                         fprintf (map->oFile, "F%s_", moduleName);               /* scope is file */
212                                 else
213                                         fprintf (map->oFile, "G_");     /* scope is global */
214                         else
215                                 /* symbol is local */
216                                 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
217                         fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
218                 }
219 #endif
220
221
222                 /* if is has an absolute address then generate
223                 an equate for this no need to allocate space */
224                 if (SPEC_ABSA (sym->etype)) {
225 //                      if (options.debug || sym->level == 0)
226 //                              fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
227 //                                      sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
228
229                         fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
230                                 sym->rname,
231                                 SPEC_ADDR (sym->etype));
232
233                         /* emit only if it is global */
234                         if(sym->level == 0) {
235                           regs *reg;
236
237                                 reg = pic16_dirregWithName( sym->name );
238                                 if(!reg) {
239                                         /* here */
240 //                                      fprintf(stderr, "%s:%d: implicit add of symbol = %s\n",
241 //                                                      __FUNCTION__, __LINE__, sym->name);
242
243                                         /* if IS_STRUCT is omitted the following
244                                          * fixes structures but break char/int etc */
245 #if SET_IMPLICIT
246                                         if(IS_STRUCT(sym->type))
247                                                 sym->implicit = 1;              // mark as implicit
248 #endif
249                                         if(!sym->ival) {
250                                                 reg = pic16_allocDirReg( operandFromSymbol(sym) );
251                                                 if(reg) {
252                                                         if(checkAddReg(&pic16_fix_udata, reg)) {
253                                                                 /* and add to globals list if not exist */
254                                                                 addSet(&publics, sym);
255                                                         }
256                                                 }
257                                         } else
258                                                 addSet(&publics, sym);
259                                 }
260                         }
261                 } else {
262                         if(!sym->used && (sym->level == 0)) {
263                           regs *reg;
264
265                                 /* symbol not used, just declared probably, but its in
266                                  * level 0, so we must declare it fine as global */
267                                 
268 //                              fprintf(stderr, "EXTRA symbol declaration sym= %s\n", sym->name);
269
270 #if SET_IMPLICIT
271                                 if(IS_STRUCT(sym->type))
272                                         sym->implicit = 1;              // mark as implicit
273 #endif
274                                 if(!sym->ival) {
275                                         reg = pic16_allocDirReg( operandFromSymbol( sym ) );
276                                         if(checkAddReg(&pic16_rel_udata, reg)) {
277                                                 addSetHead(&publics, sym);
278                                         }
279                                 } else
280                                         addSetHead(&publics, sym);
281                         }
282
283 #if 0
284                         /* allocate space */
285                         /* If this is a bit variable, then allocate storage after 8 bits have been declared */
286                         /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
287                         /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
288                         if (IS_BITVAR (sym->etype)) {
289                                 bitvars++;
290                         } else {
291                                 fprintf (map->oFile, "\t%s\n", sym->rname);
292                                 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
293                                         for (i = 1; i < size; i++)
294                                                 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
295                                 }
296                         }
297                         fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
298 #endif
299                 }
300         
301                 /* FIXME -- VR Fix the following, so that syms to be placed
302                  * in the idata section and let linker decide about their fate */
303
304                 /* if it has an initial value then do it only if
305                         it is a global variable */
306
307                 if (sym->ival && sym->level == 0) {
308                   ast *ival = NULL;
309
310 #if 0
311                         if(SPEC_OCLS(sym->etype)==data) {
312                                 fprintf(stderr, "%s: sym %s placed in data segment\n", map->sname, sym->name);
313                         }
314
315                         if(SPEC_OCLS(sym->etype)==code) {
316                                 fprintf(stderr, "%s: sym %s placed in code segment\n", map->sname, sym->name);
317                         }
318 #endif
319
320 //                      fprintf(stderr, "'%s': sym '%s' has initial value\n", map->sname, sym->name);
321
322                         if (IS_AGGREGATE (sym->type)) {
323                                 if(SPEC_ABSA(sym->etype))
324                                         addSet(&fix_idataSymSet, copySymbol(sym));
325                                 else
326                                         addSet(&rel_idataSymSet, copySymbol(sym));
327 //                              ival = initAggregates (sym, sym->ival, NULL);
328                         } else {
329                                 if(SPEC_ABSA(sym->etype))
330                                         addSet(&fix_idataSymSet, copySymbol(sym));
331                                 else
332                                         addSet(&rel_idataSymSet, copySymbol(sym));
333
334 //                                      ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
335 //                                              decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_CHECK));
336                         }
337
338                         if(ival) {
339                                 setAstLineno(ival, sym->lineDef);
340                                 codeOutFile = statsg->oFile;
341                                 GcurMemmap = statsg;
342                                 eBBlockFromiCode (iCodeFromAst (ival));
343                                 sym->ival = NULL;
344                         }
345                 }
346         }
347 }
348
349
350 /*-----------------------------------------------------------------*/
351 /* printIvalType - generates ival for int/char                     */
352 /*-----------------------------------------------------------------*/
353 static void 
354 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
355 {
356   value *val;
357   unsigned long ulval;
358
359   //fprintf(stderr, "%s\n",__FUNCTION__);
360
361   /* if initList is deep */
362   if (ilist->type == INIT_DEEP)
363     ilist = ilist->init.deep;
364
365   if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
366     werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
367   }
368
369   if (!(val = list2val (ilist))) {
370     // assuming a warning has been thrown
371     val=constVal("0");
372   }
373
374   if (val->type != type) {
375     val = valCastLiteral(type, floatFromVal(val));
376   }
377
378   if(val) 
379     ulval = (unsigned long) floatFromVal (val);
380   else
381     ulval =0;
382
383   switch (getSize (type)) {
384   case 1:
385     // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
386     pic16_emitDB(pb, BYTE_IN_LONG(ulval,0)); 
387     break;
388
389   case 2:
390     // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
391     // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
392     pic16_emitDB(pb, BYTE_IN_LONG(ulval,0)); 
393     pic16_emitDB(pb, BYTE_IN_LONG(ulval,1)); 
394     break;
395
396   case 4:
397     // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
398     // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
399     // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
400     // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
401     pic16_emitDB(pb, BYTE_IN_LONG(ulval,0)); 
402     pic16_emitDB(pb, BYTE_IN_LONG(ulval,1)); 
403     pic16_emitDB(pb, BYTE_IN_LONG(ulval,2)); 
404     pic16_emitDB(pb, BYTE_IN_LONG(ulval,3)); 
405     break;
406   }
407 }
408
409 /*-----------------------------------------------------------------*/
410 /* printIvalChar - generates initital value for character array    */
411 /*-----------------------------------------------------------------*/
412 static int 
413 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
414 {
415   value *val;
416   int remain;
417
418   if(!pb)
419     return 0;
420
421   // fprintf(stderr, "%s\n",__FUNCTION__);
422   if (!s)
423     {
424
425       val = list2val (ilist);
426       /* if the value is a character string  */
427       if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
428         {
429           if (!DCL_ELEM (type))
430             DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
431
432                 for(remain=0; remain<DCL_ELEM(type); remain++)
433                         pic16_emitDB(pb, SPEC_CVAL(val->etype).v_char[ remain ]);
434                         
435 //        pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";omitting call to printChar"));
436
437           if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
438             {
439               while (remain--)
440                 {
441                   //tfprintf (oFile, "\t!db !constbyte\n", 0);
442                   // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(0)));
443                   pic16_emitDB(pb,0);
444                 }
445             }
446           return 1;
447         }
448       else
449         return 0;
450     }
451   else {
452     //printChar (oFile, s, strlen (s) + 1);
453
454     for(remain=0; remain<strlen(s); remain++) 
455       {
456         // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(s[remain])));
457         //fprintf(stderr,"0x%02x ",s[remain]);
458         pic16_emitDB(pb, s[remain]);
459       }
460     //fprintf(stderr,"\n");
461   }
462   return 1;
463 }
464
465 /*-----------------------------------------------------------------*/
466 /* printIvalArray - generates code for array initialization        */
467 /*-----------------------------------------------------------------*/
468 static void 
469 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
470                 pBlock *pb)
471 {
472   initList *iloop;
473   int lcnt = 0, size = 0;
474
475   if(!pb)
476     return;
477
478
479   /* take care of the special   case  */
480   /* array of characters can be init  */
481   /* by a string                      */
482   if (IS_CHAR (type->next)) {
483     fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
484     if (!IS_LITERAL(list2val(ilist)->etype)) {
485       werror (W_INIT_WRONG);
486       return;
487     }
488
489         fprintf(stderr, "%s:%d adding %s to idata\n", __FILE__, __LINE__, sym->name);
490         if(SPEC_ABSA(sym->etype))
491                 addSet(&fix_idataSymSet, copySymbol(sym));
492         else
493                 addSet(&rel_idataSymSet, copySymbol(sym));
494
495     if (printIvalChar (type,
496                        (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
497                        pb, SPEC_CVAL (sym->etype).v_char))
498       return;
499   }
500   /* not the special case             */
501   if (ilist->type != INIT_DEEP)
502     {
503       werror (E_INIT_STRUCT, sym->name);
504       return;
505     }
506
507   iloop = ilist->init.deep;
508   lcnt = DCL_ELEM (type);
509
510   for (;;)
511     {
512       //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
513       size++;
514       printIval (sym, type->next, iloop, pb);
515       iloop = (iloop ? iloop->next : NULL);
516
517
518       /* if not array limits given & we */
519       /* are out of initialisers then   */
520       if (!DCL_ELEM (type) && !iloop)
521         break;
522
523       /* no of elements given and we    */
524       /* have generated for all of them */
525       if (!--lcnt) {
526         /* if initializers left */
527         if (iloop) {
528           werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
529         }
530         break;
531       }
532     }
533
534   /* if we have not been given a size  */
535   if (!DCL_ELEM (type))
536     DCL_ELEM (type) = size;
537
538   return;
539 }
540
541
542
543 /*-----------------------------------------------------------------*/
544 /* printIval - generates code for initial value                    */
545 /*-----------------------------------------------------------------*/
546 static void 
547 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
548 {
549   if (!ilist || !pb)
550     return;
551
552 //      fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
553
554   /* if structure then    */
555   if (IS_STRUCT (type))
556     {
557       //fprintf(stderr,"%s struct\n",__FUNCTION__);
558       //printIvalStruct (sym, type, ilist, oFile);
559         fprintf(stderr, "%s:%d: PIC16 port error: structure initialisation is not implemented yet.\n",
560                 __FILE__, __LINE__);
561         abort();
562       return;
563     }
564
565   /* if this is a pointer */
566   if (IS_PTR (type))
567     {
568       //fprintf(stderr,"%s pointer\n",__FUNCTION__);
569       //printIvalPtr (sym, type, ilist, oFile);
570         fprintf(stderr, "%s:%d: PIC16 port error: pointer initialisation is not implemented yet.\n",
571                 __FILE__, __LINE__);
572         abort();
573       return;
574     }
575
576   /* if this is an array   */
577   if (IS_ARRAY (type))
578     {
579       //fprintf(stderr,"%s array\n",__FUNCTION__);
580       printIvalArray (sym, type, ilist, pb);
581       return;
582     }
583
584   /* if type is SPECIFIER */
585   if (IS_SPEC (type))
586     {
587       //fprintf(stderr,"%s spec\n",__FUNCTION__);
588       printIvalType (sym, type, ilist, pb);
589       return;
590     }
591 }
592
593 int PIC16_IS_CONFIG_ADDRESS(int address)
594 {
595
596   return (address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd);
597 }
598
599 /*-----------------------------------------------------------------*/
600 /* emitStaticSeg - emitcode for the static segment                 */
601 /*-----------------------------------------------------------------*/
602 static void
603 pic16emitStaticSeg (memmap * map)
604 {
605   symbol *sym;
606
607   fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
608
609   //fprintf(stderr, "%s\n",__FUNCTION__);
610
611   /* for all variables in this segment do */
612   for (sym = setFirstItem (map->syms); sym;
613        sym = setNextItem (map->syms))
614     {
615
616 #if 0
617         fprintf(stderr, "\t%s: sym: %s\tused: %d\n", map->sname, sym->name, sym->used);
618         printTypeChain( sym->type, stderr );
619         fprintf(stderr, "\n");
620 #endif
621
622         if(SPEC_ABSA(sym->etype)
623              && (SPEC_ABSA(sym->etype) && PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))) {
624              
625                 pic16_assignConfigWordValue(SPEC_ADDR (sym->etype),
626                         (int) floatFromVal(list2val( sym->ival )));
627
628                 continue;
629         }
630
631         /* if it is "extern" then do nothing */
632         if (IS_EXTERN (sym->etype)) {
633
634                 /* do not emit if it is a config word declaration */
635                 if(!SPEC_ABSA(sym->etype)
636                         || (SPEC_ABSA(sym->etype) && !PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))))
637                         checkAddSym(&externs, sym);
638           continue;
639         }
640
641         /* if it is not static add it to the public
642            table */
643         if (!IS_STATIC (sym->etype)) {
644                 /* do not emit if it is a config word declaration */
645                 checkAddSym(&publics, sym);
646         }
647
648 #if 0
649       /* print extra debug info if required */
650       if (options.debug || sym->level == 0)
651         {
652           /* NOTE to me - cdbFile may be null in which case,
653            * the sym name will be printed to stdout. oh well */
654           if(cdbFile)
655             cdbSymbol (sym, cdbFile, FALSE, FALSE);
656
657           if (!sym->level)
658             {                   /* global */
659               if (IS_STATIC (sym->etype))
660                 fprintf (code->oFile, "F%s_", moduleName);      /* scope is file */
661               else
662                 fprintf (code->oFile, "G_");    /* scope is global */
663             }
664           else
665             /* symbol is local */
666             fprintf (code->oFile, "L%s_",
667                      (sym->localof ? sym->localof->name : "-null-"));
668           fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
669
670         }
671 #endif
672
673       /* if it has an absolute address */
674       if (SPEC_ABSA (sym->etype))
675         {
676                 fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
677                         __FILE__, __LINE__, sym->name);
678                         
679           if (options.debug || sym->level == 0)
680             fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
681
682           fprintf (code->oFile, "%s\t=\t0x%04x\n",
683                    sym->rname,
684                    SPEC_ADDR (sym->etype));
685
686           /* if it has an initial value */
687           if (sym->ival)
688             {
689               pBlock *pb;
690               symbol *asym;
691               absSym *abSym;
692               pCode *pcf;
693               
694               noAlloc++;
695               resolveIvalSym (sym->ival, sym->type);
696               asym = newSymbol(sym->rname, 0);
697               abSym = Safe_calloc(1, sizeof(absSym));
698               abSym->name = Safe_strdup( sym->rname );
699               abSym->address = SPEC_ADDR( sym->etype );
700               addSet(&absSymSet, abSym);
701               
702               pb = pic16_newpCodeChain(NULL, 'A',pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
703               pic16_addpBlock(pb);
704
705               pcf = pic16_newpCodeFunction(moduleName, asym->name);
706               PCF(pcf)->absblock = 1;
707               
708               pic16_addpCode2pBlock(pb,pcf);
709               pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
710               printIval (sym, sym->type, sym->ival, pb);
711               pic16_flushDB(pb);
712
713               pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(NULL, NULL));
714               noAlloc--;
715             }
716           else
717             {
718
719               /* allocate space */
720               fprintf (code->oFile, "%s:\n", sym->rname);
721               /* special case for character strings */
722               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
723                   SPEC_CVAL (sym->etype).v_char)
724                 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
725                 /*printChar (code->oFile,
726                            SPEC_CVAL (sym->etype).v_char,
727                            strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
728               else
729                 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
730             }
731   
732         } else {
733 //              fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
734 //                      __FILE__, __LINE__, sym->name);
735
736           if (options.debug || sym->level == 0)
737             fprintf (code->oFile, " == .\n");
738
739           /* if it has an initial value */
740           if (sym->ival)
741             {
742               pBlock *pb;
743
744               fprintf (code->oFile, "%s:\n", sym->rname);
745               noAlloc++;
746               resolveIvalSym (sym->ival, sym->type);
747               //printIval (sym, sym->type, sym->ival, code->oFile);
748               pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
749               pic16_addpBlock(pb);
750               pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
751
752               printIval (sym, sym->type, sym->ival, pb);
753               pic16_flushDB(pb);
754               noAlloc--;
755             }
756           else
757             {
758
759               /* allocate space */
760               fprintf (code->oFile, "%s:\n", sym->rname);
761               /* special case for character strings */
762               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
763                   SPEC_CVAL (sym->etype).v_char)
764                 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
765                 /*printChar (code->oFile,
766                            SPEC_CVAL (sym->etype).v_char,
767                            strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
768               else
769                 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
770             }
771         }
772     }
773
774 }
775
776
777 /*-----------------------------------------------------------------*/
778 /* pic16_emitConfigRegs - emits the configuration registers              */
779 /*-----------------------------------------------------------------*/
780 void pic16_emitConfigRegs(FILE *of)
781 {
782   int i;
783
784         for(i=0;i<pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart;i++)
785                 if(pic16->cwInfo.crInfo[i].emit)        //mask != -1)
786                         fprintf (of, "\t__config 0x%x, 0x%hhx\n",
787                                 pic16->cwInfo.confAddrStart+i,
788                                 pic16->cwInfo.crInfo[i].value);
789 }
790
791
792 static void
793 pic16emitMaps ()
794 {
795   /* no special considerations for the following
796      data, idata & bit & xdata */
797   pic16emitRegularMap (data, TRUE, TRUE);
798   pic16emitRegularMap (idata, TRUE, TRUE);
799   pic16emitRegularMap (bit, TRUE, FALSE);
800   pic16emitRegularMap (xdata, TRUE, TRUE);
801   pic16emitRegularMap (sfr, FALSE, FALSE);
802   pic16emitRegularMap (sfrbit, FALSE, FALSE);
803   pic16emitRegularMap (code, TRUE, FALSE);
804   pic16emitStaticSeg (statsg);
805 }
806
807 /*-----------------------------------------------------------------*/
808 /* createInterruptVect - creates the interrupt vector              */
809 /*-----------------------------------------------------------------*/
810 static void
811 pic16createInterruptVect (FILE * vFile)
812 {
813         /* if the main is only a prototype ie. no body then do nothing */
814 #if 0
815         if (!IFFUNC_HASBODY(mainf->type)) {
816                 /* if ! compile only then main function should be present */
817                 if (!options.cc_only)
818                         werror (E_NO_MAIN);
819                 return;
820         }
821 #endif
822
823         if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
824                 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
825                 fprintf(vFile, ".intvecs\tcode\t0x0000\n");
826                 fprintf (vFile, "__interrupt_vect:\n");
827
828                 /* this is an overkill since WE are the port,
829                  * and we know if we have a genIVT function! */
830                 if(port->genIVT) {
831                         port->genIVT(vFile, interrupts, maxInterrupts);
832                 }
833         }
834         
835 }
836
837
838 /*-----------------------------------------------------------------*/
839 /* pic16initialComments - puts in some initial comments            */
840 /*-----------------------------------------------------------------*/
841 static void
842 pic16initialComments (FILE * afile)
843 {
844   initialComments (afile);
845   fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
846   fprintf (afile, iComments2);
847
848 }
849
850 /*-----------------------------------------------------------------*/
851 /* printPublics - generates global declarations for publics        */
852 /*-----------------------------------------------------------------*/
853 static void
854 pic16printPublics (FILE *afile)
855 {
856   symbol *sym;
857
858         fprintf (afile, "%s", iComments2);
859         fprintf (afile, "; public variables in this module\n");
860         fprintf (afile, "%s", iComments2);
861
862         for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
863                 fprintf(afile, "\tglobal %s\n", sym->rname);
864 }
865
866 /*-----------------------------------------------------------------*/
867 /* printExterns - generates extern declarations for externs        */
868 /*-----------------------------------------------------------------*/
869 static void
870 pic16_printExterns(FILE *afile)
871 {
872   symbol *sym;
873
874         fprintf(afile, "%s", iComments2);
875         fprintf(afile, "; extern variables in this module\n");
876         fprintf(afile, "%s", iComments2);
877         
878         for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
879                 fprintf(afile, "\textern %s\n", sym->rname);
880
881         for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
882                 fprintf(afile, "\textern _%s\n", sym->name);
883 }
884
885 /*-----------------------------------------------------------------*/
886 /* emitOverlay - will emit code for the overlay stuff              */
887 /*-----------------------------------------------------------------*/
888 static void
889 pic16emitOverlay (FILE * afile)
890 {
891   set *ovrset;
892
893   if (!elementsInSet (ovrSetSets))
894     fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
895
896   /* for each of the sets in the overlay segment do */
897   for (ovrset = setFirstItem (ovrSetSets); ovrset;
898        ovrset = setNextItem (ovrSetSets))
899     {
900
901       symbol *sym;
902
903       if (elementsInSet (ovrset))
904         {
905           /* this dummy area is used to fool the assembler
906              otherwise the assembler will append each of these
907              declarations into one chunk and will not overlay
908              sad but true */
909           fprintf (afile, ";\t.area _DUMMY\n");
910           /* output the area informtion */
911           fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);    /* MOF */
912         }
913
914       for (sym = setFirstItem (ovrset); sym;
915            sym = setNextItem (ovrset))
916         {
917
918           /* if extern then do nothing */
919           if (IS_EXTERN (sym->etype))
920             continue;
921
922           /* if allocation required check is needed
923              then check if the symbol really requires
924              allocation only for local variables */
925           if (!IS_AGGREGATE (sym->type) &&
926               !(sym->_isparm && !IS_REGPARM (sym->etype))
927               && !sym->allocreq && sym->level)
928             continue;
929
930           /* if global variable & not static or extern
931              and addPublics allowed then add it to the public set */
932           if ((sym->_isparm && !IS_REGPARM (sym->etype))
933               && !IS_STATIC (sym->etype)) {
934               checkAddSym(&publics, sym);
935 //          addSetHead (&publics, sym);
936           }
937
938           /* if extern then do nothing or is a function
939              then do nothing */
940           if (IS_FUNC (sym->type))
941             continue;
942
943 #if 0
944           /* print extra debug info if required */
945           if (options.debug || sym->level == 0)
946             {
947
948               cdbSymbol (sym, cdbFile, FALSE, FALSE);
949
950               if (!sym->level)
951                 {               /* global */
952                   if (IS_STATIC (sym->etype))
953                     fprintf (afile, "F%s_", moduleName);        /* scope is file */
954                   else
955                     fprintf (afile, "G_");      /* scope is global */
956                 }
957               else
958                 /* symbol is local */
959                 fprintf (afile, "L%s_",
960                          (sym->localof ? sym->localof->name : "-null-"));
961               fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
962             }
963 #endif
964
965           /* if is has an absolute address then generate
966              an equate for this no need to allocate space */
967           if (SPEC_ABSA (sym->etype))
968             {
969
970               if (options.debug || sym->level == 0)
971                 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
972
973               fprintf (afile, "%s\t=\t0x%04x\n",
974                        sym->rname,
975                        SPEC_ADDR (sym->etype));
976             }
977           else
978             {
979               if (options.debug || sym->level == 0)
980                 fprintf (afile, "==.\n");
981
982               /* allocate space */
983               fprintf (afile, "%s:\n", sym->rname);
984               fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
985             }
986
987         }
988     }
989 }
990
991
992 /*-----------------------------------------------------------------*/
993 /* glue - the final glue that hold the whole thing together        */
994 /*-----------------------------------------------------------------*/
995 void
996 pic16glue ()
997 {
998
999   FILE *vFile;
1000   FILE *asmFile;
1001   FILE *ovrFile = tempfile();
1002
1003
1004         mainf = newSymbol ("main", 0);
1005         mainf->block = 0;
1006
1007         mainf = findSymWithLevel(SymbolTab, mainf);
1008 #if 0
1009         /* only if the main function exists */
1010         if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
1011                 if (!options.cc_only)
1012                         werror (E_NO_MAIN);
1013                 return;
1014         }
1015 #endif
1016
1017 //      fprintf(stderr, "main function= %p (%s)\thas body= %d\n", mainf, (mainf?mainf->name:NULL), mainf?IFFUNC_HASBODY(mainf->type):-1);
1018
1019         addSetHead(&tmpfileSet,ovrFile);
1020         pic16_pCodeInitRegisters();
1021
1022         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1023           pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1024
1025                 pic16_addpBlock(pb);
1026
1027                 /* entry point @ start of CSEG */
1028                 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1029
1030                 if(initsfpnt) {
1031                         pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1032                                 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("stack"))));
1033                         pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1034                                 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("stack"))));
1035                 }
1036
1037                 /* put in the call to main */
1038                 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1039
1040                 if (options.mainreturn) {
1041                         pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1042                         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1043                 } else {
1044                         pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1045                         pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1046                 }
1047         }
1048
1049         /* At this point we've got all the code in the form of pCode structures */
1050         /* Now it needs to be rearranged into the order it should be placed in the */
1051         /* code space */
1052
1053         pic16_movepBlock2Head('P');              // Last
1054         pic16_movepBlock2Head(code->dbName);
1055         pic16_movepBlock2Head('X');
1056         pic16_movepBlock2Head(statsg->dbName);   // First
1057
1058         /* print the global struct definitions */
1059 //      if (options.debug)
1060 //              cdbStructBlock (0);     //,cdbFile);
1061
1062         vFile = tempfile();
1063         /* PENDING: this isnt the best place but it will do */
1064         if (port->general.glue_up_main) {
1065                 /* create the interrupt vector table */
1066                 pic16createInterruptVect (vFile);
1067         }
1068
1069         addSetHead(&tmpfileSet,vFile);
1070     
1071         /* emit code for the all the variables declared */
1072         pic16emitMaps ();
1073         /* do the overlay segments */
1074         pic16emitOverlay(ovrFile);
1075         pic16_AnalyzepCode('*');
1076
1077 #if 0
1078         {
1079           FILE *cFile;
1080                 sprintf(buffer, dstFileName);
1081                 strcat(buffer, ".calltree");
1082                 cFile = fopen(buffer, "w");
1083                 pic16_printCallTree( cFile );
1084                 fclose(cFile);
1085         }
1086 #endif
1087
1088         pic16_InlinepCode();
1089         pic16_AnalyzepCode('*');
1090
1091         if(pic16_debug_verbose)
1092                 pic16_pcode_test();
1093
1094         /* now put it all together into the assembler file */
1095         /* create the assembler file name */
1096         if ((noAssemble || options.c1mode)  && fullDstFileName) {
1097                 sprintf (buffer, fullDstFileName);
1098         } else {
1099                 sprintf (buffer, dstFileName);
1100                 strcat (buffer, ".asm");
1101         }
1102
1103         if (!(asmFile = fopen (buffer, "w"))) {
1104                 werror (E_FILE_OPEN_ERR, buffer);
1105                 exit (1);
1106         }
1107     
1108         /* initial comments */
1109         pic16initialComments (asmFile);
1110     
1111         /* print module name */
1112         fprintf(asmFile, "#FILE\t\"%s\"\n", fullSrcFileName);
1113     
1114         /* Let the port generate any global directives, etc. */
1115         if (port->genAssemblerPreamble) {
1116                 port->genAssemblerPreamble(asmFile);
1117         }
1118     
1119         /* print the extern variables to this module */
1120         pic16_printExterns(asmFile);
1121   
1122         /* print the global variables in this module */
1123         pic16printPublics (asmFile);
1124
1125 #if 0
1126         /* copy the sfr segment */
1127         fprintf (asmFile, "%s", iComments2);
1128         fprintf (asmFile, "; special function registers\n");
1129         fprintf (asmFile, "%s", iComments2);
1130         copyFile (asmFile, sfr->oFile);
1131 #endif
1132     
1133
1134         /* Put all variables into a cblock */
1135         pic16_AnalyzeBanking();
1136         pic16_writeUsedRegs(asmFile);
1137
1138 #if 0
1139         /* create the overlay segments */
1140         fprintf (asmFile, "%s", iComments2);
1141         fprintf (asmFile, "; overlayable items in internal ram \n");
1142         fprintf (asmFile, "%s", iComments2);    
1143         copyFile (asmFile, ovrFile);
1144 #endif
1145
1146 #if 0
1147
1148         /* create the stack segment MOF */
1149         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1150                 fprintf (asmFile, "%s", iComments2);
1151                 fprintf (asmFile, "; Stack segment in internal ram \n");
1152                 fprintf (asmFile, "%s", iComments2);    
1153                 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1154                         ";__start__stack:\n;\t.ds\t1\n\n");
1155         }
1156 #endif
1157
1158 #if 0
1159         /* no indirect data in pic */
1160         /* create the idata segment */
1161         fprintf (asmFile, "%s", iComments2);
1162         fprintf (asmFile, "; indirectly addressable internal ram data\n");
1163         fprintf (asmFile, "%s", iComments2);
1164         copyFile (asmFile, idata->oFile);
1165 #endif
1166
1167
1168 #if 0
1169         /* no xdata in pic */
1170         /* if external stack then reserve space of it */
1171         if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1172                 fprintf (asmFile, "%s", iComments2);
1173                 fprintf (asmFile, "; external stack \n");
1174                 fprintf (asmFile, "%s", iComments2);
1175                 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1176                 fprintf (asmFile,";\t.ds 256\n");
1177         }
1178 #endif
1179
1180 #if 0   
1181         /* no xdata in pic */
1182         /* copy xtern ram data */
1183         fprintf (asmFile, "%s", iComments2);
1184         fprintf (asmFile, "; external ram data\n");
1185         fprintf (asmFile, "%s", iComments2);
1186         copyFile (asmFile, xdata->oFile);
1187 #endif
1188
1189 #if 0
1190         /* copy the bit segment */
1191         fprintf (asmFile, "%s", iComments2);
1192         fprintf (asmFile, "; bit data\n");
1193         fprintf (asmFile, "%s", iComments2);
1194         copyFile (asmFile, bit->oFile);
1195 #endif
1196
1197         /* copy the interrupt vector table */
1198         if(mainf && IFFUNC_HASBODY(mainf->type)) {
1199                 fprintf (asmFile, "%s", iComments2);
1200                 fprintf (asmFile, "; interrupt vector \n");
1201                 fprintf (asmFile, "%s", iComments2);
1202                 copyFile (asmFile, vFile);
1203         }
1204     
1205         /* copy global & static initialisations */
1206         fprintf (asmFile, "%s", iComments2);
1207         fprintf (asmFile, "; global & static initialisations\n");
1208         fprintf (asmFile, "%s", iComments2);
1209     
1210 #if 0
1211         /* copy over code */
1212         fprintf (asmFile, "%s", iComments2);
1213         fprintf (asmFile, "\tcode\n");
1214         fprintf (asmFile, "%s", iComments2);
1215 #endif
1216
1217         if(pic16_debug_verbose)
1218                 fprintf(asmFile, "; A code from now on!\n");
1219         pic16_copypCode(asmFile, 'A');
1220
1221
1222         if(mainf && IFFUNC_HASBODY(mainf->type)) {
1223                 fprintf(asmFile, "\tcode\n");
1224                 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1225
1226 #if 0
1227                 /* FIXME 8051 legacy (?!) - VR 20-Jun-2003 */
1228                 /* if external stack is specified then the
1229                  * higher order byte of the xdatalocation is
1230                  * going into P2 and the lower order going into */
1231         
1232                 if (options.useXstack) {
1233                         fprintf(asmFile,";\tmov\tP2,#0x%02x\n",
1234                                         (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1235                         fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
1236                                         (unsigned int)options.xdata_loc & 0xff);
1237                 }
1238 #endif
1239         }
1240
1241 //      copyFile (stderr, code->oFile);
1242
1243         fprintf(asmFile, "; I code from now on!\n");
1244         pic16_copypCode(asmFile, 'I');
1245
1246         if(pic16_debug_verbose)
1247                 fprintf(asmFile, "; dbName from now on!\n");
1248         pic16_copypCode(asmFile, statsg->dbName);
1249
1250
1251         if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1252                 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1253         }
1254         
1255
1256         if(pic16_debug_verbose)
1257                 fprintf(asmFile, "; X code from now on!\n");
1258         pic16_copypCode(asmFile, 'X');
1259
1260         if(pic16_debug_verbose)
1261                 fprintf(asmFile, "; M code from now on!\n");
1262         pic16_copypCode(asmFile, 'M');
1263
1264
1265         pic16_copypCode(asmFile, code->dbName);
1266
1267         pic16_copypCode(asmFile, 'P');
1268
1269         fprintf (asmFile,"\tend\n");
1270         fclose (asmFile);
1271
1272         rm_tmpfiles();
1273 }