Improved caching of pointers and division
[fw/sdcc] / src / z80 / gen.c
index e218d9b0a280808669268326217e1266863bf0a4..b45d7a8516c2fe621b1cb7e75ce53458700e8f8e 100644 (file)
 #include <string.h>
 #include <ctype.h>
 
 #include <string.h>
 #include <ctype.h>
 
-#if defined(__BORLANDC__) || defined(_MSC_VER)
-#define STRCASECMP stricmp
-#else
-#define STRCASECMP strcasecmp
-#endif
-
 #include "z80.h"
 #include "SDCCglobl.h"
 #include "SDCCpeeph.h"
 #include "z80.h"
 #include "SDCCglobl.h"
 #include "SDCCpeeph.h"
@@ -128,16 +122,16 @@ enum
 };
 
 static char *_z80_return[] =
 };
 
 static char *_z80_return[] =
-{"l", "h", "e", "d"};
+  {"l", "h", "e", "d"};
 static char *_gbz80_return[] =
 static char *_gbz80_return[] =
-{"e", "d", "l", "h"};
+  {"e", "d", "l", "h"};
 static char *_fReceive[] =
   { "c", "b", "e", "d" };
 
 static char **_fReturn;
 static char **_fTmp;
 
 static char *_fReceive[] =
   { "c", "b", "e", "d" };
 
 static char **_fReturn;
 static char **_fTmp;
 
-extern FILE *codeOutFile;
+extern struct dbuf_s *codeOutBuf;
 
 enum
   {
 
 enum
   {
@@ -388,7 +382,7 @@ _tidyUp (char *buf)
 }
 
 static lineNode *
 }
 
 static lineNode *
-_newLineNode (char *line)
+_newLineNode (const char *line)
 {
   lineNode *pl;
 
 {
   lineNode *pl;
 
@@ -401,9 +395,14 @@ _newLineNode (char *line)
 static void
 _vemit2 (const char *szFormat, va_list ap)
 {
 static void
 _vemit2 (const char *szFormat, va_list ap)
 {
-  char buffer[INITIAL_INLINEASM];
+  struct dbuf_s dbuf;
+  char *buffer;
+
+  dbuf_init(&dbuf, INITIAL_INLINEASM);
+
+  dbuf_tvprintf (&dbuf, szFormat, ap);
 
 
-  tvsprintf (buffer, sizeof(buffer), szFormat, ap);
+  buffer = (char *)dbuf_c_str(&dbuf);
 
   _tidyUp (buffer);
   _G.lines.current = (_G.lines.current ?
 
   _tidyUp (buffer);
   _G.lines.current = (_G.lines.current ?
@@ -413,6 +412,9 @@ _vemit2 (const char *szFormat, va_list ap)
   _G.lines.current->isInline = _G.lines.isInline;
   _G.lines.current->isDebug = _G.lines.isDebug;
   _G.lines.current->ic = _G.current_iCode;
   _G.lines.current->isInline = _G.lines.isInline;
   _G.lines.current->isDebug = _G.lines.isDebug;
   _G.lines.current->ic = _G.current_iCode;
+  _G.lines.current->isComment = (*buffer == ';');
+
+  dbuf_destroy(&dbuf);
 }
 
 static void
 }
 
 static void
@@ -430,6 +432,8 @@ emit2 (const char *szFormat,...)
 static void
 emitDebug (const char *szFormat,...)
 {
 static void
 emitDebug (const char *szFormat,...)
 {
+  if (!options.verboseAsm)
+    return;
   if (!DISABLE_DEBUG)
     {
       va_list ap;
   if (!DISABLE_DEBUG)
     {
       va_list ap;
@@ -699,9 +703,12 @@ _push (PAIR_ID pairId)
 static void
 _pop (PAIR_ID pairId)
 {
 static void
 _pop (PAIR_ID pairId)
 {
-  emit2 ("pop %s", _pairs[pairId].name);
-  _G.stack.pushed -= 2;
-  spillPair (pairId);
+  if (pairId != PAIR_INVALID)
+    {
+      emit2 ("pop %s", _pairs[pairId].name);
+      _G.stack.pushed -= 2;
+      spillPair (pairId);
+    }
 }
 
 void
 }
 
 void
@@ -1255,7 +1262,7 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
         /* otherwise it is fairly simple */
         if (!IS_FLOAT (val->type))
           {
         /* otherwise it is fairly simple */
         if (!IS_FLOAT (val->type))
           {
-            unsigned long v = (unsigned long) floatFromVal (val);
+            unsigned long v = ulFromVal (val);
 
             if (offset == 2)
               {
 
             if (offset == 2)
               {
@@ -1378,28 +1385,62 @@ fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
     {
       if (pairId == PAIR_HL || pairId == PAIR_IY)
         {
     {
       if (pairId == PAIR_HL || pairId == PAIR_IY)
         {
-          if (_G.pairs[pairId].last_type == left->type)
+          if ((_G.pairs[pairId].last_type == AOP_IMMD && left->type == AOP_IMMD) ||
+            (_G.pairs[pairId].last_type == AOP_IY && left->type == AOP_IY))
             {
               if (_G.pairs[pairId].base && !strcmp (_G.pairs[pairId].base, base))
                 {
                   if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
                     {
                       adjustPair (pair, &_G.pairs[pairId].offset, offset);
             {
               if (_G.pairs[pairId].base && !strcmp (_G.pairs[pairId].base, base))
                 {
                   if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
                     {
                       adjustPair (pair, &_G.pairs[pairId].offset, offset);
-                      return;
+                      goto adjusted;
                     }
                   if (pairId == PAIR_IY && (offset >= INT8MIN && offset <= INT8MAX))
                     {
                     }
                   if (pairId == PAIR_IY && (offset >= INT8MIN && offset <= INT8MAX))
                     {
-                      return;
+                       goto adjusted;
                     }
                 }
             }
         }
                     }
                 }
             }
         }
+
+      if (pairId == PAIR_HL && left->type == AOP_LIT && _G.pairs[pairId].last_type == AOP_LIT &&
+        !IS_FLOAT (left->aopu.aop_lit->type) && offset == 0 && _G.pairs[pairId].offset == 0)
+        {
+          unsigned new_low, new_high, old_low, old_high;
+          unsigned long v_new = ulFromVal (left->aopu.aop_lit);
+          unsigned long v_old = strtoul (_G.pairs[pairId].base, NULL, 0);
+          new_low = (v_new >> 0) & 0xff;
+          new_high = (v_new >> 8) & 0xff;
+          old_low = (v_old >> 0) & 0xff;
+          old_high = (v_old >> 8) & 0xff;
+
+          /* Change lower byte only. */
+          if(new_high == old_high)
+            {
+              emit2("ld l, %s", aopGet (left, 0, FALSE));
+              goto adjusted;
+            }
+          /* Change upper byte only. */
+          else if(new_low == old_low)
+            {
+              emit2("ld h, %s", aopGet (left, 1, FALSE));
+              goto adjusted;
+            }
+        }
+
+
       _G.pairs[pairId].last_type = left->type;
       _G.pairs[pairId].base = traceAlloc(&_G.trace.aops, Safe_strdup (base));
       _G.pairs[pairId].offset = offset;
     }
   /* Both a lit on the right and a true symbol on the left */
   emit2 ("ld %s,!hashedstr", pair, l);
       _G.pairs[pairId].last_type = left->type;
       _G.pairs[pairId].base = traceAlloc(&_G.trace.aops, Safe_strdup (base));
       _G.pairs[pairId].offset = offset;
     }
   /* Both a lit on the right and a true symbol on the left */
   emit2 ("ld %s,!hashedstr", pair, l);
+  return;
+
+adjusted:
+  _G.pairs[pairId].last_type = left->type;
+  _G.pairs[pairId].base = traceAlloc(&_G.trace.aops, Safe_strdup (base));
+  _G.pairs[pairId].offset = offset;
 }
 
 static PAIR_ID
 }
 
 static PAIR_ID
@@ -1503,8 +1544,18 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, iCode *ic, int offset)
           }
         else
           {
           }
         else
           {
-            emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
-            emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
+            /* Operand resides (partially) in the pair */
+            if(!strcmp(aopGet (aop, offset + 1, FALSE), _pairs[pairId].l))
+              {
+                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)
           }
         /* PENDING: check? */
         if (pairId == PAIR_HL)
@@ -1632,10 +1683,19 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset)
   _G.pairs[pairId].last_type = aop->type;
 }
 
   _G.pairs[pairId].last_type = aop->type;
 }
 
+/* Can be used for local labels where Code generation takes care of spilling */
+static void
+emitLabelNoSpill (int key)
+{
+  emit2 ("!tlabeldef", key);
+  _G.lines.current->isLabel = 1;
+}
+
 static void
 emitLabel (int key)
 {
   emit2 ("!tlabeldef", key);
 static void
 emitLabel (int key)
 {
   emit2 ("!tlabeldef", key);
+  _G.lines.current->isLabel = 1;
   spillCached ();
 }
 
   spillCached ();
 }
 
@@ -1801,11 +1861,9 @@ aopGet (asmop * aop, int offset, bool bit16)
     case AOP_PAIRPTR:
       setupPair (aop->aopu.aop_pairId, aop, offset);
       if (aop->aopu.aop_pairId==PAIR_IX)
     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)
       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);
       else
         SNPRINTF (buffer, sizeof(buffer),
                   "(%s)", _pairs[aop->aopu.aop_pairId].name);
@@ -2083,6 +2141,7 @@ aopPut (asmop * aop, const char *s, int offset)
 #define AOP_TYPE(op) AOP(op)->type
 #define AOP_SIZE(op) AOP(op)->size
 #define AOP_NEEDSACC(x) (AOP(x) && ((AOP_TYPE(x) == AOP_CRY) || (AOP_TYPE(x) == AOP_SFR)))
 #define AOP_TYPE(op) AOP(op)->type
 #define AOP_SIZE(op) AOP(op)->size
 #define AOP_NEEDSACC(x) (AOP(x) && ((AOP_TYPE(x) == AOP_CRY) || (AOP_TYPE(x) == AOP_SFR)))
+#define AOP_IS_PAIRPTR(x, p) (AOP_TYPE (x) == AOP_PAIRPTR && AOP (x)->aopu.aop_pairId == p)
 
 static void
 commitPair (asmop * aop, PAIR_ID id)
 
 static void
 commitPair (asmop * aop, PAIR_ID id)
@@ -2223,29 +2282,22 @@ outAcc (operand * result)
 /** Take the value in carry and put it into a register
  */
 void
 /** Take the value in carry and put it into a register
  */
 void
-outBitCLong (operand * result, bool swap_sense)
+outBitC (operand * result)
 {
   /* if the result is bit */
   if (AOP_TYPE (result) == AOP_CRY)
     {
 {
   /* if the result is bit */
   if (AOP_TYPE (result) == AOP_CRY)
     {
-      wassertl (0, "Tried to write carry to a bit");
+      if (!IS_OP_RUONLY (result))
+        aopPut (AOP (result), "c", 0);
     }
   else
     {
       emit2 ("ld a,!zero");
       emit2 ("rla");
     }
   else
     {
       emit2 ("ld a,!zero");
       emit2 ("rla");
-      if (swap_sense)
-        emit2 ("xor a,!immedbyte", 1);
       outAcc (result);
     }
 }
 
       outAcc (result);
     }
 }
 
-void
-outBitC (operand * result)
-{
-  outBitCLong (result, FALSE);
-}
-
 /*-----------------------------------------------------------------*/
 /* toBoolean - emit code for orl a,operator(sizeop)                */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 /* toBoolean - emit code for orl a,operator(sizeop)                */
 /*-----------------------------------------------------------------*/
@@ -2513,7 +2565,17 @@ assignResultValue (operand * oper)
     }
   else
     {
     }
   else
     {
-      while (size--)
+      if ((AOP_TYPE (oper) == AOP_REG) && (AOP_SIZE (oper) == 4) &&
+          !strcmp (AOP (oper)->aopu.aop_reg[size-1]->name, _fReturn[size-2]))
+        {
+          size--;
+          _emitMove ("a", _fReturn[size-1]);
+          _emitMove (_fReturn[size-1], _fReturn[size]);
+          _emitMove (_fReturn[size], "a");
+          aopPut (AOP (oper), _fReturn[size], size-1);
+          size--;
+        }
+      while(size--)
         {
           aopPut (AOP (oper), _fReturn[size], size);
         }
         {
           aopPut (AOP (oper), _fReturn[size], size);
         }
@@ -2656,7 +2718,6 @@ genIpush (iCode * ic)
         {
           fetchHL (AOP (IC_LEFT (ic)));
           emit2 ("push hl");
         {
           fetchHL (AOP (IC_LEFT (ic)));
           emit2 ("push hl");
-          spillPair (PAIR_HL);
           _G.stack.pushed += 2;
           goto release;
         }
           _G.stack.pushed += 2;
           goto release;
         }
@@ -2664,11 +2725,9 @@ genIpush (iCode * ic)
         {
           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
           emit2 ("push hl");
         {
           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
           emit2 ("push hl");
-          spillPair (PAIR_HL);
           _G.stack.pushed += 2;
           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 0);
           emit2 ("push hl");
           _G.stack.pushed += 2;
           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 0);
           emit2 ("push hl");
-          spillPair (PAIR_HL);
           _G.stack.pushed += 2;
           goto release;
         }
           _G.stack.pushed += 2;
           goto release;
         }
@@ -2680,13 +2739,23 @@ genIpush (iCode * ic)
               char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
               wassert (l);
               emit2 ("ld a,(%s)", l);
               char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
               wassert (l);
               emit2 ("ld a,(%s)", l);
+              emit2 ("push af");
             }
           else
             {
               l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
             }
           else
             {
               l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
-              emit2 ("ld a,%s", l);
+              if (!strcmp(l, "b"))
+                emit2 ("push bc");
+              else if (!strcmp(l, "d"))
+                emit2 ("push de");
+              else if (!strcmp(l, "h"))
+                emit2 ("push hl");
+              else
+                {
+                  emit2 ("ld a,%s", l);
+                  emit2 ("push af");
+                }
             }
             }
