unsaveRBank (int bank, iCode * ic, bool popPsw)
{
int i;
- asmop *aop;
+ asmop *aop = NULL;
regs *r = NULL;
+ if (options.useXstack)
+ {
+ if (!ic)
+ {
+ /* Assume r0 is available for use. */
+ r = ds390_regWithIdx (R0_IDX);;
+ }
+ else
+ {
+ aop = newAsmop (0);
+ r = getFreePtr (ic, &aop, FALSE);
+ }
+ emitcode ("mov", "%s,_spx", r->name);
+ }
+
if (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);
-
-
- emitcode ("mov", "%s,_spx", r->name);
+ {
emitcode ("movx", "a,@%s", r->name);
emitcode ("mov", "psw,a");
emitcode ("dec", "%s", r->name);
-
}
else
+ {
emitcode ("pop", "psw");
+ }
}
for (i = (ds390_nRegs - 1); i >= 0; i--)
if (options.useXstack)
{
-
emitcode ("mov", "_spx,%s", r->name);
- freeAsmop (NULL, aop, ic, TRUE);
-
}
+
+ if (aop)
+ {
+ freeAsmop (NULL, aop, ic, TRUE);
+ }
}
/*-----------------------------------------------------------------*/
saveRBank (int bank, iCode * ic, bool pushPsw)
{
int i;
- asmop *aop;
+ asmop *aop = NULL;
regs *r = NULL;
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);
-
+ if (!ic)
+ {
+ /* Assume r0 is available for use. */
+ r = ds390_regWithIdx (R0_IDX);;
+ }
+ else
+ {
+ aop = newAsmop (0);
+ r = getFreePtr (ic, &aop, FALSE);
+ }
+ emitcode ("mov", "%s,_spx", r->name);
}
for (i = 0; i < ds390_nRegs; i++)
emitcode ("movx", "@%s,a", r->name);
emitcode ("inc", "%s", r->name);
emitcode ("mov", "_spx,%s", r->name);
- freeAsmop (NULL, aop, ic, TRUE);
-
}
else
{
emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
}
+
+ if (aop)
+ {
+ freeAsmop (NULL, aop, ic, TRUE);
+ }
if (ic)
{
{
symbol *sym;
sym_link *fetype;
+ bool switchedPSW = FALSE;
D (emitcode (";", "genFunction "););
iCode *i;
int ix;
- D(emitcode(";", "seeking function calls..."););
-
for (i = ic; i; i = i->next)
{
if (i->op == ENDFUNCTION)
}
else
{
- D(emitcode(";", "should save bank %d",
- SPEC_BANK(detype)););
banksToSave |= (1 << SPEC_BANK(detype));
}
werror(W_FUNCPTR_IN_USING_ISR);
}
}
-
+
+ if (banksToSave && options.useXstack)
+ {
+ /* Since we aren't passing it an ic,
+ * saveRBank will assume r0 is available to abuse.
+ *
+ * So switch to our (trashable) bank now, so
+ * the caller's R0 isn't trashed.
+ */
+ emitcode ("push", "psw");
+ emitcode ("mov", "psw,#0x%02x",
+ (SPEC_BANK (sym->etype) << 3) & 0x00ff);
+ switchedPSW = TRUE;
+ }
+
for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
{
if (banksToSave & (1 << ix))
}
/* set the register bank to the desired value */
- if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
+ if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
+ && !switchedPSW)
{
emitcode ("push", "psw");
emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
/* restore the register bank */
if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
- emitcode ("pop", "psw");
+ {
+ if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
+ || !options.useXstack)
+ {
+ /* Special case of ISR using non-zero bank with useXstack
+ * is handled below.
+ */
+ emitcode ("pop", "psw");
+ }
+ }
if (IS_ISR (sym->etype))
{
registers :-) */
if (!SPEC_BANK (sym->etype))
{
-
/* if this function does not call any other
function then we can be economical and
save only those registers that are used */
/* This ISR uses a non-zero bank.
*
* Restore any register banks saved by genFunction
- * in reverse order/
+ * 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 (options.useXstack)
+ {
+ /* Restore bank AFTER calling unsaveRBank,
+ * since it can trash r0.
+ */
+ emitcode ("pop", "psw");
+ }
}
if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
unsaveRBank (int bank, iCode * ic, bool popPsw)
{
int i;
- asmop *aop;
+ asmop *aop = NULL;
regs *r = NULL;
+ if (options.useXstack)
+ {
+ if (!ic)
+ {
+ /* Assume r0 is available for use. */
+ r = mcs51_regWithIdx (R0_IDX);;
+ }
+ else
+ {
+ aop = newAsmop (0);
+ r = getFreePtr (ic, &aop, FALSE);
+ }
+ emitcode ("mov", "%s,_spx", r->name);
+ }
+
if (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);
-
-
- emitcode ("mov", "%s,_spx", r->name);
+ {
emitcode ("movx", "a,@%s", r->name);
emitcode ("mov", "psw,a");
emitcode ("dec", "%s", r->name);
-
}
else
+ {
emitcode ("pop", "psw");
+ }
}
for (i = (mcs51_nRegs - 1); i >= 0; i--)
if (options.useXstack)
{
-
emitcode ("mov", "_spx,%s", r->name);
- freeAsmop (NULL, aop, ic, TRUE);
-
}
+
+ if (aop)
+ {
+ freeAsmop (NULL, aop, ic, TRUE);
+ }
}
/*-----------------------------------------------------------------*/
saveRBank (int bank, iCode * ic, bool pushPsw)
{
int i;
- asmop *aop;
+ asmop *aop = NULL;
regs *r = NULL;
if (options.useXstack)
{
if (!ic)
{
- werror(E_INTERNAL_ERROR, __FILE__, __LINE__,
- "unexpected null IC in saveRBank");
- return;
+ /* Assume r0 is available for use. */
+ r = mcs51_regWithIdx (R0_IDX);;
+ }
+ else
+ {
+ aop = newAsmop (0);
+ r = getFreePtr (ic, &aop, FALSE);
}
- aop = newAsmop (0);
- r = getFreePtr (ic, &aop, FALSE);
emitcode ("mov", "%s,_spx", r->name);
-
}
for (i = 0; i < mcs51_nRegs; i++)
emitcode ("movx", "@%s,a", r->name);
emitcode ("inc", "%s", r->name);
emitcode ("mov", "_spx,%s", r->name);
- freeAsmop (NULL, aop, ic, TRUE);
}
else
emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
}
+ if (aop)
+ {
+ freeAsmop (NULL, aop, ic, TRUE);
+ }
+
if (ic)
{
ic->bankSaved = 1;
-}
+ }
}
/*-----------------------------------------------------------------*/
{
symbol *sym;
sym_link *fetype;
+ bool switchedPSW = FALSE;
_G.nRegsSaved = 0;
/* create the function header */
werror(W_FUNCPTR_IN_USING_ISR);
}
}
-
+
+ if (banksToSave && options.useXstack)
+ {
+ /* Since we aren't passing it an ic,
+ * saveRBank will assume r0 is available to abuse.
+ *
+ * So switch to our (trashable) bank now, so
+ * the caller's R0 isn't trashed.
+ */
+ emitcode ("push", "psw");
+ emitcode ("mov", "psw,#0x%02x",
+ (SPEC_BANK (sym->etype) << 3) & 0x00ff);
+ switchedPSW = TRUE;
+ }
+
for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
{
if (banksToSave & (1 << ix))
}
/* set the register bank to the desired value */
- if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
+ if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
+ && !switchedPSW)
{
emitcode ("push", "psw");
emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
/* restore the register bank */
if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
- emitcode ("pop", "psw");
+ {
+ if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
+ || !options.useXstack)
+ {
+ /* Special case of ISR using non-zero bank with useXstack
+ * is handled below.
+ */
+ emitcode ("pop", "psw");
+ }
+ }
if (IS_ISR (sym->etype))
{
registers :-) */
if (!SPEC_BANK (sym->etype))
{
-
/* if this function does not call any other
function then we can be economical and
save only those registers that are used */
/* This ISR uses a non-zero bank.
*
* Restore any register banks saved by genFunction
- * in reverse order/
+ * 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 (options.useXstack)
+ {
+ /* Restore bank AFTER calling unsaveRBank,
+ * since it can trash r0.
+ */
+ emitcode ("pop", "psw");
+ }
}
if (!inExcludeList ("dph"))