* src/pic/device.c (dump_sfr): replaced register declaration with
[fw/sdcc] / src / pic / glue.c
1 /*-------------------------------------------------------------------------
2
3   SDCCglue.c - glues everything we have done together into one file.
4                 Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
24
25 #include "../common.h"
26 #include <time.h>
27 #include "ralloc.h"
28 #include "pcode.h"
29 #include "newalloc.h"
30 #include "gen.h"
31
32
33 #ifdef WORDS_BIGENDIAN
34 #define _ENDIAN(x)  (3-x)
35 #else
36 #define _ENDIAN(x)  (x)
37 #endif
38
39 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
40
41 extern symbol *interrupts[256];
42 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
43 extern int noAlloc;
44 extern set *publics;
45 extern set *externs;
46 extern unsigned maxInterrupts;
47 extern int maxRegBank;
48 extern symbol *mainf;
49 extern char *VersionString;
50 extern FILE *codeOutFile;
51 extern set *tmpfileSet;
52 extern set *tmpfileNameSet;
53 extern char *iComments1;
54 extern char *iComments2;
55 //extern void emitStaticSeg (memmap * map);
56
57 extern DEFSETFUNC (closeTmpFiles);
58 extern DEFSETFUNC (rmTmpFiles);
59
60 extern void AnalyzeBanking (void);
61 extern void copyFile (FILE * dest, FILE * src);
62 extern void ReuseReg(void);
63 extern void InlinepCode(void);
64 extern void writeUsedRegs(FILE *);
65
66 extern void initialComments (FILE * afile);
67 extern void printPublics (FILE * afile);
68
69 extern void printChar (FILE * ofile, char *s, int plen);
70 void  pCodeInitRegisters(void);
71 int getConfigWord(int address);
72
73 char *udata_section_name=0;             // FIXME Temporary fix to change udata section name -- VR
74
75 /*-----------------------------------------------------------------*/
76 /* aopLiteral - string from a literal value                        */
77 /*-----------------------------------------------------------------*/
78 int pic14aopLiteral (value *val, int offset)
79 {
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 = (unsigned long) floatFromVal(val);
89                 
90                 return ( (v >> (offset * 8)) & 0xff);
91         }
92         
93         /* it is type float */
94         fl.f = (float) floatFromVal(val);
95 #ifdef WORDS_BIGENDIAN
96         return fl.c[3-offset];
97 #else
98         return fl.c[offset];
99 #endif
100         
101 }
102
103 /* set of already emitted symbols; we store only pointers to the emitted
104  * symbol names so these MUST NO BE CHANGED afterwards... */
105 static set *symbolsEmitted = NULL;
106
107 /*-------------------------------------------------------------------*/
108 /* emitSymbolToFile - write a symbol definition only if it is not    */
109 /*                    already present                                */
110 /*-------------------------------------------------------------------*/
111 void
112 emitSymbolToFile (FILE *of, const char *name, int size)
113 {
114         const char *sym;
115         
116         /* check whether the symbol is already defined */
117         for (sym = (const char *) setFirstItem (symbolsEmitted);
118                 sym;
119                 sym = (const char *) setNextItem (symbolsEmitted))
120         {
121                 if (!strcmp (sym, name))
122                 {
123                         //fprintf (stderr, "%s: already emitted: %s\n", __FUNCTION__, name);
124                         return;
125                 }
126         } // for
127         
128         /* new symbol -- define it */
129         //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
130         fprintf (of, "%s\tres\t%d\n", name, size);
131         addSet (&symbolsEmitted, (void *) name);
132 }
133
134 /*-----------------------------------------------------------------*/
135 /* emitRegularMap - emit code for maps with no special cases       */
136 /*-----------------------------------------------------------------*/
137 static void
138 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
139 {
140         symbol *sym;
141         int bitvars = 0;;
142         
143         /* print the area name */
144         if (addPublics)
145                 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
146         
147         for (sym = setFirstItem (map->syms); sym;
148         sym = setNextItem (map->syms)) {
149                 
150                 //printf("%s\n",sym->name);
151                 
152                 /* if extern then add it into the extern list */
153                 if (IS_EXTERN (sym->etype)) {
154                         addSetHead (&externs, sym);
155                         continue;
156                 }
157                 
158                 /* if allocation required check is needed
159                 then check if the symbol really requires
160                 allocation only for local variables */
161                 if (arFlag && !IS_AGGREGATE (sym->type) &&
162                         !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
163                         !sym->allocreq && sym->level)
164                         continue;
165                 
166                         /* if global variable & not static or extern
167                 and addPublics allowed then add it to the public set */
168                 if ((sym->level == 0 ||
169                         (sym->_isparm && !IS_REGPARM (sym->etype))) &&
170                         addPublics &&
171                         !IS_STATIC (sym->etype))
172                         addSetHead (&publics, sym);
173                 
174                 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
175                 if (sym->_isparm)
176                         continue;
177                         /* if extern then do nothing or is a function
178                 then do nothing */
179                 if (IS_FUNC (sym->type))
180                         continue;
181 #if 0
182                 /* print extra debug info if required */
183                 if (options.debug || sym->level == 0)
184                 {
185                         if (!sym->level)        /* global */
186                                 if (IS_STATIC (sym->etype))
187                                         fprintf (map->oFile, "F%s_", moduleName);               /* scope is file */
188                                 else
189                                         fprintf (map->oFile, "G_");     /* scope is global */
190                                 else
191                                         /* symbol is local */
192                                         fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
193                                 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
194                 }
195 #endif
196                 
197                 /* if it has an absolute address then generate
198                 an equate for this no need to allocate space */
199                 if (SPEC_ABSA (sym->etype))
200                 {
201                         //if (options.debug || sym->level == 0)
202                         //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
203                         
204                         fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
205                                 sym->rname,
206                                 SPEC_ADDR (sym->etype));
207                 }
208                 else
209                 {
210                         /* allocate space */
211                         
212                         /* If this is a bit variable, then allocate storage after 8 bits have been declared */
213                         /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
214                         /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
215                         if (IS_BITVAR (sym->etype))
216                         {
217                                 bitvars++;
218                         }
219                         else
220                         {
221                                 emitSymbolToFile (map->oFile, sym->rname, getSize (sym->type) & 0xffff);
222                                 /*
223                                 {
224                                 int i, size;
225                                 
226                                   if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
227                                   {
228                                   for (i = 1; i < size; i++)
229                                   fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
230                                   }
231                                   }
232                                 */
233                         }
234                         //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
235                 }
236                 
237                 /* if it has a initial value then do it only if
238                 it is a global variable */
239                 if (sym->ival && sym->level == 0) {
240                         ast *ival = NULL;
241                         
242                         if (IS_AGGREGATE (sym->type))
243                                 ival = initAggregates (sym, sym->ival, NULL);
244                         else
245                                 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
246                                 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
247                         codeOutFile = statsg->oFile;
248                         GcurMemmap = statsg;
249                         eBBlockFromiCode (iCodeFromAst (ival));
250                         sym->ival = NULL;
251                 }
252         }
253 }
254
255
256 /*-----------------------------------------------------------------*/
257 /* printIvalType - generates ival for int/char                     */
258 /*-----------------------------------------------------------------*/
259 static void 
260 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
261 {
262         value *val;
263         unsigned long ulval;
264         
265         //fprintf(stderr, "%s\n",__FUNCTION__);
266         
267         /* if initList is deep */
268         if (ilist->type == INIT_DEEP)
269                 ilist = ilist->init.deep;
270         
271         if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
272                 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
273         }
274         
275         if (!(val = list2val (ilist))) {
276                 // assuming a warning has been thrown
277                 val=constVal("0");
278         }
279         
280         if (val->type != type) {
281                 val = valCastLiteral(type, floatFromVal(val));
282         }
283         
284         if(val) 
285                 ulval = (unsigned long) floatFromVal (val);
286         else
287                 ulval =0;
288         
289         switch (getSize (type)) {
290         case 1:
291                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
292                 break;
293                 
294         case 2:
295                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
296                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
297                 break;
298                 
299         case 4:
300                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
301                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
302                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
303                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
304                 break;
305         }
306 }
307
308 /*-----------------------------------------------------------------*/
309 /* printIvalBitFields - generate initializer for bitfields         */
310 /*-----------------------------------------------------------------*/
311 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb ) 
312 {
313         value *val ;
314         symbol *lsym = *sym;
315         initList *lilist = *ilist ;
316         unsigned long ival = 0;
317         int size =0;
318         
319         
320         do {
321                 unsigned long i;
322                 val = list2val(lilist);
323                 if (size) {
324                         if (SPEC_BLEN(lsym->etype) > 8) {
325                                 size += ((SPEC_BLEN (lsym->etype) / 8) + 
326                                         (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
327                         }
328                 } else {
329                         size = ((SPEC_BLEN (lsym->etype) / 8) + 
330                                 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
331                 }
332                 i = (unsigned long)floatFromVal(val);
333                 i <<= SPEC_BSTR (lsym->etype);
334                 ival |= i;
335                 if (! ( lsym->next &&
336                         (IS_BITFIELD(lsym->next->type)) &&
337                         (SPEC_BSTR(lsym->next->etype)))) break;
338                 lsym = lsym->next;
339                 lilist = lilist->next;
340         } while (1);
341         switch (size) {
342         case 1:
343                 //tfprintf (oFile, "\t!db !constbyte\n",ival);
344                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
345                 break;
346                 
347         case 2:
348                 //tfprintf (oFile, "\t!dw !constword\n",ival);
349                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
350                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
351                 break;
352         case 4:
353                 //tfprintf (oFile, "\t!db  !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
354                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
355                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
356                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
357                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
358                 break;
359         }
360         *sym = lsym;
361         *ilist = lilist;
362 }
363
364 /*-----------------------------------------------------------------*/
365 /* printIvalStruct - generates initial value for structures        */
366 /*-----------------------------------------------------------------*/
367 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
368 {
369         symbol *sflds;
370         initList *iloop = NULL;
371         
372         sflds = SPEC_STRUCT (type)->fields;
373         
374         if (ilist) {
375                 if (ilist->type != INIT_DEEP) {
376                         werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
377                         return;
378                 }
379                 
380                 iloop = ilist->init.deep;
381         }
382         
383         for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
384                 if (IS_BITFIELD(sflds->type)) {
385                         printIvalBitFields(&sflds,&iloop,pb);
386                 } else {
387                         printIval (sym, sflds->type, iloop, pb);
388                 }
389         }
390         if (iloop) {
391                 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
392         }
393         return;
394 }
395
396 /*-----------------------------------------------------------------*/
397 /* printIvalChar - generates initital value for character array    */
398 /*-----------------------------------------------------------------*/
399 static int 
400 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
401 {
402         value *val;
403         int remain, ilen;
404         
405         if(!pb)
406                 return 0;
407         
408         //fprintf(stderr, "%s\n",__FUNCTION__);
409         if (!s)
410         {
411                 
412                 val = list2val (ilist);
413
414                 /* if the value is a character string  */
415                 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
416                 {
417                         ilen = DCL_ELEM(val->type);
418
419                         if (!DCL_ELEM (type))
420                                 DCL_ELEM (type) = ilen;
421                 
422                         /* emit string constant */
423                         for (remain = 0; remain < ilen; remain++) {
424                                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
425                         }
426                         
427                         /* fill array up to desired size */
428                         if ((remain = (DCL_ELEM (type) - ilen)) > 0)
429                                 while (remain--)
430                                         //tfprintf (oFile, "\t!db !constbyte\n", 0);
431                                         addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
432                                 return 1;
433                 }
434                 else
435                         return 0;
436         }
437         else {
438                 //printChar (oFile, s, strlen (s) + 1);
439                 
440                 for(remain=0; remain<(int)strlen(s); remain++) {
441                         addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
442                         //fprintf(stderr,"0x%02x ",s[remain]);
443                 }
444                 //fprintf(stderr,"\n");
445         }
446         return 1;
447 }
448
449 /*-----------------------------------------------------------------*/
450 /* printIvalArray - generates code for array initialization        */
451 /*-----------------------------------------------------------------*/
452 static void 
453 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
454                                 pBlock *pb)
455 {
456         initList *iloop;
457         unsigned size = 0;
458
459         if(!pb)
460                 return;
461         if (ilist) {
462                 /* take care of the special   case  */
463                 /* array of characters can be init  */
464                 /* by a string                      */
465                 if (IS_CHAR (type->next)) {
466                         //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
467                         if (!IS_LITERAL(list2val(ilist)->etype)) {
468                                 werror (W_INIT_WRONG);
469                                 return;
470                         }
471                         if (printIvalChar (type,
472                                 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
473                                 pb, SPEC_CVAL (sym->etype).v_char))
474                                 return;
475                 }
476                 /* not the special case */
477                 if (ilist->type != INIT_DEEP) {
478                         werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
479                         return;
480                 }
481
482                 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
483                         if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
484                                 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
485                                 break;
486                         }
487                         printIval (sym, type->next, iloop, pb);
488                 }
489         }
490
491         if (DCL_ELEM(type)) {
492                 // pad with zeros if needed
493                 if (size<DCL_ELEM(type)) {
494                         size = (DCL_ELEM(type) - size) * getSize(type->next);
495                         while (size--) {
496                                 //tfprintf (oFile, "\t!db !constbyte\n", 0);
497                                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
498                         }
499                 }
500         } else {
501                 // we have not been given a size, but we now know it
502                 DCL_ELEM (type) = size;
503         }
504
505         return;
506 }
507
508 /*-----------------------------------------------------------------*/
509 /* printIvalPtr - generates code for initial value of pointers     */
510 /*-----------------------------------------------------------------*/
511 extern value *initPointer (initList *, sym_link *toType);
512
513 static void 
514 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
515 {
516         value *val;
517         
518         if (!ilist || !pb)
519                 return;
520         
521         fprintf (stderr, "FIXME: initializers for pointers...\n");
522         printTypeChain (type, stderr);
523         
524         fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
525         fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
526
527         if (ilist && (ilist->type == INIT_DEEP))
528           ilist = ilist->init.deep;
529         
530         /* function pointers */
531         if (IS_FUNC (type->next))
532         {
533                 assert ( !"function pointers not yet handled" );
534                 //printIvalFuncPtr (type, ilist, pb);
535         }
536
537         if (!(val = initPointer (ilist, type)))
538                 return;
539         
540         if (IS_CHAR (type->next))
541         {
542                 if (printIvalChar (type, ilist, pb, NULL)) return;
543         }
544
545         /* check the type */
546         if (compareType (type, val->type) == 0)
547         {
548                 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
549                 printFromToType (val->type, type);
550         }
551
552         if (IS_LITERAL (val->etype))
553         {
554                 switch (getSize (type))
555                 {
556                 case 1:
557                         fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
558                         break;
559                 case 2:
560                         fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
561                         break;
562                 case 3: /* gneric pointers */
563                         assert ( !"generic pointers not yet handled" );
564                 case 4:
565                         fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
566                         break;
567                 default:
568                         assert ( !"invaild size of value -- aborting" );
569                 } // switch
570
571                 return;
572         } // if (IS_LITERAL)
573
574         /* now handle symbolic values */
575         switch (getSize (type))
576         {
577         case 1:
578                 fprintf (stderr, "BYTE: %s", val->name);
579                 break;
580         case 2:
581                 fprintf (stderr, "WORD: %s", val->name);
582                 break;
583         case 4:
584                 fprintf (stderr, "LONG: %s", val->name);
585                 break;
586         default:
587                 assert ( !"invalid size of (symbolic) value -- aborting" );
588         } // switch
589 }
590
591 /*-----------------------------------------------------------------*/
592 /* printIval - generates code for initial value                    */
593 /*-----------------------------------------------------------------*/
594 static void 
595 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
596 {
597         if (!ilist || !pb)
598                 return;
599         
600         /* if structure then    */
601         if (IS_STRUCT (type))
602         {
603                 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
604                 printIvalStruct (sym, type, ilist, pb);
605                 return;
606         }
607         
608         /* if this is an array   */
609         if (IS_ARRAY (type))
610         {
611                 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
612                 printIvalArray (sym, type, ilist, pb);
613                 return;
614         }
615         
616         /* if this is a pointer */
617         if (IS_PTR (type))
618         {
619                 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
620                 printIvalPtr (sym, type, ilist, pb);
621                 return;
622         }
623         
624         /* if type is SPECIFIER */
625         if (IS_SPEC (type))
626         {
627                 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
628                 printIvalType (sym, type, ilist, pb);
629                 return;
630         }
631 }
632
633 extern void pCodeConstString(char *name, char *value);
634 /*-----------------------------------------------------------------*/
635 /* emitStaticSeg - emitcode for the static segment                 */
636 /*-----------------------------------------------------------------*/
637 static void
638 pic14emitStaticSeg (memmap * map)
639 {
640         symbol *sym;
641         
642         fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
643         
644         //fprintf(stderr, "%s\n",__FUNCTION__);
645         
646         /* for all variables in this segment do */
647         for (sym = setFirstItem (map->syms); sym;
648         sym = setNextItem (map->syms))
649         {
650                 /* if extern then add it into the extern list */
651                 if (IS_EXTERN (sym->etype)) {
652                         addSetHead (&externs, sym);
653                         continue;
654                 }
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                         if (!sym->level)
665                         {                       /* global */
666                                 if (IS_STATIC (sym->etype))
667                                         fprintf (code->oFile, "F%s_", moduleName);      /* scope is file */
668                                 else
669                                         fprintf (code->oFile, "G_");    /* scope is global */
670                         }
671                         else
672                                 /* symbol is local */
673                                 fprintf (code->oFile, "L%s_",
674                                 (sym->localof ? sym->localof->name : "-null-"));
675                         fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
676                         
677                 }
678                 
679                 /* if it has an absolute address */
680                 if (SPEC_ABSA (sym->etype))
681                 {
682                         if (options.debug || sym->level == 0)
683                                 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
684                         
685                         fprintf (code->oFile, "%s\t=\t0x%04x\n",
686                                 sym->rname,
687                                 SPEC_ADDR (sym->etype));
688                 }
689                 else
690                 {
691                         if (options.debug || sym->level == 0)
692                                 fprintf (code->oFile, " == .\n");
693                         
694                         /* if it has an initial value */
695                         if (sym->ival)
696                         {
697                                 pBlock *pb;
698                                 
699                                 fprintf (code->oFile, "%s:\n", sym->rname);
700                                 noAlloc++;
701                                 resolveIvalSym (sym->ival, sym->type);
702                                 //printIval (sym, sym->type, sym->ival, code->oFile);
703                                 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
704                                 addpBlock(pb);
705                                 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
706                                 
707                                 printIval (sym, sym->type, sym->ival, pb);
708                                 noAlloc--;
709                         }
710                         else
711                         {
712                                 
713                                 /* allocate space */
714                                 fprintf (code->oFile, "%s:\n", sym->rname);
715                                 /* special case for character strings */
716                                 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
717                                         SPEC_CVAL (sym->etype).v_char)
718                                         pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
719                                         /*printChar (code->oFile,
720                                         SPEC_CVAL (sym->etype).v_char,
721                                 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
722                                 else
723                                         fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
724                         }
725                 }
726         }
727         
728 }
729
730
731 /*-----------------------------------------------------------------*/
732 /* emitMaps - emits the code for the data portion the code         */
733 /*-----------------------------------------------------------------*/
734 static void
735 pic14emitMaps ()
736 {
737 /* no special considerations for the following
738         data, idata & bit & xdata */
739         pic14emitRegularMap (data, TRUE, TRUE);
740         pic14emitRegularMap (idata, TRUE, TRUE);
741         pic14emitRegularMap (bit, TRUE, FALSE);
742         pic14emitRegularMap (xdata, TRUE, TRUE);
743         pic14emitRegularMap (sfr, FALSE, FALSE);
744         pic14emitRegularMap (sfrbit, FALSE, FALSE);
745         pic14emitRegularMap (code, TRUE, FALSE);
746         pic14emitStaticSeg (statsg);
747 }
748
749 /*-----------------------------------------------------------------*/
750 /* createInterruptVect - creates the interrupt vector              */
751 /*-----------------------------------------------------------------*/
752 static void
753 pic14createInterruptVect (FILE * vFile)
754 {
755         mainf = newSymbol ("main", 0);
756         mainf->block = 0;
757         
758         /* only if the main function exists */
759         if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
760         {
761                 struct options *op = &options;
762                 if (!(op->cc_only || noAssemble))
763                         //      werror (E_NO_MAIN);
764                         fprintf(stderr,"WARNING: function 'main' undefined\n");
765                 return;
766         }
767         
768         /* if the main is only a prototype ie. no body then do nothing */
769         if (!IFFUNC_HASBODY(mainf->type))
770         {
771                 /* if ! compile only then main function should be present */
772                 if (!(options.cc_only || noAssemble))
773                         //      werror (E_NO_MAIN);
774                         fprintf(stderr,"WARNING: function 'main' undefined\n");
775                 return;
776         }
777         
778         fprintf (vFile, "%s", iComments2);
779         fprintf (vFile, "; config word \n");
780         fprintf (vFile, "%s", iComments2);
781         fprintf (vFile, "\t__config 0x%x\n", getConfigWord(0x2007));
782         
783         fprintf (vFile, "%s", iComments2);
784         fprintf (vFile, "; reset vector \n");
785         fprintf (vFile, "%s", iComments2);
786         fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
787         fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
788         fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
789 }
790
791
792 /*-----------------------------------------------------------------*/
793 /* initialComments - puts in some initial comments                 */
794 /*-----------------------------------------------------------------*/
795 static void
796 pic14initialComments (FILE * afile)
797 {
798         initialComments (afile);
799         fprintf (afile, "; PIC port for the 14-bit core\n");
800         fprintf (afile, iComments2);
801         
802 }
803
804 /*-----------------------------------------------------------------*/
805 /* printExterns - generates extern for external variables          */
806 /*-----------------------------------------------------------------*/
807 static void
808 pic14printExterns (FILE * afile)
809 {
810         symbol *sym;
811         
812         fprintf (afile, "%s", iComments2);
813         fprintf (afile, "; extern variables in this module\n");
814         fprintf (afile, "%s", iComments2);
815         
816         for (sym = setFirstItem (externs); sym;
817         sym = setNextItem (externs))
818                 fprintf (afile, "\textern %s\n", sym->rname);
819 }
820
821 /*-----------------------------------------------------------------*/
822 /* printPublics - generates .global for publics                    */
823 /*-----------------------------------------------------------------*/
824 static void
825 pic14printPublics (FILE * afile)
826 {
827         symbol *sym;
828         
829         fprintf (afile, "%s", iComments2);
830         fprintf (afile, "; publics variables in this module\n");
831         fprintf (afile, "%s", iComments2);
832         
833         for (sym = setFirstItem (publics); sym;
834         sym = setNextItem (publics)) {
835                 
836                 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
837                         if (!IS_BITVAR(sym->type))
838                                 fprintf (afile, "\tglobal %s\n", sym->rname);
839                 } else {
840                         /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
841                         if (!SPEC_ABSA (sym->etype))
842                                 fprintf (afile, "\tglobal %s\n", sym->rname);
843                 }
844         }
845 }
846
847 /*-----------------------------------------------------------------*/
848 /* emitOverlay - will emit code for the overlay stuff              */
849 /*-----------------------------------------------------------------*/
850 static void
851 pic14emitOverlay (FILE * afile)
852 {
853         set *ovrset;
854         
855         /*  if (!elementsInSet (ovrSetSets))*/
856         
857         /* the hack below, fixes translates for devices which
858         * only have udata_shr memory */
859         fprintf (afile, "%s\t%s\n",
860                 (elementsInSet(ovrSetSets)?"":";"),
861                 port->mem.overlay_name);
862         
863         /* for each of the sets in the overlay segment do */
864         for (ovrset = setFirstItem (ovrSetSets); ovrset;
865         ovrset = setNextItem (ovrSetSets))
866         {
867                 
868                 symbol *sym;
869                 
870                 if (elementsInSet (ovrset))
871                 {
872                 /* this dummy area is used to fool the assembler
873                 otherwise the assembler will append each of these
874                 declarations into one chunk and will not overlay
875                         sad but true */
876                         
877                         /* I don't think this applies to us. We are using gpasm.  CRF */
878                         
879                         fprintf (afile, ";\t.area _DUMMY\n");
880                         /* output the area informtion */
881                         fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);      /* MOF */
882                 }
883                 
884                 for (sym = setFirstItem (ovrset); sym;
885                 sym = setNextItem (ovrset))
886                 {
887                         
888                         /* if extern then do nothing */
889                         if (IS_EXTERN (sym->etype))
890                                 continue;
891                         
892                                 /* if allocation required check is needed
893                                 then check if the symbol really requires
894                         allocation only for local variables */
895                         if (!IS_AGGREGATE (sym->type) &&
896                                 !(sym->_isparm && !IS_REGPARM (sym->etype))
897                                 && !sym->allocreq && sym->level)
898                                 continue;
899                         
900                                 /* if global variable & not static or extern
901                         and addPublics allowed then add it to the public set */
902                         if ((sym->_isparm && !IS_REGPARM (sym->etype))
903                                 && !IS_STATIC (sym->etype))
904                                 addSetHead (&publics, sym);
905                         
906                                 /* if extern then do nothing or is a function
907                         then do nothing */
908                         if (IS_FUNC (sym->type))
909                                 continue;
910                         
911                         /* print extra debug info if required */
912                         if (options.debug || sym->level == 0)
913                         {
914                                 if (!sym->level)
915                                 {               /* global */
916                                         if (IS_STATIC (sym->etype))
917                                                 fprintf (afile, "F%s_", moduleName);    /* scope is file */
918                                         else
919                                                 fprintf (afile, "G_");  /* scope is global */
920                                 }
921                                 else
922                                         /* symbol is local */
923                                         fprintf (afile, "L%s_",
924                                         (sym->localof ? sym->localof->name : "-null-"));
925                                 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
926                         }
927                         
928                         /* if is has an absolute address then generate
929                         an equate for this no need to allocate space */
930                         if (SPEC_ABSA (sym->etype))
931                         {
932                                 
933                                 if (options.debug || sym->level == 0)
934                                         fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
935                                 
936                                 fprintf (afile, "%s\t=\t0x%04x\n",
937                                         sym->rname,
938                                         SPEC_ADDR (sym->etype));
939                         }
940                         else
941                         {
942                                 if (options.debug || sym->level == 0)
943                                         fprintf (afile, "==.\n");
944                                 
945                                 /* allocate space */
946                                 fprintf (afile, "%s:\n", sym->rname);
947                                 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
948                         }
949                         
950                 }
951         }
952 }
953
954
955 /*-----------------------------------------------------------------*/
956 /* glue - the final glue that hold the whole thing together        */
957 /*-----------------------------------------------------------------*/
958 void
959 picglue ()
960 {
961         char udata_name[80];
962         FILE *vFile;
963         FILE *asmFile;
964         FILE *ovrFile = tempfile();
965         
966         addSetHead(&tmpfileSet,ovrFile);
967         pCodeInitRegisters();
968         
969         if (mainf && IFFUNC_HASBODY(mainf->type)) {
970                 
971                 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
972                 addpBlock(pb);
973                 
974                 /* entry point @ start of CSEG */
975                 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
976                 /* put in the call to main */
977                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
978                 
979                 if (options.mainreturn) {
980                         
981                         addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
982                         addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
983                         
984                 } else {
985                         
986                         addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
987                         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
988                         
989                 }
990         }
991         
992         
993         /* At this point we've got all the code in the form of pCode structures */
994         /* Now it needs to be rearranged into the order it should be placed in the */
995         /* code space */
996         
997         movepBlock2Head('P');              // Last
998         movepBlock2Head(code->dbName);
999         movepBlock2Head('X');
1000         movepBlock2Head(statsg->dbName);   // First
1001         
1002         
1003         /* print the global struct definitions */
1004         if (options.debug)
1005                 cdbStructBlock (0);
1006         
1007         vFile = tempfile();
1008         
1009         addSetHead(&tmpfileSet,vFile);
1010         
1011         /* emit code for the all the variables declared */
1012         pic14emitMaps ();
1013         /* do the overlay segments */
1014         pic14emitOverlay(ovrFile);
1015         
1016         /* PENDING: this isnt the best place but it will do */
1017         if (port->general.glue_up_main) {
1018                 /* create the interrupt vector table */
1019                 pic14createInterruptVect (vFile);
1020         }
1021         
1022         AnalyzepCode('*');
1023         
1024         ReuseReg(); // ReuseReg where call tree permits
1025         
1026         InlinepCode();
1027         
1028         AnalyzepCode('*');
1029         
1030         pcode_test();
1031         
1032         
1033         /* now put it all together into the assembler file */
1034         /* create the assembler file name */
1035         
1036         if ((noAssemble || options.c1mode) && fullDstFileName)
1037         {
1038                 sprintf (buffer, fullDstFileName);
1039         }
1040         else
1041         {
1042                 sprintf (buffer, dstFileName);
1043                 strcat (buffer, ".asm");
1044         }
1045         
1046         if (!(asmFile = fopen (buffer, "w"))) {
1047                 werror (E_FILE_OPEN_ERR, buffer);
1048                 exit (1);
1049         }
1050
1051         /* prepare statistics */
1052         resetpCodeStatistics ();
1053         
1054         /* initial comments */
1055         pic14initialComments (asmFile);
1056         
1057         /* print module name */
1058         fprintf (asmFile, ";\t.module %s\n", moduleName);
1059         
1060         /* Let the port generate any global directives, etc. */
1061         if (port->genAssemblerPreamble)
1062         {
1063                 port->genAssemblerPreamble(asmFile);
1064         }
1065         
1066         /* print the extern variables in this module */
1067         pic14printExterns (asmFile);
1068         
1069         /* print the global variables in this module */
1070         pic14printPublics (asmFile);
1071         
1072         /* copy the sfr segment */
1073         fprintf (asmFile, "%s", iComments2);
1074         fprintf (asmFile, "; special function registers\n");
1075         fprintf (asmFile, "%s", iComments2);
1076         copyFile (asmFile, sfr->oFile);
1077         
1078         
1079         if (udata_section_name) {
1080                 sprintf(udata_name,"%s",udata_section_name);
1081         } else {
1082                 sprintf(udata_name,"data_%s",moduleName);
1083         }
1084         fprintf (asmFile, "%s", iComments2);
1085         fprintf (asmFile, "; udata\n");
1086         fprintf (asmFile, "%s", iComments2);
1087         fprintf (asmFile, "%s\tudata\n", udata_name);
1088         copyFile (asmFile, data->oFile);
1089         
1090         /* Put all variables into a cblock */
1091         AnalyzeBanking();
1092         writeUsedRegs(asmFile);
1093         
1094         /* create the overlay segments */
1095         fprintf (asmFile, "%s", iComments2);
1096         fprintf (asmFile, "; overlayable items in internal ram \n");
1097         fprintf (asmFile, "%s", iComments2);    
1098         copyFile (asmFile, ovrFile);
1099         
1100 #if 0
1101         
1102         /* create the stack segment MOF */
1103         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1104                 fprintf (asmFile, "%s", iComments2);
1105                 fprintf (asmFile, "; Stack segment in internal ram \n");
1106                 fprintf (asmFile, "%s", iComments2);    
1107                 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1108                         ";__start__stack:\n;\t.ds\t1\n\n");
1109         }
1110         
1111         /* create the idata segment */
1112         fprintf (asmFile, "%s", iComments2);
1113         fprintf (asmFile, "; indirectly addressable internal ram data\n");
1114         fprintf (asmFile, "%s", iComments2);
1115         copyFile (asmFile, idata->oFile);
1116         
1117         /* if external stack then reserve space of it */
1118         if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1119                 fprintf (asmFile, "%s", iComments2);
1120                 fprintf (asmFile, "; external stack \n");
1121                 fprintf (asmFile, "%s", iComments2);
1122                 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1123                 fprintf (asmFile,";\t.ds 256\n");
1124         }
1125         
1126         /* copy xtern ram data */
1127         fprintf (asmFile, "%s", iComments2);
1128         fprintf (asmFile, "; external ram data\n");
1129         fprintf (asmFile, "%s", iComments2);
1130         copyFile (asmFile, xdata->oFile);
1131         
1132 #endif
1133         
1134         /* copy the bit segment */
1135         fprintf (asmFile, "%s", iComments2);
1136         fprintf (asmFile, "; bit data\n");
1137         fprintf (asmFile, "%s", iComments2);
1138         copyFile (asmFile, bit->oFile);
1139
1140         /* copy the interrupt vector table */
1141         if (mainf && IFFUNC_HASBODY(mainf->type)) {
1142                 copyFile (asmFile, vFile);
1143                 
1144                 fprintf (asmFile, "%s", iComments2);
1145                 fprintf (asmFile, "; interrupt and initialization code\n");
1146                 fprintf (asmFile, "%s", iComments2);
1147                 fprintf (asmFile, "code_init\t%s\t0x4\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1148                 
1149                 /* interrupt service routine */
1150                 fprintf (asmFile, "__sdcc_interrupt:\n");
1151                 copypCode(asmFile, 'I');
1152                 
1153                 /* initialize data memory */
1154                 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1155                 /* FIXME: This is temporary.  The idata section should be used.  If 
1156                 not, we could add a special feature to the linker.  This will 
1157                 work in the mean time.  Put all initalized data in main.c */
1158                 copypCode(asmFile, statsg->dbName);
1159                 fprintf (asmFile,"\tpagesel _main\n");
1160                 fprintf (asmFile,"\tgoto _main\n");
1161         }
1162         
1163 #if 0    
1164         
1165         /* copy global & static initialisations */
1166         fprintf (asmFile, "%s", iComments2);
1167         fprintf (asmFile, "; global & static initialisations\n");
1168         fprintf (asmFile, "%s", iComments2);
1169         copypCode(asmFile, statsg->dbName);
1170         
1171 #endif
1172         
1173         /* copy over code */
1174         fprintf (asmFile, "%s", iComments2);
1175         fprintf (asmFile, "; code\n");
1176         fprintf (asmFile, "%s", iComments2);
1177         fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1178         
1179         /* unknown */
1180         copypCode(asmFile, 'X');
1181         
1182         /* _main function */
1183         copypCode(asmFile, 'M');
1184         
1185         /* other functions */
1186         copypCode(asmFile, code->dbName);
1187         
1188         /* unknown */
1189         copypCode(asmFile, 'P');
1190
1191         dumppCodeStatistics (asmFile);
1192         
1193         fprintf (asmFile,"\tend\n");
1194         
1195         fclose (asmFile);
1196         
1197         rm_tmpfiles();
1198 }