Improved caching of pointers and division
[fw/sdcc] / src / z80 / gen.c
index 2818150f3b63aedbdad12a2ea27e8d9239313ce5..b45d7a8516c2fe621b1cb7e75ce53458700e8f8e 100644 (file)
@@ -1,6 +1,6 @@
 /*-------------------------------------------------------------------------
   gen.c - Z80 specific code generator.
-     
+
   Michael Hope <michaelh@juju.net.nz> 2000
   Based on the mcs51 generator -
       Sandeep Dutta . sandeep.dutta@usa.net (1998)
    No asm strings
    Includes long mul/div in code
   2. Optimised memcpy for acc use       32102 102 226B
-  3. Optimised strcpy for acc use      27819 117 2237
+  3. Optimised strcpy for acc use       27819 117 2237
   3a Optimised memcpy fun
-  4. Optimised strcmp fun              21999 149 2294
-  5. Optimised strcmp further          21660 151 228C
-  6. Optimised memcpy by unroling      20885 157 2201
-  7. After turning loop induction on   19862 165 236D
-  8. Same as 7 but with more info      
-  9. With asm optimised strings                17030 192 2223
+  4. Optimised strcmp fun               21999 149 2294
+  5. Optimised strcmp further           21660 151 228C
+  6. Optimised memcpy by unroling       20885 157 2201
+  7. After turning loop induction on    19862 165 236D
+  8. Same as 7 but with more info
+  9. With asm optimised strings         17030 192 2223
 
   10 and below are with asm strings off.
 
-  10 Mucho optimisations               13562 201 1FCC
+  10 Mucho optimisations                13562 201 1FCC
 
   Apparent advantage of turning on regparams:
   1.  Cost of push
-        Decent case is push of a constant 
+        Decent case is push of a constant
           - ld hl,#n; push hl: (10+11)*nargs
   2.  Cost of pull from stack
         Using asm with ld hl, etc
@@ -74,8 +74,8 @@
   3.  Cost of fixing stack
           - pop hl*nargs
             10*nargs
-  
-  So cost is (10+11+7+6+7+10)*nargs+10+11 
+
+  So cost is (10+11+7+6+7+10)*nargs+10+11
       = 51*nargs+21
       = 123 for mul, div, strcmp, strcpy
   Saving of (98298+32766+32766+32766)*123 = 24181308
 #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"
    area.  ix-0 is the top most local variable.
 */
 
-enum 
+enum
 {
   /* Set to enable debugging trace statements in the output assembly code. */
   DISABLE_DEBUG = 0
 };
 
 static char *_z80_return[] =
-{"l", "h", "e", "d"};
+  {"l", "h", "e", "d"};
 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;
 
-extern FILE *codeOutFile;
+extern struct dbuf_s *codeOutBuf;
 
 enum
   {
@@ -175,9 +169,9 @@ static struct
 };
 
 // PENDING
-#define ACC_NAME       _pairs[PAIR_AF].h
+#define ACC_NAME        _pairs[PAIR_AF].h
 
-enum 
+enum
   {
     LSB,
     MSB16,
@@ -187,18 +181,18 @@ enum
 
 /** Code generator persistent data.
  */
-static struct 
+static struct
 {
   /** Used to optimised setting up of a pair by remebering what it
       contains and adjusting instead of reloading where possible.
   */
-  struct 
+  struct
   {
     AOP_TYPE last_type;
     const char *base;
     int offset;
   } pairs[NUM_PAIRS];
-  struct 
+  struct
   {
     int last;
     int pushed;
@@ -222,7 +216,7 @@ static struct
   const char *lastFunctionName;
   iCode *current_iCode;
   bool preserveCarry;
-  
+
   set *sendSet;
 
   struct
@@ -231,7 +225,7 @@ static struct
     bool saved;
   } saves;
 
-  struct 
+  struct
   {
     lineNode *head;
     lineNode *current;
@@ -333,9 +327,9 @@ static bool
 isPairInUseNotInRet(PAIR_ID id, iCode *ic)
 {
   bitVect *rInUse;
-  
+
   rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
-  
+
   if (id == PAIR_DE)
     {
       return bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
@@ -362,7 +356,7 @@ getFreePairId (iCode *ic)
     {
       return PAIR_INVALID;
     }
-}         
+}
 
 static void
 _tidyUp (char *buf)
@@ -388,7 +382,7 @@ _tidyUp (char *buf)
 }
 
 static lineNode *
-_newLineNode (char *line)
+_newLineNode (const char *line)
 {
   lineNode *pl;
 
@@ -401,18 +395,26 @@ _newLineNode (char *line)
 static void
 _vemit2 (const char *szFormat, va_list ap)
 {
-  char buffer[INITIAL_INLINEASM];
+  struct dbuf_s dbuf;
+  char *buffer;
+
+  dbuf_init(&dbuf, INITIAL_INLINEASM);
 
-  tvsprintf (buffer, sizeof(buffer), szFormat, ap);
+  dbuf_tvprintf (&dbuf, szFormat, ap);
+
+  buffer = (char *)dbuf_c_str(&dbuf);
 
   _tidyUp (buffer);
   _G.lines.current = (_G.lines.current ?
-             connectLine (_G.lines.current, _newLineNode (buffer)) :
-             (_G.lines.head = _newLineNode (buffer)));
+              connectLine (_G.lines.current, _newLineNode (buffer)) :
+              (_G.lines.head = _newLineNode (buffer)));
 
   _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
@@ -430,6 +432,8 @@ emit2 (const char *szFormat,...)
 static void
 emitDebug (const char *szFormat,...)
 {
+  if (!options.verboseAsm)
+    return;
   if (!DISABLE_DEBUG)
     {
       va_list ap;
@@ -492,11 +496,11 @@ _emit2 (const char *inst, const char *fmt,...)
 static void
 _emitMove(const char *to, const char *from)
 {
-  if (STRCASECMP(to, from) != 0) 
+  if (STRCASECMP(to, from) != 0)
     {
       emit2("ld %s,%s", to, from);
     }
-  else 
+  else
     {
       // Optimise it out.
       // Could leave this to the peephole, but sometimes the peephole is inhibited.
@@ -509,7 +513,7 @@ aopDump(const char *plabel, asmop *aop)
   int i;
   char regbuf[9];
   char *rbp = regbuf;
-  
+
   emitDebug("; Dump of %s: type %s size %u", plabel, aopNames[aop->type], aop->size);
   switch (aop->type)
     {
@@ -525,7 +529,7 @@ aopDump(const char *plabel, asmop *aop)
       break;
     case AOP_PAIRPTR:
       emitDebug(";  pairptr = (%s)", _pairs[aop->aopu.aop_pairId].name);
-        
+
     default:
       /* No information. */
       break;
@@ -551,17 +555,17 @@ getPairName (asmop * aop)
   if (aop->type == AOP_REG)
     {
       switch (aop->aopu.aop_reg[0]->rIdx)
-       {
-       case C_IDX:
-         return "bc";
-         break;
-       case E_IDX:
-         return "de";
-         break;
-       case L_IDX:
-         return "hl";
-         break;
-       }
+        {
+        case C_IDX:
+          return "bc";
+          break;
+        case E_IDX:
+          return "de";
+          break;
+        case L_IDX:
+          return "hl";
+          break;
+        }
     }
   else if (aop->type == AOP_STR || aop->type == AOP_HLREG)
     {
@@ -584,22 +588,22 @@ getPairId (asmop * aop)
   if (aop->size == 2)
     {
       if (aop->type == AOP_REG)
-       {
-         if ((aop->aopu.aop_reg[0]->rIdx == C_IDX) && (aop->aopu.aop_reg[1]->rIdx == B_IDX))
-           {
-             return PAIR_BC;
-           }
-         if ((aop->aopu.aop_reg[0]->rIdx == E_IDX) && (aop->aopu.aop_reg[1]->rIdx == D_IDX))
-           {
-             return PAIR_DE;
-           }
-         if ((aop->aopu.aop_reg[0]->rIdx == L_IDX) && (aop->aopu.aop_reg[1]->rIdx == H_IDX))
-           {
-             return PAIR_HL;
-           }
-       }
+        {
+          if ((aop->aopu.aop_reg[0]->rIdx == C_IDX) && (aop->aopu.aop_reg[1]->rIdx == B_IDX))
+            {
+              return PAIR_BC;
+            }
+          if ((aop->aopu.aop_reg[0]->rIdx == E_IDX) && (aop->aopu.aop_reg[1]->rIdx == D_IDX))
+            {
+              return PAIR_DE;
+            }
+          if ((aop->aopu.aop_reg[0]->rIdx == L_IDX) && (aop->aopu.aop_reg[1]->rIdx == H_IDX))
+            {
+              return PAIR_HL;
+            }
+        }
       else if (aop->type == AOP_STR || aop->type == AOP_HLREG)
-       {
+        {
           int i;
           for (i = 0; i < NUM_PAIRS; i++)
             {
@@ -661,7 +665,7 @@ spillPair (PAIR_ID pairId)
 /* Given a register name, spill the pair (if any) the register is part of */
 static void
 spillPairReg (const char *regname)
-{      
+{
   if (strlen(regname)==1)
     {
       switch (*regname)
@@ -699,9 +703,12 @@ _push (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
@@ -813,7 +820,7 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
         sym->aop = aop = newAsmop (AOP_SFR);
         aop->aopu.aop_dir = sym->rname;
         aop->size = getSize (sym->type);
-         emitDebug ("; AOP_SFR for %s", sym->rname);
+          emitDebug ("; AOP_SFR for %s", sym->rname);
         return aop;
       }
     }
@@ -867,14 +874,14 @@ aopForRemat (symbol * sym)
     {
       /* if plus or minus print the right hand side */
       if (ic->op == '+' || ic->op == '-')
-       {
-         /* PENDING: for re-target */
-         sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
-                  ic->op);
-         s += strlen (s);
-         ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
-         continue;
-       }
+        {
+          /* PENDING: for re-target */
+          sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
+                   ic->op);
+          s += strlen (s);
+          ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+          continue;
+        }
       /* we reached the end */
       sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
       break;
@@ -907,16 +914,16 @@ regsInCommon (operand * op1, operand * op2)
     {
       int j;
       if (!sym1->regs[i])
-       continue;
+        continue;
 
       for (j = 0; j < sym2->nRegs; j++)
-       {
-         if (!sym2->regs[j])
-           continue;
+        {
+          if (!sym2->regs[j])
+            continue;
 
-         if (sym2->regs[j] == sym1->regs[i])
-           return TRUE;
-       }
+          if (sym2->regs[j] == sym1->regs[i])
+            return TRUE;
+        }
     }
 
   return FALSE;
@@ -992,7 +999,7 @@ sameRegs (asmop * aop1, asmop * aop2)
 
   for (i = 0; i < aop1->size; i++)
     if (aop1->aopu.aop_reg[i] !=
-       aop2->aopu.aop_reg[i])
+        aop2->aopu.aop_reg[i])
       return FALSE;
 
   return TRUE;
@@ -1075,69 +1082,77 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a)
     {
       /* rematerialize it NOW */
       if (sym->remat)
-       {
-         sym->aop = op->aop = aop =
-           aopForRemat (sym);
-         aop->size = getSize (sym->type);
-         return;
-       }
+        {
+          sym->aop = op->aop = aop =
+            aopForRemat (sym);
+          aop->size = getSize (sym->type);
+          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;
-       }
+        {
+          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)
-           {
-             aop = op->aop = sym->aop = newAsmop (AOP_ACC);
-             aop->size = getSize (sym->type);
+        {
+          if (sym->accuse == ACCUSE_A)
+            {
+              aop = op->aop = sym->aop = newAsmop (AOP_ACC);
+              aop->size = getSize (sym->type);
               wassertl(aop->size == 1, "Internal error: Caching in A, but too big to fit in A");
 
               aop->aopu.aop_str[0] = _pairs[PAIR_AF].h;
-           }
-         else if (sym->accuse == ACCUSE_SCRATCH)
-           {
-             aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
-             aop->size = getSize (sym->type);
+            }
+          else if (sym->accuse == ACCUSE_SCRATCH)
+            {
+              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);
+              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 
+          else
               {
                   wassertl (0, "Marked as being allocated into A or HL but is actually in neither");
               }
-         return;
-       }
+          return;
+        }
 
       if (sym->usl.spillLoc)
         {
-         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
+          asmop *oldAsmOp = NULL;
+
+          if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
+            {
+              /* force a new aop if sizes differ */
+              oldAsmOp = sym->usl.spillLoc->aop;
+              sym->usl.spillLoc->aop = NULL;
+            }
+          sym->aop = op->aop = aop =
+                     aopForSym (ic, sym->usl.spillLoc, result, requires_a);
+          if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
             {
-             /* force a new aop if sizes differ */
-             sym->usl.spillLoc->aop = NULL;
-           }
-         sym->aop = op->aop = aop =
-                    aopForSym (ic, sym->usl.spillLoc, result, requires_a);
-         aop->size = getSize (sym->type);
-         return;
-        }
-      
+              /* Don't reuse the new aop, go with the last one */
+              sym->usl.spillLoc->aop = oldAsmOp;
+            }
+          aop->size = getSize (sym->type);
+          return;
+        }
+
       /* else must be a dummy iTemp */
       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
       aop->size = getSize (sym->type);
@@ -1188,12 +1203,12 @@ dealloc:
     {
       op->aop = NULL;
       if (IS_SYMOP (op))
-       {
-         OP_SYMBOL (op)->aop = NULL;
-         /* if the symbol has a spill */
-         if (SPIL_LOC (op))
-           SPIL_LOC (op)->aop = NULL;
-       }
+        {
+          OP_SYMBOL (op)->aop = NULL;
+          /* if the symbol has a spill */
+          if (SPIL_LOC (op))
+            SPIL_LOC (op)->aop = NULL;
+        }
     }
 
 }
@@ -1225,31 +1240,31 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
       /* PENDING: for re-target */
       if (with_hash)
         {
-          tsprintf (buffer, sizeof(buffer), 
-                   "!hashedstr + %d", aop->aopu.aop_immd, offset);
+          tsprintf (buffer, sizeof(buffer),
+                    "!hashedstr + %d", aop->aopu.aop_immd, offset);
         }
       else if (offset == 0)
         {
           tsprintf (buffer, sizeof(buffer),
-                   "%s", aop->aopu.aop_immd);
+                    "%s", aop->aopu.aop_immd);
         }
       else
         {
-          tsprintf (buffer, sizeof(buffer), 
-                   "%s + %d", aop->aopu.aop_immd, offset);
+          tsprintf (buffer, sizeof(buffer),
+                    "%s + %d", aop->aopu.aop_immd, offset);
         }
       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
 
     case AOP_LIT:
       {
-       value *val = aop->aopu.aop_lit;
-       /* if it is a float then it gets tricky */
-       /* otherwise it is fairly simple */
-       if (!IS_FLOAT (val->type))
-         {
-           unsigned long v = (unsigned long) floatFromVal (val);
-
-           if (offset == 2)
+        value *val = aop->aopu.aop_lit;
+        /* if it is a float then it gets tricky */
+        /* otherwise it is fairly simple */
+        if (!IS_FLOAT (val->type))
+          {
+            unsigned long v = ulFromVal (val);
+
+            if (offset == 2)
               {
                 v >>= 16;
               }
@@ -1257,20 +1272,20 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
               {
                 // OK
               }
-            else 
+            else
               {
                 wassertl(0, "Encountered an invalid offset while fetching a literal");
               }
 
-           if (with_hash)
-             tsprintf (buffer, sizeof(buffer), "!immedword", v);
-           else
-             tsprintf (buffer, sizeof(buffer), "!constword", v);
+            if (with_hash)
+              tsprintf (buffer, sizeof(buffer), "!immedword", v);
+            else
+              tsprintf (buffer, sizeof(buffer), "!constword", v);
 
             return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
-         }
-       else
-         {
+          }
+        else
+          {
             union {
               float f;
               unsigned char c[4];
@@ -1286,13 +1301,13 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
 #else
             i = fl.c[offset] | (fl.c[offset+1]<<8);
 #endif
-           if (with_hash)
-             tsprintf (buffer, sizeof(buffer), "!immedword", i);
-           else
-             tsprintf (buffer, sizeof(buffer), "!constword", i);
+            if (with_hash)
+              tsprintf (buffer, sizeof(buffer), "!immedword", i);
+            else
+              tsprintf (buffer, sizeof(buffer), "!constword", i);
 
             return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
-         }
+          }
       }
     default:
       return NULL;
@@ -1369,29 +1384,63 @@ fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
   if (isPtr (pair))
     {
       if (pairId == PAIR_HL || pairId == PAIR_IY)
-       {
-         if (_G.pairs[pairId].last_type == left->type)
-           {
-             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;
-                   }
-                 if (pairId == PAIR_IY && (offset >= INT8MIN && offset <= INT8MAX))
-                   {
-                     return;
-                   }
-               }
-           }
-       }
+        {
+          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);
+                      goto adjusted;
+                    }
+                  if (pairId == PAIR_IY && (offset >= INT8MIN && offset <= INT8MAX))
+                    {
+                       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);
+  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
@@ -1429,7 +1478,7 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, iCode *ic, int offset)
     if (isLitWord (aop)) {
         fetchLitPair (pairId, aop, offset);
     }
-    else 
+    else
       {
         if (getPairId (aop) == pairId)
           {
@@ -1493,10 +1542,20 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, iCode *ic, int offset)
             emit2("push %s", _pairs[getPairId(aop)].name);
             emit2("pop %s", _pairs[pairId].name);
           }
-        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)
@@ -1526,7 +1585,7 @@ setupPairFromSP (PAIR_ID id, int offset)
       _push (PAIR_AF);
       offset += 2;
     }
-  
+
   if (offset < INT8MIN || offset > INT8MAX)
     {
       emit2 ("ld hl,!immedword", offset);
@@ -1556,7 +1615,7 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset)
 
     case AOP_HL:
       wassertl (pairId == PAIR_HL, "AOP_HL must be in HL");
-      
+
       fetchLitPair (pairId, aop, offset);
       _G.pairs[pairId].offset = offset;
       break;
@@ -1566,7 +1625,7 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset)
       wassertl (pairId == PAIR_IY || pairId == PAIR_HL, "The Z80 extended stack must be in IY or HL");
 
       {
-       int offset = aop->aopu.aop_stk + _G.stack.offset;
+        int offset = aop->aopu.aop_stk + _G.stack.offset;
 
         if (_G.pairs[pairId].last_type == aop->type &&
             _G.pairs[pairId].offset == offset)
@@ -1591,25 +1650,25 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset)
 
     case AOP_STK:
       {
-       /* Doesnt include _G.stack.pushed */
-       int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
-
-       if (aop->aopu.aop_stk > 0)
-         {
-           abso += _G.stack.param_offset;
-         }
-       assert (pairId == PAIR_HL);
-       /* In some cases we can still inc or dec hl */
-       if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
-         {
-           adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
-         }
-       else
-         {
+        /* Doesnt include _G.stack.pushed */
+        int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
+
+        if (aop->aopu.aop_stk > 0)
+          {
+            abso += _G.stack.param_offset;
+          }
+        assert (pairId == PAIR_HL);
+        /* In some cases we can still inc or dec hl */
+        if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
+          {
+            adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
+          }
+        else
+          {
             setupPairFromSP (PAIR_HL, abso + _G.stack.pushed);
-         }
-       _G.pairs[pairId].offset = abso;
-       break;
+          }
+        _G.pairs[pairId].offset = abso;
+        break;
       }
 
     case AOP_PAIRPTR:
@@ -1617,17 +1676,26 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset)
         genMovePairPair(aop->aopu.aop_pairId, pairId);
       adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, offset);
       break;
-      
+
     default:
       wassert (0);
     }
   _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);
