* src/SDCCsymt.c (compStructSize): make bitfields without (un)signed specifier unsigned
[fw/sdcc] / src / pic / glue.c
index 85d49a3a8495e55a82336710034aa7e623cb2631..7868be5beb1eae3f0eb8e0b394eac8bf92936cf8 100644 (file)
@@ -27,6 +27,8 @@
 #include "ralloc.h"
 #include "pcode.h"
 #include "newalloc.h"
+#include "gen.h"
+#include "main.h"
 
 
 #ifdef WORDS_BIGENDIAN
@@ -99,6 +101,79 @@ int pic14aopLiteral (value *val, int offset)
        
 }
 
+/* Check whether the given reg is shared amongst all .o files of a project.
+ * This is true for the pseudo stack and WSAVE, SSAVE and PSAVE. */
+int is_shared_address (int addr)
+{
+  return ((addr > Gstack_base_addr - 18)
+       && (addr <= Gstack_base_addr));
+}
+
+int
+is_shared (regs *reg)
+{
+       if (!reg) return 0;
+       return is_shared_address (reg->address);
+}
+
+/* set of already emitted symbols; we store only pointers to the emitted
+ * symbol names so these MUST NO BE CHANGED afterwards... */
+static set *symbolsEmitted = NULL;
+
+/*-------------------------------------------------------------------*/
+/* emitSymbolToFile - write a symbol definition only if it is not    */
+/*                    already present                                */
+/*-------------------------------------------------------------------*/
+void
+emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
+{
+       const char *sym;
+       static unsigned int sec_idx = 0;
+       
+       /* check whether the symbol is already defined */
+       for (sym = (const char *) setFirstItem (symbolsEmitted);
+               sym;
+               sym = (const char *) setNextItem (symbolsEmitted))
+       {
+               if (!strcmp (sym, name))
+               {
+                       //fprintf (stderr, "%s: already emitted: %s\n", __FUNCTION__, name);
+                       return;
+               }
+       } // for
+       
+       /* new symbol -- define it */
+       //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
+       if (useEQU)
+         fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
+       else
+       {
+         /* we place each symbol into a section of its own to allow the linker
+          * to distribute the data into all available memory banks */
+         if (!section_type) section_type = "udata";
+         if (addr != -1)
+         {
+           /* workaround gpasm bug with symbols being EQUated and placed in absolute sections */
+           if (is_shared_address (addr))
+           {
+             if (globalize) fprintf (of, "\tglobal\t%s\n", name);
+             fprintf (of, "udata_%s_%u\t%s\t0x%04x\n", moduleName, sec_idx++, section_type, addr);
+             fprintf (of, "%s\tres\t%d\n", name, size);
+           }
+           else
+           {
+             /* EQUs cannot be exported... */
+             fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
+           }
+         } else {
+           if (globalize) fprintf (of, "\tglobal\t%s\n", name);
+           fprintf (of, "udata_%s_%u\t%s\n", moduleName, sec_idx++, section_type);
+           fprintf (of, "%s\tres\t%d\n", name, size);
+         }
+       }
+       
+       addSet (&symbolsEmitted, (void *) name);
+}
 
 /*-----------------------------------------------------------------*/
 /* emitRegularMap - emit code for maps with no special cases       */
