}
else
{
- emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
- emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
+ /* Swapping register contents within register pair */
+ if(!strcmp(aopGet (aop, offset, FALSE), _pairs[pairId].h))
+ {
+ emit2 ("ld a,%s",aopGet (aop, offset + 1, FALSE));
+ emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
+ emit2 ("ld %s,a", _pairs[pairId].h);
+ }
+ else
+ {
+ emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
+ emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
+ }
}
/* PENDING: check? */
if (pairId == PAIR_HL)
setupToPreserveCarry (ic);
- while (size--)
+ /* This is ugly, but it fixes the worst code generation bug on Z80. */
+ /* Probably something similar has to be done for addition of larger numbers, too. */
+ if(size == 2)
{
- if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
+ _moveA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
+ emit2 ("add a,%s", aopGet (AOP (IC_RIGHT (ic)), 0, FALSE));
+ if(strcmp (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), aopGet (AOP (IC_LEFT (ic)), 1, FALSE)))
{
- _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
- if (offset == 0)
- emit2 ("add a,%s",
- aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
- else
- emit2 ("adc a,%s",
- aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+ aopPut (AOP (IC_RESULT (ic)), "a", 0);
+ _moveA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE));
}
else
{
- _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
- if (offset == 0)
- emit2 ("add a,%s",
- aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+ emitDebug ("; Addition result is in same register as operand of next addition.");
+ if(strchr (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), 'c') ||
+ strchr (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), 'b') )
+ {
+ emit2 ("push de");
+ emit2 ("ld e, a");
+ emit2 ("ld a, %s", aopGet (AOP (IC_LEFT (ic)), 1, FALSE));
+ emit2 ("ld d, a");
+ emit2 ("ld a, e");
+ emit2 ("ld %s, a", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
+ emit2 ("ld a, d");
+ emit2 ("pop de");
+ }
else
- emit2 ("adc a,%s",
- aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+ {
+ emit2 ("push bc");
+ emit2 ("ld c, a");
+ emit2 ("ld a, %s", aopGet (AOP (IC_LEFT (ic)), 1, FALSE));
+ emit2 ("ld b, a");
+ emit2 ("ld a, c");
+ emit2 ("ld %s, a", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
+ emit2 ("ld a, b");
+ emit2 ("pop bc");
+ }
+
}
+ emit2 ("adc a,%s", aopGet (AOP (IC_RIGHT (ic)), 1, FALSE));
+ aopPut (AOP (IC_RESULT (ic)), "a", 1);
+ goto release;
+ }
+
+ while (size--)
+ {
+ _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
+ if (offset == 0)
+ emit2 ("add a,%s", aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+ else
+ emit2 ("adc a,%s", aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
aopPut (AOP (IC_RESULT (ic)), "a", offset++);
}
_G.stack.pushedDE = TRUE;
}
- if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic)))))
+ if (byteResult)
+ emit2 ("ld a,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE));
+ else if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic)))))
{
emit2 ("ld e,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE));
if (!byteResult)
i = val;
- /* Fully unroled version of mul.s. Not the most efficient.
- */
for (count = 0; count < 16; count++)
{
if (count != 0 && active)
{
- emit2 ("add hl,hl");
+ if (byteResult)
+ emit2 ("add a,a");
+ else
+ emit2 ("add hl,hl");
}
if (i & 0x8000U)
{
if (active == FALSE)
{
- emit2 ("ld l,e");
- if (!byteResult)
- emit2 ("ld h,d");
+ if (byteResult)
+ emit2("ld e,a");
+ else
+ {
+ emit2 ("ld l,e");
+ emit2 ("ld h,d");
+ }
}
else
{
- emit2 ("add hl,de");
+ if (byteResult)
+ emit2 ("add a,e");
+ else
+ emit2 ("add hl,de");
}
active = TRUE;
}
}
if (byteResult)
- aopPut (AOP (IC_RESULT (ic)), _pairs[PAIR_HL].l, 0);
+ aopPut (AOP (IC_RESULT (ic)), "a", 0);
else
commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
operand * result, int offr, int shCount)
{
const char *l;
- l = aopGet (AOP (left), offl, FALSE);
- _moveA (l);
- /* shift left accumulator */
- AccLsh (shCount);
- aopPut (AOP (result), "a", offr);
-}
+ /* If operand and result are the same we can shift in place.
+ However shifting in acc using add is cheaper than shifting
+ in place using sla; when shifting by more than 2 shifting in
+ acc is worth the additional effort for loading from/to acc. */
+ if (sameRegs (AOP (left), AOP (result)) && shCount <= 2 && offr == offl)
+ {
+ while (shCount--)
+ emit2 ("sla %s", aopGet (AOP (result), 0, FALSE));
+ }
+ else
+ {
+ l = aopGet (AOP (left), offl, FALSE);
+ _moveA (l);
+ /* shift left accumulator */
+ AccLsh (shCount);
+ aopPut (AOP (result), "a", offr);
+ }
+}
/*-----------------------------------------------------------------*/
/* genlshTwo - left shift two bytes by known amount */
}
if (options.iCodeInAsm)
{
- char *iLine = printILine(ic);
+ const char *iLine = printILine(ic);
emit2 (";ic:%d: %s", ic->key, iLine);
dbuf_free(iLine);
}