+  _G.lines.current->isLabel = 1;
   spillCached ();
 }
 
@@ -1642,7 +1710,7 @@ aopGet (asmop * aop, int offset, bool bit16)
   /* offset is greater than size then zero */
   /* PENDING: this seems a bit screwed in some pointer cases. */
   if (offset > (aop->size - 1) &&
-      aop->type != AOP_LIT) 
+      aop->type != AOP_LIT)
     {
       tsprintf (buffer, sizeof(buffer), "!zero");
       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
@@ -1654,26 +1722,26 @@ aopGet (asmop * aop, int offset, bool bit16)
     case AOP_DUMMY:
       tsprintf (buffer, sizeof(buffer), "!zero");
       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
-    
+
     case AOP_IMMD:
       /* PENDING: re-target */
       if (bit16)
-       tsprintf (buffer, sizeof(buffer), "!immedwords", aop->aopu.aop_immd);
+        tsprintf (buffer, sizeof(buffer), "!immedwords", aop->aopu.aop_immd);
       else
-       switch (offset)
-         {
-         case 2:
-           tsprintf (buffer, sizeof(buffer), "!bankimmeds", aop->aopu.aop_immd);
-           break;
-         case 1:
-           tsprintf (buffer, sizeof(buffer), "!msbimmeds", aop->aopu.aop_immd);
-           break;
-         case 0:
-           tsprintf (buffer, sizeof(buffer), "!lsbimmeds", aop->aopu.aop_immd);
-           break;
-         default:
-           wassertl (0, "Fetching from beyond the limits of an immediate value.");
-         }
+        switch (offset)
+          {
+          case 2:
+            tsprintf (buffer, sizeof(buffer), "!bankimmeds", aop->aopu.aop_immd);
+            break;
+          case 1:
+            tsprintf (buffer, sizeof(buffer), "!msbimmeds", aop->aopu.aop_immd);
+            break;
+          case 0:
+            tsprintf (buffer, sizeof(buffer), "!lsbimmeds", aop->aopu.aop_immd);
+            break;
+          default:
+            wassertl (0, "Fetching from beyond the limits of an immediate value.");
+          }
 
       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
 
@@ -1697,9 +1765,9 @@ aopGet (asmop * aop, int offset, bool bit16)
       { /*.p.t.20030716 handling for i/o port read access for Z80 */
         if( aop->paged )
         { /* banked mode */
-         /* reg A goes to address bits 15-8 during "in a,(x)" instruction */
-         emit2( "ld a,!msbimmeds", aop->aopu.aop_dir);
-         emit2( "in a,(!lsbimmeds)", aop->aopu.aop_dir);
+          /* reg A goes to address bits 15-8 during "in a,(x)" instruction */
+          emit2( "ld a,!msbimmeds", aop->aopu.aop_dir);
+          emit2( "in a,(!lsbimmeds)", aop->aopu.aop_dir);
         }
         else if( z80_opts.port_mode == 180 )
         { /* z180 in0/out0 mode */
@@ -1709,7 +1777,7 @@ aopGet (asmop * aop, int offset, bool bit16)
         { /* 8 bit mode */
           emit2( "in a,(%s)", aop->aopu.aop_dir );
         }
-        
+
         SNPRINTF (buffer, sizeof(buffer), "a");
 
         return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
@@ -1741,17 +1809,17 @@ aopGet (asmop * aop, int offset, bool bit16)
 
     case AOP_STK:
       if (IS_GB)
-       {
-         setupPair (PAIR_HL, aop, offset);
-         tsprintf (buffer, sizeof(buffer), "!*hl");
-       }
+        {
+          setupPair (PAIR_HL, aop, offset);
+          tsprintf (buffer, sizeof(buffer), "!*hl");
+        }
       else
-       {
-         if (aop->aopu.aop_stk >= 0)
-           offset += _G.stack.param_offset;
-         tsprintf (buffer, sizeof(buffer),
-                   "!*ixx", aop->aopu.aop_stk + offset);
-       }
+        {
+          if (aop->aopu.aop_stk >= 0)
+            offset += _G.stack.param_offset;
+          tsprintf (buffer, sizeof(buffer),
+                    "!*ixx", aop->aopu.aop_stk + offset);
+        }
 
       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
 
@@ -1760,9 +1828,9 @@ aopGet (asmop * aop, int offset, bool bit16)
 
     case AOP_ACC:
       if (!offset)
-       {
-         return "a";
-       }
+        {
+          return "a";
+        }
       else
         {
           tsprintf(buffer, sizeof(buffer), "!zero");
@@ -1779,11 +1847,11 @@ aopGet (asmop * aop, int offset, bool bit16)
     case AOP_SIMPLELIT:
       {
         unsigned long v = aop->aopu.aop_simplelit;
-        
+
         v >>= (offset * 8);
-        tsprintf (buffer, sizeof(buffer), 
-                 "!immedbyte", (unsigned int) v & 0xff);
-        
+        tsprintf (buffer, sizeof(buffer),
+                  "!immedbyte", (unsigned int) v & 0xff);
+
         return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
       }
     case AOP_STR:
@@ -1793,14 +1861,12 @@ aopGet (asmop * aop, int offset, bool bit16)
     case AOP_PAIRPTR:
       setupPair (aop->aopu.aop_pairId, aop, offset);
       if (aop->aopu.aop_pairId==PAIR_IX)
-        SNPRINTF (buffer, sizeof(buffer), 
-                 "!*ixx", 0);
+        tsprintf (buffer, sizeof(buffer), "!*ixx", offset);
       else if (aop->aopu.aop_pairId==PAIR_IY)
-        SNPRINTF (buffer, sizeof(buffer), 
-                 "!*iyx", 0);
+        tsprintf (buffer, sizeof(buffer), "!*iyx", offset);
       else
-        SNPRINTF (buffer, sizeof(buffer), 
-                 "(%s)", _pairs[aop->aopu.aop_pairId].name);
+        SNPRINTF (buffer, sizeof(buffer),
+                  "(%s)", _pairs[aop->aopu.aop_pairId].name);
 
       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
 
@@ -1853,7 +1919,7 @@ aopPut (asmop * aop, const char *s, int offset)
   if (aop->size && offset > (aop->size - 1))
     {
       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-             "aopPut got offset > aop->size");
+              "aopPut got offset > aop->size");
       exit (0);
     }
 
@@ -1868,78 +1934,76 @@ aopPut (asmop * aop, const char *s, int offset)
     case AOP_DUMMY:
       _moveA (s);  /* in case s is volatile */
       break;
-      
+
     case AOP_DIR:
       /* Direct.  Hmmm. */
       wassert (IS_GB);
       if (strcmp (s, "a"))
-       emit2 ("ld a,%s", s);
+        emit2 ("ld a,%s", s);
       emit2 ("ld (%s+%d),a", aop->aopu.aop_dir, offset);
       break;
 
     case AOP_SFR:
       if( IS_GB )
-      {
-        //  wassert (IS_GB);
-        if (strcmp (s, "a"))
-          emit2 ("ld a,%s", s);
-        emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
-      }
+        {
+          //  wassert (IS_GB);
+          if (strcmp (s, "a"))
+            emit2 ("ld a,%s", s);
+          emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
+        }
       else
-      { /*.p.t.20030716 handling for i/o port read access for Z80 */
-        if( aop->paged )
-        { /* banked mode */
-          if( aop->bcInUse )  emit2( "push bc" );
+        { /*.p.t.20030716 handling for i/o port read access for Z80 */
+          if (aop->paged)
+            { /* banked mode */
+              if (aop->bcInUse)
+                emit2( "push bc" );
+
+              if (strlen(s) != 1
+                  || (s[0] != 'a' && s[0] != 'd' && s[0] != 'e'
+                      && s[0] != 'h' && s[0] != 'l'))
+                {
+                  emit2( "ld a,%s", s );
+                  s = "a";
+                }
 
-          emit2( "ld bc,#%s", aop->aopu.aop_dir );
+              emit2( "ld bc,#%s", aop->aopu.aop_dir );
+              emit2( "out (c),%s", s );
 
-          if(( s[0] == '#'    ) /* immediate number */
-           ||( s[0] == '('    ) /* indirect register (ix or iy ??)*/
-           ||( isdigit( s[0] )))/* indirect register with offset (ix or iy ??)*/
-          {
-            emit2( "ld a,%s", s );
-            emit2( "out (c),a"  );
-          }
-          else
-          {
-            emit2( "out (c),%s", s );
-          }
-        
-          if( aop->bcInUse )
-            emit2( "pop bc"    );
+              if( aop->bcInUse )
+                emit2( "pop bc"    );
+              else
+                spillPair (PAIR_BC);
+            }
+          else if( z80_opts.port_mode == 180 )
+            { /* z180 in0/out0 mode */
+              emit2( "ld a,%s", s );
+              emit2( "out0 (%s),a", aop->aopu.aop_dir );
+            }
           else
-            spillPair (PAIR_BC);
-        }
-        else if( z80_opts.port_mode == 180 )
-        { /* z180 in0/out0 mode */
-          emit2( "ld a,%s", s );
-          emit2( "out0 (%s),a", aop->aopu.aop_dir );
-        }
-        else
-        { /* 8 bit mode */
-          emit2( "ld a,%s", s );
-          emit2( "out (%s),a", aop->aopu.aop_dir );
+            { /* 8 bit mode */
+              emit2( "ld a,%s", s );
+              emit2( "out (%s),a", aop->aopu.aop_dir );
+            }
         }
-      }
       break;
 
     case AOP_REG:
       if (!strcmp (s, "!*hl"))
-       emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
+        emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
       else
-       emit2 ("ld %s,%s",
-              aop->aopu.aop_reg[offset]->name, s);
+        emit2 ("ld %s,%s",
+               aop->aopu.aop_reg[offset]->name, s);
       spillPairReg(aop->aopu.aop_reg[offset]->name);
       break;
 
     case AOP_IY:
       wassert (!IS_GB);
       if (!canAssignToPtr (s))
-       {
-         emit2 ("ld a,%s", s);
+        {
+          emit2 ("ld a,%s", s);
           setupPair (PAIR_IY, aop, offset);
-         emit2 ("ld !*iyx,a", offset);
-       }
+          emit2 ("ld !*iyx,a", offset);
+        }
       else
         {
           setupPair (PAIR_IY, aop, offset);
@@ -1951,10 +2015,10 @@ aopPut (asmop * aop, const char *s, int offset)
       wassert (IS_GB);
       /* PENDING: for re-target */
       if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
-       {
-         emit2 ("ld a,!*hl");
-         s = "a";
-       }
+        {
+          emit2 ("ld a,!*hl");
+          s = "a";
+        }
       setupPair (PAIR_HL, aop, offset);
 
       emit2 ("ld !*hl,%s", s);
@@ -1963,11 +2027,11 @@ aopPut (asmop * aop, const char *s, int offset)
     case AOP_EXSTK:
       wassert (!IS_GB);
       if (!canAssignToPtr (s))
-       {
-         emit2 ("ld a,%s", s);
+        {
+          emit2 ("ld a,%s", s);
           setupPair (PAIR_IY, aop, offset);
-         emit2 ("ld !*iyx,a", offset);
-       }
+          emit2 ("ld !*iyx,a", offset);
+        }
       else
         {
           setupPair (PAIR_IY, aop, offset);
@@ -1977,77 +2041,77 @@ aopPut (asmop * aop, const char *s, int offset)
 
     case AOP_STK:
       if (IS_GB)
-       {
-         /* PENDING: re-target */
-         if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
-           {
-             emit2 ("ld a,!*hl");
-             s = "a";
-           }
-         setupPair (PAIR_HL, aop, offset);
-         if (!canAssignToPtr (s))
-           {
-             emit2 ("ld a,%s", s);
-             emit2 ("ld !*hl,a");
-           }
-         else
-           emit2 ("ld !*hl,%s", s);
-       }
+        {
+          /* PENDING: re-target */
+          if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
+            {
+              emit2 ("ld a,!*hl");
+              s = "a";
+            }
+          setupPair (PAIR_HL, aop, offset);
+          if (!canAssignToPtr (s))
+            {
+              emit2 ("ld a,%s", s);
+              emit2 ("ld !*hl,a");
+            }
+          else
+            emit2 ("ld !*hl,%s", s);
+        }
       else
-       {
-         if (aop->aopu.aop_stk >= 0)
-           offset += _G.stack.param_offset;
-         if (!canAssignToPtr (s))
-           {
-             emit2 ("ld a,%s", s);
-             emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
-           }
-         else
+        {
+          if (aop->aopu.aop_stk >= 0)
+            offset += _G.stack.param_offset;
+          if (!canAssignToPtr (s))
+            {
+              emit2 ("ld a,%s", s);
+              emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
+            }
+          else
             {
               emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
             }
-       }
+        }
       break;
 
     case AOP_CRY:
       /* if bit variable */
       if (!aop->aopu.aop_dir)
-       {
-         emit2 ("ld a,!zero");
-         emit2 ("rla");
-       }
+        {
+          emit2 ("ld a,!zero");
+          emit2 ("rla");
+        }
       else
-       {
-         /* In bit space but not in C - cant happen */
-         wassertl (0, "Tried to write into a bit variable");
-       }
+        {
+          /* In bit space but not in C - cant happen */
+          wassertl (0, "Tried to write into a bit variable");
+        }
       break;
 
     case AOP_STR:
       aop->coff = offset;
       if (strcmp (aop->aopu.aop_str[offset], s))
-       {
-         emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
-       }
+        {
+          emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
+        }
       spillPairReg(aop->aopu.aop_str[offset]);
       break;
 
     case AOP_ACC:
       aop->coff = offset;
       if (!offset && (strcmp (s, "acc") == 0))
-       break;
+        break;
       if (offset > 0)
-       {
+        {
           wassertl (0, "Tried to access past the end of A");
-       }
+        }
       else
-       {
-         if (strcmp (aop->aopu.aop_str[offset], s))
-           {
-             emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
-             spillPairReg(aop->aopu.aop_str[offset]);
-           }
-       }
+        {
+          if (strcmp (aop->aopu.aop_str[offset], s))
+            {
+              emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
+              spillPairReg(aop->aopu.aop_str[offset]);
+            }
+        }
       break;
 
     case AOP_HLREG:
@@ -2061,14 +2125,14 @@ aopPut (asmop * aop, const char *s, int offset)
       if (aop->aopu.aop_pairId==PAIR_IX)
         emit2 ("ld !*ixx,%s", 0, s);
       else if (aop->aopu.aop_pairId==PAIR_IY)
-        emit2 ("ld !*ixy,%s", 0, s);
+        emit2 ("ld !*iyx,%s", 0, s);
       else
         emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s);
       break;
 
     default:
       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-             "aopPut got unsupported aop->type");
+              "aopPut got unsupported aop->type");
       exit (0);
     }
 }
@@ -2077,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_IS_PAIRPTR(x, p) (AOP_TYPE (x) == AOP_PAIRPTR && AOP (x)->aopu.aop_pairId == p)
 
 static void
 commitPair (asmop * aop, PAIR_ID id)
@@ -2128,7 +2193,7 @@ getDataSize (operand * op)
 /*-----------------------------------------------------------------*/
 static void
 movLeft2Result (operand * left, int offl,
-               operand * result, int offr, int sign)
+                operand * result, int offr, int sign)
 {
   const char *l;
 
@@ -2137,23 +2202,23 @@ movLeft2Result (operand * left, int offl,
       l = aopGet (AOP (left), offl, FALSE);
 
       if (!sign)
-       {
-         aopPut (AOP (result), l, offr);
-       }
+        {
+          aopPut (AOP (result), l, offr);
+        }
       else
-       {
+        {
           if (getDataSize (left) == offl + 1)
             {
               emit2 ("ld a,%s", l);
               aopPut (AOP (result), "a", offr);
             }
-       }
+        }
     }
 }
 
 static void
 movLeft2ResultLong (operand * left, int offl,
-               operand * result, int offr, int sign,
+                operand * result, int offr, int sign,
                 int size)
 {
   if (size == 1)
@@ -2170,12 +2235,12 @@ movLeft2ResultLong (operand * left, int offl,
           emit2 ("ld a,%s", aopGet (AOP (left), LSB, FALSE));
           emit2 ("ld h,%s", aopGet (AOP (left), MSB16, FALSE));
           emit2 ("ld l,a");
-         spillPair (PAIR_HL);
+          spillPair (PAIR_HL);
         }
       else if ( getPairId ( AOP (result)) == PAIR_IY)
         {
           PAIR_ID id = getPairId (AOP (left));
-          if (id != PAIR_INVALID) 
+          if (id != PAIR_INVALID)
             {
               emit2("push %s", _pairs[id].name);
               emit2("pop iy");
@@ -2208,38 +2273,31 @@ outAcc (operand * result)
       offset = 1;
       /* unsigned or positive */
       while (size--)
-       {
-         aopPut (AOP (result), "!zero", offset++);
-       }
+        {
+          aopPut (AOP (result), "!zero", offset++);
+        }
     }
 }
 
 /** 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)
     {
-      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");
-      if (swap_sense)
-       emit2 ("xor a,!immedbyte", 1);
       outAcc (result);
     }
 }
 
-void
-outBitC (operand * result)
-{
-  outBitCLong (result, FALSE);
-}
-
 /*-----------------------------------------------------------------*/
 /* toBoolean - emit code for orl a,operator(sizeop)                */
 /*-----------------------------------------------------------------*/
@@ -2253,15 +2311,15 @@ _toBoolean (operand * oper)
       emit2 ("ld a,%s", aopGet (AOP (oper), offset++, FALSE));
       size--;
       while (size--)
-       emit2 ("or a,%s", aopGet (AOP (oper), offset++, FALSE));
+        emit2 ("or a,%s", aopGet (AOP (oper), offset++, FALSE));
     }
   else
     {
       if (AOP (oper)->type != AOP_ACC)
-       {
-         _clearCarry();
-         emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE));
-       }
+        {
+          _clearCarry();
+          emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE));
+        }
     }
 }
 
@@ -2397,7 +2455,7 @@ genUminusFloat (operand * op, operand * result)
   emitDebug("; genUminusFloat");
 
   /* for this we just need to flip the
-     first it then copy the rest in place */
+     first bit then copy the rest in place */
   size = AOP_SIZE (op) - 1;
 
   _moveA(aopGet (AOP (op), MSB32, FALSE));
@@ -2474,7 +2532,7 @@ genUminus (iCode * ic)
       emit2 ("rlc a");
       emit2 ("sbc a,a");
       while (size--)
-       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+        aopPut (AOP (IC_RESULT (ic)), "a", offset++);
     }
 
 release:
@@ -2507,10 +2565,20 @@ assignResultValue (operand * oper)
     }
   else
     {
-      while (size--)
-       {
-         aopPut (AOP (oper), _fReturn[size], 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);
+        }
     }
 }
 
@@ -2551,7 +2619,7 @@ _saveRegsForCall(iCode *ic, int sendSetSize)
       o Compute if DE and/or BC are used to hold the result value
       o If (DE is used, or in the send set) and is not used in the result, push.
       o If BC is used and is not in the result, push
