* src/z80/gen.c (genCmp): Fixed compare on unsigned.
[fw/sdcc] / src / z80 / gen.c
index 6bffec3cca9439c1da0ba5f1bc9f4dd5b056551b..4572471a53ccc7a58b21dc5d3de29cf895285652 100644 (file)
@@ -135,6 +135,12 @@ static char **_fTmp;
 
 extern FILE *codeOutFile;
 
+enum
+  {
+    INT8MIN = -128,
+    INT8MAX = 127
+  };
+
 /** Enum covering all the possible register pairs.
  */
 typedef enum
@@ -160,8 +166,8 @@ static struct
   {    "bc", "c", "b" },
   {    "de", "e", "d" },
   {    "hl", "l", "h" },
-  {    "iy", "iy.l?", "iy.h?" },
-  {    "ix", "ix.l?", "ix.h?" }
+  {    "iy", "iyl", "iyh" },
+  {    "ix", "ixl", "ixh" }
 };
 
 // PENDING
@@ -246,6 +252,23 @@ _getTempPairName(void)
   return _pairs[_getTempPairId()].name;
 }
 
+static PAIR_ID
+getFreePairId (iCode *ic)
+{
+  if (!(bitVectBitValue (ic->rMask, B_IDX) || bitVectBitValue(ic->rMask, C_IDX)))
+    {
+      return PAIR_BC;
+    }
+  else if (IS_Z80 && !(bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX)))
+    {
+      return PAIR_DE;
+    }
+  else
+    {
+      return PAIR_INVALID;
+    }
+}         
+
 static void
 _tidyUp (char *buf)
 {
@@ -400,20 +423,16 @@ getPairName (asmop * aop)
          break;
        }
     }
-  else if (aop->type == AOP_STR)
+  else if (aop->type == AOP_STR || aop->type == AOP_HLREG)
     {
-      switch (*aop->aopu.aop_str[0])
-       {
-       case 'c':
-         return "bc";
-         break;
-       case 'e':
-         return "de";
-         break;
-       case 'l':
-         return "hl";
-         break;
-       }
+      int i;
+      for (i = 0; i < NUM_PAIRS; i++)
+        {
+          if (strcmp(aop->aopu.aop_str[0], _pairs[i].l) == 0)
+            {
+              return _pairs[i].name;
+            }
+        }
     }
   wassertl (0, "Tried to get the pair name of something that isn't a pair");
   return NULL;
@@ -439,21 +458,17 @@ getPairId (asmop * aop)
              return PAIR_HL;
            }
        }
-      if (aop->type == AOP_STR)
+      else if (aop->type == AOP_STR || aop->type == AOP_HLREG)
        {
-         if (!strcmp (aop->aopu.aop_str[0], "c") && !strcmp (aop->aopu.aop_str[1], "b"))
-           {
-             return PAIR_BC;
-           }
-         if (!strcmp (aop->aopu.aop_str[0], "e") && !strcmp (aop->aopu.aop_str[1], "d"))
-           {
-             return PAIR_DE;
-           }
-         if (!strcmp (aop->aopu.aop_str[0], "l") && !strcmp (aop->aopu.aop_str[1], "h"))
-           {
-             return PAIR_HL;
-           }
-       }
+          int i;
+          for (i = 0; i < NUM_PAIRS; i++)
+            {
+              if (!strcmp (aop->aopu.aop_str[0], _pairs[i].l) && !strcmp (aop->aopu.aop_str[1], _pairs[i].h))
+                {
+                  return i;
+                }
+            }
+        }
     }
   return PAIR_INVALID;
 }
@@ -479,6 +494,14 @@ isPtrPair (asmop * aop)
       return FALSE;
     }
 }
+
+static void
+spillPair (PAIR_ID pairId)
+{
+  _G.pairs[pairId].last_type = AOP_INVALID;
+  _G.pairs[pairId].base = NULL;
+}
+
 /** Push a register pair onto the stack */
 void
 genPairPush (asmop * aop)
@@ -498,6 +521,7 @@ _pop (PAIR_ID pairId)
 {
   emit2 ("pop %s", _pairs[pairId].name);
   _G.stack.pushed -= 2;
+  spillPair (pairId);
 }
 
 /*-----------------------------------------------------------------*/
@@ -536,10 +560,10 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
   if (sym->onStack || sym->iaccess)
     {
       /* The pointer that is used depends on how big the offset is.
-         Normally everything is AOP_STK, but for offsets of < -127 or
-         > 128 on the Z80 an extended stack pointer is used.
+         Normally everything is AOP_STK, but for offsets of < -128 or
+         > 127 on the Z80 an extended stack pointer is used.
       */
-      if (IS_Z80 && (options.ommitFramePtr || sym->stack < -127 || sym->stack > (int)(128-getSize (sym->type))))
+      if (IS_Z80 && (options.ommitFramePtr || sym->stack < INT8MIN || sym->stack > (int)(INT8MAX-getSize (sym->type))))
         {
           emitDebug ("; AOP_EXSTK for %s", sym->rname);
           sym->aop = aop = newAsmop (AOP_EXSTK);
@@ -815,6 +839,16 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a)
          return;
        }
 
