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