-      o 
+      o
       o If DE is used in the send set, fetch
       o If HL is used in the send set, fetch
       o Call
@@ -2563,7 +2631,7 @@ _saveRegsForCall(iCode *ic, int sendSetSize)
     bool bcInRet = FALSE, deInRet = FALSE;
     bitVect *rInUse;
 
-    rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), 
+    rInUse = bitVectCplAnd (bitVectCopy (ic->rMask),
                             z80_rUmaskForOp (IC_RESULT(ic)));
 
     deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
@@ -2614,7 +2682,7 @@ genIpush (iCode * ic)
     */
     int nAddSets = 0;
     iCode *walk = ic->next;
-    
+
     while (walk) {
       if (walk->op == SEND) {
         nAddSets++;
@@ -2647,43 +2715,50 @@ genIpush (iCode * ic)
   else
     {
       if (size == 2)
-       {
-         fetchHL (AOP (IC_LEFT (ic)));
-         emit2 ("push hl");
-         spillPair (PAIR_HL);
-         _G.stack.pushed += 2;
-         goto release;
-       }
+        {
+          fetchHL (AOP (IC_LEFT (ic)));
+          emit2 ("push hl");
+          _G.stack.pushed += 2;
+          goto release;
+        }
       if (size == 4)
-       {
-         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");
-         spillPair (PAIR_HL);
-         _G.stack.pushed += 2;
-         goto release;
-       }
+        {
+          fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
+          emit2 ("push hl");
+          _G.stack.pushed += 2;
+          fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 0);
+          emit2 ("push hl");
+          _G.stack.pushed += 2;
+          goto release;
+        }
       offset = size;
       while (size--)
-       {
-         if (AOP (IC_LEFT (ic))->type == AOP_IY)
-           {
-             char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
-             wassert (l);
-             emit2 ("ld a,(%s)", l);
-           }
-         else
-           {
-             l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
-             emit2 ("ld a,%s", l);
-           }
-         emit2 ("push af");
-         emit2 ("inc sp");
-         _G.stack.pushed++;
-       }
+        {
+          if (AOP (IC_LEFT (ic))->type == AOP_IY)
+            {
+              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);
+              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 ("inc sp");
+          _G.stack.pushed++;
+        }
     }
 release:
   freeAsmop (IC_LEFT (ic), NULL, ic);
@@ -2712,12 +2787,12 @@ genIpop (iCode * ic)
   else
     {
       while (size--)
-       {
-         emit2 ("dec sp");
-         emit2 ("pop hl");
-         spillPair (PAIR_HL);
-         aopPut (AOP (IC_LEFT (ic)), "l", offset--);
-       }
+        {
+          emit2 ("dec sp");
+          emit2 ("pop hl");
+          spillPair (PAIR_HL);
+          aopPut (AOP (IC_LEFT (ic)), "l", offset--);
+        }
     }
 
   freeAsmop (IC_LEFT (ic), NULL, ic);
@@ -2766,28 +2841,28 @@ _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
     {
       int i;
       for (i = 0; i < aop->size; i++)
-       {
-         if (pairId == PAIR_DE)
-           {
-             emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
-             if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
-               ret++;
-             if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
-               ret++;
-           }
+        {
+          if (pairId == PAIR_DE)
+            {
+              emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
+              if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
+                ret++;
+              if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
+                ret++;
+            }
           else if (pairId == PAIR_BC)
             {
-             emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
-             if (!strcmp (aop->aopu.aop_reg[i]->name, "c"))
-               ret++;
-             if (!strcmp (aop->aopu.aop_reg[i]->name, "b"))
-               ret++;
+              emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
+              if (!strcmp (aop->aopu.aop_reg[i]->name, "c"))
+                ret++;
+              if (!strcmp (aop->aopu.aop_reg[i]->name, "b"))
+                ret++;
+            }
+          else
+            {
+              wassert (0);
             }
-         else
-           {
-             wassert (0);
-           }
-       }
+        }
     }
 
   freeAsmop (IC_LEFT (ic), NULL, ic);
@@ -2873,28 +2948,29 @@ emitCall (iCode * ic, bool ispcall)
   if (ispcall)
     {
       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
-       {
-         werror (W_INDIR_BANKED);
-       }
+        {
+          werror (W_INDIR_BANKED);
+        }
       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
 
       if (isLitWord (AOP (IC_LEFT (ic))))
-       {
-         emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
-       }
+        {
+          emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
+        }
       else
-       {
-         symbol *rlbl = newiTempLabel (NULL);
-         spillPair (PAIR_HL);
-         emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
-         emit2 ("push hl");
-         _G.stack.pushed += 2;
-
-         fetchHL (AOP (IC_LEFT (ic)));
-         emit2 ("jp !*hl");
-         emit2 ("!tlabeldef", (rlbl->key + 100));
-         _G.stack.pushed -= 2;
-       }
+        {
+          symbol *rlbl = newiTempLabel (NULL);
+          spillPair (PAIR_HL);
+          emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
+          emit2 ("push hl");
+          _G.stack.pushed += 2;
+
+          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);
     }
   else
@@ -2903,36 +2979,22 @@ emitCall (iCode * ic, bool ispcall)
       OP_SYMBOL (IC_LEFT (ic))->rname :
       OP_SYMBOL (IC_LEFT (ic))->name;
       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
-       {
-         emit2 ("call banked_call");
-         emit2 ("!dws", name);
-         emit2 ("!dw !bankimmeds", name);
-       }
+        {
+          emit2 ("call banked_call");
+          emit2 ("!dws", name);
+          emit2 ("!dw !bankimmeds", name);
+        }
       else
-       {
-         /* make the call */
-         emit2 ("call %s", name);
-       }
+        {
+          /* make the call */
+          emit2 ("call %s", name);
+        }
     }
   spillCached ();
 
-  /* Mark the regsiters as restored. */
+  /* 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)
     {
@@ -2940,31 +3002,44 @@ emitCall (iCode * ic, bool ispcall)
 
       _G.stack.pushed -= i;
       if (IS_GB)
-       {
-         emit2 ("!ldaspsp", i);
-       }
+        {
+          emit2 ("!ldaspsp", i);
+        }
       else
-       {
-         spillCached ();
-         if (i > 8)
-           {
-             emit2 ("ld iy,!immedword", i);
-             emit2 ("add iy,sp");
-             emit2 ("ld sp,iy");
-           }
-         else
-           {
-             while (i > 1)
-               {
-                 emit2 ("pop af");
-                 i -= 2;
-               }
-             if (i)
+        {
+          spillCached ();
+          if (i > 8)
+            {
+              emit2 ("ld iy,!immedword", i);
+              emit2 ("add iy,sp");
+              emit2 ("ld sp,iy");
+            }
+          else
+            {
+              while (i > 1)
+                {
+                  emit2 ("pop af");
+                  i -= 2;
+                }
+              if (i)
                 {
                   emit2 ("inc sp");
                 }
-           }
-       }
+            }
+        }
+    }
+
+  /* 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 ();
@@ -2984,7 +3059,7 @@ emitCall (iCode * ic, bool ispcall)
       eInRet = FALSE;
     }
 
-  if (_G.stack.pushedDE) 
+  if (_G.stack.pushedDE)
     {
       if (dInRet && eInRet)
         {
@@ -3009,8 +3084,8 @@ emitCall (iCode * ic, bool ispcall)
         }
       _G.stack.pushedDE = FALSE;
     }
-  
-  if (_G.stack.pushedBC) 
+
+  if (_G.stack.pushedBC)
     {
       if (bInRet && cInRet)
         {
@@ -3068,7 +3143,7 @@ resultRemat (iCode * ic)
     {
       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
       if (sym->remat && !POINTER_SET (ic))
-       return 1;
+        return 1;
     }
 
   return 0;
@@ -3083,7 +3158,7 @@ static void
 genFunction (iCode * ic)
 {
   bool stackParm;
-  
+
   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
   sym_link *ftype;
 
@@ -3092,42 +3167,70 @@ genFunction (iCode * ic)
 
   setArea (IFFUNC_NONBANKED (sym->type));
 
-  /* PENDING: Reset the receive offset as it doesn't seem to get reset anywhere
-     else.
+  /* PENDING: Reset the receive offset as it
+     doesn't seem to get reset anywhere else.
   */
   _G.receiveOffset = 0;
 
   /* Record the last function name for debugging. */
   _G.lastFunctionName = sym->rname;
-  
+
   /* Create the function header */
   emit2 ("!functionheader", sym->name);
-  sprintf (buffer, "%s_start", sym->rname);
-  emit2 ("!labeldef", buffer);
-  emit2 ("!functionlabeldef", sym->rname);
-
-  if (options.profile) 
+  if (!IS_STATIC(sym->etype))
     {
-      emit2 ("!profileenter");
+      sprintf (buffer, "%s_start", sym->rname);
+      emit2 ("!labeldef", buffer);
+      _G.lines.current->isLabel = 1;
     }
+  emit2 ("!functionlabeldef", sym->rname);
+  _G.lines.current->isLabel = 1;
 
   ftype = operandType (IC_LEFT (ic));
 
-  /* if this is an interrupt service routine then save all potentially used registers. */
+  if (IFFUNC_ISNAKED(ftype))
+    {
+      emitDebug("; naked function: no prologue.");
+      return;
+    }
+
+  /* if this is an interrupt service routine
+     then save all potentially used registers. */
   if (IFFUNC_ISISR (sym->type))
     {
-      if (!FUNC_ISNAKED( sym->type ))
+      /* If critical function then turn interrupts off */
+      /* except when no interrupt number is given then it implies the NMI handler */
+      if (IFFUNC_ISCRITICAL (sym->type) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC))
         {
-          emit2 ("!pusha");
-       }
+          emit2 ("!di");
+        }
+
+      emit2 ("!pusha");
     }
   else
     {
-      /* if critical function then turn interrupts off */
+      /* This is a non-ISR function.
+         If critical function then turn interrupts off */
       if (IFFUNC_ISCRITICAL (sym->type))
         {
-          emit2 ("!di");
-       }
+          if (IS_GB)
+            {
+              emit2 ("!di");
+            }
+          else
+            {
+              //get interrupt enable flag IFF2 into P/O
+              emit2 ("ld a,i");
+              emit2 ("!di");
+              //save P/O flag
+              emit2 ("push af");
+            }
+        }
+    }
+
+  if (options.profile)
+    {
+      emit2 ("!profileenter");
     }
 
   /* PENDING: callee-save etc */
@@ -3144,30 +3247,30 @@ genFunction (iCode * ic)
     {
       int i;
       for (i = 0; i < sym->regsUsed->size; i++)
-       {
-         if (bitVectBitValue (sym->regsUsed, i))
-           {
-             switch (i)
-               {
-               case C_IDX:
-               case B_IDX:
+        {
+          if (bitVectBitValue (sym->regsUsed, i))
+            {
+              switch (i)
+                {
+                case C_IDX:
+                case B_IDX:
                   bcInUse = TRUE;
-                 break;
-               case D_IDX:
-               case E_IDX:
-                 if (IS_Z80) {
+                  break;
+                case D_IDX:
+                case E_IDX:
+                  if (IS_Z80) {
                     deInUse = TRUE;
                   }
                   else {
                     /* Other systems use DE as a temporary. */
                   }
-                 break;
-               }
-           }
-       }
+                  break;
+                }
+            }
+        }
     }
 
-  if (bcInUse) 
+  if (bcInUse)
     {
       emit2 ("push bc");
       _G.stack.param_offset += 2;
@@ -3185,7 +3288,7 @@ genFunction (iCode * ic)
 
   /* adjust the stack for the function */
   _G.stack.last = sym->stack;
-  
+
   stackParm = FALSE;
   for (sym = setFirstItem (istack->syms); sym;
        sym = setNextItem (istack->syms))
@@ -3197,7 +3300,7 @@ genFunction (iCode * ic)
         }
     }
   sym = OP_SYMBOL (IC_LEFT (ic));
-  
+
   _G.omitFramePtr = options.ommitFramePtr;
   if (IS_Z80 && !stackParm && !sym->stack)
     {
@@ -3210,8 +3313,23 @@ genFunction (iCode * ic)
   else if (sym->stack && IS_GB && sym->stack > -INT8MIN)
     emit2 ("!enterxl", sym->stack);
   else if (sym->stack)
-    emit2 ("!enterx", sym->stack);
-  else if( !FUNC_ISNAKED( sym->type )) /*.p.t.20030716 - now supporting Naked funcitons */
+    {
+      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");
 
   _G.stack.offset = sym->stack;
@@ -3225,6 +3343,11 @@ genEndFunction (iCode * ic)
 {
   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
 
+  if (IFFUNC_ISNAKED(sym->type))
+  {
+      emitDebug("; naked function: no epilogue.");
+      return;
+  }
 
   /* PENDING: calleeSave */
   if (IS_Z80 && _G.omitFramePtr)
@@ -3240,52 +3363,75 @@ genEndFunction (iCode * ic)
     {
       emit2 ("!leavex", _G.stack.offset);
     }
-  else if( !FUNC_ISNAKED( sym->type )) /*.p.t.20030716 - now supporting Naked funcitons */
+  else
     {
       emit2 ("!leave");
     }
-      
-  if (_G.calleeSaves.pushedDE) 
+
+  if (_G.calleeSaves.pushedDE)
     {
       emit2 ("pop de");
       _G.calleeSaves.pushedDE = FALSE;
     }
 
-  if (_G.calleeSaves.pushedBC) 
+  if (_G.calleeSaves.pushedBC)
     {
       emit2 ("pop bc");
       _G.calleeSaves.pushedBC = FALSE;
     }
 
-  if (options.profile) 
+  if (options.profile)
     {
       emit2 ("!profileexit");
     }
 
-  /* if this is an interrupt service routine then restore all potentially used registers. */
+  /* if this is an interrupt service routine
+     then save all potentially used registers. */
   if (IFFUNC_ISISR (sym->type))
     {
-      if (!FUNC_ISNAKED( sym->type ))
+      emit2 ("!popa");
+
+      /* If critical function then turn interrupts back on */
+      /* except when no interrupt number is given then it implies the NMI handler */
+      if (IFFUNC_ISCRITICAL (sym->type) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC))
         {
-          emit2 ("!popa");
+          emit2 ("!ei");
         }
     }
   else
     {
-      /* if critical function then turn interrupts back on */
+      /* This is a non-ISR function.
+         If critical function then turn interrupts back on */
       if (IFFUNC_ISCRITICAL (sym->type))
-        emit2 ("!ei");
+        {
+          if (IS_GB)
+            {
+              emit2 ("!ei");
+            }
+          else
+            {
+              symbol *tlbl = newiTempLabel (NULL);
+              //restore P/O flag
+              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 ("!ei");
+              emit2 ("!tlabeldef", (tlbl->key + 100));
+              _G.lines.current->isLabel = 1;
+            }
+        }
     }
 
   if (options.debug && currFunc)
     {
       debugFile->writeEndFunction (currFunc, ic, 1);
     }
-      
+
   if (IFFUNC_ISISR (sym->type))
     {
       /* "critical interrupt" is used to imply NMI handler */
-      if (IS_Z80 && IFFUNC_ISCRITICAL (sym->type))
+      if (IS_Z80 && IFFUNC_ISCRITICAL (sym->type) && FUNC_INTNO(sym->type) == INTNO_UNSPEC)
         emit2 ("retn");
       else
         emit2 ("reti");
@@ -3295,10 +3441,14 @@ genEndFunction (iCode * ic)
       /* Both banked and non-banked just ret */
       emit2 ("ret");
     }
-      
-  sprintf (buffer, "%s_end", sym->rname);
-  emit2 ("!labeldef", buffer);
-  
+
+  if (!IS_STATIC(sym->etype))
+    {
+      sprintf (buffer, "%s_end", sym->rname);
+      emit2 ("!labeldef", buffer);
+      _G.lines.current->isLabel = 1;
+    }
+
   _G.flushStatics = 1;
   _G.stack.pushed = 0;
   _G.stack.offset = 0;
@@ -3327,17 +3477,17 @@ genRet (iCode * ic)
 
   aopDump("IC_LEFT", AOP(IC_LEFT(ic)));
 
-  #if 0  
+  #if 0
   if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
     {
       if (IS_GB)
-       {
-         emit2 ("ld de,%s", l);
-       }
+        {
+          emit2 ("ld de,%s", l);
+        }
       else
-       {
-         emit2 ("ld hl,%s", l);
-       }
+        {
+          emit2 ("ld hl,%s", l);
+        }
     }
   #endif
   if (size==2)
@@ -3347,21 +3497,21 @@ genRet (iCode * ic)
   else
     {
       if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
-       {
-         fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
-         fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
-       }
+        {
+          fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
+          fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
+        }
       else
-       {
-         while (size--)
-           {
-             l = aopGet (AOP (IC_LEFT (ic)), offset,
-                         FALSE);
-             if (strcmp (_fReturn[offset], l))
-               emit2 ("ld %s,%s", _fReturn[offset], l);
+        {
+          while (size--)
+            {
+              l = aopGet (AOP (IC_LEFT (ic)), offset,
+                          FALSE);
+              if (strcmp (_fReturn[offset], l))
+                emit2 ("ld %s,%s", _fReturn[offset], l);
               offset++;
-           }
-       }
+            }
+        }
     }
   freeAsmop (IC_LEFT (ic), NULL, ic);
 
@@ -3369,7 +3519,7 @@ jumpret:
   /* generate a jump to the return label
      if the next is not the return statement */
   if (!(ic->next && ic->next->op == LABEL &&
-       IC_LABEL (ic->next) == returnLabel))
+        IC_LABEL (ic->next) == returnLabel))
 
     emit2 ("jp !tlabel", returnLabel->key + 100);
 }
@@ -3414,18 +3564,18 @@ genPlusIncr (iCode * ic)
 
   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 (isLitWord (AOP (IC_LEFT (ic))))
-       {
+        {
           fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
-         return TRUE;
-       }
+          return TRUE;
+        }
       if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
-       {
+        {
           if (getPairId (AOP (IC_LEFT (ic))) == PAIR_HL)
             {
               PAIR_ID freep = getFreePairId (ic);
@@ -3442,20 +3592,20 @@ genPlusIncr (iCode * ic)
               emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
               return TRUE;
             }
-       }
+        }
       if (icount > 5)
-       return FALSE;
+        return FALSE;
       /* Inc a pair */
       if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
-       {
-         if (icount > 2)
-           return FALSE;
-         movLeft2ResultLong (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0, 2);
-       }
+        {
+          if (icount > 2)
+            return FALSE;
+          movLeft2ResultLong (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0, 2);
+        }
       while (icount--)
-       {
-         emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic))));
-       }
+        {
+          emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic))));
+        }
       return TRUE;
     }
 
@@ -3481,14 +3631,14 @@ genPlusIncr (iCode * ic)
       symbol *tlbl = NULL;
       tlbl = newiTempLabel (NULL);
       while (size--)
-       {
-         emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
-         if (size)
-           {
-             emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
-           }
-       }
-      emitLabel (tlbl->key + 100);
+        {
+          emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
+          if (size)
+            {
+              emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
+            }
+        }
+      emitLabelNoSpill (tlbl->key + 100);
       return TRUE;
     }
 
@@ -3538,9 +3688,9 @@ outBitAcc (operand * result)
     }
   else
     {
-      emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
+      emit2 ("!shortjp Z,!tlabel", tlbl->key + 100);
       emit2 ("ld a,!one");
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
       outAcc (result);
     }
 }
