save any register banks used by functions called via ISR on entry, not before call
authorkvigor <kvigor@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Tue, 29 May 2001 21:16:49 +0000 (21:16 +0000)
committerkvigor <kvigor@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Tue, 29 May 2001 21:16:49 +0000 (21:16 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@859 4a8a32a2-be11-0410-ad9d-d568d2c75423

src/mcs51/gen.c

index f30450882a0e82e3a2c129639e5bc548b2ff5d08..31fecdab5a6b35fcf819d12bce8290ed3bd9da53 100644 (file)
@@ -1717,6 +1717,13 @@ unsaveRBank (int bank, iCode * ic, bool popPsw)
     {
       if (options.useXstack)
        {
+          if (!ic)
+          {
+              werror(E_INTERNAL_ERROR, __FILE__, __LINE__,
+                     "unexpected null IC in saveRBank");
+              return;
+          }    
+       
          aop = newAsmop (0);
          r = getFreePtr (ic, &aop, FALSE);
 
@@ -1767,7 +1774,12 @@ saveRBank (int bank, iCode * ic, bool pushPsw)
 
   if (options.useXstack)
     {
-
+      if (!ic)
+      {
+          werror(E_INTERNAL_ERROR, __FILE__, __LINE__,
+                 "unexpected null IC in saveRBank");
+          return;
+      }
       aop = newAsmop (0);
       r = getFreePtr (ic, &aop, FALSE);
       emitcode ("mov", "%s,_spx", r->name);
@@ -1800,12 +1812,17 @@ saveRBank (int bank, iCode * ic, bool pushPsw)
 
        }
       else
+      {
        emitcode ("push", "psw");
+      }
 
       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
     }
-  ic->bankSaved = 1;
 
+  if (ic)
+  {  
+      ic->bankSaved = 1;
+}
 }
 
 /*-----------------------------------------------------------------*/
@@ -1815,6 +1832,8 @@ static void
 genCall (iCode * ic)
 {
   sym_link *detype;
+  bool restoreBank = FALSE;
+  bool swapBanks = FALSE;
 
   /* if send set is not empty the assign */
   if (_G.sendSet)
@@ -1848,13 +1867,27 @@ genCall (iCode * ic)
   detype = getSpec (operandType (IC_LEFT (ic)));
   if (detype &&
       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
-      IS_ISR (currFunc->etype) &&
-      !ic->bankSaved) {
-    saveRBank (SPEC_BANK (detype), ic, TRUE);
-  } else /* no need to save if we just saved the whole bank */ {
-    /* if caller saves & we have not saved then */
-    if (!ic->regsSaved)
+      IS_ISR (currFunc->etype))
+  {
+      if (!ic->bankSaved) 
+      {
+           /* This is unexpected; the bank should have been saved in
+            * genFunction.
+            */
+          saveRBank (SPEC_BANK (detype), ic, FALSE);
+          restoreBank = TRUE;
+      }
+      swapBanks = TRUE;  
+  } 
+    
+  /* if caller saves & we have not saved then */
+  if (!ic->regsSaved)
       saveRegisters (ic);
+
+  if (swapBanks)
+  {
+        emitcode ("mov", "psw,#0x%02x", 
+           ((SPEC_BANK(detype)) << 3) & 0xff);
   }
 
   /* make the call */
@@ -1862,6 +1895,12 @@ genCall (iCode * ic)
                            OP_SYMBOL (IC_LEFT (ic))->rname :
                            OP_SYMBOL (IC_LEFT (ic))->name));
 
+  if (swapBanks)
+  {
+       emitcode ("mov", "psw,#0x%02x", 
+          ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
+  }
+
   /* if we need assign a result value */
   if ((IS_ITEMP (IC_RESULT (ic)) &&
        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
@@ -1892,18 +1931,15 @@ genCall (iCode * ic)
       else
        for (i = 0; i < ic->parmBytes; i++)
          emitcode ("dec", "%s", spname);
-
     }
 
-  /* if register bank was saved then pop them */
-  if (ic->bankSaved)
-    unsaveRBank (SPEC_BANK (detype), ic, TRUE);
-
   /* if we hade saved some registers then unsave them */
   if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
     unsaveRegisters (ic);
 
-
+  /* if register bank was saved then pop them */
+  if (restoreBank)
+    unsaveRBank (SPEC_BANK (detype), ic, FALSE);
 }
 
 /*-----------------------------------------------------------------*/
@@ -2155,6 +2191,81 @@ genFunction (iCode * ic)
              saveRBank (0, ic, FALSE);
            }
        }
+       else
+       {
+           /* This ISR uses a non-zero bank.
+            *
+            * We assume that the bank is available for our
+            * exclusive use.
+            *
+            * However, if this ISR calls a function which uses some
+            * other bank, we must save that bank entirely.
+            */
+           unsigned long banksToSave = 0;
+           
+           if (sym->hasFcall)
+           {
+
+#define MAX_REGISTER_BANKS 4
+
+               iCode *i;
+               int ix;
+
+               for (i = ic; i; i = i->next)
+               {
+                   if (i->op == ENDFUNCTION)
+                   {
+                       /* we got to the end OK. */
+                       break;
+                   }
+                   
+                   if (i->op == CALL)
+                   {
+                       sym_link *detype;
+                       
+                       detype = getSpec(operandType (IC_LEFT(i)));
+                       if (detype 
+                        && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
+                       {
+                            /* Mark this bank for saving. */
+                            if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
+                            {
+                                werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
+                            }
+                            else
+                            {
+                                banksToSave |= (1 << SPEC_BANK(detype));
+                            }
+                            
+                            /* And note that we don't need to do it in 
+                             * genCall.
+                             */
+                            i->bankSaved = 1;
+                       }
+                   }
+                   if (i->op == PCALL)
+                   {
+                       /* This is a mess; we have no idea what
+                        * register bank the called function might
+                        * use.
+                        *
+                        * The only thing I can think of to do is
+                        * throw a warning and hope.
+                        */
+                       werror(W_FUNCPTR_IN_USING_ISR);   
+                   }
+               }
+               
+               for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
+               {
+                    if (banksToSave & (1 << ix))
+                    {
+                        saveRBank(ix, NULL, FALSE);
+                    }
+               }
+           }
+           SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
+       }
     }
   else
     {
@@ -2318,6 +2429,24 @@ genEndFunction (iCode * ic)
              unsaveRBank (0, ic, FALSE);
            }
        }
+       else
+       {
+           /* This ISR uses a non-zero bank.
+            *
+            * Restore any register banks saved by genFunction
+            * in reverse order/
+            */
+           unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
+           int ix;
+           
+           for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
+           {
+               if (savedBanks & (1 << ix))
+               {
+                   unsaveRBank(ix, NULL, FALSE);
+               }
+           }
+       }
 
       if (!inExcludeList ("dph"))
        emitcode ("pop", "dph");