+      if (sym->ruonly)
+       {
+         int i;
+         aop = op->aop = sym->aop = newAsmop (AOP_STR);
+         aop->size = getSize (sym->type);
+         for (i = 0; i < 4; i++)
+           aop->aopu.aop_str[i] = _fReturn[i];
+         return;
+       }
+
       if (sym->accuse)
        {
          if (sym->accuse == ACCUSE_A)
@@ -825,15 +859,22 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a)
 
               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");
               aop->aopu.aop_str[0] = _pairs[PAIR_HL].l;
               aop->aopu.aop_str[1] = _pairs[PAIR_HL].h;
            }
+          else if (sym->accuse == ACCUSE_IY)
+            {
+             aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
+             aop->size = getSize (sym->type);
+              wassertl(aop->size <= 2, "Internal error: Caching in IY, but too big to fit in IY");
+              aop->aopu.aop_str[0] = _pairs[PAIR_IY].l;
+              aop->aopu.aop_str[1] = _pairs[PAIR_IY].h;
+            }
          else 
               {
                   wassertl (0, "Marked as being allocated into A or HL but is actually in neither");
@@ -841,16 +882,6 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a)
          return;
        }
 
-      if (sym->ruonly)
-       {
-         int i;
-         aop = op->aop = sym->aop = newAsmop (AOP_STR);
-         aop->size = getSize (sym->type);
-         for (i = 0; i < 4; i++)
-           aop->aopu.aop_str[i] = _fReturn[i];
-         return;
-       }
-
       /* else spill location  */
       sym->aop = op->aop = aop =
        aopForSym (ic, sym->usl.spillLoc, result, requires_a);
@@ -926,7 +957,6 @@ char *
 aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
 {
   char *s = buffer;
-  char *rs;
 
   /* depending on type */
   switch (aop->type)
@@ -980,15 +1010,27 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
          }
        else
          {
-           /* A float */
-           Z80_FLOAT f;
-           convertFloat (&f, floatFromVal (val));
+            union {
+              float f;
+              unsigned char c[4];
+            }
+            fl;
+            unsigned int i;
+
+            /* it is type float */
+            fl.f = (float) floatFromVal (val);
+
+#ifdef _BIG_ENDIAN
+            i = fl.c[3-offset] | (fl.c[3-offset-1]<<8);
+#else
+            i = fl.c[offset] | (fl.c[offset+1]<<8);
+#endif
            if (with_hash)
-             tsprintf (buffer, "!immedword", f.w[offset / 2]);
+             tsprintf (buffer, "!immedword", i);
            else
-             tsprintf (buffer, "!constword", f.w[offset / 2]);
-           rs = Safe_calloc (1, strlen (buffer) + 1);
-           return strcpy (rs, buffer);
+             tsprintf (buffer, "!constword", i);
+
+            return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
          }
       }
     default:
@@ -1031,13 +1073,6 @@ adjustPair (const char *pair, int *pold, int new)
     }
 }
 
-static void
-spillPair (PAIR_ID pairId)
-{
-  _G.pairs[pairId].last_type = AOP_INVALID;
-  _G.pairs[pairId].base = NULL;
-}
-
 static void
 spillCached (void)
 {
@@ -1054,6 +1089,7 @@ requiresHL (asmop * aop)
     case AOP_HL:
     case AOP_STK:
     case AOP_EXSTK:
+    case AOP_HLREG:
       return TRUE;
     default:
       return FALSE;
@@ -1082,7 +1118,7 @@ fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
                      adjustPair (pair, &_G.pairs[pairId].offset, offset);
                      return;
                    }
-                 if (pairId == PAIR_IY && abs (offset) < 127)
+                 if (pairId == PAIR_IY && (offset >= INT8MIN && offset <= INT8MAX))
                    {
                      return;
                    }
@@ -1104,9 +1140,14 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
     if (isLitWord (aop)) {
         fetchLitPair (pairId, aop, offset);
     }
-    else {
+    else 
+      {
+        if (getPairId (aop) == pairId)
+          {
+            /* Do nothing */
+          }
         /* we need to get it byte by byte */
-        if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
+        else if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
             aopGet (aop, offset, FALSE);
             switch (aop->size - offset) {
             case 1:
@@ -1136,6 +1177,24 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
                 emit2("ld %s,!zero", _pairs[pairId].h);
             }
         }
+        else if (pairId == PAIR_IY)
+          {
+            if (isPair (aop))
+              {
+                emit2 ("push %s", _pairs[getPairId(aop)].name);
+                emit2 ("pop iy");
+              }
+            else
+              {
+                _push (PAIR_HL);
+                /* Can't load into parts, so load into HL then exchange. */
+                emit2 ("ld %s,%s", _pairs[PAIR_HL].l, aopGet (aop, offset, FALSE));
+                emit2 ("ld %s,%s", _pairs[PAIR_HL].h, aopGet (aop, offset + 1, FALSE));
+                emit2 ("push hl");
+                emit2 ("pop iy");
+                _pop (PAIR_HL);
+              }
+          }
         else {
             emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
             emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
@@ -1158,6 +1217,22 @@ 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)
 {
@@ -1215,7 +1290,7 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset)
          }
        else
          {
-           emit2 ("!ldahlsp", abso + _G.stack.pushed);
+            setupPairFromSP (PAIR_HL, abso + _G.stack.pushed);
          }
        _G.pairs[pairId].offset = abso;
        break;