@@ -3566,30 +3716,27 @@ shiftIntoPair (int idx, asmop *aop)
   wassertl (IS_Z80, "Only implemented for the Z80");
   //  wassertl (aop->type == AOP_EXSTK, "Only implemented for EXSTK");
 
-  switch (idx) 
+  emitDebug ("; Shift into pair idx %u", idx);
+
+  switch (idx)
     {
     case 0:
       id = PAIR_HL;
+      setupPair (PAIR_HL, aop, 0);
       break;
     case 1:
       id = PAIR_DE;
       _push (PAIR_DE);
-      break;
-    default:
-      wassertl (0, "Internal error - hit default case");
-    }
-
-  emitDebug ("; Shift into pair idx %u", idx);
-
-  if (id == PAIR_HL)
-    {
-      setupPair (PAIR_HL, aop, 0);
-    }
-  else
-    {
       setupPair (PAIR_IY, aop, 0);
       emit2 ("push iy");
       emit2 ("pop %s", _pairs[id].name);
+      break;
+    case 2:
+      id = PAIR_IY;
+      setupPair (PAIR_IY, aop, 0);
+      break;
+    default:
+      wassertl (0, "Internal error - hit default case");
     }
 
   aop->type = AOP_PAIRPTR;
@@ -3598,9 +3745,13 @@ shiftIntoPair (int idx, asmop *aop)
   _G.pairs[id].last_type = aop->type;
 }
 
-static void 
-setupToPreserveCarry (asmop *result, asmop *left, asmop *right)
+static void
+setupToPreserveCarry (iCode * ic)
 {
+  asmop *left   = AOP (IC_LEFT (ic));
+  asmop *right  = AOP (IC_RIGHT (ic));
+  asmop *result = AOP (IC_RESULT (ic));
+
   wassert (left && right);
 
   if (IS_Z80)
@@ -3610,7 +3761,12 @@ setupToPreserveCarry (asmop *result, asmop *left, asmop *right)
           shiftIntoPair (0, right);
           /* check result again, in case right == result */
           if (couldDestroyCarry (result))
-            shiftIntoPair (1, result);
+            {
+              if (!isPairInUse (PAIR_DE, ic))
+                shiftIntoPair (1, result);
+              else
+                shiftIntoPair (2, result);
+            }
         }
       else if (couldDestroyCarry (right))
         {
@@ -3681,8 +3837,6 @@ genPlus (iCode * ic)
   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 */
@@ -3694,14 +3848,14 @@ genPlus (iCode * ic)
 
       if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT && AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT &&
           left && right)
-       {
-         /* It's a pair */
-         /* PENDING: fix */
-         char buffer[100];
-         sprintf (buffer, "#(%s + %s)", left, right);
-         emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
-         goto release;
-       }
+        {
+          /* It's a pair */
+          /* PENDING: fix */
+          char buffer[100];
+          sprintf (buffer, "#(%s + %s)", left, right);
+          emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
+          goto release;
+        }
     }
 
   if ((isPair (AOP (IC_RIGHT (ic))) || isPair (AOP (IC_LEFT (ic)))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
@@ -3711,7 +3865,7 @@ genPlus (iCode * 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);
@@ -3729,7 +3883,7 @@ genPlus (iCode * 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;
@@ -3744,14 +3898,23 @@ genPlus (iCode * 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;
     }
 
   /* Special case:
-     ld hl,sp+n trashes C so we cant afford to do it during an
-     add with stack based varibles.  Worst case is:
+     ld hl,sp+n trashes C so we can't afford to do it during an
+     add with stack based variables.  Worst case is:
      ld  hl,sp+left
      ld  a,(hl)
      ld  hl,sp+right
@@ -3764,7 +3927,7 @@ genPlus (iCode * ic)
      adc (hl)
      ld  hl,sp+result+1
      ld  (hl),a
-     So you cant afford to load up hl if either left, right, or result
+     So you can't afford to load up hl if either left, right, or result
      is on the stack (*sigh*)  The alt is:
      ld  hl,sp+left
      ld  de,(hl)
@@ -3780,36 +3943,36 @@ genPlus (iCode * ic)
   if (IS_GB)
     {
       if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
-         AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
-         AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
-       {
-         if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
-              AOP_SIZE (IC_RIGHT (ic)) == 2) &&
-             (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
-              AOP_SIZE (IC_RIGHT (ic)) <= 2))
-           {
-             if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
-               {
-                 /* Swap left and right */
-                 operand *t = IC_RIGHT (ic);
-                 IC_RIGHT (ic) = IC_LEFT (ic);
-                 IC_LEFT (ic) = t;
-               }
-             if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
-               {
-                 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
-                 emit2 ("add hl,bc");
-               }
-             else
-               {
-                 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
-                 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
-                 emit2 ("add hl,de");
-               }
-             commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
-             goto release;
-           }
-       }
+          AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
+          AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
+        {
+          if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
+               AOP_SIZE (IC_RIGHT (ic)) == 2) &&
+              (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
+               AOP_SIZE (IC_RIGHT (ic)) <= 2))
+            {
+              if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
+                {
+                  /* Swap left and right */
+                  operand *t = IC_RIGHT (ic);
+                  IC_RIGHT (ic) = IC_LEFT (ic);
+                  IC_LEFT (ic) = t;
+                }
+              if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
+                {
+                  fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
+                  emit2 ("add hl,bc");
+                }
+              else
+                {
+                  fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
+                  fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
+                  emit2 ("add hl,de");
+                }
+              commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
+              goto release;
+            }
+        }
       if (size == 4)
         {
           /* Be paranoid on the GB with 4 byte variables due to how C
@@ -3819,31 +3982,65 @@ genPlus (iCode * ic)
           goto release;
         }
     }
-  
-  setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
+
+  setupToPreserveCarry (ic);
+
+  /* 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)
+    {
+      _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)))
+        {
+          aopPut (AOP (IC_RESULT (ic)), "a", 0);
+          _moveA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE));
+        }
+      else
+        {
+          emitDebug ("; Addition result is in same register as operand of next addition.");
+          if(strchr (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), 'c') ||
+             strchr (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), 'b') )
+            {
+              emit2 ("push de");
+              emit2 ("ld e, a");
+              emit2 ("ld a, %s", aopGet (AOP (IC_LEFT (ic)), 1, FALSE));
+              emit2 ("ld d, a");
+              emit2 ("ld a, e");
+              emit2 ("ld %s, a", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
+              emit2 ("ld a, d");
+              emit2 ("pop de");
+            }
+          else
+            {
+              emit2 ("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--)
     {
-      if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
-       {
-         _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));
-       }
+      _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
-       {
-         _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));
-       }
+        emit2 ("adc a,%s", aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
     }
 
@@ -3852,7 +4049,6 @@ release:
   freeAsmop (IC_LEFT (ic), NULL, ic);
   freeAsmop (IC_RIGHT (ic), NULL, ic);
   freeAsmop (IC_RESULT (ic), NULL, ic);
-
 }
 
 /*-----------------------------------------------------------------*/
@@ -3871,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 ((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));
@@ -3881,7 +4077,7 @@ genMinusDec (iCode * ic)
       (size > 1) && isPair (AOP (IC_RESULT (ic))))
     {
       while (icount--)
-       emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
+        emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
       return TRUE;
     }
 
@@ -3890,7 +4086,7 @@ genMinusDec (iCode * ic)
     {
       movLeft2ResultLong (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0, 2);
       while (icount--)
-       emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
+        emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
       return TRUE;
     }
 
@@ -3921,7 +4117,7 @@ genMinusDec (iCode * ic)
   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
     {
       while (icount--)
-       emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
+        emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
       return TRUE;
     }
 
@@ -3961,7 +4157,7 @@ genMinus (iCode * ic)
     }
   else
     {
-      lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+      lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
       lit = -(long) lit;
     }
 
@@ -3969,45 +4165,45 @@ genMinus (iCode * ic)
   if (IS_GB)
     {
       if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
-         AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
-         AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
-       {
-         if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
-              AOP_SIZE (IC_RIGHT (ic)) == 2) &&
-             (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
-              AOP_SIZE (IC_RIGHT (ic)) <= 2))
-           {
-             PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
-             PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
-
-             if (left == PAIR_INVALID && right == PAIR_INVALID)
-               {
-                 left = PAIR_DE;
-                 right = PAIR_HL;
-               }
-             else if (right == PAIR_INVALID)
-               right = PAIR_DE;
-             else if (left == PAIR_INVALID)
-               left = PAIR_DE;
-
-             fetchPair (left, AOP (IC_LEFT (ic)));
-             /* Order is important.  Right may be HL */
-             fetchPair (right, AOP (IC_RIGHT (ic)));
-
-             emit2 ("ld a,%s", _pairs[left].l);
-             emit2 ("sub a,%s", _pairs[right].l);
-             emit2 ("ld e,a");
-             emit2 ("ld a,%s", _pairs[left].h);
-             emit2 ("sbc a,%s", _pairs[right].h);
+          AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
+          AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
+        {
+          if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
+               AOP_SIZE (IC_RIGHT (ic)) == 2) &&
+              (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
+               AOP_SIZE (IC_RIGHT (ic)) <= 2))
+            {
+              PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
+              PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
+
+              if (left == PAIR_INVALID && right == PAIR_INVALID)
+                {
+                  left = PAIR_DE;
+                  right = PAIR_HL;
+                }
+              else if (right == PAIR_INVALID)
+                right = PAIR_DE;
+              else if (left == PAIR_INVALID)
+                left = PAIR_DE;
+
+              fetchPair (left, AOP (IC_LEFT (ic)));
+              /* Order is important.  Right may be HL */
+              fetchPair (right, AOP (IC_RIGHT (ic)));
+
+              emit2 ("ld a,%s", _pairs[left].l);
+              emit2 ("sub a,%s", _pairs[right].l);
+              emit2 ("ld e,a");
+              emit2 ("ld a,%s", _pairs[left].h);
+              emit2 ("sbc a,%s", _pairs[right].h);
 
               if ( AOP_SIZE (IC_RESULT (ic)) > 1)
                 {
                   aopPut (AOP (IC_RESULT (ic)), "a", 1);
                 }
-             aopPut (AOP (IC_RESULT (ic)), "e", 0);
-             goto release;
-           }
-       }
+              aopPut (AOP (IC_RESULT (ic)), "e", 0);
+              goto release;
+            }
+        }
       if (size == 4)
         {
           /* Be paranoid on the GB with 4 byte variables due to how C
@@ -4018,29 +4214,34 @@ genMinus (iCode * ic)
         }
     }
 
-  setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
+  setupToPreserveCarry (ic);
 
   /* if literal, add a,#-lit, else normal subb */
   while (size--)
     {
       _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
-       {
-         if (!offset)
-           emit2 ("sub a,%s",
-                     aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
-         else
-           emit2 ("sbc a,%s",
-                     aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
-       }
+        {
+          if (!offset)
+            emit2 ("sub a,%s",
+                      aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+          else
+            emit2 ("sbc a,%s",
+                      aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+        }
       else
-       {
-         /* first add without previous c */
-         if (!offset)
-           emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
-         else
-           emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
-       }
+        {
+          /* first add without previous c */
+          if (!offset)
+            {
+              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));
+        }
       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
     }
 
@@ -4058,6 +4259,72 @@ release:
   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                     */
 /*-----------------------------------------------------------------*/
@@ -4074,7 +4341,7 @@ genMult (iCode * ic)
   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
   aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
-  
+
   byteResult =  (AOP_SIZE (IC_RESULT (ic)) == 1);
 
   if (AOP_SIZE (IC_LEFT (ic)) > 2 ||
@@ -4092,9 +4359,15 @@ genMult (iCode * ic)
       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");
 
-  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");
 
@@ -4103,7 +4376,9 @@ genMult (iCode * ic)
     _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)
@@ -4112,7 +4387,7 @@ genMult (iCode * ic)
           emit2 ("rlc a");
           emit2 ("sbc a,a");
           emit2 ("ld d,a");
-       }
+        }
     }
   else
     {
@@ -4121,32 +4396,40 @@ genMult (iCode * 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 (byteResult)
+            emit2 ("add a,a");
+          else
+            emit2 ("add hl,hl");
         }
       if (i & 0x8000U)
         {
           if (active == FALSE)
             {
-              emit2 ("ld l,e");
-              if (!byteResult)
-               emit2 ("ld h,d");
+              if (byteResult)
+                emit2("ld e,a");
+              else
+                {
+                  emit2 ("ld l,e");
+                  emit2 ("ld h,d");
+                }
             }
           else
             {
-              emit2 ("add hl,de");
+              if (byteResult)
+                emit2 ("add a,e");
+              else
+                emit2 ("add hl,de");
             }
           active = TRUE;
         }
       i <<= 1;
     }
 
-  spillCached();
+  spillPair(PAIR_HL);
 
   if (IS_Z80 && _G.stack.pushedDE)
     {
@@ -4155,7 +4438,7 @@ genMult (iCode * ic)
     }
 
   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);
 
@@ -4199,60 +4482,60 @@ genIfxJump (iCode * ic, char *jval)
     {
       jlbl = IC_TRUE (ic);
       if (!strcmp (jval, "a"))
-       {
-         inst = "nz";
-       }
+        {
+          inst = "NZ";
+        }
       else if (!strcmp (jval, "c"))
-       {
-         inst = "c";
-       }
+        {
+          inst = "C";
+        }
       else if (!strcmp (jval, "nc"))
-       {
-         inst = "nc";
-       }
+        {
+          inst = "NC";
+        }
       else if (!strcmp (jval, "m"))
-       {
-         inst = "m";
-       }
+        {
+          inst = "M";
+        }
       else if (!strcmp (jval, "p"))
-       {
-         inst = "p";
-       }
+        {
+          inst = "P";
+        }
       else
-       {
-         /* The buffer contains the bit on A that we should test */
-         inst = "nz";
-       }
+        {
+          /* The buffer contains the bit on A that we should test */
+          inst = "NZ";
+        }
     }
   else
     {
       /* false label is present */
       jlbl = IC_FALSE (ic);
       if (!strcmp (jval, "a"))
-       {
-         inst = "z";
-       }
+        {
+          inst = "Z";
+        }
       else if (!strcmp (jval, "c"))
-       {
-         inst = "nc";
-       }
+        {
+          inst = "NC";
+        }
       else if (!strcmp (jval, "nc"))
-       {
-         inst = "c";
-       }
+        {
+          inst = "C";
+        }
       else if (!strcmp (jval, "m"))
-       {
-         inst = "p";
-       }
+        {
+          inst = "P";
+        }
       else if (!strcmp (jval, "p"))
-       {
-         inst = "m";
-       }
+        {
+          inst = "M";
+        }
       else
-       {
-         /* The buffer contains the bit on A that we should test */
-         inst = "z";
-       }
+        {
+          /* The buffer contains the bit on A that we should test */
+          inst = "Z";
+        }
     }
   /* Z80 can do a conditional long jump */
   if (!strcmp (jval, "a"))
@@ -4292,17 +4575,17 @@ _getPairIdName (PAIR_ID id)
 #if OLD
       /* if unsigned char cmp with lit, just compare */
       if ((size == 1) &&
-         (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
-       {
-         emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
-         if (sign)
-           {
-             emit2 ("xor a,!immedbyte", 0x80);
-             emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
-           }
-         else
-           emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
-       }
+          (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
+        {
+          emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
+          if (sign)
+            {
+              emit2 ("xor a,!immedbyte", 0x80);
+              emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
+            }
+          else
+            emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
+        }
       else if (size == 4 && IS_GB && requiresHL(AOP(right)) && requiresHL(AOP(left)))
         {
           // On the Gameboy we can't afford to adjust HL as it may trash the carry.
@@ -4334,7 +4617,7 @@ _getPairIdName (PAIR_ID id)
                   emit2 ("ld a,(de)");
                   emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc");
                 }
-              
+
               if (size != 0)
                 {
                   emit2 ("inc hl");
@@ -4371,7 +4654,7 @@ _getPairIdName (PAIR_ID id)
                   emit2 ("ld a,(hl)");
                   emit2 ("%s a,%d(iy)", offset == 0 ? "sub" : "sbc", offset);
                 }
-              
+
               if (size != 0)
                 {
                   emit2 ("inc hl");
@@ -4382,87 +4665,85 @@ _getPairIdName (PAIR_ID id)
           spillPair (PAIR_IY);
         }
       else
-       {
-         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 == 0L)
-               {
-                 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
-                       emit2 ("rlc a");
-                   }
-                 goto release;
-               }
-           }
-          
-         if (sign)
-           {
-             /* First setup h and l contaning the top most bytes XORed */
-             bool fDidXor = FALSE;
-             if (AOP_TYPE (left) == AOP_LIT)
-               {
-                 unsigned long lit = (unsigned long)
-                 floatFromVal (AOP (left)->aopu.aop_lit);
-                 emit2 ("ld %s,!immedbyte", _fTmp[0],
-                        0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
-               }
-             else
-               {
-                 emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE));
-                 emit2 ("xor a,!immedbyte", 0x80);
-                 emit2 ("ld %s,a", _fTmp[0]);
-                 fDidXor = TRUE;
-               }
-             if (AOP_TYPE (right) == AOP_LIT)
-               {
-                 unsigned long lit = (unsigned long)
-                 floatFromVal (AOP (right)->aopu.aop_lit);
-                 emit2 ("ld %s,!immedbyte", _fTmp[1],
-                        0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
-               }
-             else
-               {
-                 emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE));
-                 emit2 ("xor a,!immedbyte", 0x80);
-                 emit2 ("ld %s,a", _fTmp[1]);
-                 fDidXor = TRUE;
-               }
-           }
-         while (size--)
-           {
-             /* Do a long subtract */
-             if (!sign || size)
-               {
-                 _moveA (aopGet (AOP (left), offset, FALSE));
-               }
-             if (sign && size == 0)
-               {
-                 emit2 ("ld a,%s", _fTmp[0]);
-                 emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", _fTmp[1]);
-               }
-             else
-               {
-                 /* Subtract through, propagating the carry */
-                 emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE));
-                 offset++;
-               }
-           }
-       }
+        {
+          if (AOP_TYPE (right) == AOP_LIT)
+            {
+              lit = ulFromVal (AOP (right)->aopu.aop_lit);
+              /* optimize if(x < 0) or if(x >= 0) */
+              if (lit == 0L)
+                {
+                  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
+                        emit2 ("rlc a");
+                    }
+                  goto release;
+                }
+            }
+
+          if (sign)
+            {
+              /* First setup h and l contaning the top most bytes XORed */
+              bool fDidXor = FALSE;
+              if (AOP_TYPE (left) == 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));
+                }
+              else
+                {
+                  emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE));
+                  emit2 ("xor a,!immedbyte", 0x80);
+                  emit2 ("ld %s,a", _fTmp[0]);
+                  fDidXor = TRUE;
+                }
+              if (AOP_TYPE (right) == 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));
+                }
+              else
+                {
+                  emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE));
+                  emit2 ("xor a,!immedbyte", 0x80);
+                  emit2 ("ld %s,a", _fTmp[1]);
+                  fDidXor = TRUE;
+                }
+            }
+          while (size--)
+            {
+              /* Do a long subtract */
+              if (!sign || size)
+                {
+                  _moveA (aopGet (AOP (left), offset, FALSE));
+                }
+              if (sign && size == 0)
+                {
+                  emit2 ("ld a,%s", _fTmp[0]);
+                  emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", _fTmp[1]);
+                }
+              else
+                {
+                  /* Subtract through, propagating the carry */
+                  emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE));
+                  offset++;
+                }
+            }
+        }
     }
 #endif
 
