- Added setReverse to reverse the order of a set
[fw/sdcc] / src / pic / glue.c
1 /*-------------------------------------------------------------------------
2
3   SDCCglue.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
31
32 extern symbol *interrupts[256];
33 void printIval (symbol *, sym_link *, initList *, FILE *);
34 extern int noAlloc;
35 extern set *publics;
36 extern unsigned maxInterrupts;
37 extern int maxRegBank;
38 extern symbol *mainf;
39 extern char *VersionString;
40 extern FILE *codeOutFile;
41 extern set *tmpfileSet;
42 extern set *tmpfileNameSet;
43 extern char *iComments1;
44 extern char *iComments2;
45 //extern void emitStaticSeg (memmap * map);
46
47 extern DEFSETFUNC (closeTmpFiles);
48 extern DEFSETFUNC (rmTmpFiles);
49
50 extern void copyFile (FILE * dest, FILE * src);
51
52
53 //extern void emitMaps ();
54 //extern void createInterruptVect (FILE * vFile);
55 extern void initialComments (FILE * afile);
56 extern void printPublics (FILE * afile);
57
58 extern void printChar (FILE * ofile, char *s, int plen);
59
60 #if 0
61 char *
62 aopLiteral (value * val, int offset)
63      static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
64      value *initPointer (initList * ilist)
65      void printIvalType (sym_link * type, initList * ilist, FILE * oFile)
66      void printIvalStruct (symbol * sym, sym_link * type,
67                            initList * ilist, FILE * oFile)
68      int printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
69      void printIvalArray (symbol * sym, sym_link * type, initList * ilist,
70                           FILE * oFile)
71      void printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
72      int printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
73      void printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
74 #endif
75
76 /*-----------------------------------------------------------------*/
77 /* Allocation macros that replace those in SDCCalloc.h             */
78 /*   Why? I dunno. I ran across a bug with those macros that       */
79 /*   I couldn't fix, but I could work around...                    */
80 /*-----------------------------------------------------------------*/
81
82 #define  _ALLOC(x,sz) if (!(x = calloc((sz),1) ))      \
83          {                                          \
84             werror(E_OUT_OF_MEM,__FILE__,(long) sz);\
85             exit (1);                               \
86          }
87
88 #define _ALLOC_ATOMIC(x,y) if (!((x) = malloc(y)))   \
89          {                                               \
90             werror(E_OUT_OF_MEM,__FILE__,(long) y);     \
91             exit (1);                                    \
92          }
93
94
95 /*-----------------------------------------------------------------*/
96 /* aopLiteral - string from a literal value                        */
97 /*-----------------------------------------------------------------*/
98 int pic14aopLiteral (value *val, int offset)
99 {
100   union {
101     float f;
102     unsigned char c[4];
103   } fl;
104
105   /* if it is a float then it gets tricky */
106   /* otherwise it is fairly simple */
107   if (!IS_FLOAT(val->type)) {
108     unsigned long v = (unsigned long) floatFromVal(val);
109
110     //v >>= (offset * 8);
111     return ( (v >> (offset * 8)) & 0xff);
112     //sprintf(buffer,"0x%02x",((char) v) & 0xff);
113     //_ALLOC_ATOMIC(rs,strlen(buffer)+1);
114     //return strcpy (rs,buffer);
115   }
116
117   /* it is type float */
118   fl.f = (float) floatFromVal(val);
119 #ifdef _BIG_ENDIAN    
120   return fl.c[3-offset];
121 #else
122   return fl.c[offset];
123 #endif
124
125 }
126
127
128 /*-----------------------------------------------------------------*/
129 /* emitRegularMap - emit code for maps with no special cases       */
130 /*-----------------------------------------------------------------*/
131 static void
132 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
133 {
134   symbol *sym;
135   int i, size, bitvars = 0;;
136
137   if (addPublics)
138     fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
139
140   /* print the area name */
141   for (sym = setFirstItem (map->syms); sym;
142        sym = setNextItem (map->syms))
143     {
144
145       /* if extern then do nothing */
146       if (IS_EXTERN (sym->etype))
147         continue;
148
149       /* if allocation required check is needed
150          then check if the symbol really requires
151          allocation only for local variables */
152       if (arFlag && !IS_AGGREGATE (sym->type) &&
153           !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
154           !sym->allocreq && sym->level)
155         continue;
156
157       /* if global variable & not static or extern
158          and addPublics allowed then add it to the public set */
159       if ((sym->level == 0 ||
160            (sym->_isparm && !IS_REGPARM (sym->etype))) &&
161           addPublics &&
162           !IS_STATIC (sym->etype))
163         addSetHead (&publics, sym);
164
165       /* if extern then do nothing or is a function
166          then do nothing */
167       if (IS_FUNC (sym->type))
168         continue;
169 #if 0
170       /* print extra debug info if required */
171       if (options.debug || sym->level == 0)
172         {
173
174           cdbSymbol (sym, cdbFile, FALSE, FALSE);
175
176           if (!sym->level)      /* global */
177             if (IS_STATIC (sym->etype))
178               fprintf (map->oFile, "F%s_", moduleName);         /* scope is file */
179             else
180               fprintf (map->oFile, "G_");       /* scope is global */
181           else
182             /* symbol is local */
183             fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
184           fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
185         }
186 #endif
187
188       /* if is has an absolute address then generate
189          an equate for this no need to allocate space */
190       if (SPEC_ABSA (sym->etype))
191         {
192           //if (options.debug || sym->level == 0)
193           //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
194
195           fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
196                    sym->rname,
197                    SPEC_ADDR (sym->etype));
198         }
199       else
200         {
201           /* allocate space */
202
203           /* If this is a bit variable, then allocate storage after 8 bits have been declared */
204           /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
205           /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
206           if (IS_BITVAR (sym->etype))
207             {
208               if ((bitvars % 8) == 0)
209                 {
210                   fprintf (map->oFile, "  cblock\n");
211                   fprintf (map->oFile, "\tbitfield%d\n", bitvars);
212                   fprintf (map->oFile, "  endc\n");
213                 }
214
215               fprintf (map->oFile, "%s\tEQU\t( (bitfield%d<<3)+%d)\n",
216                        sym->rname,
217                        bitvars & 0xfff8,
218                        bitvars & 0x0007);
219
220               bitvars++;
221             }
222           else
223             {
224               fprintf (map->oFile, "\t%s\n", sym->rname);
225               if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
226                 {
227                   for (i = 1; i < size; i++)
228                     fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
229                 }
230             }
231           //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
232         }
233         
234         /* if it has a initial value then do it only if
235            it is a global variable */
236         if (sym->ival && sym->level == 0) {
237             ast *ival = NULL;
238             
239             if (IS_AGGREGATE (sym->type))
240                 ival = initAggregates (sym, sym->ival, NULL);
241             else
242                 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
243                                 decorateType (resolveSymbols (list2expr (sym->ival))));
244             codeOutFile = statsg->oFile;
245             GcurMemmap = statsg;
246             eBBlockFromiCode (iCodeFromAst (ival));
247             sym->ival = NULL;
248         }
249     }
250 }
251
252
253 #if 0
254 /*-----------------------------------------------------------------*/
255 /* initPointer - pointer initialization code massaging             */
256 /*-----------------------------------------------------------------*/
257 value *
258 initPointer (initList * ilist)
259 {
260   value *val;
261   ast *expr = list2expr (ilist);
262
263   if (!expr)
264     goto wrong;
265
266   /* try it the oldway first */
267   if ((val = constExprValue (expr, FALSE)))
268     return val;
269
270   /* no then we have to do these cludgy checks */
271   /* pointers can be initialized with address of
272      a variable or address of an array element */
273   if (IS_AST_OP (expr) && expr->opval.op == '&')
274     {
275       /* address of symbol */
276       if (IS_AST_SYM_VALUE (expr->left))
277         {
278           val = copyValue (AST_VALUE (expr->left));
279           val->type = newLink ();
280           if (SPEC_SCLS (expr->left->etype) == S_CODE)
281             {
282               DCL_TYPE (val->type) = CPOINTER;
283               DCL_PTR_CONST (val->type) = port->mem.code_ro;
284             }
285           else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
286             DCL_TYPE (val->type) = FPOINTER;
287           else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
288             DCL_TYPE (val->type) = PPOINTER;
289           else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
290             DCL_TYPE (val->type) = IPOINTER;
291           else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
292             DCL_TYPE (val->type) = EEPPOINTER;
293           else
294             DCL_TYPE (val->type) = POINTER;
295           val->type->next = expr->left->ftype;
296           val->etype = getSpec (val->type);
297           return val;
298         }
299
300       /* if address of indexed array */
301       if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
302         return valForArray (expr->left);
303
304       /* if address of structure element then
305          case 1. a.b ; */
306       if (IS_AST_OP (expr->left) &&
307           expr->left->opval.op == '.')
308         {
309           return valForStructElem (expr->left->left,
310                                    expr->left->right);
311         }
312
313       /* case 2. (&a)->b ;
314          (&some_struct)->element */
315       if (IS_AST_OP (expr->left) &&
316           expr->left->opval.op == PTR_OP &&
317           IS_ADDRESS_OF_OP (expr->left->left))
318         return valForStructElem (expr->left->left->left,
319                                  expr->left->right);
320     }
321
322 wrong:
323   werror (E_INIT_WRONG);
324   return NULL;
325
326 }
327
328 /*-----------------------------------------------------------------*/
329 /* printChar - formats and prints a characater string with DB      */
330 /*-----------------------------------------------------------------*/
331 void
332 printChar (FILE * ofile, char *s, int plen)
333 {
334   int i;
335   int len = strlen (s);
336   int pplen = 0;
337
338   while (len && pplen < plen)
339     {
340
341       fprintf (ofile, "\t.ascii /");
342       i = 60;
343       while (i && *s && pplen < plen)
344         {
345           if (*s < ' ' || *s == '/')
346             {
347               fprintf (ofile, "/\n\t.byte 0x%02x\n\t.ascii /", *s++);
348             }
349           else
350             fprintf (ofile, "%c", *s++);
351           pplen++;
352           i--;
353         }
354       fprintf (ofile, "/\n");
355
356       if (len > 60)
357         len -= 60;
358       else
359         len = 0;
360     }
361   if (pplen < plen)
362     fprintf (ofile, "\t.byte\t0\n");
363 }
364
365 /*-----------------------------------------------------------------*/
366 /* printIvalType - generates ival for int/char                     */
367 /*-----------------------------------------------------------------*/
368 void
369 printIvalType (sym_link * type, initList * ilist, FILE * oFile)
370 {
371   value *val;
372
373   /* if initList is deep */
374   if (ilist->type == INIT_DEEP)
375     ilist = ilist->init.deep;
376
377   val = list2val (ilist);
378   switch (getSize (type))
379     {
380     case 1:
381       if (!val)
382         fprintf (oFile, "\t.byte 0\n");
383       else
384         fprintf (oFile, "\t.byte %s\n",
385                  aopLiteral (val, 0));
386       break;
387
388     case 2:
389       if (!val)
390         fprintf (oFile, "\t.word 0\n");
391       else
392         fprintf (oFile, "\t.byte %s,%s\n",
393                  aopLiteral (val, 0), aopLiteral (val, 1));
394       break;
395
396     case 4:
397       if (!val)
398         fprintf (oFile, "\t.word 0,0\n");
399       else
400         fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
401                  aopLiteral (val, 0), aopLiteral (val, 1),
402                  aopLiteral (val, 2), aopLiteral (val, 3));
403       break;
404     }
405
406   return;
407 }
408
409 /*-----------------------------------------------------------------*/
410 /* printIvalStruct - generates initial value for structures        */
411 /*-----------------------------------------------------------------*/
412 void
413 printIvalStruct (symbol * sym, sym_link * type,
414                  initList * ilist, FILE * oFile)
415 {
416   symbol *sflds;
417   initList *iloop;
418
419   sflds = SPEC_STRUCT (type)->fields;
420   if (ilist->type != INIT_DEEP)
421     {
422       werror (E_INIT_STRUCT, sym->name);
423       return;
424     }
425
426   iloop = ilist->init.deep;
427
428   for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
429     printIval (sflds, sflds->type, iloop, oFile);
430
431   return;
432 }
433
434 /*-----------------------------------------------------------------*/
435 /* printIvalChar - generates initital value for character array    */
436 /*-----------------------------------------------------------------*/
437 int
438 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
439 {
440   value *val;
441   int remain;
442
443   if (!s)
444     {
445
446       val = list2val (ilist);
447       /* if the value is a character string  */
448       if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
449         {
450           if (!DCL_ELEM (type))
451             DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
452
453           /* if size mismatch  */
454 /*      if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
455 /*    werror (E_ARRAY_BOUND); */
456
457           printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
458
459           if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
460             while (remain--)
461               fprintf (oFile, "\t.byte 0\n");
462
463           return 1;
464         }
465       else
466         return 0;
467     }
468   else
469     printChar (oFile, s, strlen (s) + 1);
470   return 1;
471 }
472
473 /*-----------------------------------------------------------------*/
474 /* printIvalArray - generates code for array initialization        */
475 /*-----------------------------------------------------------------*/
476 void
477 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
478                 FILE * oFile)
479 {
480   initList *iloop;
481   int lcnt = 0, size = 0;
482
483   /* take care of the special   case  */
484   /* array of characters can be init  */
485   /* by a string                      */
486   if (IS_CHAR (type->next))
487     if (printIvalChar (type,
488                        (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
489                        oFile, SPEC_CVAL (sym->etype).v_char))
490       return;
491
492   /* not the special case             */
493   if (ilist->type != INIT_DEEP)
494     {
495       werror (E_INIT_STRUCT, sym->name);
496       return;
497     }
498
499   iloop = ilist->init.deep;
500   lcnt = DCL_ELEM (type);
501
502   for (;;)
503     {
504       size++;
505       printIval (sym, type->next, iloop, oFile);
506       iloop = (iloop ? iloop->next : NULL);
507
508
509       /* if not array limits given & we */
510       /* are out of initialisers then   */
511       if (!DCL_ELEM (type) && !iloop)
512         break;
513
514       /* no of elements given and we    */
515       /* have generated for all of them */
516       if (!--lcnt)
517         break;
518     }
519
520   /* if we have not been given a size  */
521   if (!DCL_ELEM (type))
522     DCL_ELEM (type) = size;
523
524   return;
525 }
526
527 /*-----------------------------------------------------------------*/
528 /* printIvalFuncPtr - generate initial value for function pointers */
529 /*-----------------------------------------------------------------*/
530 void
531 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
532 {
533   value *val;
534   int dLvl = 0;
535
536   val = list2val (ilist);
537   /* check the types   */
538   if ((dLvl = checkType (val->type, type->next)) <= 0)
539     {
540
541       fprintf (oFile, "\t.word 0\n");
542       return;
543     }
544
545   /* now generate the name */
546   if (!val->sym)
547     {
548       if (IS_LITERAL (val->etype))
549         fprintf (oFile, "\t.byte %s,%s\n",
550                  aopLiteral (val, 0), aopLiteral (val, 1));
551       else
552         fprintf (oFile, "\t.byte %s,(%s >> 8)\n",
553                  val->name, val->name);
554     }
555   else
556     fprintf (oFile, "\t.byte %s,(%s >> 8)\n",
557              val->sym->rname, val->sym->rname);
558
559   return;
560 }
561
562 /*-----------------------------------------------------------------*/
563 /* printIvalCharPtr - generates initial values for character pointers */
564 /*-----------------------------------------------------------------*/
565 int
566 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
567 {
568   int size = 0;
569
570   size = getSize (type);
571
572   if (size == 1)
573     fprintf (oFile,
574              "\t.byte %s", val->name);
575   else
576     fprintf (oFile,
577              "\t.byte %s,(%s >> 8)",
578              val->name, val->name);
579
580   if (size > 2)
581     fprintf (oFile, ",#0x02\n");
582   else
583     fprintf (oFile, "\n");
584
585   if (val->sym && val->sym->isstrlit)
586     addSet (&statsg->syms, val->sym);
587
588   return 1;
589 }
590
591 /*-----------------------------------------------------------------*/
592 /* printIvalPtr - generates initial value for pointers             */
593 /*-----------------------------------------------------------------*/
594 void
595 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
596 {
597   value *val;
598
599   /* if deep then   */
600   if (ilist->type == INIT_DEEP)
601     ilist = ilist->init.deep;
602
603   /* function pointer     */
604   if (IS_FUNC (type->next))
605     {
606       printIvalFuncPtr (type, ilist, oFile);
607       return;
608     }
609
610   if (!(val = initPointer (ilist)))
611     return;
612
613   /* if character pointer */
614   if (IS_CHAR (type->next))
615     if (printIvalCharPtr (sym, type, val, oFile))
616       return;
617
618   /* check the type      */
619   if (checkType (type, val->type) != 1)
620     werror (E_INIT_WRONG);
621
622   /* if val is literal */
623   if (IS_LITERAL (val->etype))
624     {
625       switch (getSize (type))
626         {
627         case 1:
628           fprintf (oFile, "\t.byte 0x%02x\n", ((char) floatFromVal (val)) & 0xff);
629           break;
630         case 2:
631           fprintf (oFile, "\t.byte %s,%s\n",
632                    aopLiteral (val, 0), aopLiteral (val, 1));
633
634           break;
635         case 3:
636           fprintf (oFile, "\t.byte %s,%s,0x%02x\n",
637                    aopLiteral (val, 0), aopLiteral (val, 1), CPOINTER);
638         }
639       return;
640     }
641
642
643   switch (getSize (type))
644     {
645     case 1:
646       fprintf (oFile, "\t.byte %s\n", val->name);
647       break;
648     case 2:
649       fprintf (oFile, "\t.byte %s,(%s >> 8)\n", val->name, val->name);
650       break;
651
652     case 3:
653       fprintf (oFile, "\t.byte %s,(%s >> 8),0x%02x\n",
654                val->name, val->name, DCL_TYPE (val->type));
655     }
656   return;
657 }
658
659 /*-----------------------------------------------------------------*/
660 /* printIval - generates code for initial value                    */
661 /*-----------------------------------------------------------------*/
662 void
663 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
664 {
665   if (!ilist)
666     return;
667
668   /* if structure then    */
669   if (IS_STRUCT (type))
670     {
671       printIvalStruct (sym, type, ilist, oFile);
672       return;
673     }
674
675   /* if this is a pointer */
676   if (IS_PTR (type))
677     {
678       printIvalPtr (sym, type, ilist, oFile);
679       return;
680     }
681
682   /* if this is an array   */
683   if (IS_ARRAY (type))
684     {
685       printIvalArray (sym, type, ilist, oFile);
686       return;
687     }
688
689   /* if type is SPECIFIER */
690   if (IS_SPEC (type))
691     {
692       printIvalType (type, ilist, oFile);
693       return;
694     }
695 }
696
697 #endif
698 /*-----------------------------------------------------------------*/
699 /* emitStaticSeg - emitcode for the static segment                 */
700 /*-----------------------------------------------------------------*/
701 static void
702 pic14emitStaticSeg (memmap * map)
703 {
704   symbol *sym;
705
706   fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
707
708
709   /* for all variables in this segment do */
710   for (sym = setFirstItem (map->syms); sym;
711        sym = setNextItem (map->syms))
712     {
713
714       /* if it is "extern" then do nothing */
715       if (IS_EXTERN (sym->etype))
716         continue;
717
718       /* if it is not static add it to the public
719          table */
720       if (!IS_STATIC (sym->etype))
721         addSetHead (&publics, sym);
722
723       /* print extra debug info if required */
724       if (options.debug || sym->level == 0)
725         {
726
727           cdbSymbol (sym, cdbFile, FALSE, FALSE);
728
729           if (!sym->level)
730             {                   /* global */
731               if (IS_STATIC (sym->etype))
732                 fprintf (code->oFile, "F%s_", moduleName);      /* scope is file */
733               else
734                 fprintf (code->oFile, "G_");    /* scope is global */
735             }
736           else
737             /* symbol is local */
738             fprintf (code->oFile, "L%s_",
739                      (sym->localof ? sym->localof->name : "-null-"));
740           fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
741         }
742
743       /* if it has an absolute address */
744       if (SPEC_ABSA (sym->etype))
745         {
746           if (options.debug || sym->level == 0)
747             fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
748
749           fprintf (code->oFile, "%s\t=\t0x%04x\n",
750                    sym->rname,
751                    SPEC_ADDR (sym->etype));
752         }
753       else
754         {
755           if (options.debug || sym->level == 0)
756             fprintf (code->oFile, " == .\n");
757
758           /* if it has an initial value */
759           if (sym->ival)
760             {
761               fprintf (code->oFile, "%s:\n", sym->rname);
762               noAlloc++;
763               resolveIvalSym (sym->ival);
764               printIval (sym, sym->type, sym->ival, code->oFile);
765               noAlloc--;
766             }
767           else
768             {
769               /* allocate space */
770               fprintf (code->oFile, "%s:\n", sym->rname);
771               /* special case for character strings */
772               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
773                   SPEC_CVAL (sym->etype).v_char)
774                 printChar (code->oFile,
775                            SPEC_CVAL (sym->etype).v_char,
776                            strlen (SPEC_CVAL (sym->etype).v_char) + 1);
777               else
778                 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
779             }
780         }
781     }
782 }
783
784
785 /*-----------------------------------------------------------------*/
786 /* emitMaps - emits the code for the data portion the code         */
787 /*-----------------------------------------------------------------*/
788 static void
789 pic14emitMaps ()
790 {
791   /* no special considerations for the following
792      data, idata & bit & xdata */
793   pic14emitRegularMap (data, TRUE, TRUE);
794   pic14emitRegularMap (idata, TRUE, TRUE);
795   pic14emitRegularMap (bit, TRUE, FALSE);
796   pic14emitRegularMap (xdata, TRUE, TRUE);
797   pic14emitRegularMap (sfr, FALSE, FALSE);
798   pic14emitRegularMap (sfrbit, FALSE, FALSE);
799   pic14emitRegularMap (code, TRUE, FALSE);
800   pic14emitStaticSeg (statsg);
801 }
802
803 /*-----------------------------------------------------------------*/
804 /* createInterruptVect - creates the interrupt vector              */
805 /*-----------------------------------------------------------------*/
806 static void
807 pic14createInterruptVect (FILE * vFile)
808 {
809   unsigned i = 0;
810   mainf = newSymbol ("main", 0);
811   mainf->block = 0;
812
813   /* only if the main function exists */
814   if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
815     {
816       if (!options.cc_only)
817         werror (E_NO_MAIN);
818       return;
819     }
820
821   /* if the main is only a prototype ie. no body then do nothing */
822   if (!IFFUNC_HASBODY(mainf->type))
823     {
824       /* if ! compile only then main function should be present */
825       if (!options.cc_only)
826         werror (E_NO_MAIN);
827       return;
828     }
829
830   fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
831   fprintf (vFile, ";__interrupt_vect:\n");
832
833
834   if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
835     {
836       /* "generic" interrupt table header (if port doesn't specify one).
837
838        * Look suspiciously like 8051 code to me...
839        */
840
841       fprintf (vFile, ";\tljmp\t__sdcc_gsinit_startup\n");
842
843
844       /* now for the other interrupts */
845       for (; i < maxInterrupts; i++)
846         {
847           if (interrupts[i])
848             fprintf (vFile, ";\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
849           else
850             fprintf (vFile, ";\treti\n;\t.ds\t7\n");
851         }
852     }
853 }
854
855
856 /*-----------------------------------------------------------------*/
857 /* initialComments - puts in some initial comments                 */
858 /*-----------------------------------------------------------------*/
859 static void
860 pic14initialComments (FILE * afile)
861 {
862   initialComments (afile);
863   fprintf (afile, "; PIC port for the 14-bit core\n");
864   fprintf (afile, iComments2);
865
866 }
867
868 /*-----------------------------------------------------------------*/
869 /* printPublics - generates .global for publics                    */
870 /*-----------------------------------------------------------------*/
871 static void
872 pic14printPublics (FILE * afile)
873 {
874   symbol *sym;
875
876   fprintf (afile, "%s", iComments2);
877   fprintf (afile, "; publics variables in this module\n");
878   fprintf (afile, "%s", iComments2);
879
880   for (sym = setFirstItem (publics); sym;
881        sym = setNextItem (publics))
882     fprintf (afile, ";\t.globl %s\n", sym->rname);
883 }
884
885
886
887 /*-----------------------------------------------------------------*/
888 /* emitOverlay - will emit code for the overlay stuff              */
889 /*-----------------------------------------------------------------*/
890 static void
891 pic14emitOverlay (FILE * afile)
892 {
893   set *ovrset;
894
895   if (!elementsInSet (ovrSetSets))
896     fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
897
898   /* for each of the sets in the overlay segment do */
899   for (ovrset = setFirstItem (ovrSetSets); ovrset;
900        ovrset = setNextItem (ovrSetSets))
901     {
902
903       symbol *sym;
904
905       if (elementsInSet (ovrset))
906         {
907           /* this dummy area is used to fool the assembler
908              otherwise the assembler will append each of these
909              declarations into one chunk and will not overlay
910              sad but true */
911           fprintf (afile, ";\t.area _DUMMY\n");
912           /* output the area informtion */
913           fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);    /* MOF */
914         }
915
916       for (sym = setFirstItem (ovrset); sym;
917            sym = setNextItem (ovrset))
918         {
919
920           /* if extern then do nothing */
921           if (IS_EXTERN (sym->etype))
922             continue;
923
924           /* if allocation required check is needed
925              then check if the symbol really requires
926              allocation only for local variables */
927           if (!IS_AGGREGATE (sym->type) &&
928               !(sym->_isparm && !IS_REGPARM (sym->etype))
929               && !sym->allocreq && sym->level)
930             continue;
931
932           /* if global variable & not static or extern
933              and addPublics allowed then add it to the public set */
934           if ((sym->_isparm && !IS_REGPARM (sym->etype))
935               && !IS_STATIC (sym->etype))
936             addSetHead (&publics, sym);
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           /* print extra debug info if required */
944           if (options.debug || sym->level == 0)
945             {
946
947               cdbSymbol (sym, cdbFile, FALSE, FALSE);
948
949               if (!sym->level)
950                 {               /* global */
951                   if (IS_STATIC (sym->etype))
952                     fprintf (afile, "F%s_", moduleName);        /* scope is file */
953                   else
954                     fprintf (afile, "G_");      /* scope is global */
955                 }
956               else
957                 /* symbol is local */
958                 fprintf (afile, "L%s_",
959                          (sym->localof ? sym->localof->name : "-null-"));
960               fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
961             }
962
963           /* if is has an absolute address then generate
964              an equate for this no need to allocate space */
965           if (SPEC_ABSA (sym->etype))
966             {
967
968               if (options.debug || sym->level == 0)
969                 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
970
971               fprintf (afile, "%s\t=\t0x%04x\n",
972                        sym->rname,
973                        SPEC_ADDR (sym->etype));
974             }
975           else
976             {
977               if (options.debug || sym->level == 0)
978                 fprintf (afile, "==.\n");
979
980               /* allocate space */
981               fprintf (afile, "%s:\n", sym->rname);
982               fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
983             }
984
985         }
986     }
987 }
988
989
990
991 /*-----------------------------------------------------------------*/
992 /* glue - the final glue that hold the whole thing together        */
993 /*-----------------------------------------------------------------*/
994 void
995 picglue ()
996 {
997
998   FILE *vFile;
999   FILE *asmFile;
1000   FILE *ovrFile = tempfile();
1001   int i;
1002   set *s=NULL,*t=NULL;
1003   char a=1,b=2,c=3;
1004
1005
1006   addSet(&s,&a);
1007   addSet(&s,&b);
1008   addSet(&s,&c);
1009
1010   fprintf(stdout,"\n\n\n******************\n\n\n");
1011   for(t=s; t; t=t->next) {
1012     if(t->item) 
1013       fprintf(stdout,"Set item %d\n",*(char *)t->item);
1014   }
1015
1016   s =reverseSet(s);
1017   for(t=s; t; t=t->next) {
1018     if(t->item) 
1019       fprintf(stdout,"Set item %d\n",*(char *)t->item);
1020   }
1021
1022   addSetHead(&tmpfileSet,ovrFile);
1023
1024
1025   if (mainf && IFFUNC_HASBODY(mainf->type)) {
1026
1027     pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1028     addpBlock(pb);
1029
1030     /* entry point @ start of CSEG */
1031     addpCode2pBlock(pb,newpCodeLabelStr("__sdcc_program_startup"));
1032     /* put in the call to main */
1033     addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1034
1035     if (options.mainreturn) {
1036
1037       addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1038       addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1039
1040     } else {
1041
1042       addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1043       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1044
1045     }
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   movepBlock2Head(code->dbName);     // Last
1054   movepBlock2Head('X');
1055   movepBlock2Head(statsg->dbName);   // First
1056
1057
1058   AnalyzepCode('*'); //code->dbName);
1059   printCallTree(stderr);
1060
1061   //pCodePeepInit();
1062
1063   //OptimizepCode(code->dbName);
1064
1065
1066   /* print the global struct definitions */
1067   if (options.debug)
1068     cdbStructBlock (0,cdbFile);
1069
1070   vFile = tempfile();
1071   /* PENDING: this isnt the best place but it will do */
1072   if (port->general.glue_up_main) {
1073     /* create the interrupt vector table */
1074     pic14createInterruptVect (vFile);
1075   }
1076
1077   addSetHead(&tmpfileSet,vFile);
1078     
1079   /* emit code for the all the variables declared */
1080   pic14emitMaps ();
1081   /* do the overlay segments */
1082   pic14emitOverlay(ovrFile);
1083
1084
1085   pcode_test();
1086
1087
1088   /* now put it all together into the assembler file */
1089   /* create the assembler file name */
1090     
1091   if (!options.c1mode) {
1092     sprintf (buffer, srcFileName);
1093     strcat (buffer, ".asm");
1094   }
1095   else {
1096     strcpy(buffer, options.out_name);
1097   }
1098
1099   if (!(asmFile = fopen (buffer, "w"))) {
1100     werror (E_FILE_OPEN_ERR, buffer);
1101     exit (1);
1102   }
1103     
1104   /* initial comments */
1105   pic14initialComments (asmFile);
1106     
1107   /* print module name */
1108   fprintf (asmFile, ";\t.module %s\n", moduleName);
1109     
1110   /* Let the port generate any global directives, etc. */
1111   if (port->genAssemblerPreamble)
1112     {
1113       port->genAssemblerPreamble(asmFile);
1114     }
1115     
1116   /* print the global variables in this module */
1117   pic14printPublics (asmFile);
1118     
1119
1120   /* copy the sfr segment */
1121   fprintf (asmFile, "%s", iComments2);
1122   fprintf (asmFile, "; special function registers\n");
1123   fprintf (asmFile, "%s", iComments2);
1124   copyFile (asmFile, sfr->oFile);
1125     
1126
1127   /* Put all variables into a cblock */
1128   fprintf (asmFile, "\n\n\tcblock  0x20\n\n");
1129
1130   for(i=0; i<pic14_nRegs; i++) {
1131     if(regspic14[i].wasUsed && (regspic14[i].offset>=0x0c) )
1132       fprintf (asmFile, "\t%s\n",regspic14[i].name);
1133   }
1134
1135
1136   /* For now, create a "dpl" and a "dph" in the register space */
1137   /* of the pic so that we can use the same calling mechanism */
1138   /* as the 8051 port */
1139   fprintf (asmFile, "%s", iComments2);
1140   fprintf (asmFile, "; dpl and dph to emulate the 8051 calling mechanism \n");
1141   fprintf (asmFile, "%s", iComments2);
1142
1143   fprintf (asmFile, "\tdph\n");
1144
1145
1146
1147   /* copy the sbit segment */
1148   fprintf (asmFile, "%s", iComments2);
1149   fprintf (asmFile, "; special function bits \n");
1150   fprintf (asmFile, "%s", iComments2);
1151   copyFile (asmFile, sfrbit->oFile);
1152     
1153   /* copy the data segment */
1154   fprintf (asmFile, "%s", iComments2);
1155   fprintf (asmFile, "; internal ram data\n");
1156   fprintf (asmFile, "%s", iComments2);
1157   copyFile (asmFile, data->oFile);
1158
1159
1160   /* create the overlay segments */
1161   fprintf (asmFile, "%s", iComments2);
1162   fprintf (asmFile, "; overlayable items in internal ram \n");
1163   fprintf (asmFile, "%s", iComments2);    
1164   copyFile (asmFile, ovrFile);
1165
1166   /* create the stack segment MOF */
1167   if (mainf && IFFUNC_HASBODY(mainf->type)) {
1168     fprintf (asmFile, "%s", iComments2);
1169     fprintf (asmFile, "; Stack segment in internal ram \n");
1170     fprintf (asmFile, "%s", iComments2);    
1171     fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1172              ";__start__stack:\n;\t.ds\t1\n\n");
1173   }
1174
1175   /* create the idata segment */
1176   fprintf (asmFile, "%s", iComments2);
1177   fprintf (asmFile, "; indirectly addressable internal ram data\n");
1178   fprintf (asmFile, "%s", iComments2);
1179   copyFile (asmFile, idata->oFile);
1180     
1181   /* if external stack then reserve space of it */
1182   if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1183     fprintf (asmFile, "%s", iComments2);
1184     fprintf (asmFile, "; external stack \n");
1185     fprintf (asmFile, "%s", iComments2);
1186     fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1187     fprintf (asmFile,";\t.ds 256\n");
1188   }
1189         
1190         
1191   /* copy xtern ram data */
1192   fprintf (asmFile, "%s", iComments2);
1193   fprintf (asmFile, "; external ram data\n");
1194   fprintf (asmFile, "%s", iComments2);
1195   copyFile (asmFile, xdata->oFile);
1196     
1197
1198   fprintf (asmFile, "\tendc\n");
1199
1200
1201   /* copy the bit segment */
1202   fprintf (asmFile, "%s", iComments2);
1203   fprintf (asmFile, "; bit data\n");
1204   fprintf (asmFile, "%s", iComments2);
1205   copyFile (asmFile, bit->oFile);
1206
1207
1208   fprintf (asmFile, "\tORG 0\n");
1209
1210   /* copy the interrupt vector table */
1211   if (mainf && IFFUNC_HASBODY(mainf->type)) {
1212     fprintf (asmFile, "%s", iComments2);
1213     fprintf (asmFile, "; interrupt vector \n");
1214     fprintf (asmFile, "%s", iComments2);
1215     copyFile (asmFile, vFile);
1216   }
1217     
1218   /* copy global & static initialisations */
1219   fprintf (asmFile, "%s", iComments2);
1220   fprintf (asmFile, "; global & static initialisations\n");
1221   fprintf (asmFile, "%s", iComments2);
1222     
1223   /* Everywhere we generate a reference to the static_name area, 
1224    * (which is currently only here), we immediately follow it with a 
1225    * definition of the post_static_name area. This guarantees that
1226    * the post_static_name area will immediately follow the static_name
1227    * area.
1228    */
1229   fprintf (asmFile, ";\t.area %s\n", port->mem.static_name); /* MOF */
1230   fprintf (asmFile, ";\t.area %s\n", port->mem.post_static_name);
1231   fprintf (asmFile, ";\t.area %s\n", port->mem.static_name);
1232     
1233   if (mainf && IFFUNC_HASBODY(mainf->type)) {
1234     fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1235     /* if external stack is specified then the
1236        higher order byte of the xdatalocation is
1237        going into P2 and the lower order going into
1238        spx */
1239     if (options.useXstack) {
1240       fprintf(asmFile,";\tmov\tP2,#0x%02x\n",
1241               (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1242       fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
1243               (unsigned int)options.xdata_loc & 0xff);
1244     }
1245
1246   }
1247
1248   if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1249     {
1250       /* This code is generated in the post-static area.
1251        * This area is guaranteed to follow the static area
1252        * by the ugly shucking and jiving about 20 lines ago.
1253        */
1254       fprintf(asmFile, ";\t.area %s\n", port->mem.post_static_name);
1255       fprintf (asmFile,";\tljmp\t__sdcc_program_startup\n");
1256     }
1257         
1258   /* copy over code */
1259   fprintf (asmFile, "%s", iComments2);
1260   fprintf (asmFile, "; code\n");
1261   fprintf (asmFile, "%s", iComments2);
1262   fprintf (asmFile, ";\t.area %s\n", port->mem.code_name);
1263
1264   //copyFile (asmFile, code->oFile);
1265
1266   copypCode(asmFile, statsg->dbName);
1267   copypCode(asmFile, 'X');
1268   copypCode(asmFile, code->dbName);
1269
1270
1271   fprintf (asmFile,"\tend\n");
1272
1273   fclose (asmFile);
1274   applyToSet(tmpfileSet,closeTmpFiles);
1275   applyToSet(tmpfileNameSet, rmTmpFiles);
1276 }