_vemit2 (const char *szFormat, va_list ap)
{
struct dbuf_s dbuf;
- const char *buffer;
+ char *buffer;
dbuf_init(&dbuf, INITIAL_INLINEASM);
dbuf_tvprintf (&dbuf, szFormat, ap);
- buffer = dbuf_c_str(&dbuf);
+ buffer = (char *)dbuf_c_str(&dbuf);
- _tidyUp ((char *)buffer);
+ _tidyUp (buffer);
_G.lines.current = (_G.lines.current ?
connectLine (_G.lines.current, _newLineNode (buffer)) :
(_G.lines.head = _newLineNode (buffer)));
static void
emitDebug (const char *szFormat,...)
{
+ if (!options.verboseAsm)
+ return;
if (!DISABLE_DEBUG)
{
va_list ap;
}
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)
case AOP_PAIRPTR:
setupPair (aop->aopu.aop_pairId, aop, offset);
if (aop->aopu.aop_pairId==PAIR_IX)
- SNPRINTF (buffer, sizeof(buffer),
- "!*ixx", 0);
+ tsprintf (buffer, sizeof(buffer), "!*ixx", offset);
else if (aop->aopu.aop_pairId==PAIR_IY)
- SNPRINTF (buffer, sizeof(buffer),
- "!*iyx", 0);
+ tsprintf (buffer, sizeof(buffer), "!*iyx", offset);
else
SNPRINTF (buffer, sizeof(buffer),
"(%s)", _pairs[aop->aopu.aop_pairId].name);
aopPut (AOP (oper), _fReturn[size], size-1);
size--;
}
- while (size--)
+ while(size--)
{
aopPut (AOP (oper), _fReturn[size], size);
}
/* Mark the registers as restored. */
_G.saves.saved = FALSE;
- /* if we need assign a result value */
- if ((IS_ITEMP (IC_RESULT (ic)) &&
- (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
- OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
- IS_TRUE_SYMOP (IC_RESULT (ic)))
- {
- aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
-
- assignResultValue (IC_RESULT (ic));
-
- freeAsmop (IC_RESULT (ic), NULL, ic);
- }
-
/* adjust the stack for parameters if required */
if (ic->parmBytes)
{
}
}
+ /* if we need assign a result value */
+ if ((IS_ITEMP (IC_RESULT (ic)) &&
+ (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
+ OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
+ IS_TRUE_SYMOP (IC_RESULT (ic)))
+ {
+ aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
+
+ assignResultValue (IC_RESULT (ic));
+
+ freeAsmop (IC_RESULT (ic), NULL, ic);
+ }
+
spillCached ();
if (IC_RESULT (ic))
{
else if (sym->stack && IS_GB && sym->stack > -INT8MIN)
emit2 ("!enterxl", sym->stack);
else if (sym->stack)
- emit2 ("!enterx", sym->stack);
+ {
+ if ((optimize.codeSize && sym->stack <= 8) || sym->stack <= 4)
+ {
+ int stack = sym->stack;
+ emit2 ("!enter");
+ while (stack > 1)
+ {
+ emit2 ("push af");
+ stack -= 2;
+ }
+ if(stack > 0)
+ emit2 ("dec sp");
+ }
+ else
+ emit2 ("!enterx", sym->stack);
+ }
else
emit2 ("!enter");
{
fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
- spillCached();
+ spillPair (PAIR_HL);
+ commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
+ goto release;
+ }
+
+ if (isPair (AOP (IC_LEFT (ic))) && AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT && getPairId (AOP (IC_LEFT (ic))) != PAIR_HL)
+ {
+ fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
+ emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
+ spillPair (PAIR_HL);
commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
goto release;
}
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++);
}
{
/* first add without previous c */
if (!offset)
- emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
+ {
+ if (size == 0 && (unsigned int) (lit & 0x0FFL) == 0xFF)
+ emit2 ("dec a");
+ else
+ emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
+ }
else
emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
}
_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;
}
i <<= 1;
}
- spillCached();
+ spillPair(PAIR_HL);
if (IS_Z80 && _G.stack.pushedDE)
{
}
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);
letype = getSpec (operandType (left));
retype = getSpec (operandType (right));
sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
- /* assign the amsops */
+ /* assign the asmops */
aopOp (left, ic, FALSE, FALSE);
aopOp (right, ic, FALSE, FALSE);
aopOp (result, ic, TRUE, FALSE);
+ setupToPreserveCarry (ic);
+
genCmp (right, left, result, ifx, sign);
+ _G.preserveCarry = FALSE;
freeAsmop (left, NULL, ic);
freeAsmop (right, NULL, ic);
freeAsmop (result, NULL, ic);
retype = getSpec (operandType (right));
sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
- /* assign the amsops */
+ /* assign the asmops */
aopOp (left, ic, FALSE, FALSE);
aopOp (right, ic, FALSE, FALSE);
aopOp (result, ic, TRUE, FALSE);
+ setupToPreserveCarry (ic);
+
genCmp (left, right, result, ifx, sign);
+ _G.preserveCarry = FALSE;
freeAsmop (left, NULL, ic);
freeAsmop (right, NULL, ic);
freeAsmop (result, NULL, ic);
{
if (sym->onStack)
{
- spillCached ();
+ spillPair (PAIR_HL);
if (sym->stack <= 0)
{
setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset);
}
else
{
- spillCached ();
+ spillPair (PAIR_HL);
if (sym->onStack)
{
/* if it has an offset then we need to compute it */
emit2 ("ld e,%s", l);
emit2 ("ld d,!zero");
jtab = newiTempLabel (NULL);
- spillCached ();
+ spillPair (PAIR_HL);
emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
emit2 ("add hl,de");
emit2 ("add hl,de");
else
{
/* we need to extend the sign :{ */
- const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
- FALSE);
+ const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1, FALSE);
_moveA (l);
emit2 ("rla ");
emit2 ("sbc a,a");
//disable interrupt
emit2 ("!di");
//save P/O flag
- emit2 ("push af");
+ _push (PAIR_AF);
}
}
else
{
//restore P/O flag
- emit2 ("pop af");
+ _pop (PAIR_AF);
//parity odd <==> P/O=0 <==> interrupt enable flag IFF2 was 0 <==>
//don't enable interrupts as they were off before
emit2 ("jp PO,!tlabel", tlbl->key + 100);