@@ -4470,11 +4751,10 @@ _getPairIdName (PAIR_ID id)
  */
 static void
 genCmp (operand * left, operand * right,
-       operand * result, iCode * ifx, int sign)
+        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 &&
@@ -4501,7 +4781,7 @@ genCmp (operand * left, operand * right,
             {
               emit2 ("ld a,(de)");
               emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc");
-              
+
               if (size != 0)
                 {
                   emit2 ("inc hl");
@@ -4515,7 +4795,7 @@ genCmp (operand * left, operand * right,
 
       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)
             {
@@ -4535,13 +4815,13 @@ genCmp (operand * left, operand * right,
                     }
                   else
                     {
-                      if (!sign) 
+                      if (!sign)
                         {
                           emit2 ("rlc a");
                         }
                       if (ifx)
                         {
-                          genIfxJump (ifx, swap_sense ? "c" : "nc");
+                          genIfxJump (ifx, "nc");
                           return;
                         }
                     }
@@ -4567,7 +4847,7 @@ release:
           /* Shift the sign bit up into carry */
           emit2 ("rlca");
         }
-      outBitCLong (result, swap_sense);
+      outBitC (result);
     }
   else
     {
@@ -4581,16 +4861,16 @@ release:
               if (IS_GB)
                 {
                   emit2 ("rlca");
-                  genIfxJump (ifx, swap_sense ? "nc" : "c");
+                  genIfxJump (ifx, "c");
                 }
               else
                 {
-                  genIfxJump (ifx, swap_sense ? "p" : "m");
+                  genIfxJump (ifx, "m");
                 }
             }
           else
             {
-              genIfxJump (ifx, swap_sense ? "nc" : "c");
+              genIfxJump (ifx, "c");
             }
         }
       else
@@ -4600,7 +4880,7 @@ release:
               /* Shift the sign bit up into carry */
               emit2 ("rlca");
             }
-          outBitCLong (result, swap_sense);
+          outBitC (result);
         }
       /* leave the result in acc */
     }
@@ -4623,13 +4903,16 @@ genCmpGt (iCode * ic, iCode * ifx)
   letype = getSpec (operandType (left));
   retype = getSpec (operandType (right));
   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
-  /* assign the amsops */
+  /* assign the asmops */
   aopOp (left, ic, FALSE, FALSE);
   aopOp (right, ic, FALSE, FALSE);
   aopOp (result, ic, TRUE, FALSE);
 
+  setupToPreserveCarry (ic);
+
   genCmp (right, left, result, ifx, sign);
 
+  _G.preserveCarry = FALSE;
   freeAsmop (left, NULL, ic);
   freeAsmop (right, NULL, ic);
   freeAsmop (result, NULL, ic);
@@ -4653,13 +4936,16 @@ genCmpLt (iCode * ic, iCode * ifx)
   retype = getSpec (operandType (right));
   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
 
-  /* assign the amsops */
+  /* assign the asmops */
   aopOp (left, ic, FALSE, FALSE);
   aopOp (right, ic, FALSE, FALSE);
   aopOp (result, ic, TRUE, FALSE);
 
+  setupToPreserveCarry (ic);
+
   genCmp (left, right, result, ifx, sign);
 
+  _G.preserveCarry = FALSE;
   freeAsmop (left, NULL, ic);
   freeAsmop (right, NULL, ic);
   freeAsmop (result, NULL, ic);
@@ -4667,8 +4953,9 @@ genCmpLt (iCode * ic, iCode * ifx)
 
 /*-----------------------------------------------------------------*/
 /* 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));
@@ -4683,78 +4970,92 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
       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 (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)
-       {
-         emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
-         if (size > 1)
-           {
-             while (--size)
-               {
-                 emit2 ("or a,%s", aopGet (AOP (left), ++offset, FALSE));
-               }
-           }
-         else
-           {
-             emit2 ("or a,a");
-           }
-         emit2 ("jp nz,!tlabel", lbl->key + 100);
-       }
+        {
+          _moveA (aopGet (AOP (left), offset, FALSE));
+          if (size > 1)
+            {
+              while (--size)
+                {
+                  emit2 ("or a,%s", aopGet (AOP (left), ++offset, FALSE));
+                }
+            }
+          else
+            {
+              emit2 ("or a,a");
+            }
+          emit2 ("jp NZ,!tlabel", lbl->key + 100);
+        }
       else
-       {
-         while (size--)
-           {
-             emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
-             if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
-               emit2 ("or a,a");
-             else
-               emit2 ("cp a,%s", aopGet (AOP (right), offset, FALSE));
-             emit2 ("jp nz,!tlabel", lbl->key + 100);
-             offset++;
-           }
-       }
-    }
-  /* if the right side is in a register or in direct space or
-     if the left is a pointer register & right is not */
+        {
+          while (size--)
+            {
+              _moveA (aopGet (AOP (left), offset, FALSE));
+              if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
+                emit2 ("or a,a");
+              else
+                emit2 ("sub a,%s", aopGet (AOP (right), offset, FALSE));
+              emit2 ("jp NZ,!tlabel", lbl->key + 100);
+              offset++;
+            }
+        }
+    }
+  /* if the right side is in a register or
+     pointed to by HL, IX or IY */
   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));
-         if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
-             ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
-           /* PENDING */
-           emit2 ("jp nz,!tlabel", lbl->key + 100);
-         else
-           {
-             emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
-             emit2 ("jp nz,!tlabel", lbl->key + 100);
-           }
-         offset++;
-       }
+        {
+          _moveA (aopGet (AOP (left), offset, FALSE));
+          if (AOP_TYPE (right) == AOP_LIT &&
+              ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
+            {
+              emit2 ("or a,a");
+              emit2 ("jp NZ,!tlabel", lbl->key + 100);
+            }
+          else
+            {
+              emit2 ("sub a,%s", aopGet (AOP (right), offset, FALSE));
+              emit2 ("jp NZ,!tlabel", lbl->key + 100);
+            }
+          offset++;
+        }
     }
+  /* right is in direct space or a pointer reg, need both a & b */
   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--)
-       {
-         _moveA (aopGet (AOP (right), offset, FALSE));
-         emit2 ("cp %s", aopGet (AOP (left), offset, FALSE));
-         emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
-         offset++;
-       }
+        {
+          emit2 ("; direct compare");
+          _emitMove (_pairs[pair].l, aopGet (AOP (left), offset, FALSE));
+          _moveA (aopGet (AOP (right), offset, FALSE));
+          emit2 ("sub a,%s", _pairs[pair].l);
+          emit2 ("!shortjp NZ,!tlabel", lbl->key + 100);
+          offset++;
+        }
+      return pair;
     }
+  return PAIR_INVALID;
 }
 
 /*-----------------------------------------------------------------*/
@@ -4765,14 +5066,15 @@ gencjne (operand * left, operand * right, symbol * lbl)
 {
   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");
-  emitLabel (tlbl->key + 100);
+  emitLabelNoSpill (tlbl->key + 100);
+  _pop (pop);
 }
 
 /*-----------------------------------------------------------------*/
@@ -4804,29 +5106,34 @@ genCmpEq (iCode * ic, iCode * ifx)
       symbol *tlbl;
       /* if they are both bit variables */
       if (AOP_TYPE (left) == AOP_CRY &&
-         ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
-       {
-         wassertl (0, "Tried to compare two bits");
-       }
+          ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
+        {
+          wassertl (0, "Tried to compare two bits");
+        }
       else
-       {
-         tlbl = newiTempLabel (NULL);
-         gencjneshort (left, right, tlbl);
-         if (IC_TRUE (ifx))
-           {
-             emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
-             emitLabel (tlbl->key + 100);
-           }
-         else
-           {
-             /* PENDING: do this better */
-             symbol *lbl = newiTempLabel (NULL);
-             emit2 ("!shortjp !tlabel", lbl->key + 100);
-             emitLabel (tlbl->key + 100);
-             emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
-             emitLabel (lbl->key + 100);
-           }
-       }
+        {
+          PAIR_ID pop;
+          tlbl = newiTempLabel (NULL);
+          pop = gencjneshort (left, right, tlbl);
+          if (IC_TRUE (ifx))
+            {
+              _pop (pop);
+              emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
+              emitLabelNoSpill (tlbl->key + 100);
+              _pop (pop);
+            }
+          else
+            {
+              /* PENDING: do this better */
+              symbol *lbl = newiTempLabel (NULL);
+              _pop (pop);
+              emit2 ("!shortjp !tlabel", lbl->key + 100);
+              emitLabelNoSpill (tlbl->key + 100);
+              _pop (pop);
+              emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
+              emitLabelNoSpill (lbl->key + 100);
+            }
+        }
       /* mark the icode as generated */
       ifx->generated = 1;
       goto release;
@@ -4841,25 +5148,25 @@ genCmpEq (iCode * ic, iCode * ifx)
   else
     {
       emitDebug(";4");
-      
+
       gencjne (left, right, newiTempLabel (NULL));
       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
-       {
-         wassert (0);
-       }
+        {
+          wassert (0);
+        }
       if (ifx)
-       {
+        {
           emitDebug(";5");
-         genIfxJump (ifx, "a");
-         goto release;
-       }
+          genIfxJump (ifx, "a");
+          goto release;
+        }
       /* if the result is used in an arithmetic operation
          then put the result in place */
       if (AOP_TYPE (result) != AOP_CRY)
-       {
+        {
           emitDebug(";6");
-         outAcc (result);
-       }
+          outAcc (result);
+        }
       /* leave the result in acc */
     }
 
@@ -4917,9 +5224,9 @@ genAndOp (iCode * ic)
     {
       tlbl = newiTempLabel (NULL);
       _toBoolean (left);
-      emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
+      emit2 ("!shortjp Z,!tlabel", tlbl->key + 100);
       _toBoolean (right);
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
       outBitAcc (result);
     }
 
@@ -4954,9 +5261,9 @@ genOrOp (iCode * ic)
     {
       tlbl = newiTempLabel (NULL);
       _toBoolean (left);
-      emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+      emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
       _toBoolean (right);
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
       outBitAcc (result);
     }
 
@@ -4998,14 +5305,14 @@ jmpTrueOrFalse (iCode * ic, symbol * tlbl)
     {
       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);
-      emitLabel (nlbl->key + 100);
+      emitLabelNoSpill (nlbl->key + 100);
     }
   else
     {
       emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
     }
   ic->generated = 1;
 }
@@ -5051,7 +5358,7 @@ genAnd (iCode * ic, iCode * ifx)
       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);
 
@@ -5088,15 +5395,17 @@ genAnd (iCode * ic, iCode * ifx)
                   /* 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++;
         }
       // bit = left & literal
       if (size)
         {
           emit2 ("clr c");
           emit2 ("!tlabeldef", tlbl->key + 100);
+          _G.lines.current->isLabel = 1;
         }
       // if(left & literal)
       else
@@ -5115,82 +5424,82 @@ genAnd (iCode * ic, iCode * ifx)
   if (sameRegs (AOP (result), AOP (left)))
     {
       for (; size--; offset++)
-       {
-         if (AOP_TYPE (right) == AOP_LIT)
-           {
-             if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
-               continue;
-             else
-               {
-                 if (bytelit == 0)
-                   aopPut (AOP (result), "!zero", offset);
-                 else
-                   {
-                     _moveA (aopGet (AOP (left), offset, FALSE));
-                     emit2 ("and a,%s",
-                               aopGet (AOP (right), offset, FALSE));
-                     aopPut (AOP (left), "a", offset);
-                   }
-               }
-
-           }
-         else
-           {
-             if (AOP_TYPE (left) == AOP_ACC)
-               {
-                 wassertl (0, "Tried to perform an AND where the left operand is allocated into A");
-               }
-             else
-               {
-                 _moveA (aopGet (AOP (left), offset, FALSE));
-                 emit2 ("and a,%s",
-                           aopGet (AOP (right), offset, FALSE));
-                 aopPut (AOP (left), "a", offset);
-               }
-           }
-       }
+        {
+          if (AOP_TYPE (right) == AOP_LIT)
+            {
+              if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
+                continue;
+              else
+                {
+                  if (bytelit == 0)
+                    aopPut (AOP (result), "!zero", offset);
+                  else
+                    {
+                      _moveA (aopGet (AOP (left), offset, FALSE));
+                      emit2 ("and a,%s",
+                                aopGet (AOP (right), offset, FALSE));
+                      aopPut (AOP (left), "a", offset);
+                    }
+                }
+
+            }
+          else
+            {
+              if (AOP_TYPE (left) == AOP_ACC)
+                {
+                  wassertl (0, "Tried to perform an AND where the left operand is allocated into A");
+                }
+              else
+                {
+                  _moveA (aopGet (AOP (left), offset, FALSE));
+                  emit2 ("and a,%s",
+                            aopGet (AOP (right), offset, FALSE));
+                  aopPut (AOP (left), "a", offset);
+                }
+            }
+        }
     }
   else
     {
       // left & result in different registers
       if (AOP_TYPE (result) == AOP_CRY)
-       {
-         wassertl (0, "Tried to AND where the result is in carry");
-       }
+        {
+          wassertl (0, "Tried to AND where the result is in carry");
+        }
       else
-       {
-         for (; (size--); offset++)
-           {
-             // normal case
-             // result = left & right
-             if (AOP_TYPE (right) == AOP_LIT)
-               {
-                 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
-                   {
-                     aopPut (AOP (result),
-                             aopGet (AOP (left), offset, FALSE),
-                             offset);
-                     continue;
-                   }
-                 else if (bytelit == 0)
-                   {
-                     aopPut (AOP (result), "!zero", offset);
-                     continue;
-                   }
-               }
-             // faster than result <- left, anl result,right
-             // and better if result is SFR
-             if (AOP_TYPE (left) == AOP_ACC)
-               emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
-             else
-               {
-                 _moveA (aopGet (AOP (left), offset, FALSE));
-                 emit2 ("and a,%s",
-                           aopGet (AOP (right), offset, FALSE));
-               }
-             aopPut (AOP (result), "a", offset);
-           }
-       }
+        {
+          for (; (size--); offset++)
+            {
+              // normal case
+              // result = left & right
+              if (AOP_TYPE (right) == AOP_LIT)
+                {
+                  if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
+                    {
+                      aopPut (AOP (result),
+                              aopGet (AOP (left), offset, FALSE),
+                              offset);
+                      continue;
+                    }
+                  else if (bytelit == 0)
+                    {
+                      aopPut (AOP (result), "!zero", offset);
+                      continue;
+                    }
+                }
+              // faster than result <- left, anl result,right
+              // and better if result is SFR
+              if (AOP_TYPE (left) == AOP_ACC)
+                emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
+              else
+                {
+                  _moveA (aopGet (AOP (left), offset, FALSE));
+                  emit2 ("and a,%s",
+                            aopGet (AOP (right), offset, FALSE));
+                }
+              aopPut (AOP (result), "a", offset);
+            }
+        }
 
     }
 
@@ -5241,7 +5550,7 @@ genOr (iCode * ic, iCode * ifx)
       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);
 
@@ -5264,15 +5573,25 @@ genOr (iCode * ic, iCode * ifx)
         {
           wassertl (0, "Result is assigned to a bit");
         }
-      /* PENDING: Modeled after the AND code which is inefficent. */
+      /* PENDING: Modeled after the AND code which is inefficient. */
       while (sizel--)
         {
           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++;
         }
@@ -5287,70 +5606,70 @@ genOr (iCode * ic, iCode * ifx)
   if (sameRegs (AOP (result), AOP (left)))
     {
       for (; size--; offset++)
-       {
-         if (AOP_TYPE (right) == AOP_LIT)
-           {
-             if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
-               continue;
-             else
-               {
-                 _moveA (aopGet (AOP (left), offset, FALSE));
-                 emit2 ("or a,%s",
-                           aopGet (AOP (right), offset, FALSE));
-                 aopPut (AOP (result), "a", offset);
-               }
-           }
-         else
-           {
-             if (AOP_TYPE (left) == AOP_ACC)
-               emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
-             else
-               {
-                 _moveA (aopGet (AOP (left), offset, FALSE));
-                 emit2 ("or a,%s",
-                           aopGet (AOP (right), offset, FALSE));
-                 aopPut (AOP (result), "a", offset);
-               }
-           }
-       }
+        {
+          if (AOP_TYPE (right) == AOP_LIT)
+            {
+              if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
+                continue;
+              else
+                {
+                  _moveA (aopGet (AOP (left), offset, FALSE));
+                  emit2 ("or a,%s",
+                            aopGet (AOP (right), offset, FALSE));
+                  aopPut (AOP (result), "a", offset);
+                }
+            }
+          else
+            {
+              if (AOP_TYPE (left) == AOP_ACC)
+                emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
+              else
+                {
+                  _moveA (aopGet (AOP (left), offset, FALSE));
+                  emit2 ("or a,%s",
+                            aopGet (AOP (right), offset, FALSE));
+                  aopPut (AOP (result), "a", offset);
+                }
+            }
+        }
     }
   else
     {
       // left & result in different registers
       if (AOP_TYPE (result) == AOP_CRY)
-       {
-         wassertl (0, "Result of OR is in a bit");
-       }
+        {
+          wassertl (0, "Result of OR is in a bit");
+        }
       else
-       for (; (size--); offset++)
-         {
-           // normal case
-           // result = left & right
-           if (AOP_TYPE (right) == AOP_LIT)
-             {
-               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
-                 {
-                   aopPut (AOP (result),
-                           aopGet (AOP (left), offset, FALSE),
-                           offset);
-                   continue;
-                 }
-             }
-           // faster than result <- left, anl result,right
-           // and better if result is SFR
-           if (AOP_TYPE (left) == AOP_ACC)
-             emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
-           else
-             {
-               _moveA (aopGet (AOP (left), offset, FALSE));
-               emit2 ("or a,%s",
-                         aopGet (AOP (right), offset, FALSE));
-             }
-           aopPut (AOP (result), "a", offset);
-           /* PENDING: something weird is going on here.  Add exception. */
-           if (AOP_TYPE (result) == AOP_ACC)
-             break;
-         }
+        for (; (size--); offset++)
+          {
+            // normal case
+            // result = left & right
+            if (AOP_TYPE (right) == AOP_LIT)
+              {
+                if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
+                  {
+                    aopPut (AOP (result),
+                            aopGet (AOP (left), offset, FALSE),
+                            offset);
+                    continue;
+                  }
+              }
+            // faster than result <- left, anl result,right
+            // and better if result is SFR
+            if (AOP_TYPE (left) == AOP_ACC)
+              emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
+            else
+              {
+                _moveA (aopGet (AOP (left), offset, FALSE));
+                emit2 ("or a,%s",
+                          aopGet (AOP (right), offset, FALSE));
+              }
+            aopPut (AOP (result), "a", offset);
+            /* PENDING: something weird is going on here.  Add exception. */
+            if (AOP_TYPE (result) == AOP_ACC)
+              break;
+          }
     }
 
 release:
@@ -5399,7 +5718,7 @@ genXor (iCode * ic, iCode * ifx)
       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);
 
@@ -5427,7 +5746,7 @@ genXor (iCode * ic, iCode * ifx)
         {
           _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)