-          emit2 ("push af");
           emit2 ("inc sp");
           _G.stack.pushed++;
         }
           emit2 ("inc sp");
           _G.stack.pushed++;
         }
@@ -2899,6 +2968,7 @@ emitCall (iCode * ic, bool ispcall)
           fetchHL (AOP (IC_LEFT (ic)));
           emit2 ("jp !*hl");
           emit2 ("!tlabeldef", (rlbl->key + 100));
           fetchHL (AOP (IC_LEFT (ic)));
           emit2 ("jp !*hl");
           emit2 ("!tlabeldef", (rlbl->key + 100));
+          _G.lines.current->isLabel = 1;
           _G.stack.pushed -= 2;
         }
       freeAsmop (IC_LEFT (ic), NULL, ic);
           _G.stack.pushed -= 2;
         }
       freeAsmop (IC_LEFT (ic), NULL, ic);
@@ -2925,20 +2995,6 @@ emitCall (iCode * ic, bool ispcall)
   /* Mark the registers as restored. */
   _G.saves.saved = FALSE;
 
   /* 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)
     {
   /* adjust the stack for parameters if required */
   if (ic->parmBytes)
     {
@@ -2973,6 +3029,19 @@ emitCall (iCode * ic, bool ispcall)
         }
     }
 
         }
     }
 
+  /* 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))
     {
   spillCached ();
   if (IC_RESULT (ic))
     {
@@ -3112,8 +3181,10 @@ genFunction (iCode * ic)
     {
       sprintf (buffer, "%s_start", sym->rname);
       emit2 ("!labeldef", buffer);
     {
       sprintf (buffer, "%s_start", sym->rname);
       emit2 ("!labeldef", buffer);
+      _G.lines.current->isLabel = 1;
     }
   emit2 ("!functionlabeldef", sym->rname);
     }
   emit2 ("!functionlabeldef", sym->rname);
+  _G.lines.current->isLabel = 1;
 
   ftype = operandType (IC_LEFT (ic));
 
 
   ftype = operandType (IC_LEFT (ic));
 
@@ -3242,7 +3313,22 @@ genFunction (iCode * ic)
   else if (sym->stack && IS_GB && sym->stack > -INT8MIN)
     emit2 ("!enterxl", sym->stack);
   else if (sym->stack)
   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");
 
   else
     emit2 ("!enter");
 
@@ -3329,9 +3415,10 @@ genEndFunction (iCode * ic)
               emit2 ("pop af");
               //parity odd <==> P/O=0 <==> interrupt enable flag IFF2 was 0 <==>
               //don't enable interrupts as they were off before
               emit2 ("pop 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);
+              emit2 ("jp PO,!tlabel", tlbl->key + 100);
               emit2 ("!ei");
               emit2 ("!tlabeldef", (tlbl->key + 100));
               emit2 ("!ei");
               emit2 ("!tlabeldef", (tlbl->key + 100));
+              _G.lines.current->isLabel = 1;
             }
         }
     }
             }
         }
     }
@@ -3359,6 +3446,7 @@ genEndFunction (iCode * ic)
     {
       sprintf (buffer, "%s_end", sym->rname);
       emit2 ("!labeldef", buffer);
     {
       sprintf (buffer, "%s_end", sym->rname);
       emit2 ("!labeldef", buffer);
+      _G.lines.current->isLabel = 1;
     }
 
   _G.flushStatics = 1;
     }
 
   _G.flushStatics = 1;
@@ -3476,7 +3564,7 @@ genPlusIncr (iCode * ic)
 
   emitDebug ("; genPlusIncr");
 
 
   emitDebug ("; genPlusIncr");
 
-  icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+  icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
 
   /* If result is a pair */
   if (resultId != PAIR_INVALID)
 
   /* If result is a pair */
   if (resultId != PAIR_INVALID)
