break;
}
}
- else if (aop->type == AOP_STR)
+ else if (aop->type == AOP_STR || aop->type == AOP_HLREG)
{
switch (*aop->aopu.aop_str[0])
{
return PAIR_HL;
}
}
- if (aop->type == AOP_STR)
+ if (aop->type == AOP_STR || aop->type == AOP_HLREG)
{
if (!strcmp (aop->aopu.aop_str[0], "c") && !strcmp (aop->aopu.aop_str[1], "b"))
{
aop->aopu.aop_str[0] = _pairs[PAIR_AF].h;
}
- else if (sym->accuse == ACCUSE_HL)
+ else if (sym->accuse == ACCUSE_SCRATCH)
{
- wassert (!IS_GB);
aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
aop->size = getSize (sym->type);
wassertl(aop->size <= 2, "Internal error: Caching in HL, but too big to fit in HL");
case AOP_HL:
case AOP_STK:
case AOP_EXSTK:
+ case AOP_HLREG:
return TRUE;
default:
return FALSE;
operand * result, int offr, int sign)
{
const char *l;
+
if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
{
l = aopGet (AOP (left), offl, FALSE);
}
}
+static void
+movLeft2ResultLong (operand * left, int offl,
+ operand * result, int offr, int sign,
+ int size)
+{
+ if (size == 1)
+ {
+ movLeft2Result (left, offl, result, offr, sign);
+ }
+ else
+ {
+ wassertl (offl == 0 && offr == 0, "Only implemented for zero offset");
+ wassertl (size == 2, "Only implemented for two bytes or one");
+
+ if ( IS_GB && requiresHL ( AOP (left)) && getPairId ( AOP (result)) == PAIR_HL)
+ {
+ emit2 ("ld a,%s", aopGet (AOP (left), LSB, FALSE));
+ emit2 ("ld h,%s", aopGet (AOP (left), MSB16, FALSE));
+ emit2 ("ld l,a");
+ }
+ else
+ {
+ movLeft2Result (left, offl, result, offr, sign);
+ movLeft2Result (left, offl+1, result, offr+1, sign);
+ }
+ }
+}
/** Put Acc into a register set
*/
}
}
+/** Simple restore that doesn't take into account what is used in the
+ return.
+*/
+static void
+_restoreRegsAfterCall(void)
+{
+ if (_G.stack.pushedDE)
+ {
+ _pop ( PAIR_DE);
+ _G.stack.pushedDE = FALSE;
+ }
+ if (_G.stack.pushedBC)
+ {
+ _pop ( PAIR_BC);
+ _G.stack.pushedBC = FALSE;
+ }
+ _G.saves.saved = FALSE;
+}
+
static void
_saveRegsForCall(iCode *ic, int sendSetSize)
{
{
if (isLitWord (AOP (IC_LEFT (ic))))
{
- fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
+ fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
return TRUE;
}
if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
{
if (icount > 2)
return FALSE;
- movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
- movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
+ movLeft2ResultLong (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0, 2);
}
while (icount--)
{
/* If result is a pair */
if (isPair (AOP (IC_RESULT (ic))))
{
- movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
- movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
+ movLeft2ResultLong (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0, 2);
while (icount--)
emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
return TRUE;
emit2 ("ld a,%s", _pairs[left].h);
emit2 ("sbc a,%s", _pairs[right].h);
- aopPut (AOP (IC_RESULT (ic)), "a", 1);
+ if ( AOP_SIZE (IC_RESULT (ic)) > 1)
+ {
+ aopPut (AOP (IC_RESULT (ic)), "a", 1);
+ }
aopPut (AOP (IC_RESULT (ic)), "e", 0);
goto release;
}
aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
- if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
- {
- /* Emit the support function call and the destination address. */
- emit2("call __initrleblock");
- emit2(".dw %s", aopGetWord (AOP(IC_LEFT(ic)), 0));
- }
- else
- {
- wassertl (0, "Unexpected operand to genArrayInit.\n");
- }
+ _saveRegsForCall(ic, 0);
+
+ fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
+ emit2 ("call __initrleblock");
type = operandType(IC_LEFT(ic));
/* Mark the end of the run. */
emit2(".db 0");
+ _restoreRegsAfterCall();
+
+ spillCached ();
+
freeAsmop (IC_LEFT(ic), NULL, ic);
}
break;
case ARRAYINIT:
+ emitDebug ("; genArrayInit");
genArrayInit(ic);
break;
D_ALLOC = 0,
D_ALLOC2 = 0,
D_ACCUSE2 = 0,
- D_ACCUSE2_VERBOSE = 0
+ D_ACCUSE2_VERBOSE = 0,
+ D_HLUSE = 0
};
#if 1
{
iCode *uic;
- if (IS_GB)
- return;
-
/* has only one definition */
if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
- return;
+ {
+ D (D_HLUSE, (" + Dropping as has more than one def\n"));
+ return;
+ }
/* has only one use */
if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
- return;
+ {
+ D (D_HLUSE, (" + Dropping as has more than one use\n"));
+ return;
+ }
/* and the usage immediately follows this iCode */
if (!(uic = hTabItemWithKey (iCodehTab,
bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
- return;
+ {
+ D (D_HLUSE, (" + Dropping as usage isn't in this block\n"));
+ return;
+ }
if (ic->next != uic)
- return;
+ {
+ D (D_HLUSE, (" + Dropping as usage doesn't follow this\n"));
+ return;
+ }
- if (ic->op == CAST && uic->op == IPUSH)
- goto hluse;
- if (ic->op == ADDRESS_OF && uic->op == IPUSH)
- goto hluse;
- if (ic->op == CALL && ic->parmBytes == 0 && (uic->op == '-' || uic->op == '+'))
- goto hluse;
+ if (IS_Z80)
+ {
+ if (ic->op == CAST && uic->op == IPUSH)
+ goto hluse;
+ if (ic->op == ADDRESS_OF && uic->op == IPUSH)
+ goto hluse;
+ if (ic->op == CALL && ic->parmBytes == 0 && (uic->op == '-' || uic->op == '+'))
+ goto hluse;
+ }
+ else if (IS_GB)
+ {
+ /* Case of assign a constant to offset in a static array. */
+ if (ic->op == '+' && IS_VALOP (IC_RIGHT (ic)))
+ {
+ if (uic->op == '=' && POINTER_SET (uic))
+ {
+ goto hluse;
+ }
+ else if (uic->op == IPUSH)
+ {
+ goto hluse;
+ }
+ }
+ }
+
+ D (D_HLUSE, (" + Dropping as it's a bad op\n"));
return;
hluse:
- OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_HL;
+ OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_SCRATCH;
}
static bool
}
}
+/** Joins together two byte constant pushes into one word push.
+ */
+static iCode *
+joinPushes (iCode *lic)
+{
+ iCode *ic, *uic;
+
+ for (ic = lic; ic; ic = ic->next)
+ {
+ int first, second;
+ value *val;
+
+ uic = ic->next;
+
+ /* Anything past this? */
+ if (uic == NULL)
+ {
+ continue;
+ }
+ /* This and the next pushes? */
+ if (ic->op != IPUSH || uic->op != IPUSH)
+ {
+ continue;
+ }
+ /* Both literals? */
+ if ( !IS_OP_LITERAL (IC_LEFT (ic)) || !IS_OP_LITERAL (IC_LEFT (uic)))
+ {
+ continue;
+ }
+ /* Both characters? */
+ if ( getSize (operandType (IC_LEFT (ic))) != 1 || getSize (operandType (IC_LEFT (uic))) != 1)
+ {
+ continue;
+ }
+ /* Pull out the values, make a new type, and create the new iCode for it.
+ */
+ first = (int)operandLitValue ( IC_LEFT (ic));
+ second = (int)operandLitValue ( IC_LEFT (uic));
+
+ sprintf (buffer, "%u", ((first << 8) | (second & 0xFF)) & 0xFFFFU);
+ val = constVal (buffer);
+ SPEC_NOUN (val->type) = V_INT;
+ IC_LEFT (ic)->operand.valOperand = val;
+
+ /* Now remove the second one from the list. */
+ ic->next = uic->next;
+ if (uic->next)
+ {
+ /* Patch up the reverse link */
+ uic->next->prev = ic;
+ }
+ }
+
+ return lic;
+}
+
/*-----------------------------------------------------------------*/
/* assignRegisters - assigns registers to each live range as need */
/*-----------------------------------------------------------------*/
/* now get back the chain */
ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
+ ic = joinPushes (ic);
+
/* redo that offsets for stacked automatic variables */
redoStackOffsets ();