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