@@ -1528,7 +1603,9 @@ aopPut (asmop * aop, const char *s, int offset)
              emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
            }
          else
-           emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
+            {
+              emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
+            }
        }
       break;
 
@@ -1594,7 +1671,8 @@ aopPut (asmop * aop, const char *s, int offset)
 static void
 commitPair (asmop * aop, PAIR_ID id)
 {
-  if (id == PAIR_HL && requiresHL (aop))
+  /* PENDING: Verify this. */
+  if (id == PAIR_HL && requiresHL (aop) && IS_GB)
     {
       emit2 ("ld a,l");
       emit2 ("ld d,h");
@@ -1603,8 +1681,19 @@ commitPair (asmop * aop, PAIR_ID id)
     }
   else
     {
-      aopPut (aop, _pairs[id].l, 0);
-      aopPut (aop, _pairs[id].h, 1);
+      /* Special cases */
+      if (id == PAIR_HL && aop->type == AOP_IY && aop->size == 2)
+        {
+          char *l = aopGetLitWordLong (aop, 0, FALSE);
+          wassert (l);
+
+          emit2 ("ld (%s),%s", l, _pairs[id].name);
+        }
+      else
+        {
+          aopPut (aop, _pairs[id].l, 0);
+          aopPut (aop, _pairs[id].h, 1);
+        }
     }
 }
 
@@ -1632,6 +1721,7 @@ movLeft2Result (operand * left, int offl,
                operand * result, int offr, int sign)
 {
   const char *l;
+
   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
     {
       l = aopGet (AOP (left), offl, FALSE);
@@ -1651,6 +1741,47 @@ movLeft2Result (operand * left, int offl,
     }
 }
 
+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 if ( getPairId ( AOP (result)) == PAIR_IY)
+        {
+          PAIR_ID id = getPairId (AOP (left));
+          if (id != PAIR_INVALID) 
+            {
+              emit2("push %s", _pairs[id].name);
+              emit2("pop iy");
+            }
+          else
+            {
+              /* PENDING */
+              emitDebug("Error");
+            }
+        }
+      else
+        {
+          movLeft2Result (left, offl, result, offr, sign);
+          movLeft2Result (left, offl+1, result, offr+1, sign);
+        }
+    }
+}
 
 /** Put Acc into a register set
  */
@@ -1723,6 +1854,44 @@ _toBoolean (operand * oper)
     }
 }
 
+/*-----------------------------------------------------------------*/
+/* genNotFloat - generates not for float operations              */
+/*-----------------------------------------------------------------*/
+static void
+genNotFloat (operand * op, operand * res)
+{
+  int size, offset;
+  symbol *tlbl;
+
+  emitDebug ("; genNotFloat");
+
+  /* we will put 127 in the first byte of
+     the result */
+  aopPut (AOP (res), "!immedbyte", 0x7F);
+  size = AOP_SIZE (op) - 1;
+  offset = 1;
+
+  _moveA (aopGet (op->aop, offset++, FALSE));
+
+  while (size--)
+    {
+      emit2 ("or a,%s", aopGet (op->aop, offset++, FALSE));
+    }
+
+  tlbl = newiTempLabel (NULL);
+  aopPut (res->aop, "!one", 1);
+  emit2 ("!shortjp z !tlabel", tlbl->key + 100);
+  aopPut (res->aop, "!zero", 1);
+
+  emitLabel(tlbl->key + 100);
+
+  size = res->aop->size - 2;
+  offset = 2;
+  /* put zeros in the rest */
+  while (size--)
+    aopPut (res->aop, "!zero", offset++);
+}
+
 /*-----------------------------------------------------------------*/
 /* genNot - generate code for ! operation                          */
 /*-----------------------------------------------------------------*/
@@ -1744,7 +1913,8 @@ genNot (iCode * ic)
   /* if type float then do float */
   if (IS_FLOAT (optype))
     {
-      wassertl (0, "Tried to negate a float");
+      genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
+      goto release;
     }
 
   _toBoolean (IC_LEFT (ic));
@@ -1756,6 +1926,7 @@ genNot (iCode * ic)
   emit2 ("sub a,!one");
   outBitC (IC_RESULT (ic));
 
+ release:
   /* release the aops */
   freeAsmop (IC_LEFT (ic), NULL, ic);
   freeAsmop (IC_RESULT (ic), NULL, ic);
@@ -1850,6 +2021,32 @@ _gbz80_emitAddSubLong (iCode *ic, bool isAdd)
   _gbz80_emitAddSubLongLong (ic, AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)), isAdd);
 }
 
