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