* src/SDCCpeeph.c: made labelHashEntry global, made pcDistance, FBYNAME static,
[fw/sdcc] / src / pic / glue.c
index c5f491e146b54c2eec075a1ab1550aa00124ac62..59a31a9fcb4b0080ad9fad3a401551dddf9a3db8 100644 (file)
@@ -73,12 +73,14 @@ extern void printChar (FILE * ofile, char *s, int plen);
 void  pCodeInitRegisters(void);
 int getConfigWord(int address);
 int getHasSecondConfigReg(void);
-int pic14_getSharebankSize(void);
-int pic14_getSharebankAddress(void);
 
 char *udata_section_name=0;            // FIXME Temporary fix to change udata section name -- VR
 int pic14_hasInterrupt = 0;            // Indicates whether to emit interrupt handler or not
 
+static set *emitted = NULL;
+int pic14_stringInSet(const char *str, set **world, int autoAdd);
+static void emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize);
+
 /*-----------------------------------------------------------------*/
 /* aopLiteral - string from a literal value                        */
 /*-----------------------------------------------------------------*/
@@ -107,22 +109,6 @@ unsigned 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. */
-static int
-is_shared_address (int addr)
-{
-  return ((addr > Gstack_base_addr - 18)
-       && (addr <= Gstack_base_addr));
-}
-
-int
-pic14_is_shared (regs *reg)
-{
-       if (!reg) return 0;
-       return is_shared_address (reg->address);
-}
-
 static int
 is_valid_identifier( const char *name )
 {
@@ -150,82 +136,6 @@ is_valid_identifier( const char *name )
   return 1;
 }
 
-/* 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;
-
-       /* workaround: variables declared via `sbit' result in a numeric
-        * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
-        * sbit is heavily used in the inc2h-generated header files!
-        */
-       if (!is_valid_identifier(name))
-       {
-         //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
-         return;
-       }
-       
-       /* 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)
-         {
-           /* absolute symbols are handled in pic14_constructAbsMap */
-           /* do nothing */
-#if 0
-           /* workaround gpasm bug with symbols being EQUated and placed in absolute sections */
-           if (1 || !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++, "udata_ovr", addr);
-             fprintf (of, "%s\tres\t%d\n", name, size);
-           }
-           else
-           {
-             /* EQUs cannot be exported... */
-             fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
-           }
-#endif
-         } 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);
-         }
-       }
-
-       //if (options.verbose) fprintf (stderr, "%s: emitted %s\n", __FUNCTION__, name);
-       addSet (&symbolsEmitted, (void *) name);
-}
-
 #define IS_DEFINED_HERE(sym)   (!IS_EXTERN(sym->etype))
 extern int IS_CONFIG_ADDRESS( int addr );
 static void
@@ -238,6 +148,8 @@ pic14_constructAbsMap (FILE *ofile)
   set *aliases;
   int addr, min=-1, max=-1;
   int size;
+  PIC_device *pic;
+  int low, high, shared;
 
   for (i=0; maps[i] != NULL; i++)
   {
@@ -301,6 +213,11 @@ pic14_constructAbsMap (FILE *ofile)
        if (getSize(sym->type) > size) {
          size = getSize(sym->type);
        }
+       if (sym->islocal) {
+         // global symbols must be emitted again as 'global sym->name'
+         pic14_stringInSet(sym->name, &emitted, 1);
+         pic14_stringInSet(sym->rname, &emitted, 1);
+       }
       } // for
       fprintf (ofile, "\tres\t%d\n", size);
     } // if
@@ -312,21 +229,32 @@ pic14_constructAbsMap (FILE *ofile)
    *      required by larger devices but only up to STK03 might
    *      be defined using smaller devices. */
   fprintf (ofile, "\n");
