From 7ff6a8aa72eca3e87a6f276cdeb88e4fb0e53b3c Mon Sep 17 00:00:00 2001 From: kvigor Date: Tue, 29 May 2001 21:16:49 +0000 Subject: [PATCH] save any register banks used by functions called via ISR on entry, not before call git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@859 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- src/mcs51/gen.c | 157 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 143 insertions(+), 14 deletions(-) diff --git a/src/mcs51/gen.c b/src/mcs51/gen.c index f3045088..31fecdab 100644 --- a/src/mcs51/gen.c +++ b/src/mcs51/gen.c @@ -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"); -- 2.30.2