+/*-----------------------------------------------------------------*/
+/* genUminusFloat - unary minus for floating points                */
+/*-----------------------------------------------------------------*/
+static void
+genUminusFloat (operand * op, operand * result)
+{
+  int size, offset = 0;
+
+  emitDebug("; genUminusFloat");
+
+  /* for this we just need to flip the
+     first it then copy the rest in place */
+  size = AOP_SIZE (op) - 1;
+
+  _moveA(aopGet (AOP (op), MSB32, FALSE));
+
+  emit2("xor a,!immedbyte", 0x80);
+  aopPut (AOP (result), "a", MSB32);
+
+  while (size--)
+    {
+      aopPut (AOP (result), aopGet (AOP (op), offset, FALSE), offset);
+      offset++;
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* genUminus - unary minus code generation                         */
 /*-----------------------------------------------------------------*/
@@ -1878,7 +2075,7 @@ genUminus (iCode * ic)
   /* if float then do float stuff */
   if (IS_FLOAT (optype))
     {
-      wassertl (0, "Tried to do a unary minus on a float");
+      genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
       goto release;
     }
 
@@ -1952,6 +2149,25 @@ assignResultValue (operand * oper)
     }
 }
 
+/** 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)
 {
@@ -2057,7 +2273,7 @@ genIpush (iCode * ic)
 
   size = AOP_SIZE (IC_LEFT (ic));
 
-  if (isPair (AOP (IC_LEFT (ic))))
+  if (isPair (AOP (IC_LEFT (ic))) && size == 2)
     {
       _G.stack.pushed += 2;
       emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
@@ -2217,7 +2433,7 @@ _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
 static void
 emitCall (iCode * ic, bool ispcall)
 {
-  sym_link *detype = getSpec (operandType (IC_LEFT (ic)));
+  sym_link *dtype = operandType (IC_LEFT (ic));
 
   bitVect *rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
 
@@ -2291,7 +2507,7 @@ emitCall (iCode * ic, bool ispcall)
 
   if (ispcall)
     {
-      if (IS_BANKEDCALL (detype))
+      if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
        {
          werror (W_INDIR_BANKED);
        }
@@ -2321,7 +2537,7 @@ emitCall (iCode * ic, bool ispcall)
       char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
       OP_SYMBOL (IC_LEFT (ic))->rname :
       OP_SYMBOL (IC_LEFT (ic))->name;
-      if (IS_BANKEDCALL (detype))
+      if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
        {
          emit2 ("call banked_call");
          emit2 ("!dws", name);
@@ -2381,10 +2597,11 @@ emitCall (iCode * ic, bool ispcall)
              if (i)
                emit2 ("inc sp");
            }
-         spillCached ();
        }
     }
 
+  spillCached ();
+
   if (_G.stack.pushedDE) 
     {
       bool dInUse = bitVectBitValue(rInUse, D_IDX);
@@ -2486,14 +2703,14 @@ static void
 genFunction (iCode * ic)
 {
   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
-  sym_link *fetype;
+  sym_link *ftype;
 
 #if CALLEE_SAVES
   bool bcInUse = FALSE;
   bool deInUse = FALSE;
 #endif
 
-  setArea (IS_NONBANKED (sym->etype));
+  setArea (IFFUNC_NONBANKED (sym->type));
 
   /* PENDING: Reset the receive offset as it doesn't seem to get reset anywhere
      else.
@@ -2514,14 +2731,14 @@ genFunction (iCode * ic)
       emit2 ("!profileenter");
     }
 
-  fetype = getSpec (operandType (IC_LEFT (ic)));
+  ftype = operandType (IC_LEFT (ic));
 
   /* if critical function then turn interrupts off */
-  if (SPEC_CRTCL (fetype))
+  if (IFFUNC_ISCRITICAL (ftype))
     emit2 ("!di");
 
   /* if this is an interrupt service routine then save all potentially used registers. */
-  if (IS_ISR (sym->etype))
+  if (IFFUNC_ISISR (sym->type))
     {
       emit2 ("!pusha");
     }
@@ -2579,7 +2796,9 @@ genFunction (iCode * ic)
   /* adjust the stack for the function */
   _G.stack.last = sym->stack;
 
-  if (sym->stack)
+  if (sym->stack && IS_GB && sym->stack > -INT8MIN)
+    emit2 ("!enterxl", sym->stack);
+  else if (sym->stack)
     emit2 ("!enterx", sym->stack);
   else
     emit2 ("!enter");
