extern int mcs51_ptrRegReq;
extern int mcs51_nRegs;
extern FILE *codeOutFile;
-static void saverbank (int, iCode *, bool);
+static void saveRBank (int, iCode *, bool);
#define RESULTONSTACK(x) \
(IC_RESULT(x) && IC_RESULT(x)->aop && \
IC_RESULT(x)->aop->type == AOP_STK )
emitcode (char *inst, char *fmt,...)
{
va_list ap;
- char lb[MAX_INLINEASM];
+ char lb[INITIAL_INLINEASM];
char *lbp = lb;
va_start (ap, fmt);
return NULL;
}
- piCode (ic, stdout);
/* other wise this is true end of the world */
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
"getFreePtr should never reach here");
return aop;
}
-static void
-genSetDPTR (int n)
-{
- if (!n)
- {
- emitcode (";", "Select standard DPTR");
- emitcode ("mov", "dps, #0x00");
- }
- else
- {
- emitcode (";", "Select alternate DPTR");
- emitcode ("mov", "dps, #0x01");
- }
-}
-
/*-----------------------------------------------------------------*/
/* pointerCode - returns the code for a pointer type */
/*-----------------------------------------------------------------*/
for (;;)
{
if (ic->op == '+')
- val += operandLitValue (IC_RIGHT (ic));
+ val += (int) operandLitValue (IC_RIGHT (ic));
else if (ic->op == '-')
- val -= operandLitValue (IC_RIGHT (ic));
+ val -= (int) operandLitValue (IC_RIGHT (ic));
else
break;
if (sym->ruonly)
{
- int i;
+ unsigned i;
aop = op->aop = sym->aop = newAsmop (AOP_STR);
aop->size = getSize (sym->type);
for (i = 0; i < fReturnSizeMCS51; i++)
return rs;
case AOP_DPTR:
- case AOP_DPTR2:
-
- if (aop->type == AOP_DPTR2)
- {
- genSetDPTR (1);
- }
-
while (offset > aop->coff)
{
emitcode ("inc", "dptr");
{
emitcode ("movx", "a,@dptr");
}
-
- if (aop->type == AOP_DPTR2)
- {
- genSetDPTR (0);
- }
-
return (dname ? "acc" : "a");
break;
case AOP_DPTR:
- case AOP_DPTR2:
-
- if (aop->type == AOP_DPTR2)
- {
- genSetDPTR (1);
- }
-
if (aop->code)
{
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
MOVA (s);
emitcode ("movx", "@dptr,a");
-
- if (aop->type == AOP_DPTR2)
- {
- genSetDPTR (0);
- }
break;
case AOP_R0:
static void
reAdjustPreg (asmop * aop)
{
- aop->coff = 0;
if ((aop->coff==0) || aop->size <= 1)
return;
emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
break;
case AOP_DPTR:
- case AOP_DPTR2:
- if (aop->type == AOP_DPTR2)
- {
- genSetDPTR (1);
- }
while (aop->coff--)
{
emitcode ("lcall", "__decdptr");
}
-
- if (aop->type == AOP_DPTR2)
- {
- genSetDPTR (0);
- }
break;
-
}
-
+ aop->coff = 0;
}
#define AOP(op) op->aop
AOP_TYPE(x) == AOP_R0))
#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
- AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
- AOP(x)->paged))
+ AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
#define AOP_INPREG(x) (x && (x->type == AOP_REG && \
(x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
}
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);
+ saveRBank (SPEC_BANK (detype), ic, TRUE);
+#endif
}
/*-----------------------------------------------------------------*/
int size, offset = 0;
char *l;
-
/* if this is not a parm push : ie. it is spill push
and spill push is always done on the local stack */
if (!ic->parmPush)
}
/*-----------------------------------------------------------------*/
-/* unsaverbank - restores the resgister bank from stack */
+/* unsaveRBank - restores the resgister bank from stack */
/*-----------------------------------------------------------------*/
static void
-unsaverbank (int bank, iCode * ic, bool popPsw)
+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)
- {
- 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 - saves an entire register bank on the stack */
+/* saveRBank - saves an entire register bank on the stack */
/*-----------------------------------------------------------------*/
static void
-saverbank (int bank, iCode * ic, bool pushPsw)
+saveRBank (int bank, iCode * ic, bool pushPsw)
{
int i;
- asmop *aop;
+ asmop *aop = NULL;
regs *r = NULL;
if (options.useXstack)
{
-
- aop = newAsmop (0);
- r = getFreePtr (ic, &aop, FALSE);
+ 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);
-
}
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 ("push", "psw");
+ }
emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
}
- ic->bankSaved = 1;
+ if (aop)
+ {
+ freeAsmop (NULL, aop, ic, TRUE);
+ }
+
+ if (ic)
+ {
+ ic->bankSaved = 1;
+ }
}
/*-----------------------------------------------------------------*/
genCall (iCode * ic)
{
sym_link *detype;
-
- /* if caller saves & we have not saved then */
- if (!ic->regsSaved)
- saveRegisters (ic);
-
- /* if we are calling a 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 &&
- (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
- IS_ISR (currFunc->etype) &&
- !ic->bankSaved)
-
- saverbank (SPEC_BANK (detype), ic, TRUE);
+ bool restoreBank = FALSE;
+ bool swapBanks = FALSE;
/* if send set is not empty the assign */
if (_G.sendSet)
}
_G.sendSet = NULL;
}
+
+ /* if we are calling a 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 &&
+ (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
+ 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 */
emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
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 ||
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);
}
/*-----------------------------------------------------------------*/
if (detype &&
IS_ISR (currFunc->etype) &&
(SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
- saverbank (SPEC_BANK (detype), ic, TRUE);
+ saveRBank (SPEC_BANK (detype), ic, TRUE);
/* push the return address on to the stack */
if (detype &&
(SPEC_BANK (currFunc->etype) !=
SPEC_BANK (detype)))
- unsaverbank (SPEC_BANK (detype), ic, TRUE);
+ unsaveRBank (SPEC_BANK (detype), ic, TRUE);
/* if we hade saved some registers then
unsave them */
{
symbol *sym;
sym_link *fetype;
+ bool switchedPSW = FALSE;
_G.nRegsSaved = 0;
/* create the function header */
else
{
/* this function has a function call cannot
- determines register usage so we will have the
+ determines register usage so we will have to push the
entire bank */
- saverbank (0, ic, FALSE);
+ 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);
+ }
+ }
+
+ 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))
+ {
+ saveRBank(ix, NULL, FALSE);
+ }
+ }
+ }
+ SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
+ }
}
else
{
}
/* 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 */
else
{
/* this function has a function call cannot
- determines register usage so we will have the
+ determines register usage so we will have to pop the
entire bank */
- unsaverbank (0, ic, FALSE);
+ 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 (options.useXstack)
+ {
+ /* Restore bank AFTER calling unsaveRBank,
+ * since it can trash r0.
+ */
+ emitcode ("pop", "psw");
}
}
/* if the literal value of the right hand side
is greater than 4 then it is not worth it */
- if ((icount = floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
+ if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
return FALSE;
/* if increment 16 bits in register */
/*-----------------------------------------------------------------*/
/* genMultOneByte : 8*8=8/16 bit multiplication */
/*-----------------------------------------------------------------*/
-#if 0 // REMOVE ME
-static void
-genMultOneByte (operand * left,
- operand * right,
- operand * result)
-{
- sym_link *opetype = operandType (result);
- char *l;
- symbol *lbl;
- int size, offset;
-
- /* (if two literals, the value is computed before) */
- /* if one literal, literal on the right */
- if (AOP_TYPE (left) == AOP_LIT)
- {
- operand *t = right;
- right = left;
- left = t;
- }
-
- size = AOP_SIZE (result);
- /* signed or unsigned */
- emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
- l = aopGet (AOP (left), 0, FALSE, FALSE);
- MOVA (l);
- emitcode ("mul", "ab");
- /* if result size = 1, mul signed = mul unsigned */
- aopPut (AOP (result), "a", 0);
- if (size > 1)
- {
- if (SPEC_USIGN (opetype))
- {
- aopPut (AOP (result), "b", 1);
- if (size > 2)
- /* for filling the MSBs */
- emitcode ("clr", "a");
- }
- else
- {
- emitcode ("mov", "a,b");
-
- /* adjust the MSB if left or right neg */
-
- /* if one literal */
- if (AOP_TYPE (right) == AOP_LIT)
- {
- /* AND literal negative */
- if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0)
- {
- /* adjust MSB (c==0 after mul) */
- emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
- }
- }
- else
- {
- lbl = newiTempLabel (NULL);
- emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
- emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
- emitcode ("", "%05d$:", (lbl->key + 100));
- emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
- lbl = newiTempLabel (NULL);
- emitcode ("jc", "%05d$", (lbl->key + 100));
- emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
- emitcode ("", "%05d$:", (lbl->key + 100));
- }
-
- lbl = newiTempLabel (NULL);
- emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
- emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
- emitcode ("", "%05d$:", (lbl->key + 100));
- emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
- lbl = newiTempLabel (NULL);
- emitcode ("jc", "%05d$", (lbl->key + 100));
- emitcode ("subb", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
- emitcode ("", "%05d$:", (lbl->key + 100));
-
- aopPut (AOP (result), "a", 1);
- if (size > 2)
- {
- /* get the sign */
- emitcode ("rlc", "a");
- emitcode ("subb", "a,acc");
- }
- }
- size -= 2;
- offset = 2;
- if (size > 0)
- while (size--)
- aopPut (AOP (result), "a", offset++);
- }
-}
-#else
static void
genMultOneByte (operand * left,
operand * right,
if (size<1 || size>2) {
// this should never happen
fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
- AOP_SIZE(result), __FUNCTION__, lineno);
+ AOP_SIZE(result), __FILE__, lineno);
exit (1);
}
aopPut (AOP (result), "b", 1);
}
}
-#endif
/*-----------------------------------------------------------------*/
/* genMult - generates code for multiplication */
/*-----------------------------------------------------------------*/
static void
genCmp (operand * left, operand * right,
- operand * result, iCode * ifx, int sign)
+ operand * result, iCode * ifx, int sign, iCode *ic)
{
int size, offset = 0;
unsigned long lit = 0L;
}
release:
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
{
outBitC (result);
aopOp (right, ic, FALSE);
aopOp (result, ic, TRUE);
- genCmp (right, left, result, ifx, sign);
+ genCmp (right, left, result, ifx, sign,ic);
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
- freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (result, NULL, ic, TRUE);
}
aopOp (right, ic, FALSE);
aopOp (result, ic, TRUE);
- genCmp (left, right, result, ifx, sign);
+ genCmp (left, right, result, ifx, sign,ic);
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
- freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (result, NULL, ic, TRUE);
}
return lic;
}
/* if the operand used or deffed */
- if (bitVectBitValue(ic->uses,op->key) || ic->defKey == op->key) {
+ if (bitVectBitValue(ic->uses,op->key) || (unsigned) ic->defKey == op->key) {
return NULL;
}
lic = lic->next;
static void
genInline (iCode * ic)
{
- char buffer[MAX_INLINEASM];
- char *bp = buffer;
- char *bp1 = buffer;
+ char *buffer, *bp, *bp1;
_G.inLine += (!options.asmpeep);
+
+ buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
strcpy (buffer, IC_INLINE (ic));
/* emit each line as a code */
movLeft2Result (left, LSB, result, MSB32, 0);
aopPut (AOP (result), zero, LSB);
aopPut (AOP (result), zero, MSB16);
- aopPut (AOP (result), zero, MSB32);
+ aopPut (AOP (result), zero, MSB24);
return;
}
aopOp (right, ic, FALSE);
/* special case both in far space */
- if ((AOP_TYPE (right) == AOP_DPTR ||
- AOP_TYPE (right) == AOP_DPTR2) &&
+ if (AOP_TYPE (right) == AOP_DPTR &&
IS_TRUE_SYMOP (result) &&
isOperandInFarSpace (result))
{
aopOp (IC_RESULT (ic), ic, FALSE);
- if (IS_AOP_PREG (IC_RESULT (ic)))
+ if (AOP_NEEDSACC(IC_RESULT(ic)))
+ {
+ /* If the result is accessed indirectly via
+ * the accumulator, we must explicitly write
+ * it back after the decrement.
+ */
+ char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
+
+ if (strcmp(rByte, "a"))
+ {
+ /* Something is hopelessly wrong */
+ fprintf(stderr, "*** warning: internal error at %s:%d\n",
+ __FILE__, __LINE__);
+ /* We can just give up; the generated code will be inefficient,
+ * but what the hey.
+ */
+ freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+ return 0;
+ }
+ emitcode ("dec", "%s", rByte);
+ aopPut(AOP(IC_RESULT(ic)), rByte, 0);
+ emitcode ("jnz", "%05d$", lbl->key + 100);
+ }
+ else if (IS_AOP_PREG (IC_RESULT (ic)))
{
emitcode ("dec", "%s",
aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
default:
ic = ic;
- /* piCode(ic,stdout); */
-
}
}