(IC_RESULT(x) && IC_RESULT(x)->aop && \
IC_RESULT(x)->aop->type == AOP_STK )
-#define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
+#define MOVA(x) mova(x) /* use function to avoid multiple eval */
#define CLRC emitcode("clr","c")
#define SETC emitcode("setb","c")
va_end (ap);
}
+/*-----------------------------------------------------------------*/
+/* mova - moves specified value into accumulator */
+/*-----------------------------------------------------------------*/
+static void
+mova (char *x)
+{
+ /* do some early peephole optimization */
+ if (!strcmp(x, "a") || !strcmp(x, "acc"))
+ return;
+
+ emitcode("mov","a,%s", x);
+}
+
/*-----------------------------------------------------------------*/
/* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
/*-----------------------------------------------------------------*/
}
}
+/*-----------------------------------------------------------------*/
+/* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
+/* clobber the accumulator */
+/*-----------------------------------------------------------------*/
+static bool
+aopGetUsesAcc (asmop *aop, int offset)
+{
+ if (offset > (aop->size - 1))
+ return FALSE;
+
+ switch (aop->type)
+ {
+
+ case AOP_R0:
+ case AOP_R1:
+ if (aop->paged)
+ return TRUE;
+ return FALSE;
+ case AOP_DPTR:
+ return TRUE;
+ case AOP_IMMD:
+ return FALSE;
+ case AOP_DIR:
+ return FALSE;
+ case AOP_REG:
+ wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
+ return FALSE;
+ case AOP_CRY:
+ return TRUE;
+ case AOP_ACC:
+ return TRUE;
+ case AOP_LIT:
+ return FALSE;
+ case AOP_STR:
+ if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
+ return TRUE;
+ return FALSE;
+ default:
+ /* Error case --- will have been caught already */
+ wassert(0);
+ return FALSE;
+ }
+}
+
+
/*-----------------------------------------------------------------*/
/* aopGet - for fetching value of the aop */
/*-----------------------------------------------------------------*/
genPlus (iCode * ic)
{
int size, offset = 0;
+ char *add;
+ asmop *leftOp, *rightOp;
/* special cases :- */
size = getDataSize (IC_RESULT (ic));
+ leftOp = AOP(IC_LEFT(ic));
+ rightOp = AOP(IC_RIGHT(ic));
+ add = "add";
+
while (size--)
{
- if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
+ if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
{
- MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
- if (offset == 0)
- emitcode ("add", "a,%s",
- aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
- else
- emitcode ("addc", "a,%s",
- aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
+ 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 (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
- if (offset == 0)
- emitcode ("add", "a,%s",
- aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
- else
- emitcode ("addc", "a,%s",
- aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
+ MOVA (aopGet (rightOp, offset, FALSE, TRUE));
+ emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
}
aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+ add = "addc"; /* further adds must propagate carry */
}
adjustArithmeticResult (ic);
genMinus (iCode * ic)
{
int size, offset = 0;
- unsigned long lit = 0L;
D(emitcode (";", "genMinus"));
size = getDataSize (IC_RESULT (ic));
- if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
- {
- CLRC;
- }
- else
+ /* if literal, add a,#-lit, else normal subb */
+ if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
{
+ unsigned long lit = 0L;
+
lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
lit = -(long) lit;
- }
- /* if literal, add a,#-lit, else normal subb */
- while (size--)
- {
- MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
- if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
- emitcode ("subb", "a,%s",
- aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
- else
+ while (size--)
{
+ MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
/* first add without previous c */
if (!offset) {
if (!size && lit==-1) {
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++);
}
+ else
+ {
+ asmop *leftOp, *rightOp;
+
+ leftOp = AOP(IC_LEFT(ic));
+ rightOp = AOP(IC_RIGHT(ic));
+
+ while (size--)
+ {
+ if (aopGetUsesAcc(rightOp, offset)) {
+ wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
+ MOVA (aopGet(rightOp, offset, FALSE, TRUE));
+ if (offset > 0) {
+ emitcode( "cpl", "c");
+ } else {
+ emitcode( "setb", "c");
+ }
+ emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
+ emitcode("cpl", "a");
+ } else {
+ MOVA (aopGet (leftOp, offset, FALSE, FALSE));
+ if (offset == 0)
+ CLRC;
+ emitcode ("subb", "a,%s",
+ aopGet(rightOp, offset, FALSE, TRUE));
+ }
+ aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+ }
+ }
+
+
adjustArithmeticResult (ic);
release:
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");
genlshFour (result, left, shCount);
break;
default:
- fprintf(stderr, "*** ack! mystery literal shift!\n");
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "*** ack! mystery literal shift!\n");
break;
}
}
if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
- type = type = operandType (left);
+ type = operandType (left);
p_type = DCL_TYPE (type);
}
/* now that we have the pointer type we assign
if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
- type = type = operandType (result);
+ type = operandType (result);
p_type = DCL_TYPE (type);
}
/* now that we have the pointer type we assign
/* pointer to generic pointer */
if (IS_GENPTR (ctype))
{
- char *l = zero;
-
if (IS_PTR (type))
p_type = DCL_TYPE (type);
else
offset++;
}
/* the last byte depending on type */
- switch (p_type)
{
- case IPOINTER:
- case POINTER:
- l = zero;
- break;
- case FPOINTER:
- l = one;
- break;
- case CPOINTER:
- l = "#0x02";
- break;
- case GPOINTER:
- l = "0x03";
- break;
- case PPOINTER: // what the fck is this?
- l = "#0x03";
- break;
-
- default:
- /* this should never happen */
- werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- "got unknown pointer type");
- exit (1);
- }
- aopPut (AOP (result), l, GPTRSIZE - 1);
+ 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);
+ }
goto release;
}