@@ -3547,10 +3635,10 @@ genPlusIncr (iCode * ic)
           emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
           if (size)
             {
           emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
           if (size)
             {
-              emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+              emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
             }
         }
             }
         }
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
       return TRUE;
     }
 
       return TRUE;
     }
 
@@ -3600,9 +3688,9 @@ outBitAcc (operand * result)
     }
   else
     {
     }
   else
     {
-      emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
+      emit2 ("!shortjp Z,!tlabel", tlbl->key + 100);
       emit2 ("ld a,!one");
       emit2 ("ld a,!one");
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
       outAcc (result);
     }
 }
       outAcc (result);
     }
 }
@@ -3749,8 +3837,6 @@ genPlus (iCode * ic)
   if (genPlusIncr (ic) == TRUE)
     goto release;
 
   if (genPlusIncr (ic) == TRUE)
     goto release;
 
-  emitDebug ("; Can't optimise plus by inc, falling back to the normal way");
-
   size = getDataSize (IC_RESULT (ic));
 
   /* Special case when left and right are constant */
   size = getDataSize (IC_RESULT (ic));
 
   /* Special case when left and right are constant */
@@ -3812,7 +3898,16 @@ genPlus (iCode * ic)
     {
       fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
       emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
     {
       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;
     }
       commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
       goto release;
     }
@@ -3890,28 +3985,62 @@ genPlus (iCode * ic)
 
   setupToPreserveCarry (ic);
 
 
   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
         {
         }
       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
           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)
+      {
+        if(size == 0 && AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT && ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) == 1)
+          emit2 ("inc a");
+        else
+          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++);
     }
 
       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
     }
 
@@ -3938,7 +4067,7 @@ genMinusDec (iCode * ic)
 
   /* if the literal value of the right hand side
      is greater than 4 then it is not worth it */
 
   /* if the literal value of the right hand side
      is greater than 4 then it is not worth it */
-  if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
+  if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
     return FALSE;
 
   size = getDataSize (IC_RESULT (ic));
     return FALSE;
 
   size = getDataSize (IC_RESULT (ic));
@@ -4028,7 +4157,7 @@ genMinus (iCode * ic)
     }
   else
     {
     }
   else
     {
-      lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+      lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
       lit = -(long) lit;
     }
 
       lit = -(long) lit;
     }
 
@@ -4104,7 +4233,12 @@ genMinus (iCode * ic)
         {
           /* first add without previous c */
           if (!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));
         }
           else
             emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
         }
@@ -4125,6 +4259,72 @@ release:
   freeAsmop (IC_RESULT (ic), NULL, ic);
 }
 
   freeAsmop (IC_RESULT (ic), NULL, ic);
 }
 
+/*-----------------------------------------------------------------*/
+/* genMultChar - generates code for unsigned 8x8 multiplication    */
+/*-----------------------------------------------------------------*/
+static void
+genMultOneChar (iCode * ic)
+{
+  symbol *tlbl1, *tlbl2;
+  bool savedB = FALSE;
+
+  if(IS_GB)
+    {
+      wassertl (0, "Multiplication is handled through support function calls on gbz80");
+      return;
+    }
+
+  /* Save b into a if b is in use. */
+  if (bitVectBitValue (ic->rMask, B_IDX) &&
+    !(getPairId (AOP (IC_RESULT (ic))) == PAIR_BC))
+    {
+      emit2 ("ld a, b");
+      savedB = TRUE;
+    }
+  if (isPairInUse (PAIR_DE, ic) &&
+    !(getPairId (AOP (IC_RESULT (ic))) == PAIR_DE))
+  {
+    _push (PAIR_DE);
+    _G.stack.pushedDE = TRUE;
+  }
+
+  tlbl1 = newiTempLabel (NULL);
+  tlbl2 = newiTempLabel (NULL);
+
+  emit2 ("ld e,%s", aopGet (AOP (IC_RIGHT (ic)), LSB, FALSE));
+  emit2 ("ld h,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE));
+  emit2 ("ld l,#0x00");
+  emit2 ("ld d,l");
+  emit2 ("ld b,#0x08");
+  emitLabelNoSpill (tlbl1->key + 100);
+  emit2 ("add hl,hl");
+  emit2 ("jp NC,!tlabel", tlbl2->key + 100);
+  emit2 ("add hl,de");
+  emitLabelNoSpill (tlbl2->key + 100);
+  emit2 ("djnz !tlabel", tlbl1->key + 100);
+
+  spillPair(PAIR_HL);
+
+  if (IS_Z80 && _G.stack.pushedDE)
+    {
+      _pop (PAIR_DE);
+      _G.stack.pushedDE = FALSE;
+    }
+  if (savedB)
+    {
+      emit2 ("ld b, a");
+    }
+
+  if (AOP_SIZE (IC_RESULT (ic)) == 1)
+    aopPut (AOP (IC_RESULT (ic)), "l", 0);
+  else
+    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);
+}
+
 /*-----------------------------------------------------------------*/
 /* genMult - generates code for multiplication                     */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 /* genMult - generates code for multiplication                     */
 /*-----------------------------------------------------------------*/
@@ -4159,9 +4359,15 @@ genMult (iCode * ic)
       IC_LEFT (ic) = t;
     }
 
       IC_LEFT (ic) = t;
     }
 
+  if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
+    {
+      genMultOneChar (ic);
+      return;
+    }
+
   wassertl (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT, "Right must be a literal");
 
   wassertl (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT, "Right must be a literal");
 
-  val = (int)floatFromVal ( AOP (IC_RIGHT (ic))->aopu.aop_lit);
+  val = (int) ulFromVal ( AOP (IC_RIGHT (ic))->aopu.aop_lit);
   //  wassertl (val > 0, "Multiply must be positive");
   wassertl (val != 1, "Can't multiply by 1");
 
   //  wassertl (val > 0, "Multiply must be positive");
   wassertl (val != 1, "Can't multiply by 1");
 
@@ -4170,7 +4376,9 @@ genMult (iCode * ic)
     _G.stack.pushedDE = TRUE;
   }
 
     _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)
     {
       emit2 ("ld e,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE));
       if (!byteResult)
@@ -4188,32 +4396,40 @@ genMult (iCode * ic)
 
   i = val;
 
 
   i = val;
 
-  /* Fully unroled version of mul.s.  Not the most efficient.
-   */
   for (count = 0; count < 16; count++)
     {
       if (count != 0 && active)
         {
   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)
             {
         }
       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
             {
             }
           else
             {
-              emit2 ("add hl,de");
+              if (byteResult)
+                emit2 ("add a,e");
+              else
+                emit2 ("add hl,de");
             }
           active = TRUE;
         }
       i <<= 1;
     }
 
             }
           active = TRUE;
         }
       i <<= 1;
     }
 
-  spillCached();
+  spillPair(PAIR_HL);
 
   if (IS_Z80 && _G.stack.pushedDE)
     {
 
   if (IS_Z80 && _G.stack.pushedDE)
     {
@@ -4222,7 +4438,7 @@ genMult (iCode * ic)
     }
 
   if (byteResult)
     }
 
   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);
 
   else
     commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
 
@@ -4267,28 +4483,28 @@ genIfxJump (iCode * ic, char *jval)
       jlbl = IC_TRUE (ic);
       if (!strcmp (jval, "a"))
         {
       jlbl = IC_TRUE (ic);
       if (!strcmp (jval, "a"))
         {
-          inst = "nz";
+          inst = "NZ";
         }
       else if (!strcmp (jval, "c"))
         {
         }
       else if (!strcmp (jval, "c"))
         {
-          inst = "c";
+          inst = "C";
         }
       else if (!strcmp (jval, "nc"))
         {
         }
       else if (!strcmp (jval, "nc"))
         {
-          inst = "nc";
+          inst = "NC";
         }
       else if (!strcmp (jval, "m"))
         {
         }
       else if (!strcmp (jval, "m"))
         {
-          inst = "m";
+          inst = "M";
         }
       else if (!strcmp (jval, "p"))
         {
         }
       else if (!strcmp (jval, "p"))
         {
-          inst = "p";
+          inst = "P";
         }
       else
         {
           /* The buffer contains the bit on A that we should test */
         }
       else
         {
           /* The buffer contains the bit on A that we should test */
-          inst = "nz";
+          inst = "NZ";
         }
     }
   else
         }
     }
   else
