static char *accUse[] =
{"a", "b"};
-static short rbank = -1;
+static unsigned short rbank = -1;
static struct
{
short r0Pushed;
short r1Pushed;
+ short r0InB;
+ short r1InB;
short accInUse;
short inLine;
short debugLine;
short nRegsSaved;
set *sendSet;
+ iCode *current_iCode;
+ symbol *currentFunc;
}
_G;
/* emitcode - writes the code into a file : for now it is simple */
/*-----------------------------------------------------------------*/
static void
-emitcode (char *inst, char *fmt,...)
+emitcode (char *inst, const char *fmt,...)
{
va_list ap;
char lb[INITIAL_INLINEASM];
while (isspace (*lbp))
lbp++;
+ //printf ("%s\n", lb);
+
if (lbp && *lbp)
lineCurr = (lineCurr ?
connectLine (lineCurr, newLineNode (lb)) :
(lineHead = newLineNode (lb)));
lineCurr->isInline = _G.inLine;
lineCurr->isDebug = _G.debugLine;
+ lineCurr->ic = _G.current_iCode;
+ lineCurr->isComment = (*lbp==';');
va_end (ap);
}
+/*-----------------------------------------------------------------*/
+/* mcs51_emitDebuggerSymbol - associate the current code location */
+/* with a debugger symbol */
+/*-----------------------------------------------------------------*/
+void
+mcs51_emitDebuggerSymbol (char * debugSym)
+{
+ _G.debugLine = 1;
+ emitcode ("", "%s ==.", debugSym);
+ _G.debugLine = 0;
+}
+
/*-----------------------------------------------------------------*/
/* mova - moves specified value into accumulator */
/*-----------------------------------------------------------------*/
static void
-mova (char *x)
+mova (const char *x)
{
/* do some early peephole optimization */
if (!strcmp(x, "a") || !strcmp(x, "acc"))
if (!r0iu)
{
/* push it if not already pushed */
- if (!_G.r0Pushed)
+ if (ic->op == IPUSH)
+ {
+ emitcode ("mov", "b,%s",
+ mcs51_regWithIdx (R0_IDX)->dname);
+ _G.r0InB++;
+ }
+ else if (!_G.r0Pushed)
{
emitcode ("push", "%s",
mcs51_regWithIdx (R0_IDX)->dname);
if (!r1iu)
{
/* push it if not already pushed */
- if (!_G.r1Pushed)
+ if (ic->op == IPUSH)
+ {
+ emitcode ("mov", "b,%s",
+ mcs51_regWithIdx (R1_IDX)->dname);
+ _G.r1InB++;
+ }
+ else if (!_G.r1Pushed)
{
emitcode ("push", "%s",
mcs51_regWithIdx (R1_IDX)->dname);
(*aopp)->type = AOP_R1;
return mcs51_regWithIdx (R1_IDX);
}
-
endOfWorld:
- /* I said end of world but not quite end of world yet */
- /* if this is a result then we can push it on the stack */
- if (result)
- {
- (*aopp)->type = AOP_STK;
- return NULL;
+ /* I said end of world, but not quite end of world yet */
+ if (result) {
+ /* we can push it on the stack */
+ (*aopp)->type = AOP_STK;
+ return NULL;
+ } else {
+ /* in the case that result AND left AND right needs a pointer reg
+ we can safely use the result's */
+ if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
+ (*aopp)->type = AOP_R0;
+ return mcs51_regWithIdx (R0_IDX);
+ }
+ if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
+ (*aopp)->type = AOP_R1;
+ return mcs51_regWithIdx (R1_IDX);
}
+ }
- /* other wise this is true end of the world */
+ /* now this is REALLY the end of the world */
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
"getFreePtr should never reach here");
exit (1);
}
+
+/*-----------------------------------------------------------------*/
+/* getTempRegs - initialize an array of pointers to GPR registers */
+/* that are not in use. Returns 1 if the requested */
+/* number of registers were available, 0 otherwise. */
+/*-----------------------------------------------------------------*/
+int
+getTempRegs(regs **tempRegs, int size, iCode *ic)
+{
+ bitVect * freeRegs;
+ int i;
+ int offset;
+
+ if (!ic)
+ ic = _G.current_iCode;
+ if (!ic)
+ return 0;
+ if (!_G.currentFunc)
+ return 0;
+
+ freeRegs = newBitVect(8);
+ bitVectSetBit (freeRegs, R2_IDX);
+ bitVectSetBit (freeRegs, R3_IDX);
+ bitVectSetBit (freeRegs, R4_IDX);
+ bitVectSetBit (freeRegs, R5_IDX);
+ bitVectSetBit (freeRegs, R6_IDX);
+ bitVectSetBit (freeRegs, R7_IDX);
+
+ if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
+ {
+ bitVect * newfreeRegs;
+ newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
+ freeBitVect(freeRegs);
+ freeRegs = newfreeRegs;
+ }
+ freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
+
+ offset = 0;
+ for (i=0; i<freeRegs->size; i++)
+ {
+ if (bitVectBitValue(freeRegs,i))
+ tempRegs[offset++] = mcs51_regWithIdx(i);
+ if (offset>=size)
+ {
+ freeBitVect(freeRegs);
+ return 1;
+ }
+ }
+
+ freeBitVect(freeRegs);
+ return 1;
+}
+
+
/*-----------------------------------------------------------------*/
/* newAsmop - creates a new asmOp */
/*-----------------------------------------------------------------*/
}
+
+/*-----------------------------------------------------------------*/
+/* leftRightUseAcc - returns size of accumulator use by operands */
+/*-----------------------------------------------------------------*/
+static int
+leftRightUseAcc(iCode *ic)
+{
+ operand *op;
+ int size;
+ int accuseSize = 0;
+ int accuse = 0;
+
+ if (!ic)
+ {
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "null iCode pointer");
+ return 0;
+ }
+
+ if (ic->op == IFX)
+ {
+ op = IC_COND (ic);
+ if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
+ {
+ accuse = 1;
+ size = getSize (OP_SYMBOL (op)->type);
+ if (size>accuseSize)
+ accuseSize = size;
+ }
+ }
+ else if (ic->op == JUMPTABLE)
+ {
+ op = IC_JTCOND (ic);
+ if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
+ {
+ accuse = 1;
+ size = getSize (OP_SYMBOL (op)->type);
+ if (size>accuseSize)
+ accuseSize = size;
+ }
+ }
+ else
+ {
+ op = IC_LEFT (ic);
+ if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
+ {
+ accuse = 1;
+ size = getSize (OP_SYMBOL (op)->type);
+ if (size>accuseSize)
+ accuseSize = size;
+ }
+ op = IC_RIGHT (ic);
+ if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
+ {
+ accuse = 1;
+ size = getSize (OP_SYMBOL (op)->type);
+ if (size>accuseSize)
+ accuseSize = size;
+ }
+ }
+
+ if (accuseSize)
+ return accuseSize;
+ else
+ return accuse;
+}
+
+
/*-----------------------------------------------------------------*/
/* aopForSym - for a true symbol */
/*-----------------------------------------------------------------*/
if (sym->onStack)
{
- if (_G.accInUse)
+ if (_G.accInUse || leftRightUseAcc (ic))
emitcode ("push", "acc");
emitcode ("mov", "a,_bp");
emitcode ("mov", "%s,a",
aop->aopu.aop_ptr->name);
- if (_G.accInUse)
+ if (_G.accInUse || leftRightUseAcc (ic))
emitcode ("pop", "acc");
}
else
/* if it is in direct space */
if (IN_DIRSPACE (space))
{
+ //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
+ //printTypeChainRaw(sym->type, NULL);
+ //printf("space = %s\n", space ? space->sname : "NULL");
sym->aop = aop = newAsmop (AOP_DIR);
aop->aopu.aop_dir = sym->rname;
aop->size = getSize (sym->type);
if (sym1 == sym2)
return TRUE;
- if (strcmp (sym1->rname, sym2->rname) == 0)
+ if (sym1->rname[0] && sym2->rname[0]
+ && strcmp (sym1->rname, sym2->rname) == 0)
return TRUE;
-
/* if left is a tmp & right is not */
if (IS_ITEMP (op1) &&
!IS_ITEMP (op2) &&
return;
}
- /* else spill location */
- if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
- /* force a new aop if sizes differ */
- sym->usl.spillLoc->aop = NULL;
- }
- sym->aop = op->aop = aop =
- aopForSym (ic, sym->usl.spillLoc, result);
+ if (sym->usl.spillLoc)
+ {
+ if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
+ {
+ /* force a new aop if sizes differ */
+ sym->usl.spillLoc->aop = NULL;
+ }
+ sym->aop = op->aop = aop =
+ aopForSym (ic, sym->usl.spillLoc, result);
+ aop->size = getSize (sym->type);
+ return;
+ }
+
+ /* else must be a dummy iTemp */
+ sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
aop->size = getSize (sym->type);
return;
}
switch (aop->type)
{
case AOP_R0:
- if (_G.r0Pushed)
+ if (_G.r0InB)
+ {
+ emitcode ("mov", "r0,b");
+ _G.r0InB--;
+ }
+ else if (_G.r0Pushed)
{
if (pop)
{
break;
case AOP_R1:
+ if (_G.r1InB)
+ {
+ emitcode ("mov", "r1,b");
+ _G.r1InB--;
+ }
if (_G.r1Pushed)
{
if (pop)
case AOP_STK:
{
int sz = aop->size;
- int stk = aop->aopu.aop_stk + aop->size;
+ int stk = aop->aopu.aop_stk + aop->size - 1;
bitVectUnSetBit (ic->rUsed, R0_IDX);
bitVectUnSetBit (ic->rUsed, R1_IDX);
}
op->aop = aop;
freeAsmop (op, NULL, ic, TRUE);
- if (_G.r0Pushed)
- {
- emitcode ("pop", "ar0");
- _G.r0Pushed--;
- }
-
if (_G.r1Pushed)
{
emitcode ("pop", "ar1");
_G.r1Pushed--;
}
+
+ if (_G.r0Pushed)
+ {
+ emitcode ("pop", "ar0");
+ _G.r0Pushed--;
+ }
}
}
}
}
+/*------------------------------------------------------------------*/
+/* freeForBranchAsmop - partial free up of Asmop for a branch; just */
+/* pop r0 or r1 off stack if pushed */
+/*------------------------------------------------------------------*/
+static void
+freeForBranchAsmop (operand * op)
+{
+ asmop *aop;
+
+ if (!op)
+ return;
+
+ aop = op->aop;
+
+ if (!aop)
+ return;
+
+ if (aop->freed)
+ return;
+
+ switch (aop->type)
+ {
+ case AOP_R0:
+ if (_G.r0InB)
+ {
+ emitcode ("mov", "r0,b");
+ }
+ else if (_G.r0Pushed)
+ {
+ emitcode ("pop", "ar0");
+ }
+ break;
+
+ case AOP_R1:
+ if (_G.r1InB)
+ {
+ emitcode ("mov", "r1,b");
+ }
+ else if (_G.r1Pushed)
+ {
+ emitcode ("pop", "ar1");
+ }
+ break;
+
+ case AOP_STK:
+ {
+ int sz = aop->size;
+ int stk = aop->aopu.aop_stk + aop->size - 1;
+
+ emitcode ("mov", "b,r0");
+ if (stk)
+ {
+ emitcode ("mov", "a,_bp");
+ emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
+ emitcode ("mov", "r0,a");
+ }
+ else
+ {
+ emitcode ("mov", "r0,_bp");
+ }
+
+ while (sz--)
+ {
+ emitcode ("pop", "acc");
+ emitcode ("mov", "@r0,a");
+ if (!sz)
+ break;
+ emitcode ("dec", "r0");
+ }
+ emitcode ("mov", "r0,b");
+ }
+ }
+
+}
+
/*-----------------------------------------------------------------*/
/* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
/* clobber the accumulator */
if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
return TRUE;
return FALSE;
+ case AOP_DUMMY:
+ return FALSE;
default:
/* Error case --- will have been caught already */
wassert(0);
}
}
-
/*-----------------------------------------------------------------*/
/* aopGet - for fetching value of the aop */
/*-----------------------------------------------------------------*/
/* depending on type */
switch (aop->type)
{
+ case AOP_DUMMY:
+ return zero;
case AOP_R0:
case AOP_R1:
/* aopPut - puts a string for a aop */
/*-----------------------------------------------------------------*/
static void
-aopPut (asmop * aop, char *s, int offset)
+aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
{
char *d = buffer;
/* depending on where it is ofcourse */
switch (aop->type)
{
+ case AOP_DUMMY:
+ MOVA (s); /* read s in case it was volatile */
+ break;
+
case AOP_DIR:
if (offset)
sprintf (d, "(%s + %d)",
else
sprintf (d, "%s", aop->aopu.aop_dir);
- if (strcmp (d, s))
+ if (strcmp (d, s) ||
+ bvolatile)
emitcode ("mov", "%s,%s", d, s);
break;
if (aop->code)
{
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- "aopPut writting to code space");
+ "aopPut writing to code space");
exit (1);
}
case AOP_STR:
aop->coff = offset;
- if (strcmp (aop->aopu.aop_str[offset], s))
+ if (strcmp (aop->aopu.aop_str[offset], s) ||
+ bvolatile)
emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
break;
case AOP_ACC:
aop->coff = offset;
- if (!offset && (strcmp (s, "acc") == 0))
+ if (!offset && (strcmp (s, "acc") == 0) &&
+ !bvolatile)
break;
- if (strcmp (aop->aopu.aop_str[offset], s))
+ if (strcmp (aop->aopu.aop_str[offset], s) &&
+ !bvolatile)
emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
break;
(x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
-/*-----------------------------------------------------------------*/
-/* genNotFloat - generates not for float operations */
-/*-----------------------------------------------------------------*/
-static void
-genNotFloat (operand * op, operand * res)
-{
- int size, offset;
- char *l;
- symbol *tlbl;
-
- D(emitcode ("; genNotFloat",""));
-
- /* we will put 127 in the first byte of
- the result */
- aopPut (AOP (res), "#127", 0);
- size = AOP_SIZE (op) - 1;
- offset = 1;
-
- l = aopGet (op->aop, offset++, FALSE, FALSE);
- MOVA (l);
-
- while (size--)
- {
- emitcode ("orl", "a,%s",
- aopGet (op->aop,
- offset++, FALSE, FALSE));
- }
-
- tlbl = newiTempLabel (NULL);
- aopPut (res->aop, one, 1);
- emitcode ("jz", "%05d$", (tlbl->key + 100));
- aopPut (res->aop, zero, 1);
- emitcode ("", "%05d$:", (tlbl->key + 100));
-
- size = res->aop->size - 2;
- offset = 2;
- /* put zeros in the rest */
- while (size--)
- aopPut (res->aop, zero, offset++);
-}
/*-----------------------------------------------------------------*/
/* opIsGptr: returns non-zero if the passed operand is */
size = getDataSize (result);
if (size)
{
- aopPut (AOP (result), "a", 0);
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
size--;
offset = 1;
/* unsigned or positive */
while (size--)
{
- aopPut (AOP (result), zero, offset++);
+ aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
}
}
}
{
/* if the result is bit */
if (AOP_TYPE (result) == AOP_CRY)
- aopPut (AOP (result), "c", 0);
+ aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
else
{
emitcode ("clr", "a");
genNot (iCode * ic)
{
symbol *tlbl;
- sym_link *optype = operandType (IC_LEFT (ic));
D(emitcode ("; genNot",""));
goto release;
}
- /* if type float then do float */
- if (IS_FLOAT (optype))
- {
- genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
- goto release;
- }
-
toBoolean (IC_LEFT (ic));
tlbl = newiTempLabel (NULL);
aopOp (IC_RESULT (ic), ic, TRUE);
/* special case if in bit space */
- if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
- if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
- emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
- emitcode ("cpl", "c");
- emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
+ if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
+ {
+ if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
+ {
+ /* promotion rules are responsible for this strange result: */
+ emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
+ goto release;
+ }
+
+ tlbl=newiTempLabel(NULL);
+ if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
+ AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
+ IS_AOP_PREG (IC_LEFT (ic)))
+ {
+ emitcode ("cjne", "%s,#0x01,%05d$",
+ aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
+ tlbl->key + 100);
+ }
+ else
+ {
+ char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
+ MOVA (l);
+ emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
+ }
+ emitcode ("", "%05d$:", tlbl->key + 100);
+ outBitC (IC_RESULT(ic));
goto release;
}
- tlbl=newiTempLabel(NULL);
- emitcode ("cjne", "%s,#0x01,%05d$",
- aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
- emitcode ("", "%05d$:", tlbl->key+100);
- outBitC (IC_RESULT(ic));
- goto release;
- }
size = AOP_SIZE (IC_RESULT (ic));
while (size--)
char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
MOVA (l);
emitcode ("cpl", "a");
- aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+ aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
}
{
aopPut (AOP (result),
aopGet (AOP (op), offset, FALSE, FALSE),
- offset);
+ offset,
+ isOperandVolatile (result, FALSE));
offset++;
}
MOVA (l);
emitcode ("cpl", "acc.7");
- aopPut (AOP (result), "a", offset);
+ aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
}
/*-----------------------------------------------------------------*/
emitcode ("clr", "a");
emitcode ("subb", "a,%s", l);
}
- aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+ aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
}
/* if any remaining bytes in the result */
emitcode ("rlc", "a");
emitcode ("subb", "a,acc");
while (size--)
- aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+ aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
}
release:
/* if the registers have been saved already or don't need to be then
do nothing */
- if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
- IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
+ if (ic->regsSaved)
+ return;
+ if (IS_SYMOP(IC_LEFT(ic)) &&
+ (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
+ IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
return;
/* safe the registers in use at this time but skip the
ones for the result */
- rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
+ rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
mcs51_rUmaskForOp (IC_RESULT(ic)));
ic->regsSaved = 1;
/* restore the registers in use at this time but skip the
ones for the result */
- rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
+ rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
mcs51_rUmaskForOp (IC_RESULT(ic)));
if (options.useXstack)
AOP_TYPE (oper) != AOP_DIR &&
strcmp (l, "a"))
{
- emitcode ("mov", "a,%s", l);
+ MOVA (l);
emitcode ("push", "acc");
}
else
int size = AOP_SIZE (oper);
while (size--)
{
- aopPut (AOP (oper), fReturn[offset], offset);
+ aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
offset++;
}
}
AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
strcmp (l, "a"))
{
- emitcode ("mov", "a,%s", l);
+ MOVA (l);
emitcode ("push", "acc");
}
else
if (!ic)
{
/* Assume r0 is available for use. */
- r = mcs51_regWithIdx (R0_IDX);;
- }
+ r = mcs51_regWithIdx (R0_IDX);;
+ }
else
{
aop = newAsmop (0);
r = getFreePtr (ic, &aop, FALSE);
}
- emitcode ("mov", "%s,_spx", r->name);
+ emitcode ("mov", "%s,_spx", r->name);
}
-
+
if (popPsw)
{
if (options.useXstack)
{
emitcode ("mov", "_spx,%s", r->name);
}
-
+
if (aop)
{
- freeAsmop (NULL, aop, ic, TRUE);
- }
+ freeAsmop (NULL, aop, ic, TRUE);
+ }
}
/*-----------------------------------------------------------------*/
}
if (ic)
- {
+ {
ic->bankSaved = 1;
}
}
emitcode ("mov","b1_%d,%s",rb1_count++,
aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
}
- }
+ }
freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
}
}
(FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
!IFFUNC_ISISR (dtype))
{
- swapBanks = TRUE;
- }
-
+ swapBanks = TRUE;
+ }
+
/* if caller saves & we have not saved then */
if (!ic->regsSaved)
saveRegisters (ic);
if (swapBanks)
{
- emitcode ("mov", "psw,#0x%02x",
+ emitcode ("mov", "psw,#0x%02x",
((FUNC_REGBANK(dtype)) << 3) & 0xff);
}
if (swapBanks)
{
- emitcode ("mov", "psw,#0x%02x",
+ emitcode ("mov", "psw,#0x%02x",
((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
}
/* if we need assign a result value */
if ((IS_ITEMP (IC_RESULT (ic)) &&
(OP_SYMBOL (IC_RESULT (ic))->nRegs ||
- OP_SYMBOL (IC_RESULT (ic))->accuse ||
+ OP_SYMBOL (IC_RESULT (ic))->accuse ||
OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
IS_TRUE_SYMOP (IC_RESULT (ic)))
{
if (swapBanks)
{
- emitcode ("mov", "psw,#0x%02x",
+ emitcode ("mov", "psw,#0x%02x",
((FUNC_REGBANK(dtype)) << 3) & 0xff);
}
if (swapBanks)
{
- emitcode ("mov", "psw,#0x%02x",
+ emitcode ("mov", "psw,#0x%02x",
((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
}
/*-----------------------------------------------------------------*/
/* inExcludeList - return 1 if the string is in exclude Reg list */
/*-----------------------------------------------------------------*/
+static int
+regsCmp(void *p1, void *p2)
+{
+ return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
+}
+
static bool
inExcludeList (char *s)
{
- int i = 0;
+ const char *p = setFirstItem(options.excludeRegsSet);
- if (options.excludeRegs[i] &&
- STRCASECMP (options.excludeRegs[i], "none") == 0)
+ if (p == NULL || STRCASECMP(p, "none") == 0)
return FALSE;
- for (i = 0; options.excludeRegs[i]; i++)
- {
- if (options.excludeRegs[i] &&
- STRCASECMP (s, options.excludeRegs[i]) == 0)
- return TRUE;
- }
- return FALSE;
+
+ return isinSetWith(options.excludeRegsSet, s, regsCmp);
}
/*-----------------------------------------------------------------*/
static void
genFunction (iCode * ic)
{
- symbol *sym;
+ symbol *sym = OP_SYMBOL (IC_LEFT (ic));
sym_link *ftype;
bool switchedPSW = FALSE;
int calleesaves_saved_register = -1;
+ int stackAdjust = sym->stack;
+ int accIsFree = sym->recvSize < 4;
+ iCode * ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
_G.nRegsSaved = 0;
/* create the function header */
emitcode (";", "-----------------------------------------");
- emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
+ emitcode (";", " function %s", sym->name);
emitcode (";", "-----------------------------------------");
emitcode ("", "%s:", sym->rname);
ftype = operandType (IC_LEFT (ic));
+ _G.currentFunc = sym;
if (IFFUNC_ISNAKED(ftype))
{
emitcode(";", "naked function: no prologue.");
return;
}
-
- /* if critical function then turn interrupts off */
- if (IFFUNC_ISCRITICAL (ftype))
- emitcode ("clr", "ea");
-
+
/* here we need to generate the equates for the
register bank if required */
if (FUNC_REGBANK (ftype) != rbank)
/* save the registers used */
for (i = 0; i < sym->regsUsed->size; i++)
{
- if (bitVectBitValue (sym->regsUsed, i) ||
- (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
+ if (bitVectBitValue (sym->regsUsed, i))
emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
}
}
-
}
else
{
-
- /* this function has a function call cannot
+
+ /* this function has a function call. We cannot
determines register usage so we will have to push the
entire bank */
saveRBank (0, ic, FALSE);
* other bank, we must save that bank entirely.
*/
unsigned long banksToSave = 0;
-
+
if (IFFUNC_HASFCALL(sym->type))
{
/* we got to the end OK. */
break;
}
-
+
if (i->op == CALL)
{
sym_link *dtype;
-
+
dtype = operandType (IC_LEFT(i));
if (dtype
&& FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
{
banksToSave |= (1 << FUNC_REGBANK(dtype));
}
-
- /* And note that we don't need to do it in
+
+ /* And note that we don't need to do it in
* genCall.
*/
i->bankSaved = 1;
* The only thing I can think of to do is
* throw a warning and hope.
*/
- werror(W_FUNCPTR_IN_USING_ISR);
+ werror(W_FUNCPTR_IN_USING_ISR);
}
}
if (banksToSave && options.useXstack)
{
- /* Since we aren't passing it an ic,
+ /* 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",
+ emitcode ("mov", "psw,#0x%02x",
(FUNC_REGBANK (sym->type) << 3) & 0x00ff);
switchedPSW = TRUE;
}
-
+
for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
{
if (banksToSave & (1 << ix))
}
}
}
- // jwk: this needs a closer look
+ // TODO: this needs a closer look
SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
}
+
+ /* Set the register bank to the desired value if nothing else */
+ /* has done so yet. */
+ if (!switchedPSW)
+ {
+ emitcode ("push", "psw");
+ emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
+ }
}
else
{
+ /* This is a non-ISR function. The caller has already switched register */
+ /* banks, if necessary, so just handle the callee-saves option. */
+
/* if callee-save to be used for this function
then save the registers being used in this function */
if (IFFUNC_CALLEESAVES(sym->type))
/* save the registers used */
for (i = 0; i < sym->regsUsed->size; i++)
{
- if (bitVectBitValue (sym->regsUsed, i) ||
- (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
+ if (bitVectBitValue (sym->regsUsed, i))
{
/* remember one saved register for later usage */
if (calleesaves_saved_register < 0)
}
}
- /* set the register bank to the desired value */
- if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
- && !switchedPSW)
- {
- emitcode ("push", "psw");
- emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
- }
if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
{
if (options.useXstack)
{
+ if (!accIsFree)
+ emitcode ("push", "acc");
emitcode ("mov", "r0,%s", spname);
emitcode ("mov", "a,_bp");
emitcode ("movx", "@r0,a");
emitcode ("inc", "%s", spname);
+ if (!accIsFree)
+ emitcode ("pop", "acc");
}
else
{
}
emitcode ("mov", "_bp,%s", spname);
}
-
+
+ /* For some cases it is worthwhile to perform a RECEIVE iCode */
+ /* before setting up the stack frame completely. */
+ if (ric && ric->argreg == 1 && IC_RESULT (ric))
+ {
+ symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
+
+ if (rsym->isitmp)
+ {
+ if (rsym && rsym->regType == REG_CND)
+ rsym = NULL;
+ if (rsym && (rsym->accuse || rsym->ruonly))
+ rsym = NULL;
+ if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
+ rsym = rsym->usl.spillLoc;
+ }
+
+ /* If the RECEIVE operand immediately spills to the first entry on the */
+ /* stack, we can push it directly (since sp = _bp + 1 at this point) */
+ /* rather than the usual @r0/r1 machinations. */
+ if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
+ {
+ int ofs;
+
+ _G.current_iCode = ric;
+ D(emitcode ("; genReceive",""));
+ for (ofs=0; ofs < sym->recvSize; ofs++)
+ {
+ if (!strcmp (fReturn[ofs], "a"))
+ emitcode ("push", "acc");
+ else
+ emitcode ("push", fReturn[ofs]);
+ }
+ stackAdjust -= sym->recvSize;
+ if (stackAdjust<0)
+ {
+ assert (stackAdjust>=0);
+ stackAdjust = 0;
+ }
+ _G.current_iCode = ic;
+ ric->generated = 1;
+ accIsFree = 1;
+ }
+ /* If the RECEIVE operand is 4 registers, we can do the moves now */
+ /* to free up the accumulator. */
+ else if (rsym && rsym->nRegs && sym->recvSize == 4)
+ {
+ int ofs;
+
+ _G.current_iCode = ric;
+ D(emitcode ("; genReceive",""));
+ for (ofs=0; ofs < sym->recvSize; ofs++)
+ {
+ emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
+ }
+ _G.current_iCode = ic;
+ ric->generated = 1;
+ accIsFree = 1;
+ }
+ }
+
/* adjust the stack for the function */
- if (sym->stack)
+ if (stackAdjust)
{
- int i = sym->stack;
+ int i = stackAdjust;
if (i > 256)
werror (W_STACK_OVERFLOW, sym->name);
- if (i > 3 && sym->recvSize < 4)
+ if (i > 3 && accIsFree)
{
emitcode ("mov", "a,sp");
}
else if (i > 5)
{
+ /* The accumulator is not free, so we will need another register */
+ /* to clobber. No need to worry about a possible conflict with */
+ /* the above early RECEIVE optimizations since they would have */
+ /* freed the accumulator if they were generated. */
+
if (IFFUNC_CALLEESAVES(sym->type))
{
/* if it's a callee-saves function we need a saved register */
if (sym->xstack)
{
+ if (!accIsFree)
+ emitcode ("push", "acc");
emitcode ("mov", "a,_spx");
emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
emitcode ("mov", "_spx,a");
+ if (!accIsFree)
+ emitcode ("pop", "acc");
}
+ /* if critical function then turn interrupts off */
+ if (IFFUNC_ISCRITICAL (ftype))
+ {
+ symbol *tlbl = newiTempLabel (NULL);
+ emitcode ("setb", "c");
+ emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
+ emitcode ("clr", "c");
+ emitcode ("", "%05d$:", (tlbl->key + 100));
+ emitcode ("push", "psw"); /* save old ea via c in psw */
+ }
}
/*-----------------------------------------------------------------*/
genEndFunction (iCode * ic)
{
symbol *sym = OP_SYMBOL (IC_LEFT (ic));
-
+ lineNode *lnp = lineCurr;
+ bitVect *regsUsed;
+ bitVect *regsUsedPrologue;
+ bitVect *regsUnneeded;
+ int idx;
+
+ _G.currentFunc = NULL;
if (IFFUNC_ISNAKED(sym->type))
{
emitcode(";", "naked function: no epilogue.");
+ if (options.debug && currFunc)
+ debugFile->writeEndFunction (currFunc, ic, 0);
return;
}
+ if (IFFUNC_ISCRITICAL (sym->type))
+ {
+ emitcode ("pop", "psw"); /* restore ea via c in psw */
+ emitcode ("mov", "ea,c");
+ }
+
if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
{
emitcode ("mov", "%s,_bp", spname);
/* save the registers used */
for (i = sym->regsUsed->size; i >= 0; i--)
{
- if (bitVectBitValue (sym->regsUsed, i) ||
- (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
+ if (bitVectBitValue (sym->regsUsed, i))
emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
}
}
-
}
else
{
if (options.parms_in_bank1) {
int i;
- for (i = 7 ; i >= 0 ; i-- ) {
+ for (i = 7 ; i >= 0 ; i-- ) {
emitcode ("pop","%s",rb1regs[i]);
}
}
* Restore any register banks saved by genFunction
* in reverse order.
*/
- // jwk: this needs a closer look
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,
if (!inExcludeList ("acc"))
emitcode ("pop", "acc");
- if (IFFUNC_ISCRITICAL (sym->type))
- emitcode ("setb", "ea");
-
/* if debug then send end of function */
if (options.debug && currFunc)
{
- _G.debugLine = 1;
- emitcode ("", "C$%s$%d$%d$%d ==.",
- FileBaseName (ic->filename), currFunc->lastLine,
- ic->level, ic->block);
- if (IS_STATIC (currFunc->etype))
- emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
- else
- emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
- _G.debugLine = 0;
+ debugFile->writeEndFunction (currFunc, ic, 1);
}
emitcode ("reti", "");
}
else
{
- if (IFFUNC_ISCRITICAL (sym->type))
- emitcode ("setb", "ea");
-
if (IFFUNC_CALLEESAVES(sym->type))
{
int i;
emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
}
}
+ else if (mcs51_ptrRegReq)
+ {
+ emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
+ emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
+ }
}
/* if debug then send end of function */
if (options.debug && currFunc)
{
- _G.debugLine = 1;
- emitcode ("", "C$%s$%d$%d$%d ==.",
- FileBaseName (ic->filename), currFunc->lastLine,
- ic->level, ic->block);
- if (IS_STATIC (currFunc->etype))
- emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
- else
- emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
- _G.debugLine = 0;
+ debugFile->writeEndFunction (currFunc, ic, 1);
}
emitcode ("ret", "");
}
+ if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
+ return;
+
+ /* If this was an interrupt handler using bank 0 that called another */
+ /* function, then all registers must be saved; nothing to optimized. */
+ if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
+ && !FUNC_REGBANK(sym->type))
+ return;
+
+ /* There are no push/pops to optimize if not callee-saves or ISR */
+ if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
+ return;
+
+ /* If there were stack parameters, we cannot optimize without also */
+ /* fixing all of the stack offsets; this is too dificult to consider. */
+ if (FUNC_HASSTACKPARM(sym->type))
+ return;
+
+ /* Compute the registers actually used */
+ regsUsed = newBitVect (mcs51_nRegs);
+ regsUsedPrologue = newBitVect (mcs51_nRegs);
+ while (lnp)
+ {
+ if (lnp->ic && lnp->ic->op == FUNCTION)
+ regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
+ else
+ regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
+
+ if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
+ && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
+ break;
+ if (!lnp->prev)
+ break;
+ lnp = lnp->prev;
+ }
+
+ if (bitVectBitValue (regsUsedPrologue, CND_IDX)
+ && !bitVectBitValue (regsUsed, CND_IDX))
+ {
+ regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
+ if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
+ && !sym->stack && !FUNC_ISCRITICAL (sym->type))
+ bitVectUnSetBit (regsUsed, CND_IDX);
+ }
+ else
+ regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
+
+ /* If this was an interrupt handler that called another function */
+ /* function, then assume A, B, DPH, & DPL may be modified by it. */
+ if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
+ {
+ regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
+ regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
+ regsUsed = bitVectSetBit (regsUsed, B_IDX);
+ regsUsed = bitVectSetBit (regsUsed, A_IDX);
+ regsUsed = bitVectSetBit (regsUsed, CND_IDX);
+ }
+
+ /* Remove the unneeded push/pops */
+ regsUnneeded = newBitVect (mcs51_nRegs);
+ while (lnp)
+ {
+ if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
+ {
+ if (!strncmp(lnp->line, "push", 4))
+ {
+ idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
+ if (idx>=0 && !bitVectBitValue (regsUsed, idx))
+ {
+ connectLine (lnp->prev, lnp->next);
+ regsUnneeded = bitVectSetBit (regsUnneeded, idx);
+ }
+ }
+ if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
+ {
+ idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
+ if (idx>=0 && !bitVectBitValue (regsUsed, idx))
+ {
+ connectLine (lnp->prev, lnp->next);
+ regsUnneeded = bitVectSetBit (regsUnneeded, idx);
+ }
+ }
+ }
+ lnp = lnp->next;
+ }
+
+ for (idx = 0; idx < regsUnneeded->size; idx++)
+ if (bitVectBitValue (regsUnneeded, idx))
+ emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
+
+ freeBitVect (regsUnneeded);
+ freeBitVect (regsUsed);
+ freeBitVect (regsUsedPrologue);
}
/*-----------------------------------------------------------------*/
count++;
/* If we have any pushes or pops, we cannot predict the distance.
- I don't like this at all, this should be dealt with in the
+ I don't like this at all, this should be dealt with in the
back-end */
if (ic->op == IPUSH || ic->op == IPOP) {
return 0;
/* if increment >=16 bits in register or direct space */
if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
- sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
+ sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
(size > 1) &&
(icount == 1))
{
{
MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
- aopPut (AOP (IC_RESULT (ic)), "a", 0);
+ aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
}
else
{
/* if the result is a bit */
if (AOP_TYPE (result) == AOP_CRY)
{
- aopPut (AOP (result), "a", 0);
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
}
else
{
!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
aopPut (AOP (IC_RESULT (ic)),
aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
- 2);
+ 2,
+ isOperandVolatile (IC_RESULT (ic), FALSE));
if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
AOP_SIZE (IC_RIGHT (ic)) == 3 &&
!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
aopPut (AOP (IC_RESULT (ic)),
aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
- 2);
+ 2,
+ isOperandVolatile (IC_RESULT (ic), FALSE));
if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
AOP_SIZE (IC_LEFT (ic)) < 3 &&
{
char buffer[5];
sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
- aopPut (AOP (IC_RESULT (ic)), buffer, 2);
+ aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
}
}
#else
{
aopPut (AOP (IC_RESULT (ic)),
aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
- GPTRSIZE - 1);
+ GPTRSIZE - 1,
+ isOperandVolatile (IC_RESULT (ic), FALSE));
}
if (opIsGptr (IC_RESULT (ic)) &&
{
aopPut (AOP (IC_RESULT (ic)),
aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
- GPTRSIZE - 1);
+ GPTRSIZE - 1,
+ isOperandVolatile (IC_RESULT (ic), FALSE));
}
if (opIsGptr (IC_RESULT (ic)) &&
{
char buffer[5];
sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
- aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
+ aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
}
}
#endif
genPlus (iCode * ic)
{
int size, offset = 0;
- char *add;
+ int skip_bytes = 0;
+ char *add = "add";
asmop *leftOp, *rightOp;
+ operand * op;
/* special cases :- */
{
MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
emitcode ("addc", "a,#00");
- aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+ aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
}
}
goto release;
goto release;
size = getDataSize (IC_RESULT (ic));
-
leftOp = AOP(IC_LEFT(ic));
rightOp = AOP(IC_RIGHT(ic));
- add = "add";
+ op=IC_LEFT(ic);
+
+ /* if this is an add for an array access
+ at a 256 byte boundary */
+ if ( 2 == size
+ && AOP_TYPE (op) == AOP_IMMD
+ && IS_SYMOP (op)
+ && IS_SPEC (OP_SYM_ETYPE (op))
+ && SPEC_ABSA (OP_SYM_ETYPE (op))
+ && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
+ )
+ {
+ D(emitcode ("; genPlus aligned array",""));
+ aopPut (AOP (IC_RESULT (ic)),
+ aopGet (rightOp, 0, FALSE, FALSE),
+ 0,
+ isOperandVolatile (IC_RESULT (ic), FALSE));
- while (size--)
- {
- if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
+ if( 1 == getDataSize (IC_RIGHT (ic)) )
{
- emitcode("mov", "b,a");
- MOVA (aopGet (leftOp, offset, FALSE, TRUE));
- emitcode("xch", "a,b");
- MOVA (aopGet (rightOp, offset, FALSE, TRUE));
- emitcode (add, "a,b");
+ aopPut (AOP (IC_RESULT (ic)),
+ aopGet (leftOp, 1, FALSE, FALSE),
+ 1,
+ isOperandVolatile (IC_RESULT (ic), FALSE));
}
- else if (aopGetUsesAcc (leftOp, offset))
- {
- MOVA (aopGet (leftOp, offset, FALSE, TRUE));
- emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
+ else
+ {
+ MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
+ emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
+ aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
}
+ goto release;
+ }
+
+ /* if the lower bytes of a literal are zero skip the addition */
+ if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
+ {
+ while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
+ (skip_bytes+1 < size))
+ {
+ skip_bytes++;
+ }
+ if (skip_bytes)
+ D(emitcode ("; genPlus shortcut",""));
+ }
+
+ while (size--)
+ {
+ if( offset >= skip_bytes )
+ {
+ if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
+ {
+ emitcode("mov", "b,a");
+ MOVA (aopGet (leftOp, offset, FALSE, TRUE));
+ emitcode("xch", "a,b");
+ MOVA (aopGet (rightOp, offset, FALSE, TRUE));
+ emitcode (add, "a,b");
+ }
+ else if (aopGetUsesAcc (leftOp, offset))
+ {
+ MOVA (aopGet (leftOp, offset, FALSE, TRUE));
+ emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
+ }
+ else
+ {
+ MOVA (aopGet (rightOp, offset, FALSE, TRUE));
+ emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
+ }
+ aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
+ add = "addc"; /* further adds must propagate carry */
+ }
else
- {
- MOVA (aopGet (rightOp, offset, FALSE, TRUE));
- emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
+ {
+ if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
+ isOperandVolatile (IC_RESULT (ic), FALSE))
+ {
+ /* just move */
+ aopPut (AOP (IC_RESULT (ic)),
+ aopGet (leftOp, offset, FALSE, FALSE),
+ offset,
+ isOperandVolatile (IC_RESULT (ic), FALSE));
+ }
}
- aopPut (AOP (IC_RESULT (ic)), "a", offset++);
- add = "addc"; /* further adds must propagate carry */
+ offset++;
}
adjustArithmeticResult (ic);
emitcode ("rlc", "a");
emitcode ("subb", "a,acc");
while (size--)
- aopPut (AOP (result), "a", offset++);
+ aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
}
else
while (size--)
- aopPut (AOP (result), zero, offset++);
+ aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
}
}
emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
emitcode ("inc", "a");
emitcode ("", "%05d$:", (lbl->key + 100));
- aopPut (AOP (IC_RESULT (ic)), "a", 0);
+ aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
}
}
MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
/* first add without previous c */
if (!offset) {
- if (!size && lit==-1) {
+ if (!size && lit== (unsigned long) -1) {
emitcode ("dec", "a");
} else {
- emitcode ("add", "a,#0x%02x",
+ emitcode ("add", "a,#0x%02x",
(unsigned int) (lit & 0x0FFL));
}
} else {
emitcode ("addc", "a,#0x%02x",
(unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
}
- aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+ aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
}
}
else
aopGet(rightOp, offset, FALSE, TRUE));
}
- aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+ aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
}
}
-
-
+
+
adjustArithmeticResult (ic);
release:
outBitC (result);
}
-
/*-----------------------------------------------------------------*/
/* genMultOneByte : 8*8=8/16 bit multiplication */
/*-----------------------------------------------------------------*/
operand * right,
operand * result)
{
- sym_link *opetype = operandType (result);
symbol *lbl;
- int size=AOP_SIZE(result);
+ int size = AOP_SIZE (result);
+ bool runtimeSign, compiletimeSign;
+ bool lUnsigned, rUnsigned;
D(emitcode ("; genMultOneByte",""));
- if (size<1 || size>2) {
- // this should never happen
- fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
+ if (size < 1 || size > 2)
+ {
+ /* this should never happen */
+ fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
AOP_SIZE(result), __FILE__, lineno);
exit (1);
- }
+ }
/* (if two literals: the value is computed before) */
/* if one literal, literal on the right */
operand *t = right;
right = left;
left = t;
- //emitcode (";", "swapped left and right");
- }
-
- if (SPEC_USIGN(opetype)
- // ignore the sign of left and right, what else can we do?
- || (SPEC_USIGN(operandType(left)) &&
- SPEC_USIGN(operandType(right)))) {
- // just an unsigned 8*8=8/16 multiply
- //emitcode (";","unsigned");
- // TODO: check for accumulator clash between left & right aops?
- emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
- MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
- emitcode ("mul", "ab");
- aopPut (AOP (result), "a", 0);
- if (size==2) {
- aopPut (AOP (result), "b", 1);
+ /* emitcode (";", "swapped left and right"); */
}
- return;
- }
+ /* if no literal, unsigned on the right: shorter code */
+ if ( AOP_TYPE (right) != AOP_LIT
+ && SPEC_USIGN (getSpec (operandType (left))))
+ {
+ operand *t = right;
+ right = left;
+ left = t;
+ }
+
+ lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+ rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
+
+ if (size == 1 /* no, this is not a bug; with a 1 byte result there's
+ no need to take care about the signedness! */
+ || (lUnsigned && rUnsigned))
+ {
+ /* just an unsigned 8 * 8 = 8 multiply
+ or 8u * 8u = 16u */
+ /* emitcode (";","unsigned"); */
+ /* TODO: check for accumulator clash between left & right aops? */
+
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ /* moving to accumulator first helps peepholes */
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+ emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
+ }
+ else
+ {
+ emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+ }
- // we have to do a signed multiply
+ emitcode ("mul", "ab");
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
+ if (size == 2)
+ aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
+ return;
+ }
- //emitcode (";", "signed");
- emitcode ("clr", "F0"); // reset sign flag
- MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+ /* we have to do a signed multiply */
+ /* emitcode (";", "signed"); */
- lbl=newiTempLabel(NULL);
- emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
- // left side is negative, 8-bit two's complement, this fails for -128
- emitcode ("setb", "F0"); // set sign flag
- emitcode ("cpl", "a");
- emitcode ("inc", "a");
+ /* now sign adjust for both left & right */
- emitcode ("", "%05d$:", lbl->key+100);
+ /* let's see what's needed: */
+ /* apply negative sign during runtime */
+ runtimeSign = FALSE;
+ /* negative sign from literals */
+ compiletimeSign = FALSE;
- /* if literal */
- if (AOP_TYPE(right)==AOP_LIT) {
- signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
- /* AND literal negative */
- if (val < 0) {
- emitcode ("cpl", "F0"); // complement sign flag
- emitcode ("mov", "b,#0x%02x", -val);
- } else {
- emitcode ("mov", "b,#0x%02x", val);
+ if (!lUnsigned)
+ {
+ if (AOP_TYPE(left) == AOP_LIT)
+ {
+ /* signed literal */
+ signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+ if (val < 0)
+ compiletimeSign = TRUE;
+ }
+ else
+ /* signed but not literal */
+ runtimeSign = TRUE;
}
- } else {
- lbl=newiTempLabel(NULL);
- emitcode ("mov", "b,a");
- emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
- emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
- // right side is negative, 8-bit two's complement
- emitcode ("cpl", "F0"); // complement sign flag
- emitcode ("cpl", "a");
- emitcode ("inc", "a");
- emitcode ("", "%05d$:", lbl->key+100);
- }
- emitcode ("mul", "ab");
-
- lbl=newiTempLabel(NULL);
- emitcode ("jnb", "F0,%05d$", lbl->key+100);
- // only ONE op was negative, we have to do a 8/16-bit two's complement
- emitcode ("cpl", "a"); // lsb
- if (size==1) {
- emitcode ("inc", "a");
- } else {
- emitcode ("add", "a,#1");
- emitcode ("xch", "a,b");
- emitcode ("cpl", "a"); // msb
- emitcode ("addc", "a,#0");
- emitcode ("xch", "a,b");
- }
- emitcode ("", "%05d$:", lbl->key+100);
- aopPut (AOP (result), "a", 0);
- if (size==2) {
- aopPut (AOP (result), "b", 1);
- }
+ if (!rUnsigned)
+ {
+ if (AOP_TYPE(right) == AOP_LIT)
+ {
+ /* signed literal */
+ signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+ if (val < 0)
+ compiletimeSign ^= TRUE;
+ }
+ else
+ /* signed but not literal */
+ runtimeSign = TRUE;
+ }
+
+ /* initialize F0, which stores the runtime sign */
+ if (runtimeSign)
+ {
+ if (compiletimeSign)
+ emitcode ("setb", "F0"); /* set sign flag */
+ else
+ emitcode ("clr", "F0"); /* reset sign flag */
+ }
+
+ /* save the signs of the operands */
+ if (AOP_TYPE(right) == AOP_LIT)
+ {
+ signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+
+ if (!rUnsigned && val < 0)
+ emitcode ("mov", "b,#0x%02x", -val);
+ else
+ emitcode ("mov", "b,#0x%02x", (unsigned char) val);
+ }
+ else /* ! literal */
+ {
+ if (rUnsigned) /* emitcode (";", "signed"); */
+
+ emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
+ else
+ {
+ MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
+ lbl = newiTempLabel (NULL);
+ emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+ emitcode ("cpl", "F0"); /* complement sign flag */
+ emitcode ("cpl", "a"); /* 2's complement */
+ emitcode ("inc", "a");
+ emitcode ("", "%05d$:", (lbl->key + 100));
+ emitcode ("mov", "b,a");
+ }
+ }
+
+ if (AOP_TYPE(left) == AOP_LIT)
+ {
+ signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+
+ if (!lUnsigned && val < 0)
+ emitcode ("mov", "a,#0x%02x", -val);
+ else
+ emitcode ("mov", "a,#0x%02x", (unsigned char) val);
+ }
+ else /* ! literal */
+ {
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+
+ if (!lUnsigned)
+ {
+ lbl = newiTempLabel (NULL);
+ emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+ emitcode ("cpl", "F0"); /* complement sign flag */
+ emitcode ("cpl", "a"); /* 2's complement */
+ emitcode ("inc", "a");
+ emitcode ("", "%05d$:", (lbl->key + 100));
+ }
+ }
+
+ /* now the multiplication */
+ emitcode ("mul", "ab");
+ if (runtimeSign || compiletimeSign)
+ {
+ lbl = newiTempLabel (NULL);
+ if (runtimeSign)
+ emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
+ emitcode ("cpl", "a"); /* lsb 2's complement */
+ if (size != 2)
+ emitcode ("inc", "a"); /* inc doesn't set carry flag */
+ else
+ {
+ emitcode ("add", "a,#1"); /* this sets carry flag */
+ emitcode ("xch", "a,b");
+ emitcode ("cpl", "a"); /* msb 2's complement */
+ emitcode ("addc", "a,#0");
+ emitcode ("xch", "a,b");
+ }
+ emitcode ("", "%05d$:", (lbl->key + 100));
+ }
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
+ if (size == 2)
+ aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
}
/*-----------------------------------------------------------------*/
#if 0 // one of them can be a sloc shared with the result
if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
#else
- if (getSize(operandType(left)) == 1 &&
+ if (getSize(operandType(left)) == 1 &&
getSize(operandType(right)) == 1)
#endif
{
assert (0);
release:
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
- freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (result, NULL, ic, TRUE);
+ freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
}
/*-----------------------------------------------------------------*/
emitcode ("div", "ab");
emitcode ("rrc", "a");
- aopPut (AOP (result), "c", 0);
+ aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
}
/*-----------------------------------------------------------------*/
operand * right,
operand * result)
{
- sym_link *opetype = operandType (result);
- char *l;
+ bool lUnsigned, rUnsigned;
+ bool runtimeSign, compiletimeSign;
symbol *lbl;
int size, offset;
D(emitcode ("; genDivOneByte",""));
+ /* Why is it necessary that genDivOneByte() can return an int result?
+ Have a look at:
+
+ volatile unsigned char uc;
+ volatile signed char sc1, sc2;
+ volatile int i;
+
+ uc = 255;
+ sc1 = -1;
+ i = uc / sc1;
+
+ Or:
+
+ sc1 = -128;
+ sc2 = -1;
+ i = sc1 / sc2;
+
+ In all cases a one byte result would overflow, the following cast to int
+ would return the wrong result.
+
+ Two possible solution:
+ a) cast operands to int, if ((unsigned) / (signed)) or
+ ((signed) / (signed))
+ b) return an 16 bit signed int; this is what we're doing here!
+ */
+
size = AOP_SIZE (result) - 1;
offset = 1;
+ lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+ rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
+
/* signed or unsigned */
- if (SPEC_USIGN (opetype))
+ if (lUnsigned && rUnsigned)
{
/* unsigned is easy */
emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
- l = aopGet (AOP (left), 0, FALSE, FALSE);
- MOVA (l);
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
emitcode ("div", "ab");
- aopPut (AOP (result), "a", 0);
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
while (size--)
- aopPut (AOP (result), zero, offset++);
+ aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
return;
}
-
+
/* signed is a little bit more difficult */
+ /* now sign adjust for both left & right */
+
+ /* let's see what's needed: */
+ /* apply negative sign during runtime */
+ runtimeSign = FALSE;
+ /* negative sign from literals */
+ compiletimeSign = FALSE;
+
+ if (!lUnsigned)
+ {
+ if (AOP_TYPE(left) == AOP_LIT)
+ {
+ /* signed literal */
+ signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+ if (val < 0)
+ compiletimeSign = TRUE;
+ }
+ else
+ /* signed but not literal */
+ runtimeSign = TRUE;
+ }
+
+ if (!rUnsigned)
+ {
+ if (AOP_TYPE(right) == AOP_LIT)
+ {
+ /* signed literal */
+ signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+ if (val < 0)
+ compiletimeSign ^= TRUE;
+ }
+ else
+ /* signed but not literal */
+ runtimeSign = TRUE;
+ }
+
+ /* initialize F0, which stores the runtime sign */
+ if (runtimeSign)
+ {
+ if (compiletimeSign)
+ emitcode ("setb", "F0"); /* set sign flag */
+ else
+ emitcode ("clr", "F0"); /* reset sign flag */
+ }
+
/* save the signs of the operands */
- l = aopGet (AOP (left), 0, FALSE, FALSE);
- MOVA (l);
- emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
- emitcode ("push", "acc"); /* save it on the stack */
+ if (AOP_TYPE(right) == AOP_LIT)
+ {
+ signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
- /* now sign adjust for both left & right */
- l = aopGet (AOP (right), 0, FALSE, FALSE);
- MOVA (l);
- lbl = newiTempLabel (NULL);
- emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
- emitcode ("cpl", "a");
- emitcode ("inc", "a");
- emitcode ("", "%05d$:", (lbl->key + 100));
- emitcode ("mov", "b,a");
+ if (!rUnsigned && val < 0)
+ emitcode ("mov", "b,#0x%02x", -val);
+ else
+ emitcode ("mov", "b,#0x%02x", (unsigned char) val);
+ }
+ else /* ! literal */
+ {
+ if (rUnsigned)
+ emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
+ else
+ {
+ MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
+ lbl = newiTempLabel (NULL);
+ emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+ emitcode ("cpl", "F0"); /* complement sign flag */
+ emitcode ("cpl", "a"); /* 2's complement */
+ emitcode ("inc", "a");
+ emitcode ("", "%05d$:", (lbl->key + 100));
+ emitcode ("mov", "b,a");
+ }
+ }
- /* sign adjust left side */
- l = aopGet (AOP (left), 0, FALSE, FALSE);
- MOVA (l);
+ if (AOP_TYPE(left) == AOP_LIT)
+ {
+ signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
- lbl = newiTempLabel (NULL);
- emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
- emitcode ("cpl", "a");
- emitcode ("inc", "a");
- emitcode ("", "%05d$:", (lbl->key + 100));
+ if (!lUnsigned && val < 0)
+ emitcode ("mov", "a,#0x%02x", -val);
+ else
+ emitcode ("mov", "a,#0x%02x", (unsigned char) val);
+ }
+ else /* ! literal */
+ {
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+
+ if (!lUnsigned)
+ {
+ lbl = newiTempLabel (NULL);
+ emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+ emitcode ("cpl", "F0"); /* complement sign flag */
+ emitcode ("cpl", "a"); /* 2's complement */
+ emitcode ("inc", "a");
+ emitcode ("", "%05d$:", (lbl->key + 100));
+ }
+ }
/* now the division */
emitcode ("div", "ab");
- /* we are interested in the lower order
- only */
- emitcode ("mov", "b,a");
- lbl = newiTempLabel (NULL);
- emitcode ("pop", "acc");
- /* if there was an over flow we don't
- adjust the sign of the result */
- emitcode ("jb", "ov,%05d$", (lbl->key + 100));
- emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
- CLRC;
- emitcode ("clr", "a");
- emitcode ("subb", "a,b");
- emitcode ("mov", "b,a");
- emitcode ("", "%05d$:", (lbl->key + 100));
- /* now we are done */
- aopPut (AOP (result), "b", 0);
- if (size > 0)
+ if (runtimeSign || compiletimeSign)
{
- emitcode ("mov", "c,b.7");
- emitcode ("subb", "a,acc");
- }
- while (size--)
- aopPut (AOP (result), "a", offset++);
+ lbl = newiTempLabel (NULL);
+ if (runtimeSign)
+ emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
+ emitcode ("cpl", "a"); /* lsb 2's complement */
+ emitcode ("inc", "a");
+ emitcode ("", "%05d$:", (lbl->key + 100));
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
+ if (size > 0)
+ {
+ /* msb is 0x00 or 0xff depending on the sign */
+ if (runtimeSign)
+ {
+ emitcode ("mov", "c,F0");
+ emitcode ("subb", "a,acc");
+ while (size--)
+ aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
+ }
+ else /* compiletimeSign */
+ while (size--)
+ aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
+ }
+ }
+ else
+ {
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
+ while (size--)
+ aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
+ }
}
/*-----------------------------------------------------------------*/
/* should have been converted to function call */
assert (0);
release:
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (result, NULL, ic, TRUE);
}
emitcode ("div", "ab");
emitcode ("mov", "a,b");
emitcode ("rrc", "a");
- aopPut (AOP (result), "c", 0);
+ aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
}
/*-----------------------------------------------------------------*/
operand * right,
operand * result)
{
- sym_link *opetype = operandType (result);
- char *l;
+ bool lUnsigned, rUnsigned;
+ bool runtimeSign, compiletimeSign;
symbol *lbl;
+ int size, offset;
D(emitcode ("; genModOneByte",""));
+ size = AOP_SIZE (result) - 1;
+ offset = 1;
+ lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+ rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
+
/* signed or unsigned */
- if (SPEC_USIGN (opetype))
+ if (lUnsigned && rUnsigned)
{
/* unsigned is easy */
emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
- l = aopGet (AOP (left), 0, FALSE, FALSE);
- MOVA (l);
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
emitcode ("div", "ab");
- aopPut (AOP (result), "b", 0);
+ aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
+ while (size--)
+ aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
return;
}
/* signed is a little bit more difficult */
- /* save the signs of the operands */
- l = aopGet (AOP (left), 0, FALSE, FALSE);
- MOVA (l);
-
- emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
- emitcode ("push", "acc"); /* save it on the stack */
-
/* now sign adjust for both left & right */
- l = aopGet (AOP (right), 0, FALSE, FALSE);
- MOVA (l);
- lbl = newiTempLabel (NULL);
- emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
- emitcode ("cpl", "a");
- emitcode ("inc", "a");
- emitcode ("", "%05d$:", (lbl->key + 100));
- emitcode ("mov", "b,a");
+ /* modulus: sign of the right operand has no influence on the result! */
+ if (AOP_TYPE(right) == AOP_LIT)
+ {
+ signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+ if (!rUnsigned && val < 0)
+ emitcode ("mov", "b,#0x%02x", -val);
+ else
+ emitcode ("mov", "b,#0x%02x", (unsigned char) val);
+ }
+ else /* not literal */
+ {
+ if (rUnsigned)
+ emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
+ else
+ {
+ MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
+ lbl = newiTempLabel (NULL);
+ emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+ emitcode ("cpl", "a"); /* 2's complement */
+ emitcode ("inc", "a");
+ emitcode ("", "%05d$:", (lbl->key + 100));
+ emitcode ("mov", "b,a");
+ }
+ }
+
+ /* let's see what's needed: */
+ /* apply negative sign during runtime */
+ runtimeSign = FALSE;
+ /* negative sign from literals */
+ compiletimeSign = FALSE;
+
/* sign adjust left side */
- l = aopGet (AOP (left), 0, FALSE, FALSE);
- MOVA (l);
+ if (AOP_TYPE(left) == AOP_LIT)
+ {
+ signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
- lbl = newiTempLabel (NULL);
- emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
- emitcode ("cpl", "a");
- emitcode ("inc", "a");
- emitcode ("", "%05d$:", (lbl->key + 100));
+ if (!lUnsigned && val < 0)
+ {
+ compiletimeSign = TRUE; /* set sign flag */
+ emitcode ("mov", "a,#0x%02x", -val);
+ }
+ else
+ emitcode ("mov", "a,#0x%02x", (unsigned char) val);
+ }
+ else /* ! literal */
+ {
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
- /* now the multiplication */
- emitcode ("div", "ab");
- /* we are interested in the lower order
- only */
- lbl = newiTempLabel (NULL);
- emitcode ("pop", "acc");
- /* if there was an over flow we don't
- adjust the sign of the result */
- emitcode ("jb", "ov,%05d$", (lbl->key + 100));
- emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
- CLRC;
- emitcode ("clr", "a");
- emitcode ("subb", "a,b");
- emitcode ("mov", "b,a");
- emitcode ("", "%05d$:", (lbl->key + 100));
+ if (!lUnsigned)
+ {
+ runtimeSign = TRUE;
+ emitcode ("clr", "F0"); /* clear sign flag */
- /* now we are done */
- aopPut (AOP (result), "b", 0);
+ lbl = newiTempLabel (NULL);
+ emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+ emitcode ("setb", "F0"); /* set sign flag */
+ emitcode ("cpl", "a"); /* 2's complement */
+ emitcode ("inc", "a");
+ emitcode ("", "%05d$:", (lbl->key + 100));
+ }
+ }
+ /* now the modulus */
+ emitcode ("div", "ab");
+
+ if (runtimeSign || compiletimeSign)
+ {
+ emitcode ("mov", "a,b");
+ lbl = newiTempLabel (NULL);
+ if (runtimeSign)
+ emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
+ emitcode ("cpl", "a"); /* 2's complement */
+ emitcode ("inc", "a");
+ emitcode ("", "%05d$:", (lbl->key + 100));
+
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
+ if (size > 0)
+ {
+ /* msb is 0x00 or 0xff depending on the sign */
+ if (runtimeSign)
+ {
+ emitcode ("mov", "c,F0");
+ emitcode ("subb", "a,acc");
+ while (size--)
+ aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
+ }
+ else /* compiletimeSign */
+ while (size--)
+ aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
+ }
+ }
+ else
+ {
+ aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
+ while (size--)
+ aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
+ }
}
/*-----------------------------------------------------------------*/
assert (0);
release:
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (result, NULL, ic, TRUE);
}
/* genIfxJump :- will create a jump depending on the ifx */
/*-----------------------------------------------------------------*/
static void
-genIfxJump (iCode * ic, char *jval)
+genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
{
symbol *jlbl;
symbol *tlbl = newiTempLabel (NULL);
emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
else
emitcode (inst, "%05d$", tlbl->key + 100);
+ freeForBranchAsmop (result);
+ freeForBranchAsmop (right);
+ freeForBranchAsmop (left);
emitcode ("ljmp", "%05d$", jlbl->key + 100);
emitcode ("", "%05d$:", tlbl->key + 100);
{
int size, offset = 0;
unsigned long lit = 0L;
+ bool rightInB;
D(emitcode ("; genCmp",""));
AOP_TYPE (right) == AOP_CRY)
{
emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
- emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
+ emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
}
else
{
MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
{
- genIfxJump (ifx, "acc.7");
+ genIfxJump (ifx, "acc.7", left, right, result);
+ freeAsmop (right, NULL, ic, TRUE);
+ freeAsmop (left, NULL, ic, TRUE);
+
return;
}
else
CLRC;
while (size--)
{
+ rightInB = aopGetUsesAcc(AOP (right), offset);
+ if (rightInB)
+ emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
if (sign && size == 0)
{
}
else
{
- emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
+ if (!rightInB)
+ emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
emitcode ("xrl", "b,#0x80");
emitcode ("subb", "a,b");
}
}
else
- emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
+ {
+ if (rightInB)
+ emitcode ("subb", "a,b");
+ else
+ emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
+ }
+ offset++;
}
}
}
release:
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
{
outBitC (result);
ifx conditional branch then generate
code a little differently */
if (ifx)
- genIfxJump (ifx, "c");
+ genIfxJump (ifx, "c", NULL, NULL, result);
else
outBitC (result);
/* leave the result in acc */
letype = getSpec (operandType (left));
retype = getSpec (operandType (right));
- sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
+ sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
+ (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
/* assign the amsops */
aopOp (left, ic, FALSE);
aopOp (right, ic, FALSE);
letype = getSpec (operandType (left));
retype = getSpec (operandType (right));
- sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
-
+ sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
+ (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
/* assign the amsops */
aopOp (left, ic, FALSE);
aopOp (right, ic, FALSE);
if the right is in a pointer register and left
is not */
if ((AOP_TYPE (left) == AOP_LIT) ||
+ (AOP_TYPE (left) == AOP_IMMD) ||
(IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
{
operand *t = right;
right = left;
left = t;
}
+
if (AOP_TYPE (right) == AOP_LIT)
lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
/* if the right side is a literal then anything goes */
if (AOP_TYPE (right) == AOP_LIT &&
- AOP_TYPE (left) != AOP_DIR)
+ AOP_TYPE (left) != AOP_DIR &&
+ AOP_TYPE (left) != AOP_IMMD)
{
while (size--)
{
if the left is a pointer register & right is not */
else if (AOP_TYPE (right) == AOP_REG ||
AOP_TYPE (right) == AOP_DIR ||
+ AOP_TYPE (right) == AOP_LIT ||
+ AOP_TYPE (right) == AOP_IMMD ||
(AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
(IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
{
if (IC_TRUE (ifx))
{
emitcode ("jnc", "%05d$", tlbl->key + 100);
+ freeForBranchAsmop (result);
+ freeForBranchAsmop (right);
+ freeForBranchAsmop (left);
emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
}
else
{
emitcode ("jc", "%05d$", tlbl->key + 100);
+ freeForBranchAsmop (result);
+ freeForBranchAsmop (right);
+ freeForBranchAsmop (left);
emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
}
emitcode ("", "%05d$:", tlbl->key + 100);
gencjneshort (left, right, tlbl);
if (IC_TRUE (ifx))
{
+ freeForBranchAsmop (result);
+ freeForBranchAsmop (right);
+ freeForBranchAsmop (left);
emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
emitcode ("", "%05d$:", tlbl->key + 100);
}
symbol *lbl = newiTempLabel (NULL);
emitcode ("sjmp", "%05d$", lbl->key + 100);
emitcode ("", "%05d$:", tlbl->key + 100);
+ freeForBranchAsmop (result);
+ freeForBranchAsmop (right);
+ freeForBranchAsmop (left);
emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
emitcode ("", "%05d$:", lbl->key + 100);
}
}
if (ifx)
{
- genIfxJump (ifx, "c");
+ genIfxJump (ifx, "c", left, right, result);
goto release;
}
/* if the result is used in an arithmetic operation
gencjne (left, right, newiTempLabel (NULL));
if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
{
- aopPut (AOP (result), "a", 0);
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
goto release;
}
if (ifx)
{
- genIfxJump (ifx, "a");
+ genIfxJump (ifx, "a", left, right, result);
goto release;
}
/* if the result is used in an arithmetic operation
}
release:
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (result, NULL, ic, TRUE);
}
sym_link *retype = getSpec (type);
iCode *lic = ic->next;
int isize ;
-
+
/* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
if (!IS_SYMOP(op)) return NULL;
while (lic) {
/* if operand of the form op = op + <sizeof *op> */
if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
- isOperandEqual(IC_RESULT(lic),op) &&
+ isOperandEqual(IC_RESULT(lic),op) &&
isOperandLiteral(IC_RIGHT(lic)) &&
operandLitValue(IC_RIGHT(lic)) == isize) {
return lic;
outBitAcc (result);
}
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (result, NULL, ic, TRUE);
}
outBitAcc (result);
}
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (result, NULL, ic, TRUE);
}
/* jmpTrueOrFalse - */
/*-----------------------------------------------------------------*/
static void
-jmpTrueOrFalse (iCode * ic, symbol * tlbl)
+jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
{
// ugly but optimized by peephole
if (IC_TRUE (ic))
symbol *nlbl = newiTempLabel (NULL);
emitcode ("sjmp", "%05d$", nlbl->key + 100);
emitcode ("", "%05d$:", tlbl->key + 100);
+ freeForBranchAsmop (result);
+ freeForBranchAsmop (right);
+ freeForBranchAsmop (left);
emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
emitcode ("", "%05d$:", nlbl->key + 100);
}
else
{
+ freeForBranchAsmop (result);
+ freeForBranchAsmop (right);
+ freeForBranchAsmop (left);
emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
emitcode ("", "%05d$:", tlbl->key + 100);
}
outBitC (result);
// if(bit & ...)
else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
- genIfxJump (ifx, "c");
+ genIfxJump (ifx, "c", left, right, result);
goto release;
}
if (ifx)
{
sprintf (buffer, "acc.%d", posbit & 0x07);
- genIfxJump (ifx, buffer);
+ genIfxJump (ifx, buffer, left, right, result);
}
goto release;
}
else
{
if (ifx)
- jmpTrueOrFalse (ifx, tlbl);
+ jmpTrueOrFalse (ifx, tlbl, left, right, result);
+ else
+ emitcode ("", "%05d$:", tlbl->key + 100);
goto release;
}
}
if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
continue;
else if (bytelit == 0)
- aopPut (AOP (result), zero, offset);
+ {
+ aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
+ }
else if (IS_AOP_PREG (result))
{
MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
- aopPut (AOP (result), "a", offset);
+ aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
}
else
emitcode ("anl", "%s,%s",
if (IS_AOP_PREG (result))
{
emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
- aopPut (AOP (result), "a", offset);
+ aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
}
else
outBitC (result);
}
else if (ifx)
- jmpTrueOrFalse (ifx, tlbl);
+ jmpTrueOrFalse (ifx, tlbl, left, right, result);
+ else
+ emitcode ("", "%05d$:", tlbl->key + 100);
}
else
{
{
aopPut (AOP (result),
aopGet (AOP (left), offset, FALSE, FALSE),
- offset);
+ offset,
+ isOperandVolatile (result, FALSE));
continue;
}
else if (bytelit == 0)
{
- aopPut (AOP (result), zero, offset);
+ /* dummy read of volatile operand */
+ if (isOperandVolatile (left, FALSE))
+ MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
+ aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
continue;
}
}
emitcode ("anl", "a,%s",
aopGet (AOP (left), offset, FALSE, FALSE));
}
- aopPut (AOP (result), "a", offset);
+ aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
}
}
}
release:
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (result, NULL, ic, TRUE);
}
emitcode ("jnz", "%05d$", tlbl->key + 100);
if ((AOP_TYPE (result) == AOP_CRY) && ifx)
{
- jmpTrueOrFalse (ifx, tlbl);
+ jmpTrueOrFalse (ifx, tlbl, left, right, result);
goto release;
}
else
outBitC (result);
// if(bit | ...)
else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
- genIfxJump (ifx, "c");
+ genIfxJump (ifx, "c", left, right, result);
goto release;
}
}
else
{
- genIfxJump (ifx, "a");
+ genIfxJump (ifx, "a", left, right, result);
goto release;
}
}
if (AOP_TYPE (right) == AOP_LIT)
{
if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
- continue;
+ {
+ /* dummy read of volatile operand */
+ if (isOperandVolatile (left, FALSE))
+ MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
+ else
+ continue;
+ }
else if (IS_AOP_PREG (left))
{
MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
- aopPut (AOP (result), "a", offset);
+ aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
}
else
emitcode ("orl", "%s,%s",
if (IS_AOP_PREG (left))
{
emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
- aopPut (AOP (result), "a", offset);
+ aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
}
else
emitcode ("orl", "%s,a",
outBitC (result);
}
else if (ifx)
- jmpTrueOrFalse (ifx, tlbl);
+ jmpTrueOrFalse (ifx, tlbl, left, right, result);
+ else
+ emitcode ("", "%05d$:", tlbl->key + 100);
}
else
for (; (size--); offset++)
{
aopPut (AOP (result),
aopGet (AOP (left), offset, FALSE, FALSE),
- offset);
+ offset,
+ isOperandVolatile (result, FALSE));
continue;
}
}
emitcode ("orl", "a,%s",
aopGet (AOP (left), offset, FALSE, FALSE));
}
- aopPut (AOP (result), "a", offset);
+ aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
}
}
release:
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (result, NULL, ic, TRUE);
}
outBitC (result);
// if(bit | ...)
else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
- genIfxJump (ifx, "c");
+ genIfxJump (ifx, "c", left, right, result);
goto release;
}
{
MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
- aopPut (AOP (result), "a", offset);
+ aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
}
else
emitcode ("xrl", "%s,%s",
if (IS_AOP_PREG (left))
{
emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
- aopPut (AOP (result), "a", offset);
+ aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
}
else
emitcode ("xrl", "%s,a",
outBitC (result);
}
else if (ifx)
- jmpTrueOrFalse (ifx, tlbl);
+ jmpTrueOrFalse (ifx, tlbl, left, right, result);
}
else
for (; (size--); offset++)
{
aopPut (AOP (result),
aopGet (AOP (left), offset, FALSE, FALSE),
- offset);
+ offset,
+ isOperandVolatile (result, FALSE));
continue;
}
}
emitcode ("xrl", "a,%s",
aopGet (AOP (left), offset, FALSE, TRUE));
}
- aopPut (AOP (result), "a", offset);
+ aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
}
}
release:
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (result, NULL, ic, TRUE);
}
MOVA (l);
emitcode ("rrc", "a");
if (AOP_SIZE (result) > 1)
- aopPut (AOP (result), "a", offset--);
+ aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
}
/* now we need to put the carry into the
highest order byte of the result */
}
emitcode ("mov", "acc.7,c");
release:
- aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
+ aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
freeAsmop (left, NULL, ic, TRUE);
freeAsmop (result, NULL, ic, TRUE);
}
}
emitcode ("add", "a,acc");
if (AOP_SIZE (result) > 1)
- aopPut (AOP (result), "a", offset++);
+ aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
while (size--)
{
l = aopGet (AOP (left), offset, FALSE, FALSE);
MOVA (l);
emitcode ("rlc", "a");
if (AOP_SIZE (result) > 1)
- aopPut (AOP (result), "a", offset++);
+ aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
}
}
/* now we need to put the carry into the
}
emitcode ("mov", "acc.0,c");
release:
- aopPut (AOP (result), "a", 0);
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
freeAsmop (left, NULL, ic, TRUE);
freeAsmop (result, NULL, ic, TRUE);
}
freeAsmop (result, NULL, ic, TRUE);
}
+/*-----------------------------------------------------------------*/
+/* genSwap - generates code to swap nibbles or bytes */
+/*-----------------------------------------------------------------*/
+static void
+genSwap (iCode * ic)
+{
+ operand *left, *result;
+
+ D(emitcode ("; genSwap",""));
+
+ left = IC_LEFT (ic);
+ result = IC_RESULT (ic);
+ aopOp (left, ic, FALSE);
+ aopOp (result, ic, FALSE);
+
+ switch (AOP_SIZE (left))
+ {
+ case 1: /* swap nibbles in byte */
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+ emitcode ("swap", "a");
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
+ break;
+ case 2: /* swap bytes in word */
+ if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
+ {
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+ aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
+ 0, isOperandVolatile (result, FALSE));
+ aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
+ }
+ else if (operandsEqu (left, result))
+ {
+ char * reg = "a";
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+ if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
+ {
+ emitcode ("mov", "b,a");
+ reg = "b";
+ }
+ aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
+ 0, isOperandVolatile (result, FALSE));
+ aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
+ }
+ else
+ {
+ aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
+ 0, isOperandVolatile (result, FALSE));
+ aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
+ 1, isOperandVolatile (result, FALSE));
+ }
+ break;
+ default:
+ wassertl(FALSE, "unsupported SWAP operand size");
+ }
+
+ freeAsmop (left, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+}
+
+
/*-----------------------------------------------------------------*/
/* AccRol - rotate left accumulator by known count */
/*-----------------------------------------------------------------*/
AccSRsh (shCount);
else
AccRsh (shCount);
- aopPut (AOP (result), "a", offr);
+ aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
}
/*-----------------------------------------------------------------*/
MOVA (l);
/* shift left accumulator */
AccLsh (shCount);
- aopPut (AOP (result), "a", offr);
+ aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
}
/*-----------------------------------------------------------------*/
if (*l == '@' && (IS_AOP_PREG (result)))
{
emitcode ("mov", "a,%s", l);
- aopPut (AOP (result), "a", offr);
+ aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
}
else
{
if (!sign)
- aopPut (AOP (result), l, offr);
+ aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
else
{
/* MSB sign in acc.7 ! */
if (getDataSize (left) == offl + 1)
{
emitcode ("mov", "a,%s", l);
- aopPut (AOP (result), "a", offr);
+ aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
}
}
}
AccAXRrl1 (x); // BCCCCCCD:D000000B
AccAXRrl1 (x); // BBCCCCCC:DD000000
#else
- emitcode("rrc","a");
- emitcode("xch","a,%s", x);
- emitcode("rrc","a");
- emitcode("mov","c,acc.0"); //<< get correct bit
- emitcode("xch","a,%s", x);
-
- emitcode("rrc","a");
- emitcode("xch","a,%s", x);
- emitcode("rrc","a");
- emitcode("xch","a,%s", x);
+ emitcode("rrc","a");
+ emitcode("xch","a,%s", x);
+ emitcode("rrc","a");
+ emitcode("mov","c,acc.0"); //<< get correct bit
+ emitcode("xch","a,%s", x);
+
+ emitcode("rrc","a");
+ emitcode("xch","a,%s", x);
+ emitcode("rrc","a");
+ emitcode("xch","a,%s", x);
#endif
break;
case 7: // a:x <<= 7
}
/* ax << shCount (x = lsb(result)) */
AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
- aopPut (AOP (result), "a", offr + MSB16);
+ aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
}
else
AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
if (getDataSize (result) > 1)
- aopPut (AOP (result), "a", offr + MSB16);
+ aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
}
/*-----------------------------------------------------------------*/
/* or with result */
emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
/* back to result */
- aopPut (AOP (result), "a", offr);
+ aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
}
/*-----------------------------------------------------------------*/
/* or with result */
emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
/* back to result */
- aopPut (AOP (result), "a", offr);
+ aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
}
/*-----------------------------------------------------------------*/
else
movLeft2Result (left, LSB, result, MSB16, 0);
}
- aopPut (AOP (result), zero, LSB);
+ aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
}
/* 1 <= shCount <= 7 */
emitcode ("xch", "a,%s",
aopGet (AOP (left), LSB + offr, FALSE, FALSE));
else
- aopPut (AOP (result), "a", LSB + offr);
+ aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
}
if (size >= MSB16 + offr)
emitcode ("xch", "a,%s",
aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
else
- aopPut (AOP (result), "a", MSB16 + offr);
+ aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
}
if (size >= MSB24 + offr)
emitcode ("xch", "a,%s",
aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
else
- aopPut (AOP (result), "a", MSB24 + offr);
+ aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
}
if (size > MSB32 + offr)
MOVA (l);
}
emitcode ("rlc", "a");
- aopPut (AOP (result), "a", MSB32 + offr);
+ aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
}
if (offr != LSB)
- aopPut (AOP (result), zero, LSB);
+ aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
}
/*-----------------------------------------------------------------*/
shiftL1Left2Result (left, LSB, result, MSB32, shCount);
else
movLeft2Result (left, LSB, result, MSB32, 0);
- aopPut (AOP (result), zero, LSB);
- aopPut (AOP (result), zero, MSB16);
- aopPut (AOP (result), zero, MSB24);
+ aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
+ aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
+ aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
return;
}
movLeft2Result (left, MSB16, result, MSB32, 0);
movLeft2Result (left, LSB, result, MSB24, 0);
}
- aopPut (AOP (result), zero, MSB16);
- aopPut (AOP (result), zero, LSB);
+ aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
+ aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
return;
}
movLeft2Result (left, MSB24, result, MSB32, 0);
movLeft2Result (left, MSB16, result, MSB24, 0);
movLeft2Result (left, LSB, result, MSB16, 0);
- aopPut (AOP (result), zero, LSB);
+ aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
}
else if (shCount == 1)
shiftLLong (left, result, MSB16);
shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
shiftL1Left2Result (left, LSB, result, MSB16, shCount);
shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
- aopPut (AOP (result), zero, LSB);
+ aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
}
}
}
else if (shCount >= (size * 8))
while (size--)
- aopPut (AOP (result), zero, size);
+ aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
else
{
switch (size)
genlshFour (result, left, shCount);
break;
default:
- werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
"*** ack! mystery literal shift!\n");
break;
}
{
emitcode ("mov", "a,%s", l);
- aopPut (AOP (result), "a", offset);
+ aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
}
else
- aopPut (AOP (result), l, offset);
+ aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
offset++;
}
}
emitcode ("add", "a,acc");
emitcode ("", "%05d$:", tlbl1->key + 100);
emitcode ("djnz", "b,%05d$", tlbl->key + 100);
- aopPut (AOP (result), "a", 0);
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
goto release;
}
l = aopGet (AOP (result), offset, FALSE, FALSE);
MOVA (l);
emitcode ("add", "a,acc");
- aopPut (AOP (result), "a", offset++);
+ aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
while (--size)
{
l = aopGet (AOP (result), offset, FALSE, FALSE);
MOVA (l);
emitcode ("rlc", "a");
- aopPut (AOP (result), "a", offset++);
+ aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
}
reAdjustPreg (AOP (result));
}
MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
-
+
if (offl==MSB16) {
// shift is > 8
if (sign) {
if (isSameRegs)
emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
else {
- aopPut (AOP (result), "a", MSB32);
+ aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
}
} else {
- aopPut (AOP(result), zero, MSB32);
+ aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
}
}
if (isSameRegs && offl==MSB16) {
emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
} else {
- aopPut (AOP (result), "a", MSB32-offl);
+ aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
}
if (isSameRegs && offl==1) {
emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
} else {
- aopPut (AOP (result), "a", MSB24-offl);
+ aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
}
emitcode ("rrc", "a");
- aopPut (AOP (result), "a", MSB16 - offl);
+ aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
if (offl == LSB)
{
MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
emitcode ("rrc", "a");
- aopPut (AOP (result), "a", LSB);
+ aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
}
}
{
emitcode ("mov", "a,%s", l);
- aopPut (AOP (result), "a", offset);
+ aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
}
else
- aopPut (AOP (result), l, offset);
+ aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
offset++;
}
}
size = AOP_SIZE (result);
offset = size - 1;
- emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
+ MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
emitcode ("rlc", "a");
emitcode ("mov", "ov,c");
/* if it is only one byte then */
emitcode ("rrc", "a");
emitcode ("", "%05d$:", tlbl1->key + 100);
emitcode ("djnz", "b,%05d$", tlbl->key + 100);
- aopPut (AOP (result), "a", 0);
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
goto release;
}
l = aopGet (AOP (result), offset, FALSE, FALSE);
MOVA (l);
emitcode ("rrc", "a");
- aopPut (AOP (result), "a", offset--);
+ aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
}
reAdjustPreg (AOP (result));
emitcode ("", "%05d$:", tlbl1->key + 100);
genRightShift (iCode * ic)
{
operand *right, *left, *result;
- sym_link *retype;
+ sym_link *letype;
int size, offset;
char *l;
symbol *tlbl, *tlbl1;
/* if signed then we do it the hard way preserve the
sign bit moving it inwards */
- retype = getSpec (operandType (IC_RESULT (ic)));
+ letype = getSpec (operandType (IC_LEFT (ic)));
- if (!SPEC_USIGN (retype))
+ if (!SPEC_USIGN (letype))
{
genSignedRightShift (ic);
return;
{
emitcode ("mov", "a,%s", l);
- aopPut (AOP (result), "a", offset);
+ aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
}
else
- aopPut (AOP (result), l, offset);
+ aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
offset++;
}
}
emitcode ("rrc", "a");
emitcode ("", "%05d$:", tlbl1->key + 100);
emitcode ("djnz", "b,%05d$", tlbl->key + 100);
- aopPut (AOP (result), "a", 0);
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
goto release;
}
l = aopGet (AOP (result), offset, FALSE, FALSE);
MOVA (l);
emitcode ("rrc", "a");
- aopPut (AOP (result), "a", offset--);
+ aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
}
reAdjustPreg (AOP (result));
}
/*-----------------------------------------------------------------*/
-/* genUnpackBits - generates code for unpacking bits */
+/* emitPtrByteGet - emits code to get a byte into A through a */
+/* pointer register (R0, R1, or DPTR). The */
+/* original value of A can be preserved in B. */
/*-----------------------------------------------------------------*/
static void
-genUnpackBits (operand * result, char *rname, int ptype)
+emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
{
- int shCnt;
- int rlen = 0;
- sym_link *etype;
- int offset = 0;
- int rsize;
-
- D(emitcode ("; genUnpackBits",""));
-
- etype = getSpec (operandType (result));
- rsize = getSize (operandType (result));
- /* read the first byte */
- switch (ptype)
+ switch (p_type)
{
-
- case POINTER:
case IPOINTER:
+ case POINTER:
+ if (preserveAinB)
+ emitcode ("mov", "b,a");
emitcode ("mov", "a,@%s", rname);
break;
case PPOINTER:
+ if (preserveAinB)
+ emitcode ("mov", "b,a");
emitcode ("movx", "a,@%s", rname);
break;
case FPOINTER:
+ if (preserveAinB)
+ emitcode ("mov", "b,a");
emitcode ("movx", "a,@dptr");
break;
case CPOINTER:
+ if (preserveAinB)
+ emitcode ("mov", "b,a");
emitcode ("clr", "a");
emitcode ("movc", "a,@a+dptr");
break;
case GPOINTER:
+ if (preserveAinB)
+ {
+ emitcode ("push", "b");
+ emitcode ("push", "acc");
+ }
emitcode ("lcall", "__gptrget");
+ if (preserveAinB)
+ emitcode ("pop", "b");
break;
}
+}
- rlen = SPEC_BLEN (etype);
-
- /* if we have bitdisplacement then it fits */
- /* into this byte completely or if length is */
- /* less than a byte */
- if ((shCnt = SPEC_BSTR (etype)) ||
- (SPEC_BLEN (etype) <= 8))
- {
-
- /* shift right acc */
- AccRsh (shCnt);
-
- emitcode ("anl", "a,#0x%02x",
- ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
- aopPut (AOP (result), "a", offset++);
- goto finish;
- }
-
- /* bit field did not fit in a byte */
- aopPut (AOP (result), "a", offset++);
-
- while (1)
+/*-----------------------------------------------------------------*/
+/* emitPtrByteSet - emits code to set a byte from src through a */
+/* pointer register (R0, R1, or DPTR). */
+/*-----------------------------------------------------------------*/
+static void
+emitPtrByteSet (char *rname, int p_type, char *src)
+{
+ switch (p_type)
{
+ case IPOINTER:
+ case POINTER:
+ if (*src=='@')
+ {
+ MOVA (src);
+ emitcode ("mov", "@%s,a", rname);
+ }
+ else
+ emitcode ("mov", "@%s,%s", rname, src);
+ break;
- switch (ptype)
- {
- case POINTER:
- case IPOINTER:
- emitcode ("inc", "%s", rname);
- emitcode ("mov", "a,@%s", rname);
- break;
+ case PPOINTER:
+ MOVA (src);
+ emitcode ("movx", "@%s,a", rname);
+ break;
- case PPOINTER:
- emitcode ("inc", "%s", rname);
- emitcode ("movx", "a,@%s", rname);
- break;
+ case FPOINTER:
+ MOVA (src);
+ emitcode ("movx", "@dptr,a");
+ break;
- case FPOINTER:
- emitcode ("inc", "dptr");
- emitcode ("movx", "a,@dptr");
- break;
+ case GPOINTER:
+ MOVA (src);
+ emitcode ("lcall", "__gptrput");
+ break;
+ }
+}
- case CPOINTER:
- emitcode ("clr", "a");
- emitcode ("inc", "dptr");
- emitcode ("movc", "a,@a+dptr");
- break;
+/*-----------------------------------------------------------------*/
+/* genUnpackBits - generates code for unpacking bits */
+/*-----------------------------------------------------------------*/
+static void
+genUnpackBits (operand * result, char *rname, int ptype)
+{
+ int offset = 0; /* result byte offset */
+ int rsize; /* result size */
+ int rlen = 0; /* remaining bitfield length */
+ sym_link *etype; /* bitfield type information */
+ int blen; /* bitfield length */
+ int bstr; /* bitfield starting bit within byte */
- case GPOINTER:
- emitcode ("inc", "dptr");
- emitcode ("lcall", "__gptrget");
- break;
- }
+ D(emitcode ("; genUnpackBits",""));
- rlen -= 8;
- /* if we are done */
- if (rlen < 8)
- break;
+ etype = getSpec (operandType (result));
+ rsize = getSize (operandType (result));
+ blen = SPEC_BLEN (etype);
+ bstr = SPEC_BSTR (etype);
- aopPut (AOP (result), "a", offset++);
+ /* If the bitfield length is less than a byte */
+ if (blen < 8)
+ {
+ emitPtrByteGet (rname, ptype, FALSE);
+ AccRsh (bstr);
+ emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
+ aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
+ goto finish;
+ }
+ /* Bit field did not fit in a byte. Copy all
+ but the partial byte at the end. */
+ for (rlen=blen;rlen>=8;rlen-=8)
+ {
+ emitPtrByteGet (rname, ptype, FALSE);
+ aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
+ if (rlen>8)
+ emitcode ("inc", "%s", rname);
}
+ /* Handle the partial byte at the end */
if (rlen)
{
- // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
- AccLsh (8 - rlen);
- aopPut (AOP (result), "a", offset++);
+ emitPtrByteGet (rname, ptype, FALSE);
+ emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
+ aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
}
finish:
{
rsize -= offset;
while (rsize--)
- aopPut (AOP (result), zero, offset++);
+ aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
}
- return;
}
sprintf (buffer, "(%s + %d)", l + 1, offset);
else
sprintf (buffer, "%s", l + 1);
- aopPut (AOP (result), buffer, offset++);
+ aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
}
freeAsmop (left, NULL, ic, TRUE);
aopOp (left, ic, FALSE);
/* if left is rematerialisable and
- result is not bit variable type and
+ result is not bitfield variable type and
the left is pointer to data space i.e
lower 128 bytes of space */
if (AOP_TYPE (left) == AOP_IMMD &&
- !IS_BITVAR (retype) &&
+ !IS_BITFIELD (retype) &&
DCL_TYPE (ltype) == POINTER)
{
genDataPointerGet (left, result, ic);
return;
}
- /* if the value is already in a pointer register
+ /* if the value is already in a pointer register
then don't need anything more */
if (!AOP_INPREG (AOP (left)))
{
- /* otherwise get a free pointer register */
- aop = newAsmop (0);
- preg = getFreePtr (ic, &aop, FALSE);
- emitcode ("mov", "%s,%s",
- preg->name,
- aopGet (AOP (left), 0, FALSE, TRUE));
- rname = preg->name;
+ if (IS_AOP_PREG (left))
+ {
+ // Aha, it is a pointer, just in disguise.
+ rname = aopGet (AOP (left), 0, FALSE, FALSE);
+ if (*rname != '@')
+ {
+ fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
+ __FILE__, __LINE__);
+ }
+ else
+ {
+ // Expected case.
+ emitcode ("mov", "a%s,%s", rname + 1, rname);
+ rname++; // skip the '@'.
+ }
+ }
+ else
+ {
+ /* otherwise get a free pointer register */
+ aop = newAsmop (0);
+ preg = getFreePtr (ic, &aop, FALSE);
+ emitcode ("mov", "%s,%s",
+ preg->name,
+ aopGet (AOP (left), 0, FALSE, TRUE));
+ rname = preg->name;
+ }
}
else
rname = aopGet (AOP (left), 0, FALSE, FALSE);
-
+
//aopOp (result, ic, FALSE);
aopOp (result, ic, result?TRUE:FALSE);
/* if bitfield then unpack the bits */
- if (IS_BITVAR (retype))
+ if (IS_BITFIELD (retype))
genUnpackBits (result, rname, POINTER);
else
{
{
emitcode ("mov", "a,@%s", rname);
- aopPut (AOP (result), "a", offset);
+ aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
}
else
{
sprintf (buffer, "@%s", rname);
- aopPut (AOP (result), buffer, offset);
+ aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
}
offset++;
if (size || pi)
if (aop) /* we had to allocate for this iCode */
{
if (pi) { /* post increment present */
- aopPut(AOP ( left ),rname,0);
+ aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
}
- freeAsmop (NULL, aop, ic, TRUE);
+ freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
}
else
{
}
/* done */
+ freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
freeAsmop (left, NULL, ic, TRUE);
- freeAsmop (result, NULL, ic, TRUE);
if (pi) pi->generated = 1;
}
aopOp (result, ic, FALSE);
/* if bitfield then unpack the bits */
- if (IS_BITVAR (retype))
+ if (IS_BITFIELD (retype))
genUnpackBits (result, rname, PPOINTER);
else
{
{
emitcode ("movx", "a,@%s", rname);
- aopPut (AOP (result), "a", offset);
+ aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
offset++;
/* now some housekeeping stuff */
if (aop) /* we had to allocate for this iCode */
{
- if (pi) aopPut ( AOP (left), rname, 0);
+ if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
freeAsmop (NULL, aop, ic, TRUE);
}
else
}
+/*--------------------------------------------------------------------*/
+/* loadDptrFromOperand - load dptr (and optionally B) from operand op */
+/*--------------------------------------------------------------------*/
+static void
+loadDptrFromOperand (operand *op, bool loadBToo)
+{
+ if (AOP_TYPE (op) != AOP_STR)
+ {
+ /* if this is remateriazable */
+ if (AOP_TYPE (op) == AOP_IMMD)
+ {
+ emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
+ if (loadBToo)
+ {
+ if (AOP(op)->aopu.aop_immd.from_cast_remat)
+ emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
+ else
+ {
+ wassertl(FALSE, "need pointerCode");
+ emitcode ("", "; mov b,???");
+ /* genPointerGet and genPointerSet originally did different
+ ** things for this case. Both seem wrong.
+ ** from genPointerGet:
+ ** emitcode ("mov", "b,#%d", pointerCode (retype));
+ ** from genPointerSet:
+ ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
+ */
+ }
+ }
+ }
+ else if (AOP_TYPE (op) == AOP_DPTR)
+ {
+ if (loadBToo)
+ {
+ MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
+ emitcode ("push", "acc");
+ MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
+ emitcode ("push", "acc");
+ emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
+ emitcode ("pop", "dph");
+ emitcode ("pop", "dpl");
+ }
+ else
+ {
+ MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
+ emitcode ("push", "acc");
+ emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
+ emitcode ("pop", "dpl");
+ }
+ }
+ else
+ { /* we need to get it byte by byte */
+ emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
+ emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
+ if (loadBToo)
+ emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
+ }
+ }
+}
+
/*-----------------------------------------------------------------*/
/* genFarPointerGet - gget value from far space */
/*-----------------------------------------------------------------*/
D(emitcode ("; genFarPointerGet",""));
aopOp (left, ic, FALSE);
+ loadDptrFromOperand (left, FALSE);
- /* if the operand is already in dptr
- then we do nothing else we move the value to dptr */
- if (AOP_TYPE (left) != AOP_STR)
- {
- /* if this is remateriazable */
- if (AOP_TYPE (left) == AOP_IMMD)
- emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
- else
- { /* we need to get it byte by byte */
- emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
- emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
- }
- }
- /* so dptr know contains the address */
+ /* so dptr now contains the address */
aopOp (result, ic, FALSE);
/* if bit then unpack */
- if (IS_BITVAR (retype))
+ if (IS_BITFIELD (retype))
genUnpackBits (result, "dptr", FPOINTER);
else
{
while (size--)
{
emitcode ("movx", "a,@dptr");
- aopPut (AOP (result), "a", offset++);
+ aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
if (size || pi)
emitcode ("inc", "dptr");
}
}
-
+
if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
- aopPut ( AOP (left), "dpl", 0);
- aopPut ( AOP (left), "dph", 1);
+ aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
+ aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
pi->generated = 1;
}
freeAsmop (left, NULL, ic, TRUE);
D(emitcode ("; genCodePointerGet",""));
aopOp (left, ic, FALSE);
+ loadDptrFromOperand (left, FALSE);
- /* if the operand is already in dptr
- then we do nothing else we move the value to dptr */
- if (AOP_TYPE (left) != AOP_STR)
- {
- /* if this is remateriazable */
- if (AOP_TYPE (left) == AOP_IMMD)
- emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
- else
- { /* we need to get it byte by byte */
- emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
- emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
- }
- }
- /* so dptr know contains the address */
+ /* so dptr now contains the address */
aopOp (result, ic, FALSE);
/* if bit then unpack */
- if (IS_BITVAR (retype))
+ if (IS_BITFIELD (retype))
genUnpackBits (result, "dptr", CPOINTER);
else
{
while (size--)
{
- emitcode ("clr", "a");
- emitcode ("movc", "a,@a+dptr");
- aopPut (AOP (result), "a", offset++);
- if (size || pi)
- emitcode ("inc", "dptr");
+ if (pi)
+ {
+ emitcode ("clr", "a");
+ emitcode ("movc", "a,@a+dptr");
+ aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
+ emitcode ("inc", "dptr");
+ }
+ else
+ {
+ emitcode ("mov", "a,#0x%02x", offset);
+ emitcode ("movc", "a,@a+dptr");
+ aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
+ }
}
}
if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
- aopPut ( AOP (left), "dpl", 0);
- aopPut ( AOP (left), "dph", 1);
+ aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
+ aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
pi->generated = 1;
}
freeAsmop (left, NULL, ic, TRUE);
D(emitcode ("; genGenPointerGet",""));
aopOp (left, ic, FALSE);
+ loadDptrFromOperand (left, TRUE);
- /* if the operand is already in dptr
- then we do nothing else we move the value to dptr */
- if (AOP_TYPE (left) != AOP_STR)
- {
- /* if this is remateriazable */
- if (AOP_TYPE (left) == AOP_IMMD)
- {
- emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
- if (AOP(left)->aopu.aop_immd.from_cast_remat)
- emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
- else
- emitcode ("mov", "b,#%d", pointerCode (retype));
- }
- else
- { /* we need to get it byte by byte */
- emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
- emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
- emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
- }
- }
/* so dptr know contains the address */
aopOp (result, ic, FALSE);
/* if bit then unpack */
- if (IS_BITVAR (retype))
+ if (IS_BITFIELD (retype))
genUnpackBits (result, "dptr", GPOINTER);
else
{
while (size--)
{
emitcode ("lcall", "__gptrget");
- aopPut (AOP (result), "a", offset++);
+ aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
if (size || pi)
emitcode ("inc", "dptr");
}
}
if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
- aopPut ( AOP (left), "dpl", 0);
- aopPut ( AOP (left), "dph", 1);
- aopPut ( AOP (left), "b", 2);
+ aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
+ aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
pi->generated = 1;
}
freeAsmop (left, NULL, ic, TRUE);
}
+
+
/*-----------------------------------------------------------------*/
/* genPackBits - generates code for packed bit storage */
/*-----------------------------------------------------------------*/
operand * right,
char *rname, int p_type)
{
- int shCount = 0;
- int offset = 0;
- int rLen = 0;
- int blen, bstr;
- char *l;
+ int offset = 0; /* source byte offset */
+ int rlen = 0; /* remaining bitfield length */
+ int blen; /* bitfield length */
+ int bstr; /* bitfield starting bit within byte */
+ int litval; /* source literal value (if AOP_LIT) */
+ unsigned char mask; /* bitmask within current byte */
D(emitcode ("; genPackBits",""));
blen = SPEC_BLEN (etype);
bstr = SPEC_BSTR (etype);
- l = aopGet (AOP (right), offset++, FALSE, FALSE);
- MOVA (l);
-
- /* if the bit lenth is less than or */
- /* it exactly fits a byte then */
- if (SPEC_BLEN (etype) <= 8)
- {
- shCount = SPEC_BSTR (etype);
-
- /* shift left acc */
- AccLsh (shCount);
-
- if (SPEC_BLEN (etype) < 8)
- { /* if smaller than a byte */
-
-
- switch (p_type)
- {
- case POINTER:
- emitcode ("mov", "b,a");
- emitcode ("mov", "a,@%s", rname);
- break;
-
- case FPOINTER:
- emitcode ("mov", "b,a");
- emitcode ("movx", "a,@dptr");
- break;
-
- case GPOINTER:
- emitcode ("push", "b");
- emitcode ("push", "acc");
- emitcode ("lcall", "__gptrget");
- emitcode ("pop", "b");
- break;
- }
-
- emitcode ("anl", "a,#0x%02x", (unsigned char)
- ((unsigned char) (0xFF << (blen + bstr)) |
- (unsigned char) (0xFF >> (8 - bstr))));
- emitcode ("orl", "a,b");
- if (p_type == GPOINTER)
- emitcode ("pop", "b");
- }
- }
-
- switch (p_type)
+ /* If the bitfield length is less than a byte */
+ if (blen < 8)
{
- case POINTER:
- emitcode ("mov", "@%s,a", rname);
- break;
-
- case FPOINTER:
- emitcode ("movx", "@dptr,a");
- break;
+ mask = ((unsigned char) (0xFF << (blen + bstr)) |
+ (unsigned char) (0xFF >> (8 - bstr)));
- case GPOINTER:
- emitcode ("lcall", "__gptrput");
- break;
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ /* Case with a bitfield length <8 and literal source
+ */
+ litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+ litval <<= bstr;
+ litval &= (~mask) & 0xff;
+ emitPtrByteGet (rname, p_type, FALSE);
+ if ((mask|litval)!=0xff)
+ emitcode ("anl","a,#0x%02x", mask);
+ if (litval)
+ emitcode ("orl","a,#0x%02x", litval);
+ }
+ else
+ {
+ if ((blen==1) && (p_type!=GPOINTER))
+ {
+ /* Case with a bitfield length == 1 and no generic pointer
+ */
+ if (AOP_TYPE (right) == AOP_CRY)
+ emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
+ else
+ {
+ MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
+ emitcode ("rrc","a");
+ }
+ emitPtrByteGet (rname, p_type, FALSE);
+ emitcode ("mov","acc.%d,c",bstr);
+ }
+ else
+ {
+ /* Case with a bitfield length < 8 and arbitrary source
+ */
+ MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
+ /* shift and mask source value */
+ AccLsh (bstr);
+ emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
+
+ /* transfer A to B and get next byte */
+ emitPtrByteGet (rname, p_type, TRUE);
+
+ emitcode ("anl", "a,#0x%02x", mask);
+ emitcode ("orl", "a,b");
+ if (p_type == GPOINTER)
+ emitcode ("pop", "b");
+ }
+ }
+
+ emitPtrByteSet (rname, p_type, "a");
+ return;
}
- /* if we r done */
- if (SPEC_BLEN (etype) <= 8)
- return;
-
- emitcode ("inc", "%s", rname);
- rLen = SPEC_BLEN (etype);
-
- /* now generate for lengths greater than one byte */
- while (1)
+ /* Bit length is greater than 7 bits. In this case, copy */
+ /* all except the partial byte at the end */
+ for (rlen=blen;rlen>=8;rlen-=8)
{
-
- l = aopGet (AOP (right), offset++, FALSE, TRUE);
-
- rLen -= 8;
- if (rLen < 8)
- break;
-
- switch (p_type)
- {
- case POINTER:
- if (*l == '@')
- {
- MOVA (l);
- emitcode ("mov", "@%s,a", rname);
- }
- else
- emitcode ("mov", "@%s,%s", rname, l);
- break;
-
- case FPOINTER:
- MOVA (l);
- emitcode ("movx", "@dptr,a");
- break;
-
- case GPOINTER:
- MOVA (l);
- emitcode ("lcall", "__gptrput");
- break;
- }
- emitcode ("inc", "%s", rname);
+ emitPtrByteSet (rname, p_type,
+ aopGet (AOP (right), offset++, FALSE, TRUE) );
+ if (rlen>8)
+ emitcode ("inc", "%s", rname);
}
- MOVA (l);
-
- /* last last was not complete */
- if (rLen)
+ /* If there was a partial byte at the end */
+ if (rlen)
{
- /* save the byte & read byte */
- switch (p_type)
- {
- case POINTER:
- emitcode ("mov", "b,a");
- emitcode ("mov", "a,@%s", rname);
- break;
+ mask = (((unsigned char) -1 << rlen) & 0xff);
- case FPOINTER:
- emitcode ("mov", "b,a");
- emitcode ("movx", "a,@dptr");
- break;
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ /* Case with partial byte and literal source
+ */
+ litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+ litval >>= (blen-rlen);
+ litval &= (~mask) & 0xff;
+ emitPtrByteGet (rname, p_type, FALSE);
+ if ((mask|litval)!=0xff)
+ emitcode ("anl","a,#0x%02x", mask);
+ if (litval)
+ emitcode ("orl","a,#0x%02x", litval);
+ }
+ else
+ {
+ /* Case with partial byte and arbitrary source
+ */
+ MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
+ emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
- case GPOINTER:
- emitcode ("push", "b");
- emitcode ("push", "acc");
- emitcode ("lcall", "__gptrget");
- emitcode ("pop", "b");
- break;
- }
+ /* transfer A to B and get next byte */
+ emitPtrByteGet (rname, p_type, TRUE);
- emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
- emitcode ("orl", "a,b");
+ emitcode ("anl", "a,#0x%02x", mask);
+ emitcode ("orl", "a,b");
+ if (p_type == GPOINTER)
+ emitcode ("pop", "b");
+ }
+ emitPtrByteSet (rname, p_type, "a");
}
- if (p_type == GPOINTER)
- emitcode ("pop", "b");
-
- switch (p_type)
- {
-
- case POINTER:
- emitcode ("mov", "@%s,a", rname);
- break;
+}
- case FPOINTER:
- emitcode ("movx", "@dptr,a");
- break;
- case GPOINTER:
- emitcode ("lcall", "__gptrput");
- break;
- }
-}
/*-----------------------------------------------------------------*/
/* genDataPointerSet - remat pointer to data space */
/*-----------------------------------------------------------------*/
genDataPointerSet (right, result, ic);
return;
}
-
+
/* if the value is already in a pointer register
then don't need anything more */
if (!AOP_INPREG (AOP (result)))
else
{
// Expected case.
+ emitcode ("mov", "a%s,%s", rname + 1, rname);
rname++; // skip the '@'.
}
}
}
aopOp (right, ic, FALSE);
-
+
/* if bitfield then unpack the bits */
- if (IS_BITVAR (retype) || IS_BITVAR (letype))
- genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
+ if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
+ genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
else
{
/* we have can just get the values */
/* now some housekeeping stuff */
if (aop) /* we had to allocate for this iCode */
{
- if (pi) aopPut (AOP (result),rname,0);
+ if (pi)
+ aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
freeAsmop (NULL, aop, ic, TRUE);
}
else
aopOp (right, ic, FALSE);
/* if bitfield then unpack the bits */
- if (IS_BITVAR (retype) || IS_BITVAR (letype))
- genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
+ if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
+ genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
else
{
/* we have can just get the values */
/* now some housekeeping stuff */
if (aop) /* we had to allocate for this iCode */
{
- if (pi) aopPut (AOP (result),rname,0);
+ if (pi)
+ aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
freeAsmop (NULL, aop, ic, TRUE);
}
else
D(emitcode ("; genFarPointerSet",""));
aopOp (result, ic, FALSE);
+ loadDptrFromOperand (result, FALSE);
- /* if the operand is already in dptr
- then we do nothing else we move the value to dptr */
- if (AOP_TYPE (result) != AOP_STR)
- {
- /* if this is remateriazable */
- if (AOP_TYPE (result) == AOP_IMMD)
- emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
- else
- { /* we need to get it byte by byte */
- emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
- emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
- }
- }
/* so dptr know contains the address */
aopOp (right, ic, FALSE);
/* if bit then unpack */
- if (IS_BITVAR (retype) || IS_BITVAR (letype))
- genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
+ if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
+ genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
else
{
size = AOP_SIZE (right);
}
}
if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
- aopPut (AOP(result),"dpl",0);
- aopPut (AOP(result),"dph",1);
+ aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
+ aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
pi->generated=1;
}
freeAsmop (result, NULL, ic, TRUE);
D(emitcode ("; genGenPointerSet",""));
aopOp (result, ic, FALSE);
+ loadDptrFromOperand (result, TRUE);
- /* if the operand is already in dptr
- then we do nothing else we move the value to dptr */
- if (AOP_TYPE (result) != AOP_STR)
- {
- /* if this is remateriazable */
- if (AOP_TYPE (result) == AOP_IMMD)
- {
- emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
- if (AOP(result)->aopu.aop_immd.from_cast_remat)
- emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
- else
- emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
- }
- else
- { /* we need to get it byte by byte */
- emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
- emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
- emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
- }
- }
/* so dptr know contains the address */
aopOp (right, ic, FALSE);
/* if bit then unpack */
- if (IS_BITVAR (retype) || IS_BITVAR (letype))
- genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
+ if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
+ genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
else
{
size = AOP_SIZE (right);
}
if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
- aopPut (AOP(result),"dpl",0);
- aopPut (AOP(result),"dph",1);
- aopPut (AOP(result),"b",2);
+ aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
+ aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
pi->generated=1;
}
freeAsmop (result, NULL, ic, TRUE);
break;
default:
- werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
"genPointerSet: illegal pointer type");
}
/* if the condition is a bit variable */
if (isbit && IS_ITEMP (cond) &&
SPIL_LOC (cond))
- genIfxJump (ic, SPIL_LOC (cond)->rname);
+ genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
else if (isbit && !IS_ITEMP (cond))
- genIfxJump (ic, OP_SYMBOL (cond)->rname);
+ genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
else
- genIfxJump (ic, "a");
+ genIfxJump (ic, "a", NULL, NULL, NULL);
ic->generated = 1;
}
emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
((char) (sym->stack - _G.nRegsSaved)) :
((char) sym->stack)) & 0xff);
- aopPut (AOP (IC_RESULT (ic)), "a", 0);
+ aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
}
else
{
/* we can just move _bp */
- aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
+ aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
}
/* fill the result with zero */
size = AOP_SIZE (IC_RESULT (ic)) - 1;
offset = 1;
while (size--)
{
- aopPut (AOP (IC_RESULT (ic)), zero, offset++);
+ aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
}
goto release;
offset * 8);
else
sprintf (s, "#%s", sym->rname);
- aopPut (AOP (IC_RESULT (ic)), s, offset++);
+ aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
}
release:
while (size--)
{
emitcode ("pop", "acc");
- aopPut (AOP (result), "a", --offset);
+ aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
}
freeAsmop (result, NULL, ic, FALSE);
right = IC_RIGHT (ic);
/* if they are the same */
- if (operandsEqu (result, right)) {
+ if (operandsEqu (result, right) &&
+ !isOperandVolatile (result, FALSE) &&
+ !isOperandVolatile (right, FALSE))
return;
- }
aopOp (right, ic, FALSE);
aopOp (result, ic, TRUE);
/* if they are the same registers */
- if (sameRegs (AOP (right), AOP (result)))
+ if (sameRegs (AOP (right), AOP (result)) &&
+ !isOperandVolatile (result, FALSE) &&
+ !isOperandVolatile (right, FALSE))
goto release;
/* if the result is a bit */
if (AOP_TYPE (right) == AOP_LIT)
{
if (((int) operandLitValue (right)))
- aopPut (AOP (result), one, 0);
+ aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
else
- aopPut (AOP (result), zero, 0);
+ aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
goto release;
}
if (AOP_TYPE (right) == AOP_CRY)
{
emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
- aopPut (AOP (result), "c", 0);
+ aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
goto release;
}
/* we need to or */
toBoolean (right);
- aopPut (AOP (result), "a", 0);
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
goto release;
}
while (size--)
{
if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
- aopPut (AOP (result), "a", size);
+ aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
else
aopPut (AOP (result),
aopGet (AOP (right), size, FALSE, FALSE),
- size);
+ size,
+ isOperandVolatile (result, FALSE));
}
}
else
{
aopPut (AOP (result),
aopGet (AOP (right), offset, FALSE, FALSE),
- offset);
+ offset,
+ isOperandVolatile (result, FALSE));
offset++;
}
}
aopOp (right, ic, FALSE);
aopOp (result, ic, FALSE);
- /* if the result is a bit */
- if (IS_BITVAR(OP_SYMBOL(result)->type))
+ /* if the result is a bit (and not a bitfield) */
+ // if (AOP_TYPE (result) == AOP_CRY)
+ if (IS_BITVAR (OP_SYMBOL (result)->type)
+ && !IS_BITFIELD (OP_SYMBOL (result)->type) )
{
/* if the right size is a literal then
we know what the value is */
if (AOP_TYPE (right) == AOP_LIT)
{
if (((int) operandLitValue (right)))
- aopPut (AOP (result), one, 0);
+ aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
else
- aopPut (AOP (result), zero, 0);
+ aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
goto release;
}
if (AOP_TYPE (right) == AOP_CRY)
{
emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
- aopPut (AOP (result), "c", 0);
+ aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
goto release;
}
/* we need to or */
toBoolean (right);
- aopPut (AOP (result), "a", 0);
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
goto release;
}
+
/* if they are the same size : or less */
if (AOP_SIZE (result) <= AOP_SIZE (right))
{
{
aopPut (AOP (result),
aopGet (AOP (right), offset, FALSE, FALSE),
- offset);
+ offset,
+ isOperandVolatile (result, FALSE));
offset++;
}
goto release;
{
aopPut (AOP (result),
aopGet (AOP (right), offset, FALSE, FALSE),
- offset);
+ offset,
+ isOperandVolatile (result, FALSE));
offset++;
}
/* the last byte depending on type */
{
int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
char gpValStr[10];
-
+
if (gpVal == -1)
{
// pointerTypeToGPByte will have bitched.
exit(1);
}
-
+
sprintf(gpValStr, "#0x%d", gpVal);
- aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
- }
+ aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
+ }
goto release;
}
{
aopPut (AOP (result),
aopGet (AOP (right), offset, FALSE, FALSE),
- offset);
+ offset,
+ isOperandVolatile (result, FALSE));
offset++;
}
goto release;
{
aopPut (AOP (result),
aopGet (AOP (right), offset, FALSE, FALSE),
- offset);
+ offset,
+ isOperandVolatile (result, FALSE));
offset++;
}
if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
{
while (size--)
- aopPut (AOP (result), zero, offset++);
+ aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
}
else
{
emitcode ("rlc", "a");
emitcode ("subb", "a,acc");
while (size--)
- aopPut (AOP (result), "a", offset++);
+ aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
}
/* we are done hurray !!!! */
* it back after the decrement.
*/
char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
-
+
if (strcmp(rByte, "a"))
{
/* Something is hopelessly wrong */
return 0;
}
emitcode ("dec", "%s", rByte);
- aopPut(AOP(IC_RESULT(ic)), rByte, 0);
+ aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
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));
- emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
+ MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
emitcode ("jnz", "%05d$", lbl->key + 100);
}
else
if (isOperandInFarSpace (IC_RESULT (ic)) &&
(OP_SYMBOL (IC_RESULT (ic))->isspilt ||
IS_TRUE_SYMOP (IC_RESULT (ic)))) {
-
+
+ regs *tempRegs[4];
+ int receivingA = 0;
+ int roffset = 0;
+
+ for (offset = 0; offset<size; offset++)
+ if (!strcmp (fReturn[offset], "a"))
+ receivingA = 1;
+
+ if (!receivingA)
+ {
+ if (size==1 || getTempRegs(tempRegs, size-1, ic))
+ {
+ for (offset = size-1; offset>0; offset--)
+ emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
+ emitcode("mov","a,%s", fReturn[0]);
+ _G.accInUse++;
+ aopOp (IC_RESULT (ic), ic, FALSE);
+ _G.accInUse--;
+ aopPut (AOP (IC_RESULT (ic)), "a", offset,
+ isOperandVolatile (IC_RESULT (ic), FALSE));
+ for (offset = 1; offset<size; offset++)
+ aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
+ isOperandVolatile (IC_RESULT (ic), FALSE));
+ goto release;
+ }
+ }
+ else
+ {
+ if (getTempRegs(tempRegs, size, ic))
+ {
+ for (offset = 0; offset<size; offset++)
+ emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
+ aopOp (IC_RESULT (ic), ic, FALSE);
+ for (offset = 0; offset<size; offset++)
+ aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
+ isOperandVolatile (IC_RESULT (ic), FALSE));
+ goto release;
+ }
+ }
+
offset = fReturnSizeMCS51 - size;
while (size--) {
emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
offset = 0;
while (size--) {
emitcode ("pop", "acc");
- aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+ aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
}
-
+
} else {
_G.accInUse++;
aopOp (IC_RESULT (ic), ic, FALSE);
aopOp (IC_RESULT (ic), ic, FALSE);
rb1off = ic->argreg;
while (size--) {
- aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
+ aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
}
}
+
+release:
freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
}
+/*-----------------------------------------------------------------*/
+/* genDummyRead - generate code for dummy read of volatiles */
+/*-----------------------------------------------------------------*/
+static void
+genDummyRead (iCode * ic)
+{
+ operand *op;
+ int size, offset;
+
+ D(emitcode("; genDummyRead",""));
+
+ op = IC_RIGHT (ic);
+ if (op && IS_SYMOP (op))
+ {
+ aopOp (op, ic, FALSE);
+
+ /* if the result is a bit */
+ if (AOP_TYPE (op) == AOP_CRY)
+ emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
+ else
+ {
+ /* bit variables done */
+ /* general case */
+ size = AOP_SIZE (op);
+ offset = 0;
+ while (size--)
+ {
+ MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
+ offset++;
+ }
+ }
+
+ freeAsmop (op, NULL, ic, TRUE);
+ }
+
+ op = IC_LEFT (ic);
+ if (op && IS_SYMOP (op))
+ {
+ aopOp (op, ic, FALSE);
+
+ /* if the result is a bit */
+ if (AOP_TYPE (op) == AOP_CRY)
+ emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
+ else
+ {
+ /* bit variables done */
+ /* general case */
+ size = AOP_SIZE (op);
+ offset = 0;
+ while (size--)
+ {
+ MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
+ offset++;
+ }
+ }
+
+ freeAsmop (op, NULL, ic, TRUE);
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* genCritical - generate code for start of a critical sequence */
+/*-----------------------------------------------------------------*/
+static void
+genCritical (iCode *ic)
+{
+ symbol *tlbl = newiTempLabel (NULL);
+
+ D(emitcode("; genCritical",""));
+
+ if (IC_RESULT (ic))
+ aopOp (IC_RESULT (ic), ic, TRUE);
+
+ emitcode ("setb", "c");
+ emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
+ emitcode ("clr", "c");
+ emitcode ("", "%05d$:", (tlbl->key + 100));
+
+ if (IC_RESULT (ic))
+ outBitC (IC_RESULT (ic)); /* save old ea in an operand */
+ else
+ emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
+
+ if (IC_RESULT (ic))
+ freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genEndCritical - generate code for end of a critical sequence */
+/*-----------------------------------------------------------------*/
+static void
+genEndCritical (iCode *ic)
+{
+ D(emitcode("; genEndCritical",""));
+
+ if (IC_RIGHT (ic))
+ {
+ aopOp (IC_RIGHT (ic), ic, FALSE);
+ if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
+ {
+ emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
+ emitcode ("mov", "ea,c");
+ }
+ else
+ {
+ MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
+ emitcode ("rrc", "a");
+ emitcode ("mov", "ea,c");
+ }
+ freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
+ }
+ else
+ {
+ emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
+ emitcode ("mov", "ea,c");
+ }
+}
+
/*-----------------------------------------------------------------*/
/* gen51Code - generate code for 8051 based controllers */
/*-----------------------------------------------------------------*/
{
iCode *ic;
int cln = 0;
+ /* int cseq = 0; */
+ _G.currentFunc = NULL;
lineHead = lineCurr = NULL;
/* print the allocation information */
- if (allocInfo)
+ if (allocInfo && currFunc)
printAllocInfo (currFunc, codeOutFile);
/* if debug information required */
if (options.debug && currFunc)
{
- cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
- _G.debugLine = 1;
- if (IS_STATIC (currFunc->etype))
- emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
- else
- emitcode ("", "G$%s$0$0 ==.", currFunc->name);
- _G.debugLine = 0;
+ debugFile->writeFunction (currFunc, lic);
}
/* stack pointer name */
if (options.useXstack)
for (ic = lic; ic; ic = ic->next)
{
+ _G.current_iCode = ic;
if (ic->lineno && cln != ic->lineno)
{
if (options.debug)
{
- _G.debugLine = 1;
- emitcode ("", "C$%s$%d$%d$%d ==.",
- FileBaseName (ic->filename), ic->lineno,
- ic->level, ic->block);
- _G.debugLine = 0;
+ debugFile->writeCLine(ic);
}
if (!options.noCcodeInAsm) {
- emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
+ emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
printCLine(ic->filename, ic->lineno));
}
cln = ic->lineno;
}
+ #if 0
+ if (ic->seqPoint && ic->seqPoint != cseq)
+ {
+ emitcode ("", "; sequence point %d", ic->seqPoint);
+ cseq = ic->seqPoint;
+ }
+ #endif
if (options.iCodeInAsm) {
- emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
+ char regsInUse[80];
+ int i;
+
+ for (i=0; i<8; i++) {
+ sprintf (®sInUse[i],
+ "%c", ic->riu & (1<<i) ? i+'0' : '-');
+ }
+ regsInUse[i]=0;
+ emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
}
/* if the result is marked as
spilt and rematerializable or code for
addSet (&_G.sendSet, ic);
break;
+ case DUMMY_READ_VOLATILE:
+ genDummyRead (ic);
+ break;
+
+ case CRITICAL:
+ genCritical (ic);
+ break;
+
+ case ENDCRITICAL:
+ genEndCritical (ic);
+ break;
+
+ case SWAP:
+ genSwap (ic);
+ break;
+
default:
ic = ic;
}
}
+ _G.current_iCode = NULL;
/* now we are ready to call the
peep hole optimizer */