@@ -2594,18 +2813,22 @@ genEndFunction (iCode * ic)
 {
   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
 
-  if (IS_ISR (sym->etype))
+  if (IFFUNC_ISISR (sym->type))
     {
       wassertl (0, "Tried to close an interrupt support function");
     }
   else
     {
-      if (SPEC_CRTCL (sym->etype))
+      if (IFFUNC_ISCRITICAL (sym->type))
        emit2 ("!ei");
 
       /* PENDING: calleeSave */
 
-      if (_G.stack.offset)
+      if (_G.stack.offset && IS_GB && _G.stack.offset > INT8MAX)
+        {
+          emit2 ("!leavexl", _G.stack.offset);
+        }
+      else if (_G.stack.offset)
         {
           emit2 ("!leavex", _G.stack.offset);
         }
@@ -2753,14 +2976,27 @@ genPlusIncr (iCode * ic)
     {
       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)
        {
-         fetchPair (resultId, AOP (IC_RIGHT (ic)));
-         emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
-         return TRUE;
+          if (getPairId (AOP (IC_LEFT (ic))) == PAIR_HL)
+            {
+              PAIR_ID freep = getFreePairId (ic);
+              if (freep != PAIR_INVALID)
+                {
+                  fetchPair (freep, AOP (IC_RIGHT (ic)));
+                  emit2 ("add hl,%s", _pairs[freep].name);
+                  return TRUE;
+                }
+            }
+          else
+            {
+              fetchPair (resultId, AOP (IC_RIGHT (ic)));
+              emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
+              return TRUE;
+            }
        }
       if (icount > 5)
        return FALSE;
@@ -2769,8 +3005,7 @@ genPlusIncr (iCode * ic)
        {
          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--)
        {
@@ -2779,6 +3014,13 @@ genPlusIncr (iCode * ic)
       return TRUE;
     }
 
+  if (IS_Z80 && isLitWord (AOP (IC_LEFT (ic))) && size == 2)
+    {
+      fetchLitPair (PAIR_HL, AOP (IC_LEFT (ic)), icount);
+      commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
+      return TRUE;
+    }
+
   /* if the literal value of the right hand side
      is greater than 4 then it is not worth it */
   if (icount > 4)
@@ -2810,6 +3052,18 @@ genPlusIncr (iCode * ic)
       AOP_SIZE (IC_LEFT (ic)) > 1)
     return FALSE;
 
+  /* If the result is in a register then we can load then increment.
+   */
+  if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG)
+    {
+      aopPut (AOP (IC_RESULT (ic)), aopGet (AOP (IC_LEFT (ic)), LSB, FALSE), LSB);
+      while (icount--)
+        {
+          emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE));
+        }
+      return TRUE;
+    }
+
   /* we can if the aops of the left & result match or
      if they are in registers and the registers are the
      same */
@@ -3000,12 +3254,48 @@ genPlus (iCode * ic)
        }
     }
 
-  if (isPair (AOP (IC_RIGHT (ic))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
+  if ((isPair (AOP (IC_RIGHT (ic))) || isPair (AOP (IC_LEFT (ic)))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
     {
       /* Fetch into HL then do the add */
+      PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
+      PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
+
       spillPair (PAIR_HL);
+      
+      if (left == PAIR_HL && right != PAIR_INVALID)
+        {
+          emit2 ("add hl,%s", _pairs[right].name);
+          goto release;
+        }
+      else if (right == PAIR_HL && left != PAIR_INVALID)
+        {
+          emit2 ("add hl,%s", _pairs[left].name);
+          goto release;
+        }
+      else if (right != PAIR_INVALID && right != PAIR_HL)
+        {
+          fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
+          emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
+          goto release;
+        }
+      else if (left != PAIR_INVALID && left != PAIR_HL)
+        { 
+          fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
+          emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
+          goto release;
+        }
+      else
+        {
+          /* Can't do it */
+        }
+    }
+
+  if (isPair (AOP (IC_RIGHT (ic))) && AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD && getPairId (AOP (IC_RIGHT (ic))) != PAIR_HL)
+    {
       fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
-      emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
+      emit2 ("add hl,%s ; 2", getPairName (AOP (IC_RIGHT (ic))));
+      spillCached();
+      commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
       goto release;
     }
 
@@ -3147,8 +3437,7 @@ genMinusDec (iCode * ic)
   /* 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;
@@ -3260,7 +3549,10 @@ genMinus (iCode * ic)
              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;
            }
@@ -3320,8 +3612,92 @@ release:
 static void
 genMult (iCode * ic)
 {
+  int val;
+  int count, i;
+  /* If true then the final operation should be a subtract */
+  bool active = FALSE;
+
   /* Shouldn't occur - all done through function calls */
-  wassertl (0, "Multiplication is handled through support function calls");
+  aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
+  aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
+  aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
+
+  if (AOP_SIZE (IC_LEFT (ic)) > 2 ||
+      AOP_SIZE (IC_RIGHT (ic)) > 2 ||
+      AOP_SIZE (IC_RESULT (ic)) > 2)
+    {
+      wassertl (0, "Multiplication is handled through support function calls");
+    }
+
+  /* Swap left and right such that right is a literal */
+  if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT))
+    {
+      operand *t = IC_RIGHT (ic);
+      IC_RIGHT (ic) = IC_LEFT (ic);
+      IC_LEFT (ic) = t;
+    }
+
+  wassertl (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT, "Right must be a literal");
+
+  val = (int)floatFromVal ( AOP (IC_RIGHT (ic))->aopu.aop_lit);
+  //  wassertl (val > 0, "Multiply must be positive");
+  wassertl (val != 1, "Can't multiply by 1");
+
+  if (IS_Z80) {
+    _push (PAIR_DE);
+  }
+
+  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));
+      emit2 ("ld a,e");
+      emit2 ("rlc a");
+      emit2 ("sbc a,a");
+      emit2 ("ld d,a");
+    }
+  else
+    {
+      fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
+    }
+
+  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 (i & 0x8000U)
+        {
+          if (active == FALSE)
+            {
+              emit2 ("ld l,e");
+              emit2 ("ld h,d");
+            }
+          else
+            {
+              emit2 ("add hl,de");
+            }
+          active = TRUE;
+        }
+      i <<= 1;
+    }
+
+  spillCached();
+
+  if (IS_Z80)
+    {
+      _pop (PAIR_DE);
+    }
+
+  commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
+
+  freeAsmop (IC_LEFT (ic), NULL, ic);
+  freeAsmop (IC_RIGHT (ic), NULL, ic);
+  freeAsmop (IC_RESULT (ic), NULL, ic);
 }
 
 /*-----------------------------------------------------------------*/