@@ -4297,28 +4513,28 @@ genIfxJump (iCode * ic, char *jval)
       jlbl = IC_FALSE (ic);
       if (!strcmp (jval, "a"))
         {
       jlbl = IC_FALSE (ic);
       if (!strcmp (jval, "a"))
         {
-          inst = "z";
+          inst = "Z";
         }
       else if (!strcmp (jval, "c"))
         {
         }
       else if (!strcmp (jval, "c"))
         {
-          inst = "nc";
+          inst = "NC";
         }
       else if (!strcmp (jval, "nc"))
         {
         }
       else if (!strcmp (jval, "nc"))
         {
-          inst = "c";
+          inst = "C";
         }
       else if (!strcmp (jval, "m"))
         {
         }
       else if (!strcmp (jval, "m"))
         {
-          inst = "p";
+          inst = "P";
         }
       else if (!strcmp (jval, "p"))
         {
         }
       else if (!strcmp (jval, "p"))
         {
-          inst = "m";
+          inst = "M";
         }
       else
         {
           /* The buffer contains the bit on A that we should test */
         }
       else
         {
           /* The buffer contains the bit on A that we should test */
-          inst = "z";
+          inst = "Z";
         }
     }
   /* Z80 can do a conditional long jump */
         }
     }
   /* Z80 can do a conditional long jump */
@@ -4452,7 +4668,7 @@ _getPairIdName (PAIR_ID id)
         {
           if (AOP_TYPE (right) == AOP_LIT)
             {
         {
           if (AOP_TYPE (right) == AOP_LIT)
             {
-              lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+              lit = ulFromVal (AOP (right)->aopu.aop_lit);
               /* optimize if(x < 0) or if(x >= 0) */
               if (lit == 0L)
                 {
               /* optimize if(x < 0) or if(x >= 0) */
               if (lit == 0L)
                 {
@@ -4483,8 +4699,7 @@ _getPairIdName (PAIR_ID id)
               bool fDidXor = FALSE;
               if (AOP_TYPE (left) == AOP_LIT)
                 {
               bool fDidXor = FALSE;
               if (AOP_TYPE (left) == AOP_LIT)
                 {
-                  unsigned long lit = (unsigned long)
-                  floatFromVal (AOP (left)->aopu.aop_lit);
+                  unsigned long lit = ulFromVal (AOP (left)->aopu.aop_lit);
                   emit2 ("ld %s,!immedbyte", _fTmp[0],
                          0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
                 }
                   emit2 ("ld %s,!immedbyte", _fTmp[0],
                          0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
                 }
@@ -4497,8 +4712,7 @@ _getPairIdName (PAIR_ID id)
                 }
               if (AOP_TYPE (right) == AOP_LIT)
                 {
                 }
               if (AOP_TYPE (right) == AOP_LIT)
                 {
-                  unsigned long lit = (unsigned long)
-                  floatFromVal (AOP (right)->aopu.aop_lit);
+                  unsigned long lit = ulFromVal (AOP (right)->aopu.aop_lit);
                   emit2 ("ld %s,!immedbyte", _fTmp[1],
                          0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
                 }
                   emit2 ("ld %s,!immedbyte", _fTmp[1],
                          0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
                 }
@@ -4541,7 +4755,6 @@ genCmp (operand * left, operand * right,
 {
   int size, offset = 0;
   unsigned long lit = 0L;
 {
   int size, offset = 0;
   unsigned long lit = 0L;
-  bool swap_sense = FALSE;
 
   /* if left & right are bit variables */
   if (AOP_TYPE (left) == AOP_CRY &&
 
   /* if left & right are bit variables */
   if (AOP_TYPE (left) == AOP_CRY &&
@@ -4582,7 +4795,7 @@ genCmp (operand * left, operand * right,
 
       if (AOP_TYPE (right) == AOP_LIT)
         {
 
       if (AOP_TYPE (right) == AOP_LIT)
         {
-          lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+          lit = ulFromVal (AOP (right)->aopu.aop_lit);
           /* optimize if(x < 0) or if(x >= 0) */
           if (lit == 0)
             {
           /* optimize if(x < 0) or if(x >= 0) */
           if (lit == 0)
             {
@@ -4608,7 +4821,7 @@ genCmp (operand * left, operand * right,
                         }
                       if (ifx)
                         {
                         }
                       if (ifx)
                         {
-                          genIfxJump (ifx, swap_sense ? "c" : "nc");
+                          genIfxJump (ifx, "nc");
                           return;
                         }
                     }
                           return;
                         }
                     }
@@ -4634,7 +4847,7 @@ release:
           /* Shift the sign bit up into carry */
           emit2 ("rlca");
         }
           /* Shift the sign bit up into carry */
           emit2 ("rlca");
         }
-      outBitCLong (result, swap_sense);
+      outBitC (result);
     }
   else
     {
     }
   else
     {
@@ -4648,16 +4861,16 @@ release:
               if (IS_GB)
                 {
                   emit2 ("rlca");
               if (IS_GB)
                 {
                   emit2 ("rlca");
-                  genIfxJump (ifx, swap_sense ? "nc" : "c");
+                  genIfxJump (ifx, "c");
                 }
               else
                 {
                 }
               else
                 {
-                  genIfxJump (ifx, swap_sense ? "p" : "m");
+                  genIfxJump (ifx, "m");
                 }
             }
           else
             {
                 }
             }
           else
             {
-              genIfxJump (ifx, swap_sense ? "nc" : "c");
+              genIfxJump (ifx, "c");
             }
         }
       else
             }
         }
       else
@@ -4667,7 +4880,7 @@ release:
               /* Shift the sign bit up into carry */
               emit2 ("rlca");
             }
               /* Shift the sign bit up into carry */
               emit2 ("rlca");
             }
-          outBitCLong (result, swap_sense);
+          outBitC (result);
         }
       /* leave the result in acc */
     }
         }
       /* leave the result in acc */
     }
@@ -4690,13 +4903,16 @@ genCmpGt (iCode * ic, iCode * ifx)
   letype = getSpec (operandType (left));
   retype = getSpec (operandType (right));
   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
   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);
 
   aopOp (left, ic, FALSE, FALSE);
   aopOp (right, ic, FALSE, FALSE);
   aopOp (result, ic, TRUE, FALSE);
 
+  setupToPreserveCarry (ic);
+
   genCmp (right, left, result, ifx, sign);
 
   genCmp (right, left, result, ifx, sign);
 
+  _G.preserveCarry = FALSE;
   freeAsmop (left, NULL, ic);
   freeAsmop (right, NULL, ic);
   freeAsmop (result, NULL, ic);
   freeAsmop (left, NULL, ic);
   freeAsmop (right, NULL, ic);
   freeAsmop (result, NULL, ic);
@@ -4720,13 +4936,16 @@ genCmpLt (iCode * ic, iCode * ifx)
   retype = getSpec (operandType (right));
   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
 
   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);
 
   aopOp (left, ic, FALSE, FALSE);
   aopOp (right, ic, FALSE, FALSE);
   aopOp (result, ic, TRUE, FALSE);
 
+  setupToPreserveCarry (ic);
+
   genCmp (left, right, result, ifx, sign);
 
   genCmp (left, right, result, ifx, sign);
 
+  _G.preserveCarry = FALSE;
   freeAsmop (left, NULL, ic);
   freeAsmop (right, NULL, ic);
   freeAsmop (result, NULL, ic);
   freeAsmop (left, NULL, ic);
   freeAsmop (right, NULL, ic);
   freeAsmop (result, NULL, ic);
@@ -4734,8 +4953,9 @@ genCmpLt (iCode * ic, iCode * ifx)
 
 /*-----------------------------------------------------------------*/
 /* gencjneshort - compare and jump if not equal                    */
 
 /*-----------------------------------------------------------------*/
 /* gencjneshort - compare and jump if not equal                    */
+/* returns pair that still needs to be popped                      */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
-static void
+static PAIR_ID
 gencjneshort (operand * left, operand * right, symbol * lbl)
 {
   int size = max (AOP_SIZE (left), AOP_SIZE (right));
 gencjneshort (operand * left, operand * right, symbol * lbl)
 {
   int size = max (AOP_SIZE (left), AOP_SIZE (right));
@@ -4750,18 +4970,13 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
       left = t;
     }
 
       left = t;
     }
 
-  if (AOP_TYPE (right) == AOP_LIT)
-    {
-      lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
-    }
-
   /* if the right side is a literal then anything goes */
   /* if the right side is a literal then anything goes */
-  if (AOP_TYPE (right) == AOP_LIT &&
-      AOP_TYPE (left) != AOP_DIR)
+  if (AOP_TYPE (right) == AOP_LIT)
     {
     {
+      lit = ulFromVal (AOP (right)->aopu.aop_lit);
       if (lit == 0)
         {
       if (lit == 0)
         {
-          emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
+          _moveA (aopGet (AOP (left), offset, FALSE));
           if (size > 1)
             {
               while (--size)
           if (size > 1)
             {
               while (--size)
@@ -4773,55 +4988,74 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
             {
               emit2 ("or a,a");
             }
             {
               emit2 ("or a,a");
             }
-          emit2 ("jp nz,!tlabel", lbl->key + 100);
+          emit2 ("jp NZ,!tlabel", lbl->key + 100);
         }
       else
         {
           while (size--)
             {
         }
       else
         {
           while (size--)
             {
-              emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
-              if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
+              _moveA (aopGet (AOP (left), offset, FALSE));
+              if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
                 emit2 ("or a,a");
               else
                 emit2 ("or a,a");
               else
-                emit2 ("cp a,%s", aopGet (AOP (right), offset, FALSE));
-              emit2 ("jp nz,!tlabel", lbl->key + 100);
+                emit2 ("sub a,%s", aopGet (AOP (right), offset, FALSE));
+              emit2 ("jp NZ,!tlabel", lbl->key + 100);
               offset++;
             }
         }
     }
               offset++;
             }
         }
     }
-  /* if the right side is in a register or in direct space or
-     if the left is a pointer register & right is not */
+  /* if the right side is in a register or
+     pointed to by HL, IX or IY */
   else if (AOP_TYPE (right) == AOP_REG ||
   else if (AOP_TYPE (right) == AOP_REG ||
-           AOP_TYPE (right) == AOP_DIR ||
-           (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
+           AOP_TYPE (right) == AOP_HL  ||
+           AOP_TYPE (right) == AOP_IY  ||
+           AOP_TYPE (right) == AOP_STK ||
+           AOP_IS_PAIRPTR (right, PAIR_HL) ||
+           AOP_IS_PAIRPTR (right, PAIR_IX) ||
+           AOP_IS_PAIRPTR (right, PAIR_IY))
     {
       while (size--)
         {
           _moveA (aopGet (AOP (left), offset, FALSE));
     {
       while (size--)
         {
           _moveA (aopGet (AOP (left), offset, FALSE));
-          if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
+          if (AOP_TYPE (right) == AOP_LIT &&
               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
-            /* PENDING */
-            emit2 ("jp nz,!tlabel", lbl->key + 100);
+            {
+              emit2 ("or a,a");
+              emit2 ("jp NZ,!tlabel", lbl->key + 100);
+            }
           else
             {
           else
             {
-              emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
-              emit2 ("jp nz,!tlabel", lbl->key + 100);
+              emit2 ("sub a,%s", aopGet (AOP (right), offset, FALSE));
+              emit2 ("jp NZ,!tlabel", lbl->key + 100);
             }
           offset++;
         }
     }
             }
           offset++;
         }
     }
+  /* right is in direct space or a pointer reg, need both a & b */
   else
     {
   else
     {
-      /* right is a pointer reg need both a & b */
-      /* PENDING: is this required? */
+      PAIR_ID pair;
+      for (pair = PAIR_BC; pair <= PAIR_HL; pair++)
+        {
+          if (((AOP_TYPE (left)  != AOP_PAIRPTR) || (AOP (left)->aopu.aop_pairId  != pair)) &&
+              ((AOP_TYPE (right) != AOP_PAIRPTR) || (AOP (right)->aopu.aop_pairId != pair)))
+            {
+              break;
+            }
+        }
+      _push (pair);
       while (size--)
         {
       while (size--)
         {
+          emit2 ("; direct compare");
+          _emitMove (_pairs[pair].l, aopGet (AOP (left), offset, FALSE));
           _moveA (aopGet (AOP (right), offset, FALSE));
           _moveA (aopGet (AOP (right), offset, FALSE));
-          emit2 ("cp %s", aopGet (AOP (left), offset, FALSE));
-          emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
+          emit2 ("sub a,%s", _pairs[pair].l);
+          emit2 ("!shortjp NZ,!tlabel", lbl->key + 100);
           offset++;
         }
           offset++;
         }
+      return pair;
     }
     }
+  return PAIR_INVALID;
 }
 
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
@@ -4832,14 +5066,15 @@ gencjne (operand * left, operand * right, symbol * lbl)
 {
   symbol *tlbl = newiTempLabel (NULL);
 
 {
   symbol *tlbl = newiTempLabel (NULL);
 
-  gencjneshort (left, right, lbl);
+  PAIR_ID pop = gencjneshort (left, right, lbl);
 
   /* PENDING: ?? */
   emit2 ("ld a,!one");
   emit2 ("!shortjp !tlabel", tlbl->key + 100);
   emitLabel (lbl->key + 100);
   emit2 ("xor a,a");
 
   /* PENDING: ?? */
   emit2 ("ld a,!one");
   emit2 ("!shortjp !tlabel", tlbl->key + 100);
   emitLabel (lbl->key + 100);
   emit2 ("xor a,a");
-  emitLabel (tlbl->key + 100);
+  emitLabelNoSpill (tlbl->key + 100);
+  _pop (pop);
 }
 
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
@@ -4877,21 +5112,26 @@ genCmpEq (iCode * ic, iCode * ifx)
         }
       else
         {
         }
       else
         {
+          PAIR_ID pop;
           tlbl = newiTempLabel (NULL);
           tlbl = newiTempLabel (NULL);
-          gencjneshort (left, right, tlbl);
+          pop = gencjneshort (left, right, tlbl);
           if (IC_TRUE (ifx))
             {
           if (IC_TRUE (ifx))
             {
+              _pop (pop);
               emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
               emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
-              emitLabel (tlbl->key + 100);
+              emitLabelNoSpill (tlbl->key + 100);
+              _pop (pop);
             }
           else
             {
               /* PENDING: do this better */
               symbol *lbl = newiTempLabel (NULL);
             }
           else
             {
               /* PENDING: do this better */
               symbol *lbl = newiTempLabel (NULL);
+              _pop (pop);
               emit2 ("!shortjp !tlabel", lbl->key + 100);
               emit2 ("!shortjp !tlabel", lbl->key + 100);
-              emitLabel (tlbl->key + 100);
+              emitLabelNoSpill (tlbl->key + 100);
+              _pop (pop);
               emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
               emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
-              emitLabel (lbl->key + 100);
+              emitLabelNoSpill (lbl->key + 100);
             }
         }
       /* mark the icode as generated */
             }
         }
       /* mark the icode as generated */
@@ -4984,9 +5224,9 @@ genAndOp (iCode * ic)
     {
       tlbl = newiTempLabel (NULL);
       _toBoolean (left);
     {
       tlbl = newiTempLabel (NULL);
       _toBoolean (left);
-      emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
+      emit2 ("!shortjp Z,!tlabel", tlbl->key + 100);
       _toBoolean (right);
       _toBoolean (right);
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
       outBitAcc (result);
     }
 
       outBitAcc (result);
     }
 
@@ -5021,9 +5261,9 @@ genOrOp (iCode * ic)
     {
       tlbl = newiTempLabel (NULL);
       _toBoolean (left);
     {
       tlbl = newiTempLabel (NULL);
       _toBoolean (left);
-      emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+      emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
       _toBoolean (right);
       _toBoolean (right);
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
       outBitAcc (result);
     }
 
       outBitAcc (result);
     }
 
@@ -5065,14 +5305,14 @@ jmpTrueOrFalse (iCode * ic, symbol * tlbl)
     {
       symbol *nlbl = newiTempLabel (NULL);
       emit2 ("jp !tlabel", nlbl->key + 100);
     {
       symbol *nlbl = newiTempLabel (NULL);
       emit2 ("jp !tlabel", nlbl->key + 100);
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
       emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
       emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
-      emitLabel (nlbl->key + 100);
+      emitLabelNoSpill (nlbl->key + 100);
     }
   else
     {
       emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
     }
   else
     {
       emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
     }
   ic->generated = 1;
 }
     }
   ic->generated = 1;
 }
@@ -5118,7 +5358,7 @@ genAnd (iCode * ic, iCode * ifx)
       left = tmp;
     }
   if (AOP_TYPE (right) == AOP_LIT)
       left = tmp;
     }
   if (AOP_TYPE (right) == AOP_LIT)
