/* if the registers have been saved already then
do nothing */
- if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
+ if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
+ SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT(ic))))
return;
/* find the registers in use at this time
}
detype = getSpec (operandType (IC_LEFT (ic)));
-
-#if 0 // why should we do this here??? jwk20011105
- if (detype &&
- (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
- IS_ISR (currFunc->etype) &&
- !ic->bankSaved)
- saveRBank (SPEC_BANK (detype), ic, TRUE);
-#endif
-
}
+
/*-----------------------------------------------------------------*/
/* unsaveRegisters - pop the pushed registers */
/*-----------------------------------------------------------------*/
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)
{
D (emitcode (";", "genCall "););
- /* if we are calling a function that is not using
+ /* if we are calling a not _naked function that is not using
the same register bank then we need to save the
destination registers on the stack */
detype = getSpec (operandType (IC_LEFT (ic)));
- if (detype &&
+ if (detype && !SPEC_NAKED(detype) &&
(SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
IS_ISR (currFunc->etype))
{
{
symbol *sym;
sym_link *fetype;
+ bool switchedPSW = FALSE;
D (emitcode (";", "genFunction "););
emitcode ("", "%s:", sym->rname);
fetype = getSpec (operandType (IC_LEFT (ic)));
+ if (SPEC_NAKED(fetype))
+ {
+ emitcode(";", "naked function: no prologue.");
+ return;
+ }
+
/* if critical function then turn interrupts off */
if (SPEC_CRTCL (fetype))
emitcode ("clr", "ea");
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);
D (emitcode (";", "genEndFunction "););
+ if (SPEC_NAKED(sym->etype))
+ {
+ emitcode(";", "naked function: no epilogue.");
+ return;
+ }
+
if (IS_RENT (sym->etype) || options.stackAuto)
{
emitcode ("mov", "%s,_bp", spname);
/* 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"))
emitcode ("setb", "ea");
/* if debug then send end of function */
-/* if (options.debug && currFunc) { */
+/* if (options.debug && currFunc) */
if (currFunc)
{
_G.debugLine = 1;
emitcode (";", "signed");
emitcode ("clr", "F0"); // reset sign flag
- emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
lbl=newiTempLabel(NULL);
emitcode ("inc", "a");
emitcode ("", "%05d$:", lbl->key+100);
- emitcode ("xch", "a,b");
/* if literal */
if (AOP_TYPE(right)==AOP_LIT) {
+ signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
/* AND literal negative */
- if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
- // two's complement for literal<0
- emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
- emitcode ("cpl", "a");
- emitcode ("inc", "a");
+ if ((int) val < 0) {
+ emitcode ("cpl", "F0"); // complement sign flag
+ emitcode ("mov", "b,#0x%02x", -val);
+ } else {
+ emitcode ("mov", "b,#0x%02x", val);
}
} else {
lbl=newiTempLabel(NULL);
+ emitcode ("mov", "b,a");
+ emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
// right side is negative, 8-bit two's complement
- emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
+ emitcode ("cpl", "F0"); // complement sign flag
emitcode ("cpl", "a");
emitcode ("inc", "a");
emitcode ("", "%05d$:", lbl->key+100);
shiftRLong (operand * left, int offl,
operand * result, int sign)
{
- if (!sign)
+ int isSameRegs=sameRegs(AOP(left),AOP(result));
+
+ if (isSameRegs && offl>1) {
+ // we are in big trouble, but this shouldn't happen
+ werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
+ }
+
+ MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
+
+ if (offl==MSB16) {
+ // shift is > 8
+ if (sign) {
+ emitcode ("rlc", "a");
+ emitcode ("subb", "a,acc");
+ emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
+ } else {
+ aopPut (AOP(result), zero, MSB32);
+ }
+ }
+
+ if (!sign) {
emitcode ("clr", "c");
- MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
- if (sign)
+ } else {
emitcode ("mov", "c,acc.7");
- emitcode ("rrc", "a");
- aopPut (AOP (result), "a", MSB32 - offl);
- if (offl == MSB16)
- /* add sign of "a" */
- addSign (result, MSB32, sign);
+ }
- MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
emitcode ("rrc", "a");
- aopPut (AOP (result), "a", MSB24 - offl);
- MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
+ if (isSameRegs && offl==MSB16) {
+ emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
+ } else {
+ aopPut (AOP (result), "a", MSB32);
+ MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
+ }
+
+ emitcode ("rrc", "a");
+ if (isSameRegs && offl==1) {
+ emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
+ } else {
+ aopPut (AOP (result), "a", MSB24);
+ MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
+ }
emitcode ("rrc", "a");
aopPut (AOP (result), "a", MSB16 - offl);
if (offl == LSB)
{
- MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
+ MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
emitcode ("rrc", "a");
aopPut (AOP (result), "a", LSB);
}