Fixed up implicit data type conversions
[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 (!mainf->fbody)
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
1003   addSetHead(&tmpfileSet,ovrFile);
1004
1005
1006   if (mainf && mainf->fbody) {
1007
1008     pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1009     addpBlock(pb);
1010
1011     /* entry point @ start of CSEG */
1012     addpCode2pBlock(pb,newpCodeLabelStr("__sdcc_program_startup"));
1013     /* put in the call to main */
1014     addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1015
1016     if (options.mainreturn) {
1017
1018       addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1019       addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1020
1021     } else {
1022
1023       addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1024       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1025
1026     }
1027   }
1028
1029
1030   /* At this point we've got all the code in the form of pCode structures */
1031   /* Now it needs to be rearranged into the order it should be placed in the */
1032   /* code space */
1033
1034   movepBlock2Head(code->dbName);     // Last
1035   movepBlock2Head('X');
1036   movepBlock2Head(statsg->dbName);   // First
1037
1038
1039   AnalyzepCode('*'); //code->dbName);
1040   printCallTree(stderr);
1041
1042   pCodePeepInit();
1043
1044   OptimizepCode(code->dbName);
1045
1046
1047   /* print the global struct definitions */
1048   if (options.debug)
1049     cdbStructBlock (0,cdbFile);
1050
1051   vFile = tempfile();
1052   /* PENDING: this isnt the best place but it will do */
1053   if (port->general.glue_up_main) {
1054     /* create the interrupt vector table */
1055     pic14createInterruptVect (vFile);
1056   }
1057
1058   addSetHead(&tmpfileSet,vFile);
1059     
1060   /* emit code for the all the variables declared */
1061   pic14emitMaps ();
1062   /* do the overlay segments */
1063   pic14emitOverlay(ovrFile);
1064
1065
1066   pcode_test();
1067
1068
1069   /* now put it all together into the assembler file */
1070   /* create the assembler file name */
1071     
1072   if (!options.c1mode) {
1073     sprintf (buffer, srcFileName);
1074     strcat (buffer, ".asm");
1075   }
1076   else {
1077     strcpy(buffer, options.out_name);
1078   }
1079
1080   if (!(asmFile = fopen (buffer, "w"))) {
1081     werror (E_FILE_OPEN_ERR, buffer);
1082     exit (1);
1083   }
1084     
1085   /* initial comments */
1086   pic14initialComments (asmFile);
1087     
1088   /* print module name */
1089   fprintf (asmFile, ";\t.module %s\n", moduleName);
1090     
1091   /* Let the port generate any global directives, etc. */
1092   if (port->genAssemblerPreamble)
1093     {
1094       port->genAssemblerPreamble(asmFile);
1095     }
1096     
1097   /* print the global variables in this module */
1098   pic14printPublics (asmFile);
1099     
1100
1101   /* copy the sfr segment */
1102   fprintf (asmFile, "%s", iComments2);
1103   fprintf (asmFile, "; special function registers\n");
1104   fprintf (asmFile, "%s", iComments2);
1105   copyFile (asmFile, sfr->oFile);
1106     
1107
1108   /* Put all variables into a cblock */
1109   fprintf (asmFile, "\n\n\tcblock  0x0c\n\n");
1110
1111   for(i=0; i<pic14_nRegs; i++) {
1112     if(regspic14[i].wasUsed && (regspic14[i].offset>=0x0c) )
1113       fprintf (asmFile, "\t%s\n",regspic14[i].name);
1114   }
1115
1116
1117   /* For now, create a "dpl" and a "dph" in the register space */
1118   /* of the pic so that we can use the same calling mechanism */
1119   /* as the 8051 port */
1120   fprintf (asmFile, "%s", iComments2);
1121   fprintf (asmFile, "; dpl and dph to emulate the 8051 calling mechanism \n");
1122   fprintf (asmFile, "%s", iComments2);
1123
1124   fprintf (asmFile, "\tdph\n");
1125
1126
1127
1128   /* copy the sbit segment */
1129   fprintf (asmFile, "%s", iComments2);
1130   fprintf (asmFile, "; special function bits \n");
1131   fprintf (asmFile, "%s", iComments2);
1132   copyFile (asmFile, sfrbit->oFile);
1133     
1134   /* copy the data segment */
1135   fprintf (asmFile, "%s", iComments2);
1136   fprintf (asmFile, "; internal ram data\n");
1137   fprintf (asmFile, "%s", iComments2);
1138   copyFile (asmFile, data->oFile);
1139
1140
1141   /* create the overlay segments */
1142   fprintf (asmFile, "%s", iComments2);
1143   fprintf (asmFile, "; overlayable items in internal ram \n");
1144   fprintf (asmFile, "%s", iComments2);    
1145   copyFile (asmFile, ovrFile);
1146
1147   /* create the stack segment MOF */
1148   if (mainf && mainf->fbody) {
1149     fprintf (asmFile, "%s", iComments2);
1150     fprintf (asmFile, "; Stack segment in internal ram \n");
1151     fprintf (asmFile, "%s", iComments2);    
1152     fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1153              ";__start__stack:\n;\t.ds\t1\n\n");
1154   }
1155
1156   /* create the idata segment */
1157   fprintf (asmFile, "%s", iComments2);
1158   fprintf (asmFile, "; indirectly addressable internal ram data\n");
1159   fprintf (asmFile, "%s", iComments2);
1160   copyFile (asmFile, idata->oFile);
1161     
1162   /* if external stack then reserve space of it */
1163   if (mainf && mainf->fbody && options.useXstack ) {
1164     fprintf (asmFile, "%s", iComments2);
1165     fprintf (asmFile, "; external stack \n");
1166     fprintf (asmFile, "%s", iComments2);
1167     fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1168     fprintf (asmFile,";\t.ds 256\n");
1169   }
1170         
1171         
1172   /* copy xtern ram data */
1173   fprintf (asmFile, "%s", iComments2);
1174   fprintf (asmFile, "; external ram data\n");
1175   fprintf (asmFile, "%s", iComments2);
1176   copyFile (asmFile, xdata->oFile);
1177     
1178
1179   fprintf (asmFile, "\tendc\n");
1180
1181
1182   /* copy the bit segment */
1183   fprintf (asmFile, "%s", iComments2);
1184   fprintf (asmFile, "; bit data\n");
1185   fprintf (asmFile, "%s", iComments2);
1186   copyFile (asmFile, bit->oFile);
1187
1188
1189   fprintf (asmFile, "\tORG 0\n");
1190
1191   /* copy the interrupt vector table */
1192   if (mainf && mainf->fbody) {
1193     fprintf (asmFile, "%s", iComments2);
1194     fprintf (asmFile, "; interrupt vector \n");
1195     fprintf (asmFile, "%s", iComments2);
1196     copyFile (asmFile, vFile);
1197   }
1198     
1199   /* copy global & static initialisations */
1200   fprintf (asmFile, "%s", iComments2);
1201   fprintf (asmFile, "; global & static initialisations\n");
1202   fprintf (asmFile, "%s", iComments2);
1203     
1204   /* Everywhere we generate a reference to the static_name area, 
1205    * (which is currently only here), we immediately follow it with a 
1206    * definition of the post_static_name area. This guarantees that
1207    * the post_static_name area will immediately follow the static_name
1208    * area.
1209    */
1210   fprintf (asmFile, ";\t.area %s\n", port->mem.static_name); /* MOF */
1211   fprintf (asmFile, ";\t.area %s\n", port->mem.post_static_name);
1212   fprintf (asmFile, ";\t.area %s\n", port->mem.static_name);
1213     
1214   if (mainf && mainf->fbody) {
1215     fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1216     /* if external stack is specified then the
1217        higher order byte of the xdatalocation is
1218        going into P2 and the lower order going into
1219        spx */
1220     if (options.useXstack) {
1221       fprintf(asmFile,";\tmov\tP2,#0x%02x\n",
1222               (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1223       fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
1224               (unsigned int)options.xdata_loc & 0xff);
1225     }
1226
1227   }
1228
1229   if (port->general.glue_up_main && mainf && mainf->fbody)
1230     {
1231       /* This code is generated in the post-static area.
1232        * This area is guaranteed to follow the static area
1233        * by the ugly shucking and jiving about 20 lines ago.
1234        */
1235       fprintf(asmFile, ";\t.area %s\n", port->mem.post_static_name);
1236       fprintf (asmFile,";\tljmp\t__sdcc_program_startup\n");
1237     }
1238         
1239   /* copy over code */
1240   fprintf (asmFile, "%s", iComments2);
1241   fprintf (asmFile, "; code\n");
1242   fprintf (asmFile, "%s", iComments2);
1243   fprintf (asmFile, ";\t.area %s\n", port->mem.code_name);
1244
1245   //copyFile (asmFile, code->oFile);
1246
1247   copypCode(asmFile, statsg->dbName);
1248   copypCode(asmFile, 'X');
1249   copypCode(asmFile, code->dbName);
1250
1251
1252   fprintf (asmFile,"\tend\n");
1253
1254   fclose (asmFile);
1255   applyToSet(tmpfileSet,closeTmpFiles);
1256   applyToSet(tmpfileNameSet, rmTmpFiles);
1257 }