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)
+ {
+ 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);
+ 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--)
/* if critical function then turn interrupts off */
if (IFFUNC_ISCRITICAL (ftype))
{
- emitcode ("mov", "c,ea");
+ 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 */
- emitcode ("clr", "ea");
}
}
genPlus (iCode * ic)
{
int size, offset = 0;
- char *add;
+ int skip_bytes = 0;
+ char *add = "add";
asmop *leftOp, *rightOp;
+ operand * op;
/* special cases :- */
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++, isOperandVolatile (IC_RESULT (ic), FALSE));
- add = "addc"; /* further adds must propagate carry */
+ offset++;
}
adjustArithmeticResult (ic);
// 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));
+
+ 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));
+ }
+
emitcode ("mul", "ab");
aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
if (size==2) {
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);
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 (ifx)
jmpTrueOrFalse (ifx, tlbl);
+ else
+ emitcode ("", "%05d$:", tlbl->key + 100);
goto release;
}
}
}
else if (ifx)
jmpTrueOrFalse (ifx, tlbl);
+ else
+ emitcode ("", "%05d$:", tlbl->key + 100);
}
else
{
}
else if (ifx)
jmpTrueOrFalse (ifx, tlbl);
+ else
+ emitcode ("", "%05d$:", tlbl->key + 100);
}
else
for (; (size--); offset++)
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 */
/*-----------------------------------------------------------------*/
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;
static void
genDummyRead (iCode * ic)
{
- operand *right;
+ operand *op;
int size, offset;
D(emitcode("; genDummyRead",""));
- right = IC_RIGHT (ic);
+ op = IC_RIGHT (ic);
+ if (op && IS_SYMOP (op))
+ {
+ aopOp (op, ic, FALSE);
- aopOp (right, 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++;
+ }
+ }
- /* if the result is a bit */
- if (AOP_TYPE (right) == AOP_CRY)
- {
- emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
- goto release;
+ freeAsmop (op, NULL, ic, TRUE);
}
- /* bit variables done */
- /* general case */
- size = AOP_SIZE (right);
- offset = 0;
- while (size--)
+ op = IC_LEFT (ic);
+ if (op && IS_SYMOP (op))
{
- MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
- offset++;
+ 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);
}
+}
-release:
- freeAsmop (right, 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 */
/*-----------------------------------------------------------------*/
genDummyRead (ic);
break;
+ case CRITICAL:
+ genCritical (ic);
+ break;
+
+ case ENDCRITICAL:
+ genEndCritical (ic);
+ break;
+
+ case SWAP:
+ genSwap (ic);
+ break;
+
default:
ic = ic;
}