+}
+
+static void
+fetchPair (PAIR_ID pairId, asmop * aop)
+{
+ fetchPairLong (pairId, aop, 0);
+}
+
+static void
+fetchHL (asmop * aop)
+{
+ fetchPair (PAIR_HL, aop);
+}
+
+static void
+setupPairFromSP (PAIR_ID id, int offset)
+{
+ wassertl (id == PAIR_HL, "Setup relative to SP only implemented for HL");
+
+ if (offset < INT8MIN || offset > INT8MAX)
+ {
+ emit2 ("ld hl,!immedword", offset);
+ emit2 ("add hl,sp");
+ }
+ else
+ {
+ emit2 ("!ldahlsp", offset);
+ }
+}
+
+static void
+setupPair (PAIR_ID pairId, asmop * aop, int offset)
+{
+ switch (aop->type)
+ {
+ case AOP_IY:
+ wassertl (pairId == PAIR_IY || pairId == PAIR_HL, "AOP_IY must be in IY or HL");
+ fetchLitPair (pairId, aop, 0);
+ break;
+
+ case AOP_HL:
+ wassertl (pairId == PAIR_HL, "AOP_HL must be in HL");
+
+ fetchLitPair (pairId, aop, offset);
+ _G.pairs[pairId].offset = offset;
+ break;
+
+ case AOP_EXSTK:
+ wassertl (IS_Z80, "Only the Z80 has an extended stack");
+ wassertl (pairId == PAIR_IY || pairId == PAIR_HL, "The Z80 extended stack must be in IY or HL");
+
+ {
+ int offset = aop->aopu.aop_stk + _G.stack.offset;
+
+ if (_G.pairs[pairId].last_type == aop->type &&
+ _G.pairs[pairId].offset == offset)
+ {
+ /* Already setup */
+ }
+ else
+ {
+ /* PENDING: Do this better. */
+ sprintf (buffer, "%d", offset + _G.stack.pushed);
+ emit2 ("ld %s,!hashedstr", _pairs[pairId].name, buffer);
+ emit2 ("add %s,sp", _pairs[pairId].name);
+ _G.pairs[pairId].last_type = aop->type;
+ _G.pairs[pairId].offset = offset;
+ }
+ }
+ break;
+
+ case AOP_STK:
+ {
+ /* Doesnt include _G.stack.pushed */
+ int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
+ if (aop->aopu.aop_stk > 0)
+ {
+ abso += _G.stack.param_offset;
+ }
+ assert (pairId == PAIR_HL);
+ /* In some cases we can still inc or dec hl */
+ if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
+ {
+ adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
+ }
+ else
+ {
+ setupPairFromSP (PAIR_HL, abso + _G.stack.pushed);
+ }
+ _G.pairs[pairId].offset = abso;
+ break;
+ }
+
+ case AOP_PAIRPTR:
+ adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, offset);
+ break;
+
+ default:
+ wassert (0);
+ }
+ _G.pairs[pairId].last_type = aop->type;
+}
+
+static void
+emitLabel (int key)
+{
+ emit2 ("!tlabeldef", key);
+ spillCached ();