Changed Safe_calloc to use 2 arguements to mimic teh standard calloc function
[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(1,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(1,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 }