@@ -187,7 +262,7 @@ pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
                        }
                        else
                        {
-                               fprintf (map->oFile, "%s\tres\t%d\n", sym->rname,getSize (sym->type) & 0xffff);
+                               emitSymbolToFile (map->oFile, sym->rname, NULL, getSize (sym->type) & 0xffff, -1, 0, 0);
                                /*
                                {
                                int i, size;
@@ -424,7 +499,7 @@ printIvalArray (symbol * sym, sym_link * type, initList * ilist,
 {
        initList *iloop;
        unsigned size = 0;
-       
+
        if(!pb)
                return;
        if (ilist) {
@@ -474,6 +549,89 @@ printIvalArray (symbol * sym, sym_link * type, initList * ilist,
        return;
 }
 
+/*-----------------------------------------------------------------*/
+/* printIvalPtr - generates code for initial value of pointers     */
+/*-----------------------------------------------------------------*/
+extern value *initPointer (initList *, sym_link *toType);
+
+static void 
+printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
+{
+       value *val;
+       
+       if (!ilist || !pb)
+               return;
+       
+       fprintf (stderr, "FIXME: initializers for pointers...\n");
+       printTypeChain (type, stderr);
+       
+       fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
+       fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
+
+       if (ilist && (ilist->type == INIT_DEEP))
+         ilist = ilist->init.deep;
+       
+       /* function pointers */
+       if (IS_FUNC (type->next))
+       {
+               assert ( !"function pointers not yet handled" );
+               //printIvalFuncPtr (type, ilist, pb);
+       }
+
+       if (!(val = initPointer (ilist, type)))
+               return;
+       
+       if (IS_CHAR (type->next))
+       {
+               if (printIvalChar (type, ilist, pb, NULL)) return;
+       }
+
+       /* check the type */
+       if (compareType (type, val->type) == 0)
+       {
+               werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
+               printFromToType (val->type, type);
+       }
+
+       if (IS_LITERAL (val->etype))
+       {
+               switch (getSize (type))
+               {
+               case 1:
+                       fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
+                       break;
+               case 2:
+                       fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
+                       break;
+               case 3: /* gneric pointers */
+                       assert ( !"generic pointers not yet handled" );
+               case 4:
+                       fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
+                       break;
+               default:
+                       assert ( !"invaild size of value -- aborting" );
+               } // switch
+
+               return;
+       } // if (IS_LITERAL)
+
+       /* now handle symbolic values */
+       switch (getSize (type))
+       {
+       case 1:
+               fprintf (stderr, "BYTE: %s", val->name);
+               break;
+       case 2:
+               fprintf (stderr, "WORD: %s", val->name);
+               break;
+       case 4:
+               fprintf (stderr, "LONG: %s", val->name);
+               break;
+       default:
+               assert ( !"invalid size of (symbolic) value -- aborting" );
+       } // switch
+}
+
 /*-----------------------------------------------------------------*/
 /* printIval - generates code for initial value                    */
 /*-----------------------------------------------------------------*/
@@ -486,31 +644,31 @@ printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
        /* if structure then    */
        if (IS_STRUCT (type))
        {
-               //fprintf(stderr,"%s struct\n",__FUNCTION__);
+               //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
                printIvalStruct (sym, type, ilist, pb);
                return;
        }
        
-       /* if this is a pointer */
-       if (IS_PTR (type))
+       /* if this is an array   */
+       if (IS_ARRAY (type))
        {
-               //fprintf(stderr,"%s pointer\n",__FUNCTION__);
-               //printIvalPtr (sym, type, ilist, oFile);
+               //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
+               printIvalArray (sym, type, ilist, pb);
                return;
        }
        
-       /* if this is an array   */
-       if (IS_ARRAY (type))
+       /* if this is a pointer */
+       if (IS_PTR (type))
        {
-               //fprintf(stderr,"%s array\n",__FUNCTION__);
-               printIvalArray (sym, type, ilist, pb);
+               //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
+               printIvalPtr (sym, type, ilist, pb);
                return;
        }
        
        /* if type is SPECIFIER */
        if (IS_SPEC (type))
        {
-               //fprintf(stderr,"%s spec\n",__FUNCTION__);
+               //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
                printIvalType (sym, type, ilist, pb);
                return;
        }
@@ -851,7 +1009,20 @@ picglue ()
        
        addSetHead(&tmpfileSet,ovrFile);
        pCodeInitRegisters();
-       
+
+       /* check for main() */
+       mainf = newSymbol ("main", 0);
+       mainf->block = 0;
+       mainf = findSymWithLevel (SymbolTab, mainf);
+
+       if (!mainf || !IFFUNC_HASBODY(mainf->type))
+       {
+               /* main missing -- import stack from main module */
+               //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
+               pic14_options.isLibrarySource = 1;
+       }
+
+#if 0
        if (mainf && IFFUNC_HASBODY(mainf->type)) {
                
                pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
@@ -874,7 +1045,7 @@ picglue ()
                        
                }
        }
-       
+#endif 
        
        /* At this point we've got all the code in the form of pCode structures */
        /* Now it needs to be rearranged into the order it should be placed in the */
@@ -933,6 +1104,9 @@ picglue ()
                werror (E_FILE_OPEN_ERR, buffer);
                exit (1);
        }
+
+       /* prepare statistics */
+       resetpCodeStatistics ();
        
        /* initial comments */
        pic14initialComments (asmFile);
@@ -1019,7 +1193,7 @@ picglue ()
        fprintf (asmFile, "; bit data\n");
        fprintf (asmFile, "%s", iComments2);
        copyFile (asmFile, bit->oFile);
-       
+
        /* copy the interrupt vector table */
        if (mainf && IFFUNC_HASBODY(mainf->type)) {
                copyFile (asmFile, vFile);
@@ -1027,14 +1201,15 @@ picglue ()
                fprintf (asmFile, "%s", iComments2);
                fprintf (asmFile, "; interrupt and initialization code\n");
                fprintf (asmFile, "%s", iComments2);
-               fprintf (asmFile, "code_init\t%s\t0x4\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
+               fprintf (asmFile, "code_interrupt\t%s\t0x4\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
                
                /* interrupt service routine */
-               fprintf (asmFile, "__sdcc_interrupt:\n");
+               fprintf (asmFile, "__sdcc_interrupt\n");
                copypCode(asmFile, 'I');
                
                /* initialize data memory */
-               fprintf (asmFile,"__sdcc_gsinit_startup:\n");
+               fprintf (asmFile, "code_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
+               fprintf (asmFile,"__sdcc_gsinit_startup\n");
                /* FIXME: This is temporary.  The idata section should be used.  If 
                not, we could add a special feature to the linker.  This will 
                work in the mean time.  Put all initalized data in main.c */
@@ -1070,6 +1245,8 @@ picglue ()
        
        /* unknown */
        copypCode(asmFile, 'P');
+
+       dumppCodeStatistics (asmFile);
        
        fprintf (asmFile,"\tend\n");