-    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+    lit = ulFromVal (AOP (right)->aopu.aop_lit);
 
   size = AOP_SIZE (result);
 
 
   size = AOP_SIZE (result);
 
@@ -5155,7 +5395,8 @@ genAnd (iCode * ic, iCode * ifx)
                   /* For the flags */
                   emit2 ("or a,a");
                 }
                   /* For the flags */
                   emit2 ("or a,a");
                 }
-              emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+          if (size || ifx)  /* emit jmp only, if it is actually used */
+              emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
             }
               offset++;
         }
             }
               offset++;
         }
@@ -5164,6 +5405,7 @@ genAnd (iCode * ic, iCode * ifx)
         {
           emit2 ("clr c");
           emit2 ("!tlabeldef", tlbl->key + 100);
         {
           emit2 ("clr c");
           emit2 ("!tlabeldef", tlbl->key + 100);
+          _G.lines.current->isLabel = 1;
         }
       // if(left & literal)
       else
         }
       // if(left & literal)
       else
@@ -5308,7 +5550,7 @@ genOr (iCode * ic, iCode * ifx)
       left = tmp;
     }
   if (AOP_TYPE (right) == AOP_LIT)
       left = tmp;
     }
   if (AOP_TYPE (right) == AOP_LIT)
-    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+    lit = ulFromVal (AOP (right)->aopu.aop_lit);
 
   size = AOP_SIZE (result);
 
 
   size = AOP_SIZE (result);
 