@@ -5445,71 +5764,71 @@ genXor (iCode * ic, iCode * ifx)
   if (sameRegs (AOP (result), AOP (left)))
     {
       for (; size--; offset++)
-       {
-         if (AOP_TYPE (right) == AOP_LIT)
-           {
-             if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
-               continue;
-             else
-               {
-                 _moveA (aopGet (AOP (left), offset, FALSE));
-                 emit2 ("xor a,%s",
-                           aopGet (AOP (right), offset, FALSE));
-                 aopPut (AOP (result), "a", offset);
-               }
-           }
-         else
-           {
-             if (AOP_TYPE (left) == AOP_ACC)
+        {
+          if (AOP_TYPE (right) == AOP_LIT)
+            {
+              if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
+                continue;
+              else
+                {
+                  _moveA (aopGet (AOP (left), offset, FALSE));
+                  emit2 ("xor a,%s",
+                            aopGet (AOP (right), offset, FALSE));
+                  aopPut (AOP (result), "a", offset);
+                }
+            }
+          else
+            {
+              if (AOP_TYPE (left) == AOP_ACC)
                 {
                   emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
                 }
-             else
-               {
-                 _moveA (aopGet (AOP (left), offset, FALSE));
-                 emit2 ("xor a,%s",
-                           aopGet (AOP (right), offset, FALSE));
-                 aopPut (AOP (result), "a", offset);
-               }
-           }
-       }
+              else
+                {
+                  _moveA (aopGet (AOP (left), offset, FALSE));
+                  emit2 ("xor a,%s",
+                            aopGet (AOP (right), offset, FALSE));
+                  aopPut (AOP (result), "a", offset);
+                }
+            }
+        }
     }
   else
     {
       // left & result in different registers
       if (AOP_TYPE (result) == AOP_CRY)
-       {
-         wassertl (0, "Result of XOR is in a bit");
-       }
+        {
+          wassertl (0, "Result of XOR is in a bit");
+        }
       else
-       for (; (size--); offset++)
-         {
-           // normal case
-           // result = left & right
-           if (AOP_TYPE (right) == AOP_LIT)
-             {
-               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
-                 {
-                   aopPut (AOP (result),
-                           aopGet (AOP (left), offset, FALSE),
-                           offset);
-                   continue;
-                 }
-             }
-           // faster than result <- left, anl result,right
-           // and better if result is SFR
-           if (AOP_TYPE (left) == AOP_ACC) 
+        for (; (size--); offset++)
+          {
+            // normal case
+            // result = left & right
+            if (AOP_TYPE (right) == AOP_LIT)
+              {
+                if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
+                  {
+                    aopPut (AOP (result),
+                            aopGet (AOP (left), offset, FALSE),
+                            offset);
+                    continue;
+                  }
+              }
+            // faster than result <- left, anl result,right
+            // and better if result is SFR
+            if (AOP_TYPE (left) == AOP_ACC)
               {
                 emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
               }
-           else
-             {
-               _moveA (aopGet (AOP (left), offset, FALSE));
-               emit2 ("xor a,%s",
-                         aopGet (AOP (right), offset, FALSE));
-             }
-           aopPut (AOP (result), "a", offset);
-         }
+            else
+              {
+                _moveA (aopGet (AOP (left), offset, FALSE));
+                emit2 ("xor a,%s",
+                          aopGet (AOP (right), offset, FALSE));
+              }
+            aopPut (AOP (result), "a", offset);
+          }
     }
 
 release:
@@ -5525,37 +5844,49 @@ static void
 genInline (iCode * ic)
 {
   char *buffer, *bp, *bp1;
+  bool inComment = FALSE;
 
   _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)
     {
-      if (*bp == '\n')
-       {
-         *bp++ = '\0';
-         emit2 (bp1);
-         bp1 = bp;
-       }
-      else
-       {
-         if (*bp == ':')
-           {
-             bp++;
-             *bp = '\0';
-             bp++;
-             emit2 (bp1);
-             bp1 = bp;
-           }
-         else
-           bp++;
-       }
+      switch (*bp)
+        {
+        case ';':
+          inComment = TRUE;
+          ++bp;
+          break;
+
+        case '\n':
+          inComment = FALSE;
+          *bp++ = '\0';
+          emit2 (bp1);
+          bp1 = bp;
+          break;
+
+        default:
+          /* Add \n for labels, not dirs such as c:\mydir */
+          if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
+            {
+              ++bp;
+              *bp = '\0';
+              ++bp;
+              emit2 (bp1);
+              bp1 = bp;
+            }
+          else
+            ++bp;
+          break;
+        }
     }
   if (bp1 != bp)
     emit2 (bp1);
+
+  Safe_free (buffer);
+
   _G.lines.isInline -= (!options.asmpeep);
 
 }
@@ -5636,22 +5967,25 @@ emitRsh2 (asmop *aop, int size, int is_signed)
 /*-----------------------------------------------------------------*/
 static void
 shiftR2Left2Result (operand * left, int offl,
-                   operand * result, int offr,
-                   int shCount, int is_signed)
+                    operand * result, int offr,
+                    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);
 
+  if (shCount == 0)
+    return;
+
   /*  if (AOP(result)->type == AOP_REG) { */
-  
+
   tlbl = newiTempLabel (NULL);
-  tlbl1 = newiTempLabel (NULL);
 
   /* 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--)
         {
@@ -5660,15 +5994,14 @@ shiftR2Left2Result (operand * left, int offl,
     }
   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);
 
-      emitLabel (tlbl1->key + 100);
       emit2 ("dec a");
-      emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+      emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
     }
 }
 
@@ -5677,7 +6010,7 @@ shiftR2Left2Result (operand * left, int offl,
 /*-----------------------------------------------------------------*/
 static void
 shiftL2Left2Result (operand * left, int offl,
-                   operand * result, int offr, int shCount)
+                    operand * result, int offr, int shCount)
 {
   if (sameRegs (AOP (result), AOP (left)) &&
       ((offl + MSB16) == offr))
@@ -5691,12 +6024,15 @@ shiftL2Left2Result (operand * left, int offl,
       movLeft2Result (left, offl + 1, result, offr + 1, 0);
     }
 
+  if (shCount == 0)
+    return;
+
   if (getPairId (AOP (result)) == PAIR_HL)
     {
       while (shCount--)
-       {
-         emit2 ("add hl,hl");
-       }
+        {
+          emit2 ("add hl,hl");
+        }
     }
   else
     {
@@ -5710,54 +6046,54 @@ shiftL2Left2Result (operand * left, int offl,
 
     if (AOP (result)->type == AOP_REG)
       {
-       while (shCount--)
-         {
-           for (offset = 0; offset < size; offset++)
-             {
-               l = aopGet (AOP (result), offset, FALSE);
-           
-               if (offset == 0)
-                 {
-                   emit2 ("sla %s", l);
-                 }
-               else
-                 {
-                   emit2 ("rl %s", l);
-                 }
-             }
-         }
+        while (shCount--)
+          {
+            for (offset = 0; offset < size; offset++)
+              {
+                l = aopGet (AOP (result), offset, FALSE);
+
+                if (offset == 0)
+                  {
+                    emit2 ("sla %s", l);
+                  }
+                else
+                  {
+                    emit2 ("rl %s", l);
+                  }
+              }
+          }
       }
     else
       {
-       /* Left is already in result - so now do the shift */
-       if (shCount > 1)
-         {
-           emit2 ("ld a,!immedbyte+1", shCount);
-           emit2 ("!shortjp !tlabel", tlbl1->key + 100);
-           emitLabel (tlbl->key + 100);
-         }
-
-       while (size--)
-         {
-           l = aopGet (AOP (result), offset, FALSE);
-           
-           if (offset == 0)
-             {
-               emit2 ("sla %s", l);
-             }
-           else
-             {
-               emit2 ("rl %s", l);
-             }
-           
-           offset++;
-         }
-       if (shCount > 1)
-         {
-           emitLabel (tlbl1->key + 100);
-           emit2 ("dec a");
-           emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
-         }
+        /* Left is already in result - so now do the shift */
+        if (shCount > 1)
+          {
+            emit2 ("ld a,!immedbyte+1", shCount);
+            emit2 ("!shortjp !tlabel", tlbl1->key + 100);
+            emitLabelNoSpill (tlbl->key + 100);
+          }
+
+        while (size--)
+          {
+            l = aopGet (AOP (result), offset, FALSE);
+
+            if (offset == 0)
+              {
+                emit2 ("sla %s", l);
+              }
+            else
+              {
+                emit2 ("rl %s", l);
+              }
+
+            offset++;
+          }
+        if (shCount > 1)
+          {
+            emitLabelNoSpill (tlbl1->key + 100);
+            emit2 ("dec a");
+            emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
+          }
       }
   }
 }
@@ -5768,7 +6104,7 @@ shiftL2Left2Result (operand * left, int offl,
 static void
 AccRol (int shCount)
 {
-  shCount &= 0x0007;           // shCount : 0..7
+  shCount &= 0x0007;            // shCount : 0..7
 
 #if 0
   switch (shCount)
@@ -5859,21 +6195,21 @@ AccLsh (int shCount)
   if (shCount != 0)
     {
       if (shCount == 1)
-       {
-         emit2 ("add a,a");
-       }
+        {
+          emit2 ("add a,a");
+        }
       else if (shCount == 2)
-       {
-         emit2 ("add a,a");
-         emit2 ("add a,a");
-       }
+        {
+          emit2 ("add a,a");
+          emit2 ("add a,a");
+        }
       else
-       {
-         /* rotate left accumulator */
-         AccRol (shCount);
-         /* and kill the lower order bits */
-         emit2 ("and a,!immedbyte", SLMask[shCount]);
-       }
+        {
+          /* rotate left accumulator */
+          AccRol (shCount);
+          /* and kill the lower order bits */
+          emit2 ("and a,!immedbyte", SLMask[shCount]);
+        }
     }
 }
 
@@ -5882,19 +6218,31 @@ AccLsh (int shCount)
 /*-----------------------------------------------------------------*/
 static void
 shiftL1Left2Result (operand * left, int offl,
-                   operand * result, int offr, int shCount)
+                    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 != 0           */
+/* genlshTwo - left shift two bytes by known amount                */
 /*-----------------------------------------------------------------*/
 static void
 genlshTwo (operand * result, operand * left, int shCount)
@@ -5908,35 +6256,35 @@ genlshTwo (operand * result, operand * left, int shCount)
     {
       shCount -= 8;
       if (size > 1)
-       {
-         if (shCount)
-           {
-             movLeft2Result (left, LSB, result, MSB16, 0);
-             aopPut (AOP (result), "!zero", 0);
-             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
-           }
-         else
-           {
-             movLeft2Result (left, LSB, result, MSB16, 0);
-             aopPut (AOP (result), "!zero", 0);
-           }
-       }
+        {
+          if (shCount)
+            {
+              movLeft2Result (left, LSB, result, MSB16, 0);
+              shiftL1Left2Result (left, LSB, result, MSB16, shCount);
+              aopPut (AOP (result), "!zero", LSB);
+            }
+          else
+            {
+              movLeft2Result (left, LSB, result, MSB16, 0);
+              aopPut (AOP (result), "!zero", 0);
+            }
+        }
       else
-       {
-         aopPut (AOP (result), "!zero", LSB);
-       }
+        {
+          aopPut (AOP (result), "!zero", LSB);
+        }
     }
-  /*  1 <= shCount <= 7 */
+  /*  0 <= shCount <= 7 */
   else
     {
       if (size == 1)
-       {
-         wassert (0);
-       }
+        {
+          wassert (0);
+        }
       else
-       {
-         shiftL2Left2Result (left, LSB, result, LSB, shCount);
-       }
+        {
+          shiftL2Left2Result (left, LSB, result, LSB, shCount);
+        }
     }
 }
 
@@ -5954,11 +6302,11 @@ genlshOne (operand * result, operand * left, int shCount)
 /*-----------------------------------------------------------------*/
 static void
 genLeftShiftLiteral (operand * left,
-                    operand * right,
-                    operand * result,
-                    iCode * ic)
+                     operand * right,
+                     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);
@@ -5969,12 +6317,8 @@ genLeftShiftLiteral (operand * left,
   size = getSize (operandType (result));
 
   /* I suppose that the left size >= result size */
-  if (shCount == 0)
-    {
-      wassert (0);
-    }
 
-  else if (shCount >= (size * 8)) 
+  if (shCount >= (size * 8))
     {
       while (size--)
         {
@@ -5984,19 +6328,19 @@ genLeftShiftLiteral (operand * left,
   else
     {
       switch (size)
-       {
-       case 1:
-         genlshOne (result, left, shCount);
-         break;
-       case 2:
-         genlshTwo (result, left, shCount);
-         break;
-       case 4:
-         wassertl (0, "Shifting of longs is currently unsupported");
-         break;
-       default:
-         wassert (0);
-       }
+        {
+        case 1:
+          genlshOne (result, left, shCount);
+          break;
+        case 2:
+          genlshTwo (result, left, shCount);
+          break;
+        case 4:
+          wassertl (0, "Shifting of longs is currently unsupported");
+          break;
+        default:
+          wassert (0);
+        }
     }
   freeAsmop (left, NULL, ic);
   freeAsmop (result, NULL, ic);
@@ -6037,6 +6381,9 @@ genLeftShift (iCode * ic)
   aopOp (left, ic, FALSE, FALSE);
   aopOp (result, ic, FALSE, FALSE);
 
+  if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
+     _push (PAIR_AF);
+
   /* now move the left to the result if they are not the
      same */
 
@@ -6046,11 +6393,11 @@ genLeftShift (iCode * ic)
       size = AOP_SIZE (result);
       offset = 0;
       while (size--)
-       {
-         l = aopGet (AOP (left), offset, FALSE);
-         aopPut (AOP (result), l, offset);
-         offset++;
-       }
+        {
+          l = aopGet (AOP (left), offset, FALSE);
+          aopPut (AOP (result), l, offset);
+          offset++;
+        }
     }
 
   tlbl = newiTempLabel (NULL);
@@ -6058,8 +6405,11 @@ genLeftShift (iCode * ic)
   offset = 0;
   tlbl1 = newiTempLabel (NULL);
 
+  if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
+     _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--)
@@ -6076,9 +6426,9 @@ genLeftShift (iCode * ic)
         }
       offset++;
     }
-  emitLabel (tlbl1->key + 100);
+  emitLabelNoSpill (tlbl1->key + 100);
   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);
@@ -6112,9 +6462,9 @@ genrshOne (operand * result, operand * left, int shCount, int is_signed)
     {
       _moveA (l);
       while (shCount--)
-       {
-         emit2 ("%s a", is_signed ? "sra" : "srl");
-       }
+        {
+          emit2 ("%s a", is_signed ? "sra" : "srl");
+        }
       aopPut (AOP (result), "a", 0);
     }
 }