+  shared = pic14_getSharedStack(&low, &high, &size);
   if (!pic14_options.isLibrarySource)
   {
+    pic = pic14_getPIC();
+
     fprintf (ofile, "\tglobal PSAVE\n");
     fprintf (ofile, "\tglobal SSAVE\n");
     fprintf (ofile, "\tglobal WSAVE\n");
-    for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
+    for (i = size - 4; i >= 0; i--) {
       fprintf (ofile, "\tglobal STK%02d\n", i);
     } // for i
-    fprintf (ofile, "sharebank udata_ovr 0x%04x\n",
-         pic14_getSharebankAddress() - pic14_getSharebankSize() + 1);
+
+    // 16f84 has no SHAREBANK (in linkerscript) but memory aliased in two
+    // banks, sigh...
+    if (1 || !shared) {
+       // for single banked devices: use normal, "banked" RAM
+       fprintf (ofile, "sharebank udata_ovr 0x%04X\n", low);
+    } else {
+       // for devices with at least two banks, require a sharebank section
+       fprintf (ofile, "sharebank udata_shr\n");
+    }
     fprintf (ofile, "PSAVE\tres 1\n");
     fprintf (ofile, "SSAVE\tres 1\n");
-    fprintf (ofile, "WSAVE\tres 1\n");
+    fprintf (ofile, "WSAVE\tres 1\n"); // WSAVE *must* be in sharebank (IRQ handlers)
     /* fill rest of sharebank with stack STKxx .. STK00 */
-    for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
+    for (i = size - 4; i >= 0; i--) {
       fprintf (ofile, "STK%02d\tres 1\n", i);
     } // for i
   } else {
@@ -335,8 +263,11 @@ pic14_constructAbsMap (FILE *ofile)
     fprintf (ofile, "\textern PSAVE\n");
     fprintf (ofile, "\textern SSAVE\n");
     fprintf (ofile, "\textern WSAVE\n");
-    for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
-      fprintf (ofile, "\textern STK%02d\n", i);
+    for (i = size - 4; i >= 0; i--) {
+       char buffer[128];
+       SNPRINTF(&buffer[0], 127, "STK%02d", i);
+       fprintf (ofile, "\textern %s\n", &buffer[0]);
+       pic14_stringInSet(&buffer[0], &emitted, 1);
     } // for i
   }
 }
@@ -974,6 +905,7 @@ pic14emitMaps ()
        pic14emitRegularMap (sfrbit, FALSE, FALSE);
        pic14emitRegularMap (code, TRUE, FALSE);
        pic14emitStaticSeg (statsg);
+       pic14emitStaticSeg (c_abs);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1010,6 +942,7 @@ pic14createInterruptVect (FILE * vFile)
        fprintf (vFile, "%s", iComments2);
        fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
        fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
+       fprintf( vFile, "\tpagesel __sdcc_gsinit_startup\n");
        fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
 }
 
@@ -1048,8 +981,6 @@ pic14_stringInSet(const char *str, set **world, int autoAdd)
 static int
 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
 {
-  static set *emitted = NULL;
-
   if (!pic14_stringInSet(sym, &emitted, 1)) {
     /* sym was not in emittedSymbols */
     if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
@@ -1061,6 +992,49 @@ pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLoc
   return 1;
 }
 
+/*-------------------------------------------------------------------*/
+/* emitSymbolToFile - write a symbol definition only if it is not    */
+/*                    already present                                */
+/*-------------------------------------------------------------------*/
+static void
+emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
+{
+    static unsigned int sec_idx = 0;
+
+    /* workaround: variables declared via `sbit' result in a numeric
+     * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
+     * sbit is heavily used in the inc2h-generated header files!
+     */
+    if (!is_valid_identifier(name))
+    {
+       //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
+       return;
+    }
+
+    /* check whether the symbol is already defined */
+    if (pic14_stringInSet(name, &emitted, 1)) return;
+
+    /* 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)
+       {
+           /* absolute symbols are handled in pic14_constructAbsMap */
+           /* do nothing */
+       } 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);
+       }
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* printExterns - generates extern for external variables          */
 /*-----------------------------------------------------------------*/
@@ -1086,7 +1060,7 @@ pic14printPublics (FILE * afile)
   symbol *sym;
 
   fprintf (afile, "%s", iComments2);
-  fprintf (afile, "; publics variables in this module\n");
+  fprintf (afile, "; public variables in this module\n");
   fprintf (afile, "%s", iComments2);
 
   for (sym = setFirstItem (publics); sym;
@@ -1104,6 +1078,28 @@ pic14printPublics (FILE * afile)
   }
 }
 
+static void
+pic14printLocals (FILE * afile)
+{
+  set *allregs[6] = { dynAllocRegs, dynStackRegs, dynProcessorRegs, dynDirectRegs, dynDirectBitRegs, dynInternalRegs };
+  regs *reg;
+  int i;
+
+  /* emit all registers from all possible sets */
+  for (i = 0; i < 6; i++) {
+    if (allregs[i] == NULL) continue;
+
+    for (reg = setFirstItem(allregs[i]); reg; reg = setNextItem(allregs[i])) {
+      if (reg->isEmitted) continue;
+
+      if (reg->wasUsed && !reg->isExtern) {
+        emitSymbolToFile(afile, reg->name, "udata", reg->size, reg->isFixed ? reg->address : -1, 0, reg->isPublic);
+      }
+      reg->isEmitted = 1;
+    } // for
+  } // for
+}
+
 /*-----------------------------------------------------------------*/
 /* emitOverlay - will emit code for the overlay stuff              */
 /*-----------------------------------------------------------------*/
@@ -1385,7 +1381,10 @@ picglue ()
        
        /* Put all variables into a cblock */
        AnalyzeBanking();
+
+       /* print the locally defined variables in this module */
        writeUsedRegs(asmFile);
+       pic14printLocals (asmFile);
        
        /* create the overlay segments */
        fprintf (asmFile, "%s", iComments2);