@@ -3370,6 +3746,14 @@ genIfxJump (iCode * ic, char *jval)
        {
          inst = "nc";
        }
+      else if (!strcmp (jval, "m"))
+       {
+         inst = "m";
+       }
+      else if (!strcmp (jval, "p"))
+       {
+         inst = "p";
+       }
       else
        {
          /* The buffer contains the bit on A that we should test */
@@ -3392,6 +3776,14 @@ genIfxJump (iCode * ic, char *jval)
        {
          inst = "c";
        }
+      else if (!strcmp (jval, "m"))
+       {
+         inst = "p";
+       }
+      else if (!strcmp (jval, "p"))
+       {
+         inst = "m";
+       }
       else
        {
          /* The buffer contains the bit on A that we should test */
@@ -3409,6 +3801,12 @@ genIfxJump (iCode * ic, char *jval)
   else if (!strcmp (jval, "nc"))
     {
     }
+  else if (!strcmp (jval, "m"))
+    {
+    }
+  else if (!strcmp (jval, "p"))
+    {
+    }
   else
     {
       emit2 ("bit %s,a", jval);
@@ -3427,30 +3825,7 @@ _getPairIdName (PAIR_ID id)
 }
 #endif
 
-/** Generic compare for > or <
- */
-static void
-genCmp (operand * left, operand * right,
-       operand * result, iCode * ifx, int sign)
-{
-  int size, offset = 0;
-  unsigned long lit = 0L;
-  bool swap_sense = FALSE;
-
-  /* if left & right are bit variables */
-  if (AOP_TYPE (left) == AOP_CRY &&
-      AOP_TYPE (right) == AOP_CRY)
-    {
-      /* Cant happen on the Z80 */
-      wassertl (0, "Tried to compare two bits");
-    }
-  else
-    {
-      /* subtract right from left if at the
-         end the carry flag is set then we know that
-         left is greater than right */
-      size = max (AOP_SIZE (left), AOP_SIZE (right));
-
+#if OLD
       /* if unsigned char cmp with lit, just compare */
       if ((size == 1) &&
          (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
@@ -3625,10 +4000,109 @@ genCmp (operand * left, operand * right,
            }
        }
     }
+#endif
+
+/** Generic compare for > or <
+ */
+static void
+genCmp (operand * left, operand * right,
+       operand * result, iCode * ifx, int sign)
+{
+  int size, offset = 0;
+  unsigned long lit = 0L;
+  bool swap_sense = FALSE;
+
+  /* if left & right are bit variables */
+  if (AOP_TYPE (left) == AOP_CRY &&
+      AOP_TYPE (right) == AOP_CRY)
+    {
+      /* Cant happen on the Z80 */
+      wassertl (0, "Tried to compare two bits");
+    }
+  else
+    {
+      /* Do a long subtract of right from left. */
+      size = max (AOP_SIZE (left), AOP_SIZE (right));
+
+      if (size > 1 && IS_GB && requiresHL(AOP(right)) && requiresHL(AOP(left)))
+        {
+          // On the Gameboy we can't afford to adjust HL as it may trash the carry.
+          // Pull left into DE and right into HL
+          aopGet (AOP(left), LSB, FALSE);
+          emit2 ("ld d,h");
+          emit2 ("ld e,l");
+          aopGet (AOP(right), LSB, FALSE);
+
+          while (size--)
+            {
+              emit2 ("ld a,(de)");
+              emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc");
+              
+              if (size != 0)
+                {
+                  emit2 ("inc hl");
+                  emit2 ("inc de");
+                }
+              offset++;
+            }
+          spillPair (PAIR_HL);
+          goto release;
+        }
+
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+          /* optimize if(x < 0) or if(x >= 0) */
+          if (lit == 0)
+            {
+              if (!sign)
+                {
+                  /* No sign so it's always false */
+                  _clearCarry();
+                }
+              else
+                {
+                  /* Just load in the top most bit */
+                  _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
+                  if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
+                    {
+                      genIfxJump (ifx, "7");
+                      return;
+                    }
+                  else
+                    {
+                      if (!sign) 
+                        {
+                          emit2 ("rlc a");
+                        }
+                      if (ifx)
+                        {
+                          genIfxJump (ifx, swap_sense ? "c" : "nc");
+                          return;
+                        }
+                    }
+                }
+              goto release;
+            }
+        }
+
+      while (size--)
+        {
+          _moveA (aopGet (AOP (left), offset, FALSE));
+          /* Subtract through, propagating the carry */
+          emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE));
+          offset++;
+        }
+    }
 
 release:
   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
     {
+      if (sign)
+        {
+          /* Shift the sign bit up into carry */
+          emit2 ("rlca");
+        }
       outBitCLong (result, swap_sense);
     }
   else
@@ -3637,9 +4111,33 @@ release:
          ifx conditional branch then generate
          code a little differently */
       if (ifx)
-       genIfxJump (ifx, swap_sense ? "nc" : "c");
+        {
+          if (sign)
+            {
+              if (IS_GB)
+                {
+                  emit2 ("rlca");
+                  genIfxJump (ifx, swap_sense ? "nc" : "c");
+                }
+              else
+                {
+                  genIfxJump (ifx, swap_sense ? "p" : "m");
+                }
+            }
+          else
+            {
+              genIfxJump (ifx, swap_sense ? "nc" : "c");
+            }
+        }
       else
-       outBitCLong (result, swap_sense);
+        {
+          if (sign)
+            {
+              /* Shift the sign bit up into carry */
+              emit2 ("rlca");
+            }
+          outBitCLong (result, swap_sense);
+        }
       /* leave the result in acc */
     }
 }
