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