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