@@ -3823,7 +4321,7 @@ genCmpEq (iCode * ic, iCode * ifx)
   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
 
-  emitDebug ("; genCmpEq: left %u, right %u, result %u\n", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
+  emitDebug ("; genCmpEq: left %u, right %u, result %u", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
 
   /* Swap operands if it makes the operation easier. ie if:
      1.  Left is a literal.
@@ -3847,9 +4345,11 @@ genCmpEq (iCode * ic, iCode * ifx)
       else
        {
          tlbl = newiTempLabel (NULL);
+          emitDebug(";1");
          gencjneshort (left, right, tlbl);
          if (IC_TRUE (ifx))
            {
+              emitDebug(";2");
              emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
              emitLabel (tlbl->key + 100);
            }
@@ -3857,6 +4357,7 @@ genCmpEq (iCode * ic, iCode * ifx)
            {
              /* PENDING: do this better */
              symbol *lbl = newiTempLabel (NULL);
+              emitDebug(";3");
              emit2 ("!shortjp !tlabel", lbl->key + 100);
              emitLabel (tlbl->key + 100);
              emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
@@ -3876,6 +4377,8 @@ genCmpEq (iCode * ic, iCode * ifx)
     }
   else
     {
+      emitDebug(";4");
+      
       gencjne (left, right, newiTempLabel (NULL));
       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
        {
@@ -3883,6 +4386,7 @@ genCmpEq (iCode * ic, iCode * ifx)
        }
       if (ifx)
        {
+          emitDebug(";5");
          genIfxJump (ifx, "a");
          goto release;
        }
@@ -3890,6 +4394,7 @@ genCmpEq (iCode * ic, iCode * ifx)
          then put the result in place */
       if (AOP_TYPE (result) != AOP_CRY)
        {
+          emitDebug(";6");
          outAcc (result);
        }
       /* leave the result in acc */
@@ -5327,7 +5832,9 @@ genGenPointerGet (operand * left,
   aopOp (left, ic, FALSE, FALSE);
   aopOp (result, ic, FALSE, FALSE);
 
-  if (isPair (AOP (left)) && AOP_SIZE (result) == 1)
+  size = AOP_SIZE (result);
+
+  if (isPair (AOP (left)) && size == 1)
     {
       /* Just do it */
       if (isPtrPair (AOP (left)))
@@ -5344,11 +5851,24 @@ genGenPointerGet (operand * left,
       goto release;
     }
 
+  if ( getPairId( AOP (left)) == PAIR_IY)
+    {
+      /* Just do it */
+      offset = 0;
+      while (size--) 
+        {
+          char at[20];
+          tsprintf (at, "!*iyx", offset);
+          aopPut (AOP (result), at, offset);
+          offset++;
+        }
+      goto release;
+    }
+
   /* For now we always load into IY */
   /* if this is remateriazable */
   fetchPair (pair, AOP (left));
 
-  /* so iy now contains the address */
   freeAsmop (left, NULL, ic);
 
   /* if bit then unpack */
@@ -5356,6 +5876,14 @@ genGenPointerGet (operand * left,
     {
       wassert (0);
     }
+  else if ( getPairId( AOP (result)) == PAIR_HL)
+    {
+      wassertl (size == 2, "HL must be of size 2");
+      emit2 ("ld a,!*hl");
+      emit2 ("inc hl");
+      emit2 ("ld h,!*hl");
+      emit2 ("ld l,a");
+    }
   else
     {
       size = AOP_SIZE (result);
@@ -5408,7 +5936,7 @@ genPointerGet (iCode * ic)
 bool
 isRegOrLit (asmop * aop)
 {
-  if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
+  if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD || aop->type == AOP_HLREG)
     return TRUE;
   return FALSE;
 }
@@ -5423,15 +5951,17 @@ genGenPointerSet (operand * right,
   int size, offset;
   sym_link *retype = getSpec (operandType (right));
   PAIR_ID pairId = PAIR_HL;
-
+  
   aopOp (result, ic, FALSE, FALSE);
   aopOp (right, ic, FALSE, FALSE);
 
   if (IS_GB)
     pairId = PAIR_DE;
 
+  size = AOP_SIZE (right);
+
   /* Handle the exceptions first */
-  if (isPair (AOP (result)) && (AOP_SIZE (right) == 1))
+  if (isPair (AOP (result)) && size == 1)
     {
       /* Just do it */
       const char *l = aopGet (AOP (right), 0, FALSE);
@@ -5447,6 +5977,28 @@ genGenPointerSet (operand * right,
        }
       goto release;
     }
+  
+  if ( getPairId( AOP (result)) == PAIR_IY)
+    {
+      /* Just do it */
+      const char *l = aopGet (AOP (right), 0, FALSE);
+
+      offset = 0;
+      while (size--) 
+        {
+          if (canAssignToPtr (l))
+            {
+              emit2 ("ld !*iyx,%s", offset, aopGet( AOP(right), offset, FALSE));
+            }
+          else
+            {
+              _moveA (aopGet (AOP (right), offset, FALSE));
+              emit2 ("ld !*iyx,a", offset);
+            }
+          offset++;
+        }
+      goto release;
+    }
 
   /* if the operand is already in dptr
      then we do nothing else we move the value to dptr */
@@ -5464,7 +6016,6 @@ genGenPointerSet (operand * right,
     }
   else
     {
-      size = AOP_SIZE (right);
       offset = 0;
 
       while (size--)
@@ -5566,21 +6117,19 @@ genAddrOf (iCode * ic)
          spillCached ();
          if (sym->stack <= 0)
            {
-             emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
+              setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset);
            }
          else
            {
-             emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
+              setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
            }
-         emit2 ("ld d,h");
-         emit2 ("ld e,l");
+          commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
        }
       else
        {
          emit2 ("ld de,!hashedstr", sym->rname);
+          commitPair (AOP (IC_RESULT (ic)), PAIR_DE);
        }
-      aopPut (AOP (IC_RESULT (ic)), "e", 0);
-      aopPut (AOP (IC_RESULT (ic)), "d", 1);
     }
   else
     {
@@ -5598,8 +6147,7 @@ genAddrOf (iCode * ic)
        {
          emit2 ("ld hl,#%s", sym->rname);
        }
-      aopPut (AOP (IC_RESULT (ic)), "l", 0);
-      aopPut (AOP (IC_RESULT (ic)), "h", 1);
+      commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
     }
   freeAsmop (IC_RESULT (ic), NULL, ic);
 }
@@ -5645,7 +6193,10 @@ genAssign (iCode * ic)
   offset = 0;
 
   if (AOP_TYPE (right) == AOP_LIT)
+    {
     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+    }
+
   if (isPair (AOP (result)))
     {
       fetchPair (getPairId (AOP (result)), AOP (right));
@@ -5686,6 +6237,12 @@ genAssign (iCode * ic)
          offset++;
        }
     }
+  else if (size == 2 && AOP_TYPE (right) == AOP_IY)
+    {
+      emit2 ("ld hl,(%s)", AOP (right)->aopu.aop_dir);
+      aopPut (AOP (result), "l", LSB);
+      aopPut (AOP (result), "h", MSB16);
+    }
   else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
     {
       /* Special case.  Load into a and d, then load out. */
@@ -5721,7 +6278,7 @@ genAssign (iCode * ic)
       while (size--)
        {
          /* PENDING: do this check better */
-         if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
+         if (IS_GB && requiresHL (AOP (right)) && requiresHL (AOP (result)))
            {
              _moveA (aopGet (AOP (right), offset, FALSE));
              aopPut (AOP (result), "a", offset);
@@ -6068,16 +6625,10 @@ genArrayInit (iCode * ic)
 
   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));
     
@@ -6121,6 +6672,10 @@ genArrayInit (iCode * ic)
   /* Mark the end of the run. */
   emit2(".db 0");
 
+  _restoreRegsAfterCall();
+
+  spillCached ();
+
   freeAsmop (IC_LEFT(ic), NULL, ic);
 }
 
@@ -6396,6 +6951,7 @@ genZ80Code (iCode * lic)
          break;
 
        case ARRAYINIT:
+         emitDebug ("; genArrayInit");
           genArrayInit(ic);
           break;