}
freeBitVect(freeRegs);
- return 1;
+ return 0;
}
"aopget got unsupported aop->type");
exit (1);
}
+
+/*-----------------------------------------------------------------*/
+/* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
+/* clobber the accumulator */
+/*-----------------------------------------------------------------*/
+static bool
+aopPutUsesAcc (operand * oper, const char *s, int offset)
+{
+ asmop * aop = AOP (oper);
+
+ if (offset > (aop->size - 1))
+ return FALSE;
+
+ switch (aop->type)
+ {
+ case AOP_DUMMY:
+ return TRUE;
+ case AOP_DIR:
+ return FALSE;
+ case AOP_REG:
+ wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
+ return FALSE;
+ case AOP_DPTR:
+ return TRUE;
+ case AOP_R0:
+ case AOP_R1:
+ return ((aop->paged) || (*s == '@'));
+ case AOP_STK:
+ return (*s == '@');
+ case AOP_CRY:
+ return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
+ case AOP_STR:
+ return FALSE;
+ case AOP_IMMD:
+ return FALSE;
+ case AOP_ACC:
+ return FALSE;
+ default:
+ /* Error case --- will have been caught already */
+ wassert(0);
+ return FALSE;
+ }
+}
+
/*-----------------------------------------------------------------*/
/* aopPut - puts a string for a aop and indicates if acc is in use */
/*-----------------------------------------------------------------*/
case AOP_DIR:
if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
- sprintf (d, "(%s >> %d)",
- aop->aopu.aop_dir, offset * 8);
+ sprintf (d, "(%s >> %d)", aop->aopu.aop_dir, offset * 8);
else if (offset)
- sprintf (d, "(%s + %d)",
- aop->aopu.aop_dir, offset);
+ sprintf (d, "(%s + %d)", aop->aopu.aop_dir, offset);
else
sprintf (d, "%s", aop->aopu.aop_dir);
- if (strcmp (d, s) ||
- bvolatile)
+ if (strcmp (d, s) || bvolatile)
emitcode ("mov", "%s,%s", d, s);
if (!strcmp (d, "acc"))
accuse = TRUE;
{
MOVA (s);
emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
-
}
else if (*s == '@')
{
int offset = 0;
int size = AOP_SIZE (oper);
bool accuse = FALSE;
+ bool pushedA = FALSE;
if (func && IS_BIT (OP_SYM_ETYPE (func)))
{
return FALSE;
}
+ if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
+ {
+ emitcode ("push", "acc");
+ pushedA = TRUE;
+ }
while (size--)
{
+ if ((offset == 3) && pushedA)
+ emitcode ("pop", "acc");
accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
offset++;
}
saveRBank (int bank, iCode * ic, bool pushPsw)
{
int i;
- int count = mcs51_nRegs + (pushPsw ? 1 : 0);
+ int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
asmop *aop = NULL;
regs *r = NULL;
emitcode ("mov", "%s,a", spname);
}
- for (i = 0; i < mcs51_nRegs; i++)
+ for (i = 0; i < 8; i++)
{
if (options.useXstack)
{
regs8051[i].base, 8 * bank + regs8051[i].offset);
}
+ if (mcs51_nRegs > 8)
+ {
+ if (options.useXstack)
+ {
+ emitcode ("mov", "a,bits");
+ emitcode ("movx", "@%s,a", r->name);
+ if (--count)
+ emitcode ("inc", "%s", r->name);
+ }
+ else
+ {
+ emitcode ("push", "bits");
+ }
+ BitBankUsed = 1;
+ }
+
if (pushPsw)
{
if (options.useXstack)
}
}
- for (i = (mcs51_nRegs - 1); i >= 0; i--)
+ if (mcs51_nRegs > 8)
+ {
+ if (options.useXstack)
+ {
+ emitcode ("dec", "%s", r->name);
+ emitcode ("movx", "a,@%s", r->name);
+ emitcode ("mov", "bits,a");
+ }
+ else
+ {
+ emitcode ("pop", "bits");
+ }
+ }
+
+ for (i = 7; i >= 0; i--)
{
if (options.useXstack)
{
same */
if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
{
+ char *l;
+
+ if (aopGetUsesAcc (IC_LEFT (ic), 0))
+ {
+ MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
+ l = "a";
+ }
+ else
+ {
+ l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
+ }
while (icount--)
- emitcode ("dec", "%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
+ emitcode ("dec", "%s", l);
+
+ if (AOP_NEEDSACC (IC_RESULT (ic)))
+ aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
return TRUE;
}
emitcode ("subb", "a,b");
popB (pushedB);
} else {
+ /* reverse subtraction with 2's complement */
+ if (offset == 0)
+ emitcode( "setb", "c");
+ else
+ emitcode( "cpl", "c");
wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
MOVA (aopGet(rightOp, offset, FALSE, TRUE));
- if (offset == 0) {
- emitcode( "setb", "c");
- }
emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
emitcode("cpl", "a");
+ if (size) /* skip if last byte */
+ emitcode( "cpl", "c");
}
} else {
MOVA (aopGet (leftOp, offset, FALSE, FALSE));
D(emitcode ("; genMult",""));
- /* assign the amsops */
+ /* assign the asmops */
aopOp (left, ic, FALSE);
aopOp (right, ic, FALSE);
aopOp (result, ic, TRUE);
{
bool lUnsigned, rUnsigned, pushedB;
bool runtimeSign, compiletimeSign;
+ bool accuse = FALSE;
+ bool pushedA = FALSE;
symbol *lbl;
int size, offset;
emitcode ("inc", "a");
emitcode ("", "%05d$:", (lbl->key + 100));
- aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
+ accuse = aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
if (size > 0)
{
/* msb is 0x00 or 0xff depending on the sign */
if (runtimeSign)
{
+ if (accuse)
+ {
+ emitcode ("push", "acc");
+ pushedA = TRUE;
+ }
emitcode ("mov", "c,F0");
emitcode ("subb", "a,acc");
while (size--)
aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
}
else /* compiletimeSign */
- while (size--)
- aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
+ {
+ if (aopPutUsesAcc (result, "#0xFF", offset))
+ {
+ emitcode ("push", "acc");
+ pushedA = TRUE;
+ }
+ while (size--)
+ aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
+ }
}
}
else
aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
}
+ if (pushedA)
+ emitcode ("pop", "acc");
popB (pushedB);
}
}
else
{
- if (AOP_TYPE (left) == AOP_ACC && offset == 0)
+ if (AOP_TYPE (left) == AOP_ACC)
{
+ if (offset)
+ emitcode("mov", "a,b");
emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
}
+ else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
+ {
+ emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+ MOVA (aopGet (right, offset, FALSE, FALSE));
+ emitcode ("anl", "a,b");
+ aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
+ }
+ else if (aopGetUsesAcc (left, offset))
+ {
+ MOVA (aopGet (left, offset, FALSE, FALSE));
+ emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+ aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
+ }
else
{
MOVA (aopGet (right, offset, FALSE, FALSE));
emitcode("mov", "a,b");
emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
}
+ else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
+ {
+ emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+ MOVA (aopGet (right, offset, FALSE, FALSE));
+ emitcode ("anl", "a,b");
+ }
+ else if (aopGetUsesAcc (left, offset))
+ {
+ MOVA (aopGet (left, offset, FALSE, FALSE));
+ emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+ }
else
{
MOVA (aopGet (right, offset, FALSE, FALSE));
- emitcode ("anl", "a,%s",
- aopGet (left, offset, FALSE, FALSE));
+ emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
}
aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
}
emitcode("mov", "a,b");
emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
}
+ else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
+ {
+ emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+ MOVA (aopGet (right, offset, FALSE, FALSE));
+ emitcode ("orl", "a,b");
+ aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
+ }
+ else if (aopGetUsesAcc (left, offset))
+ {
+ MOVA (aopGet (left, offset, FALSE, FALSE));
+ emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+ aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
+ }
else
{
MOVA (aopGet (right, offset, FALSE, FALSE));
emitcode("mov", "a,b");
emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
}
+ else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
+ {
+ emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+ MOVA (aopGet (right, offset, FALSE, FALSE));
+ emitcode ("orl", "a,b");
+ }
+ else if (aopGetUsesAcc (left, offset))
+ {
+ MOVA (aopGet (left, offset, FALSE, FALSE));
+ emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+ }
else
{
MOVA (aopGet (right, offset, FALSE, FALSE));
- emitcode ("orl", "a,%s",
- aopGet (left, offset, FALSE, FALSE));
+ emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
}
aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
}
emitcode("mov", "a,b");
emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
}
+ else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
+ {
+ emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+ MOVA (aopGet (right, offset, FALSE, FALSE));
+ emitcode ("xrl", "a,b");
+ aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
+ }
+ else if (aopGetUsesAcc (left, offset))
+ {
+ MOVA (aopGet (left, offset, FALSE, FALSE));
+ emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+ aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
+ }
else
{
MOVA (aopGet (right, offset, FALSE, FALSE));
emitcode("mov", "a,b");
emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
}
+ else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
+ {
+ emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+ MOVA (aopGet (right, offset, FALSE, FALSE));
+ emitcode ("xrl", "a,b");
+ }
+ else if (aopGetUsesAcc (left, offset))
+ {
+ MOVA (aopGet (left, offset, FALSE, FALSE));
+ emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+ }
else
{
MOVA (aopGet (right, offset, FALSE, FALSE));
- emitcode ("xrl", "a,%s",
- aopGet (left, offset, FALSE, TRUE));
+ emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
}
aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
}
/* MSB sign in acc.7 ! */
if (getDataSize (left) == offl + 1)
{
- emitcode ("mov", "a,%s", l);
+ MOVA (l);
aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
}
}
shiftL2Left2Result (operand * left, int offl,
operand * result, int offr, int shCount)
{
+ char * x;
+ bool pushedB = FALSE;
+ bool usedB = FALSE;
+
if (sameRegs (AOP (result), AOP (left)) &&
((offl + MSB16) == offr))
{
/* don't crash result[offr] */
MOVA (aopGet (left, offl, FALSE, FALSE));
emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
+ x = aopGet (result, offr, FALSE, FALSE);
+ }
+ else if (aopGetUsesAcc (result, offr))
+ {
+ movLeft2Result (left, offl, result, offr, 0);
+ pushedB = pushB ();
+ usedB = TRUE;
+ emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
+ MOVA (aopGet (result, offr, FALSE, FALSE));
+ emitcode ("xch", "a,b");
+ x = "b";
}
else
{
movLeft2Result (left, offl, result, offr, 0);
MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
+ x = aopGet (result, offr, FALSE, FALSE);
}
/* ax << shCount (x = lsb(result)) */
- AccAXLsh (aopGet (result, offr, FALSE, FALSE), shCount);
- aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
+ AccAXLsh (x, shCount);
+ if (usedB)
+ {
+ emitcode ("xch", "a,b");
+ aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
+ aopPut (result, "b", offr + MSB16, isOperandVolatile (result, FALSE));
+ popB (pushedB);
+ }
+ else
+ {
+ aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
+ }
}
operand * result, int offr,
int shCount, int sign)
{
+ char * x;
+ bool pushedB = FALSE;
+ bool usedB = FALSE;
+
if (sameRegs (AOP (result), AOP (left)) &&
((offl + MSB16) == offr))
{
/* don't crash result[offr] */
MOVA (aopGet (left, offl, FALSE, FALSE));
emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
+ x = aopGet (result, offr, FALSE, FALSE);
+ }
+ else if (aopGetUsesAcc (result, offr))
+ {
+ movLeft2Result (left, offl, result, offr, 0);
+ pushedB = pushB ();
+ usedB = TRUE;
+ emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
+ MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
+ x = "b";
}
else
{
movLeft2Result (left, offl, result, offr, 0);
MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
+ x = aopGet (result, offr, FALSE, FALSE);
}
/* a:x >> shCount (x = lsb(result)) */
if (sign)
- AccAXRshS (aopGet (result, offr, FALSE, FALSE), shCount);
+ AccAXRshS (x, shCount);
else
- AccAXRsh (aopGet (result, offr, FALSE, FALSE), shCount);
+ AccAXRsh (x, shCount);
+ if (usedB)
+ {
+ emitcode ("xch", "a,b");
+ aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
+ emitcode ("xch", "a,b");
+ popB (pushedB);
+ }
if (getDataSize (result) > 1)
aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
}
/* shift left accumulator */
AccLsh (shCount);
/* or with result */
- emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
+ if (aopGetUsesAcc (result, offr))
+ {
+ emitcode ("xch", "a,b");
+ MOVA (aopGet (result, offr, FALSE, FALSE));
+ emitcode ("orl", "a,b");
+ }
+ else
+ {
+ emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
+ }
/* back to result */
aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
}
shiftRLong (operand * left, int offl,
operand * result, int sign)
{
- int isSameRegs=sameRegs(AOP(left),AOP(result));
+ int isSameRegs = sameRegs (AOP (left), AOP (result));
if (isSameRegs && offl>1) {
// we are in big trouble, but this shouldn't happen
emitPtrByteGet (rname, ptype, FALSE);
AccRsh (bstr);
emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
+ if (!SPEC_USIGN (etype))
+ {
+ /* signed bitfield */
+ symbol *tlbl = newiTempLabel (NULL);
+
+ emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
+ emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
+ emitcode ("", "%05d$:", tlbl->key + 100);
+ }
aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
goto finish;
}
{
emitPtrByteGet (rname, ptype, FALSE);
emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
+ if (!SPEC_USIGN (etype))
+ {
+ /* signed bitfield */
+ symbol *tlbl = newiTempLabel (NULL);
+
+ emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
+ emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
+ emitcode ("", "%05d$:", tlbl->key + 100);
+ }
aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
}
finish:
if (offset < rsize)
{
+ char *source;
+
+ if (SPEC_USIGN (etype))
+ source = zero;
+ else
+ {
+ /* signed bitfield: sign extension with 0x00 or 0xff */
+ emitcode ("rlc", "a");
+ emitcode ("subb", "a,acc");
+
+ source = "a";
+ }
rsize -= offset;
while (rsize--)
- aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
+ aopPut (result, source, offset++, isOperandVolatile (result, FALSE));
}
}
if (ic->argreg == 1)
{ /* first parameter */
- if (isOperandInFarSpace (IC_RESULT (ic)) &&
+ if ((isOperandInFarSpace (IC_RESULT (ic)) ||
+ isOperandInPagedSpace (IC_RESULT (ic))) &&
(OP_SYMBOL (IC_RESULT (ic))->isspilt ||
IS_TRUE_SYMOP (IC_RESULT (ic))))
{