@@ -6144,16 +6494,16 @@ AccRsh (int shCount)
 /*-----------------------------------------------------------------*/
 static void
 shiftR1Left2Result (operand * left, int offl,
-                   operand * result, int offr,
-                   int shCount, int sign)
+                    operand * result, int offr,
+                    int shCount, int sign)
 {
   _moveA (aopGet (AOP (left), offl, FALSE));
   if (sign)
     {
       while (shCount--)
-       {
-         emit2 ("%s a", sign ? "sra" : "srl");
-       }
+        {
+          emit2 ("%s a", sign ? "sra" : "srl");
+        }
     }
   else
     {
@@ -6163,25 +6513,25 @@ shiftR1Left2Result (operand * left, int offl,
 }
 
 /*-----------------------------------------------------------------*/
-/* genrshTwo - right shift two bytes by known amount != 0          */
+/* genrshTwo - right shift two bytes by known amount               */
 /*-----------------------------------------------------------------*/
 static void
 genrshTwo (operand * result, operand * left,
-          int shCount, int sign)
+           int shCount, int sign)
 {
   /* if shCount >= 8 */
   if (shCount >= 8)
     {
       shCount -= 8;
       if (shCount)
-       {
-         shiftR1Left2Result (left, MSB16, result, LSB,
-                             shCount, sign);
-       }
+        {
+          shiftR1Left2Result (left, MSB16, result, LSB,
+                              shCount, sign);
+        }
       else
-       {
-         movLeft2Result (left, MSB16, result, LSB, sign);
-       }
+        {
+          movLeft2Result (left, MSB16, result, LSB, sign);
+        }
       if (sign)
         {
           /* Sign extend the result */
@@ -6196,7 +6546,7 @@ genrshTwo (operand * result, operand * left,
           aopPut (AOP (result), "!zero", 1);
         }
     }
-  /*  1 <= shCount <= 7 */
+  /*  0 <= shCount <= 7 */
   else
     {
       shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
@@ -6208,12 +6558,12 @@ genrshTwo (operand * result, operand * left,
 /*-----------------------------------------------------------------*/
 static void
 genRightShiftLiteral (operand * left,
-                     operand * right,
-                     operand * result,
-                     iCode * ic,
+                      operand * right,
+                      operand * result,
+                      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);
@@ -6224,12 +6574,8 @@ genRightShiftLiteral (operand * left,
   size = getSize (operandType (result));
 
   /* I suppose that the left size >= result size */
-  if (shCount == 0)
-    {
-      wassert (0);
-    }
 
-  else if (shCount >= (size * 8)) {
+  if (shCount >= (size * 8)) {
     const char *s;
     if (!SPEC_USIGN(getSpec(operandType(left)))) {
       _moveA(aopGet (AOP (left), 0, FALSE));
@@ -6245,19 +6591,19 @@ genRightShiftLiteral (operand * left,
   else
     {
       switch (size)
-       {
-       case 1:
-         genrshOne (result, left, shCount, sign);
-         break;
-       case 2:
-         genrshTwo (result, left, shCount, sign);
-         break;
-       case 4:
-         wassertl (0, "Asked to shift right a long which should be a function call");
-         break;
-       default:
-         wassertl (0, "Entered default case in right shift delegate");
-       }
+        {
+        case 1:
+          genrshOne (result, left, shCount, sign);
+          break;
+        case 2:
+          genrshTwo (result, left, shCount, sign);
+          break;
+        case 4:
+          wassertl (0, "Asked to shift right a long which should be a function call");
+          break;
+        default:
+          wassertl (0, "Entered default case in right shift delegate");
+        }
     }
   freeAsmop (left, NULL, ic);
   freeAsmop (result, NULL, ic);
@@ -6311,6 +6657,9 @@ genRightShift (iCode * ic)
   aopOp (left, ic, FALSE, FALSE);
   aopOp (result, ic, FALSE, FALSE);
 
+  if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
+     _push (PAIR_AF);
+
   /* now move the left to the result if they are not the
      same */
   if (!sameRegs (AOP (left), AOP (result)))
@@ -6319,11 +6668,11 @@ genRightShift (iCode * ic)
       size = AOP_SIZE (result);
       offset = 0;
       while (size--)
-       {
-         l = aopGet (AOP (left), offset, FALSE);
-         aopPut (AOP (result), l, offset);
-         offset++;
-       }
+        {
+          l = aopGet (AOP (left), offset, FALSE);
+          aopPut (AOP (result), l, offset);
+          offset++;
+        }
     }
 
   tlbl = newiTempLabel (NULL);
@@ -6331,24 +6680,27 @@ genRightShift (iCode * ic)
   size = AOP_SIZE (result);
   offset = size - 1;
 
+  if (AOP_TYPE (left) != AOP_REG || AOP_TYPE (result) != AOP_REG)
+     _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);
       if (first)
-       {
+        {
           emit2 ("%s %s", is_signed ? "sra" : "srl", l);
-         first = 0;
-       }
+          first = 0;
+        }
       else
         {
           emit2 ("rr %s", l);
         }
     }
-  emitLabel (tlbl1->key + 100);
+  emitLabelNoSpill (tlbl1->key + 100);
   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);
@@ -6361,12 +6713,12 @@ genRightShift (iCode * ic)
 static void
 genUnpackBits (operand * result, int pair)
 {
-  int offset = 0;      /* result byte offset */
-  int rsize;           /* result size */
-  int rlen = 0;                /* remaining bitfield length */
-  sym_link *etype;     /* bitfield type information */
-  int blen;            /* bitfield length */
-  int bstr;            /* bitfield starting bit within byte */
+  int offset = 0;       /* result byte offset */
+  int rsize;            /* result size */
+  int rlen = 0;         /* remaining bitfield length */
+  sym_link *etype;      /* bitfield type information */
+  int blen;             /* bitfield length */
+  int bstr;             /* bitfield starting bit within byte */
 
   emitDebug ("; genUnpackBits");
 
@@ -6379,8 +6731,18 @@ genUnpackBits (operand * result, int pair)
   if (blen < 8)
     {
       emit2 ("ld a,!*pair", _pairs[pair].name);
-      AccRsh (bstr);
+      AccRol (8 - bstr);
       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - blen));
+      if (!SPEC_USIGN (etype))
+        {
+          /* 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));
+          emitLabelNoSpill (tlbl->key + 100);
+        }
       aopPut (AOP (result), "a", offset++);
       goto finish;
     }
@@ -6395,6 +6757,15 @@ genUnpackBits (operand * result, int pair)
       emit2 ("ld l,a");
       emit2 ("ld a,h");
       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (16 - blen));
+      if (!SPEC_USIGN (etype))
+        {
+          /* signed bitfield */
+          symbol *tlbl = newiTempLabel (NULL);
+          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);
       return;
@@ -6418,15 +6789,37 @@ genUnpackBits (operand * result, int pair)
     {
       emit2 ("ld a,!*pair", _pairs[pair].name);
       emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - rlen));
+      if (!SPEC_USIGN (etype))
+        {
+          /* signed bitfield */
+          symbol *tlbl = newiTempLabel (NULL);
+
+          emit2 ("bit %d,a", rlen - 1);
+          emit2 ("jp Z,!tlabel", tlbl->key + 100);
+          emit2 ("or a,!immedbyte", (unsigned char) (0xff << rlen));
+          emitLabelNoSpill (tlbl->key + 100);
+        }
       aopPut (AOP (result), "a", offset++);
     }
 
 finish:
   if (offset < rsize)
     {
+      char *source;
+
+      if (SPEC_USIGN (etype))
+        source = "!zero";
+      else
+        {
+          /* signed bitfield: sign extension with 0x00 or 0xff */
+          emit2 ("rla");
+          emit2 ("sbc a,a");
+
+          source = "a";
+        }
       rsize -= offset;
       while (rsize--)
-       aopPut (AOP (result), "!zero", offset++);
+        aopPut (AOP (result), source, offset++);
     }
 }
 
@@ -6435,7 +6828,7 @@ finish:
 /*-----------------------------------------------------------------*/
 static void
 genGenPointerGet (operand * left,
-                 operand * result, iCode * ic)
+                  operand * result, iCode * ic)
 {
   int size, offset;
   sym_link *retype = getSpec (operandType (result));
@@ -6453,16 +6846,16 @@ genGenPointerGet (operand * left,
     {
       /* Just do it */
       if (isPtrPair (AOP (left)))
-       {
-         tsprintf (buffer, sizeof(buffer), 
-                   "!*pair", getPairName (AOP (left)));
-         aopPut (AOP (result), buffer, 0);
-       }
+        {
+          tsprintf (buffer, sizeof(buffer),
+                    "!*pair", getPairName (AOP (left)));
+          aopPut (AOP (result), buffer, 0);
+        }
       else
-       {
-         emit2 ("ld a,!*pair", getPairName (AOP (left)));
-         aopPut (AOP (result), "a", 0);
-       }
+        {
+          emit2 ("ld a,!*pair", getPairName (AOP (left)));
+          aopPut (AOP (result), "a", 0);
+        }
       freeAsmop (left, NULL, ic);
       goto release;
     }
@@ -6471,14 +6864,14 @@ genGenPointerGet (operand * left,
     {
       /* Just do it */
       offset = 0;
-      while (size--) 
+      while (size--)
         {
           char at[20];
           tsprintf (at, sizeof(at), "!*iyx", offset);
           aopPut (AOP (result), at, offset);
           offset++;
         }
+
       freeAsmop (left, NULL, ic);
       goto release;
     }
@@ -6510,23 +6903,23 @@ genGenPointerGet (operand * left,
       offset = 0;
 
       while (size--)
-       {
-         /* PENDING: make this better */
-         if (!IS_GB && AOP_TYPE (result) == AOP_REG)
-           {
-             aopPut (AOP (result), "!*hl", offset++);
-           }
-         else
-           {
-             emit2 ("ld a,!*pair", _pairs[pair].name);
-             aopPut (AOP (result), "a", offset++);
-           }
-         if (size)
-           {
-             emit2 ("inc %s", _pairs[pair].name);
-             _G.pairs[pair].offset++;
-           }
-       }
+        {
+          /* PENDING: make this better */
+          if (!IS_GB && AOP_TYPE (result) == AOP_REG)
+            {
+              aopPut (AOP (result), "!*hl", offset++);
+            }
+          else
+            {
+              emit2 ("ld a,!*pair", _pairs[pair].name);
+              aopPut (AOP (result), "a", offset++);
+            }
+          if (size)
+            {
+              emit2 ("inc %s", _pairs[pair].name);
+              _G.pairs[pair].offset++;
+            }
+        }
       /* Fixup HL back down */
       for (size = AOP_SIZE (result)-1; size; size--)
         {
@@ -6539,24 +6932,24 @@ genGenPointerGet (operand * left,
       offset = 0;
 
       while (size--)
-       {
-         /* PENDING: make this better */
-         if (!IS_GB && 
+        {
+          /* PENDING: make this better */
+          if (!IS_GB &&
               (AOP_TYPE (result) == AOP_REG || AOP_TYPE (result) == AOP_HLREG))
-           {
-             aopPut (AOP (result), "!*hl", offset++);
-           }
-         else
-           {
-             emit2 ("ld a,!*pair", _pairs[pair].name);
-             aopPut (AOP (result), "a", offset++);
-           }
-         if (size)
-           {
-             emit2 ("inc %s", _pairs[pair].name);
-             _G.pairs[pair].offset++;
-           }
-       }
+            {
+              aopPut (AOP (result), "!*hl", offset++);
+            }
+          else
+            {
+              emit2 ("ld a,!*pair", _pairs[pair].name);
+              aopPut (AOP (result), "a", offset++);
+            }
+          if (size)
+            {
+              emit2 ("inc %s", _pairs[pair].name);
+              _G.pairs[pair].offset++;
+            }
+        }
     }
 
   freeAsmop (left, NULL, ic);
@@ -6599,18 +6992,18 @@ isRegOrLit (asmop * aop)
 /*-----------------------------------------------------------------*/
 static void
 genPackBits (sym_link * etype,
-            operand * right,
-            int pair,
-            iCode *ic)
-{
-  int offset = 0;      /* source byte offset */
-  int rlen = 0;                /* remaining bitfield length */
-  int blen;            /* bitfield length */
-  int bstr;            /* bitfield starting bit within byte */
-  int litval;          /* source literal value (if AOP_LIT) */
-  unsigned char mask;  /* bitmask within current byte */
-  int extraPair;       /* a tempory register */
-  bool needPopExtra=0; /* need to restore original value of temp reg */
+             operand * right,
+             int pair,
+             iCode *ic)
+{
+  int offset = 0;       /* source byte offset */
+  int rlen = 0;         /* remaining bitfield length */
+  int blen;             /* bitfield length */
+  int bstr;             /* bitfield starting bit within byte */
+  int litval;           /* source literal value (if AOP_LIT) */
+  unsigned char mask;   /* bitmask within current byte */
+  int extraPair;        /* a tempory register */
+  bool needPopExtra=0;  /* need to restore original value of temp reg */
 
   emitDebug (";     genPackBits","");
 
@@ -6621,13 +7014,13 @@ genPackBits (sym_link * etype,
   if (blen < 8)
     {
       mask = ((unsigned char) (0xFF << (blen + bstr)) |
-             (unsigned char) (0xFF >> (8 - bstr)));
+              (unsigned char) (0xFF >> (8 - bstr)));
 
       if (AOP_TYPE (right) == AOP_LIT)
         {
           /* 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);
@@ -6687,12 +7080,12 @@ genPackBits (sym_link * etype,
   if (rlen)
     {
       mask = (((unsigned char) -1 << rlen) & 0xff);
-      
+
       if (AOP_TYPE (right) == AOP_LIT)
         {
           /* 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);
@@ -6741,14 +7134,14 @@ genPackBits (sym_link * etype,
 /*-----------------------------------------------------------------*/
 static void
 genGenPointerSet (operand * right,
-                 operand * result, iCode * ic)
+                  operand * result, iCode * ic)
 {
   int size, offset;
   sym_link *retype = getSpec (operandType (right));
   sym_link *letype = getSpec (operandType (result));
   PAIR_ID pairId = PAIR_HL;
   bool isBitvar;
-  
+
   aopOp (result, ic, FALSE, FALSE);
   aopOp (right, ic, FALSE, FALSE);
 
@@ -6767,24 +7160,24 @@ genGenPointerSet (operand * right,
       const char *l = aopGet (AOP (right), 0, FALSE);
       const char *pair = getPairName (AOP (result));
       if (canAssignToPtr (l) && isPtr (pair))
-       {
-         emit2 ("ld !*pair,%s", pair, l);
-       }
+        {
+          emit2 ("ld !*pair,%s", pair, l);
+        }
       else
-       {
-         _moveA (l);
-         emit2 ("ld !*pair,a", pair);
-       }
+        {
+          _moveA (l);
+          emit2 ("ld !*pair,a", pair);
+        }
       goto release;
     }
-  
+
   if ( getPairId( AOP (result)) == PAIR_IY && !isBitvar)
     {
       /* Just do it */
       const char *l = aopGet (AOP (right), 0, FALSE);
 
       offset = 0;
-      while (size--) 
+      while (size--)
         {
           if (canAssignToPtr (l))
             {
@@ -6805,24 +7198,24 @@ genGenPointerSet (operand * right,
       offset = 0;
 
       while (size--)
-       {
-         const char *l = aopGet (AOP (right), offset, FALSE);
-         if (isRegOrLit (AOP (right)) && !IS_GB)
-           {
-             emit2 ("ld !*pair,%s", _pairs[PAIR_HL].name, l);
-           }
-         else
-           {
-             _moveA (l);
-             emit2 ("ld !*pair,a", _pairs[PAIR_HL].name);
-           }
-         if (size)
-           {
-             emit2 ("inc %s", _pairs[PAIR_HL].name);
-             _G.pairs[PAIR_HL].offset++;
-           }
-         offset++;
-       }
+        {
+          const char *l = aopGet (AOP (right), offset, FALSE);
+          if (isRegOrLit (AOP (right)) && !IS_GB)
+            {
+              emit2 ("ld !*pair,%s", _pairs[PAIR_HL].name, l);
+            }
+          else
+            {
+              _moveA (l);
+              emit2 ("ld !*pair,a", _pairs[PAIR_HL].name);
+            }
+          if (size)
+            {
+              emit2 ("inc %s", _pairs[PAIR_HL].name);
+              _G.pairs[PAIR_HL].offset++;
+            }
+          offset++;
+        }
 
       /* Fixup HL back down */
       for (size = AOP_SIZE (right)-1; size; size--)
@@ -6853,24 +7246,24 @@ genGenPointerSet (operand * right,
       offset = 0;
 
       while (size--)
-       {
-         const char *l = aopGet (AOP (right), offset, FALSE);
-         if (isRegOrLit (AOP (right)) && !IS_GB)
-           {
-             emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
-           }
-         else
-           {
-             _moveA (l);
-             emit2 ("ld !*pair,a", _pairs[pairId].name);
-           }
-         if (size)
-           {
-             emit2 ("inc %s", _pairs[pairId].name);
-             _G.pairs[pairId].offset++;
-           }
-         offset++;
-       }
+        {
+          const char *l = aopGet (AOP (right), offset, FALSE);
+          if (isRegOrLit (AOP (right)) && !IS_GB)
+            {
+              emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
+            }
+          else
+            {
+              _moveA (l);
+              emit2 ("ld !*pair,a", _pairs[pairId].name);
+            }
+          if (size)
+            {
+              emit2 ("inc %s", _pairs[pairId].name);
+              _G.pairs[pairId].offset++;
+            }
+          offset++;
+        }
     }
 release:
   freeAsmop (right, NULL, ic);
@@ -6947,40 +7340,40 @@ genAddrOf (iCode * ic)
   if (IS_GB)
     {
       if (sym->onStack)
-       {
-         spillCached ();
-         if (sym->stack <= 0)
-           {
+        {
+          spillPair (PAIR_HL);
+          if (sym->stack <= 0)
+            {
               setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset);
-           }
-         else
-           {
+            }
+          else
+            {
               setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
-           }
+            }
           commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
-       }
+        }
       else
-       {
-         emit2 ("ld de,!hashedstr", sym->rname);
+        {
+          emit2 ("ld de,!hashedstr", sym->rname);
           commitPair (AOP (IC_RESULT (ic)), PAIR_DE);
-       }
+        }
     }
   else
     {
-      spillCached ();
+      spillPair (PAIR_HL);
       if (sym->onStack)
-       {
-         /* if it has an offset  then we need to compute it */
-         if (sym->stack > 0)
-           emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
-         else
-           emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset);
-         emit2 ("add hl,sp");
-       }
+        {
+          /* if it has an offset  then we need to compute it */
+          if (sym->stack > 0)
+            emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
+          else
+            emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset);
+          emit2 ("add hl,sp");
+        }
       else
-       {
-         emit2 ("ld hl,!hashedstr", sym->rname);
-       }
+        {
+          emit2 ("ld hl,!hashedstr", sym->rname);
+        }
       commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
     }
   freeAsmop (IC_RESULT (ic), NULL, ic);
@@ -7028,7 +7421,7 @@ genAssign (iCode * ic)
 
   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)))
@@ -7036,10 +7429,10 @@ genAssign (iCode * ic)
       fetchPairLong (getPairId (AOP (result)), AOP (right), ic, LSB);
     }
   else if ((size > 1) &&
-          (AOP_TYPE (result) != AOP_REG) &&
-          (AOP_TYPE (right) == AOP_LIT) &&
-          !IS_FLOAT (operandType (right)) &&
-          (lit < 256L))
+           (AOP_TYPE (result) != AOP_REG) &&
+           (AOP_TYPE (right) == AOP_LIT) &&
+           !IS_FLOAT (operandType (right)) &&
+           (lit < 256L))
     {
       bool fXored = FALSE;
       offset = 0;
@@ -7047,29 +7440,29 @@ genAssign (iCode * ic)
          Done this way so that we can use the cached copy of 0
          in A for a fast clear */
       while (size--)
-       {
-         if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
-           {
-             if (!fXored && size > 1)
-               {
-                 emit2 ("xor a,a");
-                 fXored = TRUE;
-               }
-             if (fXored)
-               {
-                 aopPut (AOP (result), "a", offset);
-               }
-             else
-               {
-                 aopPut (AOP (result), "!zero", offset);
-               }
-           }
-         else
-           aopPut (AOP (result),
-                   aopGet (AOP (right), offset, FALSE),
-                   offset);
-         offset++;
-       }
+        {
+          if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
+            {
+              if (!fXored && size > 1)
+                {
+                  emit2 ("xor a,a");
+                  fXored = TRUE;
+                }
+              if (fXored)
+                {
+                  aopPut (AOP (result), "a", offset);
+                }
+              else
+                {
+                  aopPut (AOP (result), "!zero", offset);
+                }
+            }
+          else
+            aopPut (AOP (result),
+                    aopGet (AOP (right), offset, FALSE),
+                    offset);
+          offset++;
+        }
     }
   else if (size == 2 && AOP_TYPE (right) == AOP_IY)
     {
@@ -7110,19 +7503,19 @@ genAssign (iCode * ic)
   else
     {
       while (size--)
-       {
-         /* PENDING: do this check better */
-         if (IS_GB && requiresHL (AOP (right)) && requiresHL (AOP (result)))
-           {
-             _moveA (aopGet (AOP (right), offset, FALSE));
-             aopPut (AOP (result), "a", offset);
-           }
-         else
-           aopPut (AOP (result),
-                   aopGet (AOP (right), offset, FALSE),
-                   offset);
-         offset++;
-       }
+        {
+          /* PENDING: do this check better */
+          if (IS_GB && requiresHL (AOP (right)) && requiresHL (AOP (result)))
+            {
+              _moveA (aopGet (AOP (right), offset, FALSE));
+              aopPut (AOP (result), "a", offset);
+            }
+          else
+            aopPut (AOP (result),
+                    aopGet (AOP (right), offset, FALSE),
+                    offset);
+          offset++;
+        }
     }
 
 release:
@@ -7147,7 +7540,7 @@ genJumpTab (iCode * ic)
   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");
@@ -7193,18 +7586,18 @@ genCast (iCode * ic)
 
       /* if they are in the same place */
       if (sameRegs (AOP (right), AOP (result)))
-       goto release;
+        goto release;
 
       /* if they in different places then copy */
       size = AOP_SIZE (result);
       offset = 0;
       while (size--)
-       {
-         aopPut (AOP (result),
-                 aopGet (AOP (right), offset, FALSE),
-                 offset);
-         offset++;
-       }
+        {
+          aopPut (AOP (result),
+                  aopGet (AOP (right), offset, FALSE),
+                  offset);
+          offset++;
+        }
       goto release;
     }
 
@@ -7216,8 +7609,8 @@ genCast (iCode * ic)
   while (size--)
     {
       aopPut (AOP (result),
-             aopGet (AOP (right), offset, FALSE),
-             offset);
+              aopGet (AOP (right), offset, FALSE),
+              offset);
       offset++;
     }
 
@@ -7227,18 +7620,17 @@ genCast (iCode * ic)
   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
     {
       while (size--)
-       aopPut (AOP (result), "!zero", offset++);
+        aopPut (AOP (result), "!zero", offset++);
     }
   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");
       while (size--)
-       aopPut (AOP (result), "a", offset++);
+        aopPut (AOP (result), "a", offset++);
     }
 
 release:
@@ -7269,7 +7661,7 @@ genReceive (iCode * ic)
 
         for (i = 0; i < size; i++) {
             aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
-       }
+        }
     }
 
   freeAsmop (IC_RESULT (ic), NULL, ic);
@@ -7288,39 +7680,112 @@ genDummyRead (iCode * ic)
   if (op && IS_SYMOP (op))
     {
       aopOp (op, ic, FALSE, FALSE);
-  
+
       /* general case */
       size = AOP_SIZE (op);
       offset = 0;
 
       while (size--)
-       {
-         _moveA (aopGet (AOP (op), offset, FALSE));
-         offset++;
-       }
+        {
+          _moveA (aopGet (AOP (op), offset, FALSE));
+          offset++;
+        }
 
       freeAsmop (op, NULL, ic);
     }
-  
+
   op = IC_LEFT (ic);
   if (op && IS_SYMOP (op))
     {
       aopOp (op, ic, FALSE, FALSE);
-  
+
       /* general case */
       size = AOP_SIZE (op);
       offset = 0;
 
       while (size--)
-       {
-         _moveA (aopGet (AOP (op), offset, FALSE));
-         offset++;
-       }
+        {
+          _moveA (aopGet (AOP (op), offset, FALSE));
+          offset++;
+        }
 
       freeAsmop (op, NULL, ic);
     }
 }
 
+/*-----------------------------------------------------------------*/
+/* genCritical - generate code for start of a critical sequence    */
+/*-----------------------------------------------------------------*/
+static void
+genCritical (iCode *ic)
+{
+  symbol *tlbl = newiTempLabel (NULL);
+
+  if (IS_GB)
+    {
+      emit2 ("!di");
+    }
+  else if (IC_RESULT (ic))
+    {
+      aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
+      aopPut (AOP (IC_RESULT (ic)), "!zero", 0);
+      //get interrupt enable flag IFF2 into P/O
+      emit2 ("ld a,i");
+      //disable interrupt
+      emit2 ("!di");
+      //parity odd <==> P/O=0 <==> interrupt enable flag IFF2=0
+      emit2 ("jp PO,!tlabel", 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
+    {
+      //get interrupt enable flag IFF2 into P/O
+      emit2 ("ld a,i");
+      //disable interrupt
+      emit2 ("!di");
+      //save P/O flag
+      _push (PAIR_AF);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genEndCritical - generate code for end of a critical sequence   */
+/*-----------------------------------------------------------------*/
+static void
+genEndCritical (iCode *ic)
+{
+  symbol *tlbl = newiTempLabel (NULL);
+
+  if (IS_GB)
+    {
+      emit2 ("!ei");
+    }
+  else if (IC_RIGHT (ic))
+    {
+      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 ("!ei");
+      emitLabel (tlbl->key + 100);
+      freeAsmop (IC_RIGHT (ic), NULL, ic);
+    }
+  else
+    {
+      //restore P/O flag
+      _pop (PAIR_AF);
+      //parity odd <==> P/O=0 <==> interrupt enable flag IFF2 was 0 <==>
+      //don't enable interrupts as they were off before
+      emit2 ("jp PO,!tlabel", tlbl->key + 100);
+      emit2 ("!ei");
+      emit2 ("!tlabeldef", (tlbl->key + 100));
+      _G.lines.current->isLabel = 1;
+    }
+}
+
 enum
   {
     /** Maximum number of bytes to emit per line. */
@@ -7336,7 +7801,7 @@ typedef struct
 
 
 /** Flushes a byte chunker by writing out all in the buffer and
-    reseting. 
+    reseting.
 */
 static void
 _dbFlush(DBEMITCTX *self)
@@ -7397,9 +7862,9 @@ _rleCommit(RLECTX *self)
     {
       DBEMITCTX db;
       memset(&db, 0, sizeof(db));
-          
+
       emit2(".db %u", self->pos);
-      
+
       for (i = 0; i < self->pos; i++)
         {
           _dbEmit(&db, self->buffer[i]);
@@ -7431,7 +7896,7 @@ _rleCommit(RLECTX *self)
     chunks.
 */
 static void
-_rleAppend(RLECTX *self, int c)
+_rleAppend(RLECTX *self, unsigned c)
 {
   int i;
 
@@ -7509,9 +7974,9 @@ genArrayInit (iCode * ic)
 
   fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
   emit2 ("call __initrleblock");
-    
+
   type = operandType(IC_LEFT(ic));
-    
+
   if (type && type->next)
     {
       if (IS_SPEC(type->next) || IS_PTR(type->next))
@@ -7524,7 +7989,7 @@ genArrayInit (iCode * ic)
         }
       else
         {
-         printTypeChainRaw (type, NULL);
+          printTypeChainRaw (type, NULL);
           wassertl (0, "Can't determine element size in genArrayInit.");
         }
     }
@@ -7555,7 +8020,7 @@ genArrayInit (iCode * ic)
               _rleAppend(&rle, val);
             }
         }
-       
+
       iLoop = iLoop->next;
     }
 
@@ -7588,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
-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_BC, PAIR_HL, PAIR_DE
+    PAIR_DE, PAIR_HL, PAIR_BC
   };
   int i, j, nunity = 0;
   memset (ids, PAIR_INVALID, sizeof (ids));
@@ -7656,10 +8066,6 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
   /* 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);
@@ -7667,7 +8073,7 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
     }
 
   /* Count the number of unity or iTemp assigns. */
-  for (i = 0; i < 3; i++) 
+  for (i = 0; i < 3; i++)
     {
       if (ids[dest[i]][dest[i]] == TRUE || ids[dest[i]][PAIR_INVALID] == TRUE)
         {
@@ -7681,7 +8087,7 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
     }
   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++)
@@ -7704,7 +8110,7 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
     }
   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++)
@@ -7713,12 +8119,22 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams)
                 {
                   if (j == PAIR_INVALID || j == dest[i])
                     {
-                      /* Keep looking. */
+                      /* This one is OK. */
                     }
                   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;
+                        }
                     }
                 }
             }
