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