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