@@ -7752,59 +8168,33 @@ 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;
-  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];
 
-  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);
 
+  spillPair (PAIR_HL);
+
   _restoreRegsAfterCall();
 
   /* 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)) ||
+        OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
       IS_TRUE_SYMOP (IC_RESULT (ic)))
     {
       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
@@ -7817,7 +8207,7 @@ genBuiltInMemcpy (iCode *ic, int nParams, operand **pparams)
 
 /*-----------------------------------------------------------------*/
 /* genBuiltIn - calls the appropriate function to  generating code */
-/* for a built in function                                        */
+/* for a built in function                                         */
 /*-----------------------------------------------------------------*/
 static void genBuiltIn (iCode *ic)
 {
@@ -7832,17 +8222,13 @@ static void genBuiltIn (iCode *ic)
     /* 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);
-      } 
-    else 
+        genBuiltInMemcpy(bi_iCode, nbi_parms, bi_parms);
+      }
+    else
       {
-       wassertl (0, "Unknown builtin function encountered");
+        wassertl (0, "Unknown builtin function encountered");
       }
 }
 
@@ -7868,7 +8254,7 @@ genZ80Code (iCode * lic)
     }
 
   _G.lines.head = _G.lines.current = NULL;
-  
+
   /* if debug information required */
   if (options.debug && currFunc)
     {
@@ -7880,257 +8266,261 @@ genZ80Code (iCode * lic)
       _G.current_iCode = ic;
 
       if (ic->lineno && cln != ic->lineno)
-       {
-         if (options.debug)
-           {
-             debugFile->writeCLine (ic);
-           }
-         if (!options.noCcodeInAsm) {
-           emit2 (";%s:%d: %s", ic->filename, ic->lineno,
-                  printCLine(ic->filename, ic->lineno));
-         }
-         cln = ic->lineno;
-       }
-      if (options.iCodeInAsm) {
-       emit2 (";ic:%d: %s", ic->key, printILine(ic));
-      }
+        {
+          if (options.debug)
+            {
+              debugFile->writeCLine (ic);
+            }
+          if (!options.noCcodeInAsm)
+            {
+              emit2 (";%s:%d: %s", ic->filename, ic->lineno,
+                     printCLine(ic->filename, ic->lineno));
+            }
+          cln = ic->lineno;
+        }
+      if (options.iCodeInAsm)
+        {
+          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
          this has already been generated then
          do nothing */
       if (resultRemat (ic) || ic->generated)
-       continue;
+        continue;
 
       /* depending on the operation */
       switch (ic->op)
-       {
-       case '!':
-         emitDebug ("; genNot");
-         genNot (ic);
-         break;
-
-       case '~':
-         emitDebug ("; genCpl");
-         genCpl (ic);
-         break;
-
-       case UNARYMINUS:
-         emitDebug ("; genUminus");
-         genUminus (ic);
-         break;
-
-       case IPUSH:
-         emitDebug ("; genIpush");
-         genIpush (ic);
-         break;
-
-       case IPOP:
-         /* IPOP happens only when trying to restore a
-            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
-            we need to check for this condition and handle it */
-         if (ic->next &&
-             ic->next->op == IFX &&
-             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
-           {
+        {
+        case '!':
+          emitDebug ("; genNot");
+          genNot (ic);
+          break;
+
+        case '~':
+          emitDebug ("; genCpl");
+          genCpl (ic);
+          break;
+
+        case UNARYMINUS:
+          emitDebug ("; genUminus");
+          genUminus (ic);
+          break;
+
+        case IPUSH:
+          emitDebug ("; genIpush");
+          genIpush (ic);
+          break;
+
+        case IPOP:
+          /* IPOP happens only when trying to restore a
+             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 destroy the contents of the register so
+             we need to check for this condition and handle it */
+          if (ic->next &&
+              ic->next->op == IFX &&
+              regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
+            {
               emitDebug ("; genIfx");
-             genIfx (ic->next, ic);
-           }
-         else
-           {
-             emitDebug ("; genIpop");
-             genIpop (ic);
-           }
-         break;
-
-       case CALL:
-         emitDebug ("; genCall");
-         genCall (ic);
-         break;
-
-       case PCALL:
-         emitDebug ("; genPcall");
-         genPcall (ic);
-         break;
-
-       case FUNCTION:
-         emitDebug ("; genFunction");
-         genFunction (ic);
-         break;
-
-       case ENDFUNCTION:
-         emitDebug ("; genEndFunction");
-         genEndFunction (ic);
-         break;
-
-       case RETURN:
-         emitDebug ("; genRet");
-         genRet (ic);
-         break;
-
-       case LABEL:
-         emitDebug ("; genLabel");
-         genLabel (ic);
-         break;
-
-       case GOTO:
-         emitDebug ("; genGoto");
-         genGoto (ic);
-         break;
-
-       case '+':
-         emitDebug ("; genPlus");
-         genPlus (ic);
-         break;
-
-       case '-':
-         emitDebug ("; genMinus");
-         genMinus (ic);
-         break;
-
-       case '*':
-         emitDebug ("; genMult");
-         genMult (ic);
-         break;
-
-       case '/':
-         emitDebug ("; genDiv");
-         genDiv (ic);
-         break;
-
-       case '%':
-         emitDebug ("; genMod");
-         genMod (ic);
-         break;
-
-       case '>':
-         emitDebug ("; genCmpGt");
-         genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
-         break;
-
-       case '<':
-         emitDebug ("; genCmpLt");
-         genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
-         break;
-
-       case LE_OP:
-       case GE_OP:
-       case NE_OP:
-
-         /* note these two are xlated by algebraic equivalence
-            during parsing SDCC.y */
-         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-                 "got '>=' or '<=' shouldn't have come here");
-         break;
-
-       case EQ_OP:
-         emitDebug ("; genCmpEq");
-         genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
-         break;
-
-       case AND_OP:
-         emitDebug ("; genAndOp");
-         genAndOp (ic);
-         break;
-
-       case OR_OP:
-         emitDebug ("; genOrOp");
-         genOrOp (ic);
-         break;
-
-       case '^':
-         emitDebug ("; genXor");
-         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
-         break;
-
-       case '|':
-         emitDebug ("; genOr");
-         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
-         break;
-
-       case BITWISEAND:
-         emitDebug ("; genAnd");
-         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
-         break;
-
-       case INLINEASM:
-         emitDebug ("; genInline");
-         genInline (ic);
-         break;
-
-       case RRC:
-         emitDebug ("; genRRC");
-         genRRC (ic);
-         break;
-
-       case RLC:
-         emitDebug ("; genRLC");
-         genRLC (ic);
-         break;
-
-       case GETHBIT:
-         emitDebug ("; genGetHBIT");
-         genGetHbit (ic);
+              genIfx (ic->next, ic);
+            }
+          else
+            {
+              emitDebug ("; genIpop");
+              genIpop (ic);
+            }
+          break;
+
+        case CALL:
+          emitDebug ("; genCall");
+          genCall (ic);
+          break;
+
+        case PCALL:
+          emitDebug ("; genPcall");
+          genPcall (ic);
+          break;
+
+        case FUNCTION:
+          emitDebug ("; genFunction");
+          genFunction (ic);
+          break;
+
+        case ENDFUNCTION:
+          emitDebug ("; genEndFunction");
+          genEndFunction (ic);
+          break;
+
+        case RETURN:
+          emitDebug ("; genRet");
+          genRet (ic);
+          break;
+
+        case LABEL:
+          emitDebug ("; genLabel");
+          genLabel (ic);
+          break;
+
+        case GOTO:
+          emitDebug ("; genGoto");
+          genGoto (ic);
+          break;
+
+        case '+':
+          emitDebug ("; genPlus");
+          genPlus (ic);
+          break;
+
+        case '-':
+          emitDebug ("; genMinus");
+          genMinus (ic);
           break;
 
-       case LEFT_OP:
-         emitDebug ("; genLeftShift");
-         genLeftShift (ic);
-         break;
-
-       case RIGHT_OP:
-         emitDebug ("; genRightShift");
-         genRightShift (ic);
-         break;
-
-       case GET_VALUE_AT_ADDRESS:
-         emitDebug ("; genPointerGet");
-         genPointerGet (ic);
-         break;
-
-       case '=':
-
-         if (POINTER_SET (ic))
-           {
-             emitDebug ("; genAssign (pointer)");
-             genPointerSet (ic);
-           }
-         else
-           {
-             emitDebug ("; genAssign");
-             genAssign (ic);
-           }
-         break;
-
-       case IFX:
+        case '*':
+          emitDebug ("; genMult");
+          genMult (ic);
+          break;
+
+        case '/':
+          emitDebug ("; genDiv");
+          genDiv (ic);
+          break;
+
+        case '%':
+          emitDebug ("; genMod");
+          genMod (ic);
+          break;
+
+        case '>':
+          emitDebug ("; genCmpGt");
+          genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
+          break;
+
+        case '<':
+          emitDebug ("; genCmpLt");
+          genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
+          break;
+
+        case LE_OP:
+        case GE_OP:
+        case NE_OP:
+
+          /* note these two are xlated by algebraic equivalence
+             during parsing SDCC.y */
+          werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                  "got '>=' or '<=' shouldn't have come here");
+          break;
+
+        case EQ_OP:
+          emitDebug ("; genCmpEq");
+          genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
+          break;
+
+        case AND_OP:
+          emitDebug ("; genAndOp");
+          genAndOp (ic);
+          break;
+
+        case OR_OP:
+          emitDebug ("; genOrOp");
+          genOrOp (ic);
+          break;
+
+        case '^':
+          emitDebug ("; genXor");
+          genXor (ic, ifxForOp (IC_RESULT (ic), ic));
+          break;
+
+        case '|':
+          emitDebug ("; genOr");
+          genOr (ic, ifxForOp (IC_RESULT (ic), ic));
+          break;
+
+        case BITWISEAND:
+          emitDebug ("; genAnd");
+          genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
+          break;
+
+        case INLINEASM:
+          emitDebug ("; genInline");
+          genInline (ic);
+          break;
+
+        case RRC:
+          emitDebug ("; genRRC");
+          genRRC (ic);
+          break;
+
+        case RLC:
+          emitDebug ("; genRLC");
+          genRLC (ic);
+          break;
+
+        case GETHBIT:
+          emitDebug ("; genGetHBIT");
+          genGetHbit (ic);
+          break;
+
+        case LEFT_OP:
+          emitDebug ("; genLeftShift");
+          genLeftShift (ic);
+          break;
+
+        case RIGHT_OP:
+          emitDebug ("; genRightShift");
+          genRightShift (ic);
+          break;
+
+        case GET_VALUE_AT_ADDRESS:
+          emitDebug ("; genPointerGet");
+          genPointerGet (ic);
+          break;
+
+        case '=':
+
+          if (POINTER_SET (ic))
+            {
+              emitDebug ("; genAssign (pointer)");
+              genPointerSet (ic);
+            }
+          else
+            {
+              emitDebug ("; genAssign");
+              genAssign (ic);
+            }
+          break;
+
+        case IFX:
           emitDebug ("; genIfx");
-         genIfx (ic, NULL);
-         break;
-
-       case ADDRESS_OF:
-         emitDebug ("; genAddrOf");
-         genAddrOf (ic);
-         break;
-
-       case JUMPTABLE:
-         emitDebug ("; genJumpTab");
-         genJumpTab (ic);
-         break;
-
-       case CAST:
-         emitDebug ("; genCast");
-         genCast (ic);
-         break;
-
-       case RECEIVE:
-         emitDebug ("; genReceive");
-         genReceive (ic);
-         break;
-
-       case SEND:
-         if (ic->builtinSEND)
+          genIfx (ic, NULL);
+          break;
+
+        case ADDRESS_OF:
+          emitDebug ("; genAddrOf");
+          genAddrOf (ic);
+          break;
+
+        case JUMPTABLE:
+          emitDebug ("; genJumpTab");
+          genJumpTab (ic);
+          break;
+
+        case CAST:
+          emitDebug ("; genCast");
+          genCast (ic);
+          break;
+
+        case RECEIVE:
+          emitDebug ("; genReceive");
+          genReceive (ic);
+          break;
+
+        case SEND:
+          if (ic->builtinSEND)
             {
               emitDebug ("; genBuiltIn");
               genBuiltIn(ic);
@@ -8140,21 +8530,31 @@ genZ80Code (iCode * lic)
               emitDebug ("; addSet");
               addSet (&_G.sendSet, ic);
             }
-         break;
+          break;
 
-       case ARRAYINIT:
-         emitDebug ("; genArrayInit");
+        case ARRAYINIT:
+          emitDebug ("; genArrayInit");
           genArrayInit(ic);
           break;
 
-       case DUMMY_READ_VOLATILE:
-         emitDebug ("; genDummyRead");
-         genDummyRead (ic);
-         break;
+        case DUMMY_READ_VOLATILE:
+          emitDebug ("; genDummyRead");
+          genDummyRead (ic);
+          break;
+
+        case CRITICAL:
+          emitDebug ("; genCritical");
+          genCritical (ic);
+          break;
+
+        case ENDCRITICAL:
+          emitDebug ("; genEndCritical");
+          genEndCritical (ic);
+          break;
 
-       default:
-         ic = ic;
-       }
+        default:
+          ic = ic;
+        }
     }
 
 
@@ -8166,16 +8566,16 @@ genZ80Code (iCode * lic)
   /* 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;
+        flushStatics ();
+        _G.flushStatics = 0;
       }
-    codeOutFile = fp;
+    codeOutBuf = buf;
   }
 
   freeTrace(&_G.lines.trace);
@@ -8192,9 +8592,9 @@ _isPairUsed (iCode * ic, PAIR_ID pairId)
     {
     case PAIR_DE:
       if (bitVectBitValue (ic->rMask, D_IDX))
-       ret++;
+        ret++;
       if (bitVectBitValue (ic->rMask, E_IDX))
-       ret++;
+        ret++;
       break;
     default:
       wassert (0);
@@ -8211,7 +8611,7 @@ fetchLitSpecial (asmop * aop, bool negate, bool xor)
   wassert (aop->type == AOP_LIT);
   wassert (!IS_FLOAT (val->type));
 
-  v = (unsigned long) floatFromVal (val);
+  v = ulFromVal (val);
 
   if (xor)
     v ^= 0x8000;