@@ -5337,9 +5579,19 @@ genOr (iCode * ic, iCode * ifx)
           bytelit = (lit >> (offset * 8)) & 0x0FFL;
 
           _moveA (aopGet (AOP (left), offset, FALSE));
           bytelit = (lit >> (offset * 8)) & 0x0FFL;
 
           _moveA (aopGet (AOP (left), offset, FALSE));
-          /* OR with any literal is the same as OR with itself. */
-          emit2 ("or a,a");
-          emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+
+          if (bytelit != 0)
+            { /* FIXME, allways true, shortcut possible */
+              emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
+            }
+          else
+            {
+              /* For the flags */
+              emit2 ("or a,a");
+            }
+
+          if (ifx)  /* emit jmp only, if it is actually used */
+            emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
 
           offset++;
         }
 
           offset++;
         }
@@ -5466,7 +5718,7 @@ genXor (iCode * ic, iCode * ifx)
       left = tmp;
     }
   if (AOP_TYPE (right) == AOP_LIT)
       left = tmp;
     }
   if (AOP_TYPE (right) == AOP_LIT)
-    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+    lit = ulFromVal (AOP (right)->aopu.aop_lit);
 
   size = AOP_SIZE (result);
 
 
   size = AOP_SIZE (result);
 
@@ -5494,7 +5746,7 @@ genXor (iCode * ic, iCode * ifx)
         {
           _moveA (aopGet (AOP (left), offset, FALSE));
           emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
         {
           _moveA (aopGet (AOP (left), offset, FALSE));
           emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
-          emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+          emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
           offset++;
         }
       if (ifx)
           offset++;
         }
       if (ifx)
@@ -5592,37 +5844,49 @@ static void
 genInline (iCode * ic)
 {
   char *buffer, *bp, *bp1;
 genInline (iCode * ic)
 {
   char *buffer, *bp, *bp1;
+  bool inComment = FALSE;
 
   _G.lines.isInline += (!options.asmpeep);
 
 
   _G.lines.isInline += (!options.asmpeep);
 
-  buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
-  strcpy (buffer, IC_INLINE (ic));
+  buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
 
   /* emit each line as a code */
   while (*bp)
     {
 
   /* emit each line as a code */
   while (*bp)
     {
-      if (*bp == '\n')
+      switch (*bp)
         {
         {
+        case ';':
+          inComment = TRUE;
+          ++bp;
+          break;
+
+        case '\n':
+          inComment = FALSE;
           *bp++ = '\0';
           emit2 (bp1);
           bp1 = bp;
           *bp++ = '\0';
           emit2 (bp1);
           bp1 = bp;
-        }
-      else
-        {
-          if (*bp == ':')
+          break;
+
+        default:
+          /* Add \n for labels, not dirs such as c:\mydir */
+          if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
             {
             {
-              bp++;
+              ++bp;
               *bp = '\0';
               *bp = '\0';
-              bp++;
+              ++bp;
               emit2 (bp1);
               bp1 = bp;
             }
           else
               emit2 (bp1);
               bp1 = bp;
             }
           else
-            bp++;
+            ++bp;
+          break;
         }
     }
   if (bp1 != bp)
     emit2 (bp1);
         }
     }
   if (bp1 != bp)
     emit2 (bp1);
+
+  Safe_free (buffer);
+
   _G.lines.isInline -= (!options.asmpeep);
 
 }
   _G.lines.isInline -= (!options.asmpeep);
 
 }
@@ -5707,7 +5971,7 @@ shiftR2Left2Result (operand * left, int offl,
                     int shCount, int is_signed)
 {
   int size = 2;
                     int shCount, int is_signed)
 {
   int size = 2;
-  symbol *tlbl, *tlbl1;
+  symbol *tlbl;
 
   movLeft2Result (left, offl, result, offr, 0);
   movLeft2Result (left, offl + 1, result, offr + 1, 0);
 
   movLeft2Result (left, offl, result, offr, 0);
   movLeft2Result (left, offl + 1, result, offr + 1, 0);
@@ -5718,10 +5982,10 @@ shiftR2Left2Result (operand * left, int offl,
   /*  if (AOP(result)->type == AOP_REG) { */
 
   tlbl = newiTempLabel (NULL);
   /*  if (AOP(result)->type == AOP_REG) { */
 
   tlbl = newiTempLabel (NULL);
-  tlbl1 = newiTempLabel (NULL);
 
   /* Left is already in result - so now do the shift */
 
   /* Left is already in result - so now do the shift */
-  if (shCount <= 4)
+  /* Optimizing for speed by default. */
+  if (!optimize.codeSize || shCount <= 2)
     {
       while (shCount--)
         {
     {
       while (shCount--)
         {
@@ -5730,15 +5994,14 @@ shiftR2Left2Result (operand * left, int offl,
     }
   else
     {
     }
   else
     {
-      emit2 ("ld a,!immedbyte+1", shCount);
-      emit2 ("!shortjp !tlabel", tlbl1->key + 100);
-      emitLabel (tlbl->key + 100);
+      emit2 ("ld a,!immedbyte", shCount);
+
+      emitLabelNoSpill (tlbl->key + 100);
 
       emitRsh2 (AOP (result), size, is_signed);
 
 
       emitRsh2 (AOP (result), size, is_signed);
 
-      emitLabel (tlbl1->key + 100);
       emit2 ("dec a");
       emit2 ("dec a");
-      emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+      emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
     }
 }
 
     }
 }
 
@@ -5807,7 +6070,7 @@ shiftL2Left2Result (operand * left, int offl,
           {
             emit2 ("ld a,!immedbyte+1", shCount);
             emit2 ("!shortjp !tlabel", tlbl1->key + 100);
           {
             emit2 ("ld a,!immedbyte+1", shCount);
             emit2 ("!shortjp !tlabel", tlbl1->key + 100);
-            emitLabel (tlbl->key + 100);
+            emitLabelNoSpill (tlbl->key + 100);
           }
 
         while (size--)
           }
 
         while (size--)
@@ -5827,9 +6090,9 @@ shiftL2Left2Result (operand * left, int offl,
           }
         if (shCount > 1)
           {
           }
         if (shCount > 1)
           {
-            emitLabel (tlbl1->key + 100);
+            emitLabelNoSpill (tlbl1->key + 100);
             emit2 ("dec a");
             emit2 ("dec a");
-            emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+            emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
           }
       }
   }
           }
       }
   }
@@ -5958,13 +6221,25 @@ shiftL1Left2Result (operand * left, int offl,
                     operand * result, int offr, int shCount)
 {
   const char *l;
                     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                */
 
 /*-----------------------------------------------------------------*/
 /* genlshTwo - left shift two bytes by known amount                */
@@ -6031,7 +6306,7 @@ genLeftShiftLiteral (operand * left,
                      operand * result,
                      iCode * ic)
 {
                      operand * result,
                      iCode * ic)
 {
-  int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+  int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
   int size;
 
   freeAsmop (right, NULL, ic);
   int size;
 
   freeAsmop (right, NULL, ic);
@@ -6134,7 +6409,7 @@ genLeftShift (iCode * ic)
      _pop (PAIR_AF);
 
   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
      _pop (PAIR_AF);
 
   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
-  emitLabel (tlbl->key + 100);
+  emitLabelNoSpill (tlbl->key + 100);
   l = aopGet (AOP (result), offset, FALSE);
 
   while (size--)
   l = aopGet (AOP (result), offset, FALSE);
 
   while (size--)
@@ -6151,9 +6426,9 @@ genLeftShift (iCode * ic)
         }
       offset++;
     }
         }
       offset++;
     }
-  emitLabel (tlbl1->key + 100);
+  emitLabelNoSpill (tlbl1->key + 100);
   emit2 ("dec a");
   emit2 ("dec a");
-  emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+  emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
 
   freeAsmop (left, NULL, ic);
   freeAsmop (result, NULL, ic);
 
   freeAsmop (left, NULL, ic);
   freeAsmop (result, NULL, ic);
@@ -6288,7 +6563,7 @@ genRightShiftLiteral (operand * left,
                       iCode * ic,
                       int sign)
 {
                       iCode * ic,
                       int sign)
 {
-  int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+  int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
   int size;
 
   freeAsmop (right, NULL, ic);
   int size;
 
   freeAsmop (right, NULL, ic);
@@ -6409,7 +6684,7 @@ genRightShift (iCode * ic)
      _pop (PAIR_AF);
 
   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
      _pop (PAIR_AF);
 
   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
-  emitLabel (tlbl->key + 100);
+  emitLabelNoSpill (tlbl->key + 100);
   while (size--)
     {
       l = aopGet (AOP (result), offset--, FALSE);
   while (size--)
     {
       l = aopGet (AOP (result), offset--, FALSE);
@@ -6423,9 +6698,9 @@ genRightShift (iCode * ic)
           emit2 ("rr %s", l);
         }
     }
           emit2 ("rr %s", l);
         }
     }
