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