-  emitLabel (tlbl1->key + 100);
+  emitLabelNoSpill (tlbl1->key + 100);
   emit2 ("dec a");
   emit2 ("dec a");
-  emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+  emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
 
   freeAsmop (left, NULL, ic);
   freeAsmop (result, NULL, ic);
 
   freeAsmop (left, NULL, ic);
   freeAsmop (result, NULL, ic);
@@ -6464,9 +6739,9 @@ genUnpackBits (operand * result, int pair)
           symbol *tlbl = newiTempLabel (NULL);
 
           emit2 ("bit %d,a", blen - 1);
           symbol *tlbl = newiTempLabel (NULL);
 
           emit2 ("bit %d,a", blen - 1);
-          emit2 ("jp z,!tlabel", tlbl->key + 100);
+          emit2 ("jp Z,!tlabel", tlbl->key + 100);
           emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen));
           emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen));
-          emitLabel (tlbl->key + 100);
+          emitLabelNoSpill (tlbl->key + 100);
         }
       aopPut (AOP (result), "a", offset++);
       goto finish;
         }
       aopPut (AOP (result), "a", offset++);
       goto finish;
@@ -6486,11 +6761,10 @@ genUnpackBits (operand * result, int pair)
         {
           /* signed bitfield */
           symbol *tlbl = newiTempLabel (NULL);
         {
           /* signed bitfield */
           symbol *tlbl = newiTempLabel (NULL);
-
-          emit2 ("bit %d,a", blen - 1);
-          emit2 ("jp z,!tlabel", tlbl->key + 100);
-          emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen));
-          emitLabel (tlbl->key + 100);
+          emit2 ("bit %d,a", blen - 1 - 8);
+          emit2 ("jp Z,!tlabel", tlbl->key + 100);
+          emit2 ("or a,!immedbyte", (unsigned char) (0xff << (blen - 8)));
+          emitLabelNoSpill (tlbl->key + 100);
         }
       emit2 ("ld h,a");
       spillPair (PAIR_HL);
         }
       emit2 ("ld h,a");
       spillPair (PAIR_HL);
@@ -6521,9 +6795,9 @@ genUnpackBits (operand * result, int pair)
           symbol *tlbl = newiTempLabel (NULL);
 
           emit2 ("bit %d,a", rlen - 1);
           symbol *tlbl = newiTempLabel (NULL);
 
           emit2 ("bit %d,a", rlen - 1);
-          emit2 ("jp z,!tlabel", tlbl->key + 100);
+          emit2 ("jp Z,!tlabel", tlbl->key + 100);
           emit2 ("or a,!immedbyte", (unsigned char) (0xff << rlen));
           emit2 ("or a,!immedbyte", (unsigned char) (0xff << rlen));
-          emitLabel (tlbl->key + 100);
+          emitLabelNoSpill (tlbl->key + 100);
         }
       aopPut (AOP (result), "a", offset++);
     }
         }
       aopPut (AOP (result), "a", offset++);
     }
@@ -6746,7 +7020,7 @@ genPackBits (sym_link * etype,
         {
           /* Case with a bitfield length <8 and literal source
           */
         {
           /* Case with a bitfield length <8 and literal source
           */
-          litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+          litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
           litval <<= bstr;
           litval &= (~mask) & 0xff;
           emit2 ("ld a,!*pair", _pairs[pair].name);
           litval <<= bstr;
           litval &= (~mask) & 0xff;
           emit2 ("ld a,!*pair", _pairs[pair].name);
@@ -6811,7 +7085,7 @@ genPackBits (sym_link * etype,
         {
           /* Case with partial byte and literal source
           */
         {
           /* Case with partial byte and literal source
           */
-          litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+          litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
           litval >>= (blen-rlen);
           litval &= (~mask) & 0xff;
           emit2 ("ld a,!*pair", _pairs[pair].name);
           litval >>= (blen-rlen);
           litval &= (~mask) & 0xff;
           emit2 ("ld a,!*pair", _pairs[pair].name);
@@ -7067,7 +7341,7 @@ genAddrOf (iCode * ic)
     {
       if (sym->onStack)
         {
     {
       if (sym->onStack)
         {
-          spillCached ();
+          spillPair (PAIR_HL);
           if (sym->stack <= 0)
             {
               setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset);
           if (sym->stack <= 0)
             {
               setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset);
@@ -7086,7 +7360,7 @@ genAddrOf (iCode * ic)
     }
   else
     {
     }
   else
     {
-      spillCached ();
+      spillPair (PAIR_HL);
       if (sym->onStack)
         {
           /* if it has an offset  then we need to compute it */
       if (sym->onStack)
         {
           /* if it has an offset  then we need to compute it */
@@ -7147,7 +7421,7 @@ genAssign (iCode * ic)
 
   if (AOP_TYPE (right) == AOP_LIT)
     {
 
   if (AOP_TYPE (right) == AOP_LIT)
     {
-      lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+      lit = ulFromVal (AOP (right)->aopu.aop_lit);
     }
 
   if (isPair (AOP (result)))
     }
 
   if (isPair (AOP (result)))
@@ -7266,7 +7540,7 @@ genJumpTab (iCode * ic)
   emit2 ("ld e,%s", l);
   emit2 ("ld d,!zero");
   jtab = newiTempLabel (NULL);
   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");
   emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
   emit2 ("add hl,de");
   emit2 ("add hl,de");
@@ -7351,8 +7625,7 @@ genCast (iCode * ic)
   else
     {
       /* we need to extend the sign :{ */
   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");
       _moveA (l);
       emit2 ("rla ");
       emit2 ("sbc a,a");
@@ -7461,9 +7734,10 @@ genCritical (iCode *ic)
       //disable interrupt
       emit2 ("!di");
       //parity odd <==> P/O=0 <==> interrupt enable flag IFF2=0
       //disable interrupt
       emit2 ("!di");
       //parity odd <==> P/O=0 <==> interrupt enable flag IFF2=0
-      emit2 ("jp po,!tlabel", tlbl->key + 100);
+      emit2 ("jp PO,!tlabel", tlbl->key + 100);
       aopPut (AOP (IC_RESULT (ic)), "!one", 0);
       emit2 ("!tlabeldef", (tlbl->key + 100));
       aopPut (AOP (IC_RESULT (ic)), "!one", 0);
       emit2 ("!tlabeldef", (tlbl->key + 100));
+      _G.lines.current->isLabel = 1;
       freeAsmop (IC_RESULT (ic), NULL, ic);
     }
   else
       freeAsmop (IC_RESULT (ic), NULL, ic);
     }
   else
@@ -7473,7 +7747,7 @@ genCritical (iCode *ic)
       //disable interrupt
       emit2 ("!di");
       //save P/O flag
       //disable interrupt
       emit2 ("!di");
       //save P/O flag
-      emit2 ("push af");
+      _push (PAIR_AF);
     }
 }
 
     }
 }
 
@@ -7494,7 +7768,7 @@ genEndCritical (iCode *ic)
       aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
       _toBoolean (IC_RIGHT (ic));
       //don't enable interrupts if they were off before
       aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
       _toBoolean (IC_RIGHT (ic));
       //don't enable interrupts if they were off before
-      emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
+      emit2 ("!shortjp Z,!tlabel", tlbl->key + 100);
       emit2 ("!ei");
       emitLabel (tlbl->key + 100);
       freeAsmop (IC_RIGHT (ic), NULL, ic);
       emit2 ("!ei");
       emitLabel (tlbl->key + 100);
       freeAsmop (IC_RIGHT (ic), NULL, ic);
@@ -7502,12 +7776,13 @@ genEndCritical (iCode *ic)
   else
     {
       //restore P/O flag
   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
       //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);
+      emit2 ("jp PO,!tlabel", tlbl->key + 100);
       emit2 ("!ei");
       emit2 ("!tlabeldef", (tlbl->key + 100));
       emit2 ("!ei");
       emit2 ("!tlabeldef", (tlbl->key + 100));
+      _G.lines.current->isLabel = 1;
     }
 }
 
     }
 }
 
@@ -7778,67 +8053,12 @@ _swap (PAIR_ID one, PAIR_ID two)
     }
 }
 
     }
 }
 
-/* The problem is that we may have all three pairs used and they may
-   be needed in a different order.
-
-   Note: Have ex de,hl
-
-   Combinations:
-     hl = hl            => unity, fine
-     bc = bc
-     de = de
-
-     hl = hl            hl = hl, swap de <=> bc
-     bc = de
-     de = bc
-
-     hl = bc            Worst case
-     bc = de
-     de = hl
-
-     hl = bc            de = de, swap bc <=> hl
-     bc = hl
-     de = de
-
-     hl = de            Worst case
-     bc = hl
-     de = bc
-
-     hl = de            bc = bc, swap hl <=> de
-     bc = bc
-     de = hl
-
-   Break it down into:
-    * Any pair = pair are done last
-    * Any pair = iTemp are done last
-    * Any swaps can be done any time
-
-   A worst case:
-    push p1
-    p1 = p2
-    p2 = p3
-    pop  p3
-
-   So how do we detect the cases?
-   How about a 3x3 matrix?
-        source
-   dest x x x x
-        x x x x
-        x x x x (Fourth for iTemp/other)
-
-   First determin which mode to use by counting the number of unity and
-   iTemp assigns.
-     Three - any order
-     Two - Assign the pair first, then the rest
-     One - Swap the two, then the rest
-     Zero - Worst case.
-*/
 static void
 static void
-setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
+setupForMemcpy (iCode *ic, int nparams, operand **pparams)
 {
   PAIR_ID ids[NUM_PAIRS][NUM_PAIRS];
   PAIR_ID dest[3] = {
 {
   PAIR_ID ids[NUM_PAIRS][NUM_PAIRS];
   PAIR_ID dest[3] = {
-    PAIR_BC, PAIR_HL, PAIR_DE
+    PAIR_DE, PAIR_HL, PAIR_BC
   };
   int i, j, nunity = 0;
   memset (ids, PAIR_INVALID, sizeof (ids));
   };
   int i, j, nunity = 0;
   memset (ids, PAIR_INVALID, sizeof (ids));
@@ -7846,10 +8066,6 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
   /* Sanity checks */
   wassert (nparams == 3);
 
   /* Sanity checks */
   wassert (nparams == 3);
 
-  /* First save everything that needs to be saved. */
-  _saveRegsForCall (ic, 0);
-
-  /* Loading HL first means that DE is always fine. */
   for (i = 0; i < nparams; i++)
     {
       aopOp (pparams[i], ic, FALSE, FALSE);
   for (i = 0; i < nparams; i++)
     {
       aopOp (pparams[i], ic, FALSE, FALSE);
@@ -7871,7 +8087,7 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
     }
   else if (nunity == 2)
     {
     }
   else if (nunity == 2)
     {
-      /* One is assigned.  Pull it out and assign. */
+      /* Two are OK.  Assign the other one. */
       for (i = 0; i < 3; i++)
         {
           for (j = 0; j < NUM_PAIRS; j++)
       for (i = 0; i < 3; i++)
         {
           for (j = 0; j < NUM_PAIRS; j++)
@@ -7894,7 +8110,7 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
     }
   else if (nunity == 1)
     {
     }
   else if (nunity == 1)
     {
-      /* Find the pairs to swap. */
+      /* One is OK. Find the other two. */
       for (i = 0; i < 3; i++)
         {
           for (j = 0; j < NUM_PAIRS; j++)
       for (i = 0; i < 3; i++)
         {
           for (j = 0; j < NUM_PAIRS; j++)
@@ -7903,12 +8119,22 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
                 {
                   if (j == PAIR_INVALID || j == dest[i])
                     {
                 {
                   if (j == PAIR_INVALID || j == dest[i])
                     {
-                      /* Keep looking. */
+                      /* This one is OK. */
                     }
                   else
                     {
                     }
                   else
                     {
-                      _swap (j, dest[i]);
-                      goto done;
+                      /* Found one. */
+                      if(ids[j][dest[i]] == TRUE)
+                        {
+                          /* Just swap. */
+                           _swap (j, dest[i]);
+                           goto done;
+                        }
+                      else
+                        {
+                          fetchPair (dest[i], AOP (pparams[i]));
+                          continue;
+                        }
                     }
                 }
             }
                     }
                 }
             }
@@ -7942,53 +8168,27 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
     }
 }
 
     }
 }
 
-static void
-genBuiltInStrcpy (iCode *ic, int nParams, operand **pparams)
-{
-  operand *from, *to;
-  symbol *label;
-  bool deInUse;
-
-  wassertl (nParams == 2, "Built-in strcpy must have two parameters");
-  to = pparams[0];
-  from = pparams[1];
-
-  deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
-
-  setupForBuiltin3 (ic, nParams, pparams);
-
-  label = newiTempLabel(NULL);
-
-  emitLabel (label->key);
-  emit2 ("ld a,(hl)");
-  emit2 ("ldi");
-  emit2 ("or a");
-  emit2 ("!shortjp nz,!tlabel ; 1", label->key);
-
-  freeAsmop (from, NULL, ic->next);
-  freeAsmop (to, NULL, ic);
-}
-
 static void
 genBuiltInMemcpy (iCode *ic, int nParams, operand **pparams)
 {
   operand *from, *to, *count;
 static void
 genBuiltInMemcpy (iCode *ic, int nParams, operand **pparams)
 {
   operand *from, *to, *count;
-  bool deInUse;
 
 
-  wassertl (nParams == 3, "Built-in memcpy must have two parameters");
+  wassertl (nParams == 3, "Built-in memcpy() must have three parameters");
   to = pparams[2];
   from = pparams[1];
   count = pparams[0];
 
   to = pparams[2];
   from = pparams[1];
   count = pparams[0];
 
-  deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
+  _saveRegsForCall (ic, 0);
 
 
-  setupForBuiltin3 (ic, nParams, pparams);
+  setupForMemcpy (ic, nParams, pparams);
 
   emit2 ("ldir");
 
   freeAsmop (count, NULL, ic->next->next);
   freeAsmop (from, NULL, ic);
 
 
   emit2 ("ldir");
 
   freeAsmop (count, NULL, ic->next->next);
   freeAsmop (from, NULL, ic);
 
+  spillPair (PAIR_HL);
+
   _restoreRegsAfterCall();
 
   /* if we need assign a result value */
   _restoreRegsAfterCall();
 
   /* if we need assign a result value */
@@ -8022,11 +8222,7 @@ static void genBuiltIn (iCode *ic)
     /* which function is it */
     bif = OP_SYMBOL(IC_LEFT(bi_iCode));
 
     /* which function is it */
     bif = OP_SYMBOL(IC_LEFT(bi_iCode));
 
-    if (strcmp(bif->name,"__builtin_strcpy")==0)
-      {
-        genBuiltInStrcpy(bi_iCode, nbi_parms, bi_parms);
-      }
-    else if (strcmp(bif->name,"__builtin_memcpy")==0)
+    if (strcmp(bif->name,"__builtin_memcpy")==0)
       {
         genBuiltInMemcpy(bi_iCode, nbi_parms, bi_parms);
       }
       {
         genBuiltInMemcpy(bi_iCode, nbi_parms, bi_parms);
       }
@@ -8084,7 +8280,9 @@ genZ80Code (iCode * lic)
         }
       if (options.iCodeInAsm)
         {
         }
       if (options.iCodeInAsm)
         {
-          emit2 (";ic:%d: %s", ic->key, printILine(ic));
+          const char *iLine = printILine(ic);
+          emit2 (";ic:%d: %s", ic->key, iLine);
+          dbuf_free(iLine);
         }
       /* if the result is marked as
          spilt and rematerializable or code for
         }
       /* if the result is marked as
          spilt and rematerializable or code for
@@ -8121,7 +8319,7 @@ genZ80Code (iCode * lic)
              spilt live range, if there is an ifx statement
              following this pop then the if statement might
              be using some of the registers being popped which
              spilt live range, if there is an ifx statement
              following this pop then the if statement might
              be using some of the registers being popped which
-             would destory the contents of the register so
+             would destroy the contents of the register so
              we need to check for this condition and handle it */
           if (ic->next &&
               ic->next->op == IFX &&
              we need to check for this condition and handle it */
           if (ic->next &&
               ic->next->op == IFX &&
@@ -8368,16 +8566,16 @@ genZ80Code (iCode * lic)
   /* This is unfortunate */
   /* now do the actual printing */
   {
   /* This is unfortunate */
   /* now do the actual printing */
   {
-    FILE *fp = codeOutFile;
-    if (isInHome () && codeOutFile == code->oFile)
-      codeOutFile = home->oFile;
-    printLine (_G.lines.head, codeOutFile);
+    struct dbuf_s *buf = codeOutBuf;
+    if (isInHome () && codeOutBuf == &code->oBuf)
+      codeOutBuf = &home->oBuf;
+    printLine (_G.lines.head, codeOutBuf);
     if (_G.flushStatics)
       {
         flushStatics ();
         _G.flushStatics = 0;
       }
     if (_G.flushStatics)
       {
         flushStatics ();
         _G.flushStatics = 0;
       }
-    codeOutFile = fp;
+    codeOutBuf = buf;
   }
 
   freeTrace(&_G.lines.trace);
   }
 
   freeTrace(&_G.lines.trace);
@@ -8413,7 +8611,7 @@ fetchLitSpecial (asmop * aop, bool negate, bool xor)
   wassert (aop->type == AOP_LIT);
   wassert (!IS_FLOAT (val->type));
 
   wassert (aop->type == AOP_LIT);
   wassert (!IS_FLOAT (val->type));
 
-  v = (unsigned long) floatFromVal (val);
+  v = ulFromVal (val);
 
   if (xor)
     v ^= 0x8000;
 
   if (xor)
     v ^= 0x8000;