* src/SDCCast.c (createIvalArray): fixed bug 770487 SIGSEGV
[fw/sdcc] / src / z80 / gen.c
index 4572471a53ccc7a58b21dc5d3de29cf895285652..c474b6c26466414fa8eba19f5d25ed67d8c45a84 100644 (file)
@@ -60,7 +60,9 @@
   9. With asm optimised strings                17030 192 2223
 
   10 and below are with asm strings off.
   9. With asm optimised strings                17030 192 2223
 
   10 and below are with asm strings off.
-  
+
+  10 Mucho optimisations               13562 201 1FCC
+
   Apparent advantage of turning on regparams:
   1.  Cost of push
         Decent case is push of a constant 
   Apparent advantage of turning on regparams:
   1.  Cost of push
         Decent case is push of a constant 
 #include <string.h>
 #include <ctype.h>
 
 #include <string.h>
 #include <ctype.h>
 
-#ifdef HAVE_SYS_ISA_DEFS_H
-#include <sys/isa_defs.h>
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+#define STRCASECMP stricmp
+#else
+#define STRCASECMP strcasecmp
 #endif
 
 #include "z80.h"
 #endif
 
 #include "z80.h"
@@ -203,12 +207,22 @@ static struct
     int pushedBC;
     int pushedDE;
   } stack;
     int pushedBC;
     int pushedDE;
   } stack;
+
+  struct
+  {
+    int pushedBC;
+    int pushedDE;
+  } calleeSaves;
+
+  bool omitFramePtr;
   int frameId;
   int receiveOffset;
   bool flushStatics;
   bool in_home;
   const char *lastFunctionName;
   int frameId;
   int receiveOffset;
   bool flushStatics;
   bool in_home;
   const char *lastFunctionName;
-
+  iCode *current_iCode;
+  bool preserveCarry;
+  
   set *sendSet;
 
   struct
   set *sendSet;
 
   struct
@@ -222,6 +236,7 @@ static struct
     lineNode *head;
     lineNode *current;
     int isInline;
     lineNode *head;
     lineNode *current;
     int isInline;
+    int isDebug;
     allocTrace trace;
   } lines;
 
     allocTrace trace;
   } lines;
 
@@ -233,6 +248,50 @@ static struct
 
 static const char *aopGet (asmop * aop, int offset, bool bit16);
 
 
 static const char *aopGet (asmop * aop, int offset, bool bit16);
 
+static const char *aopNames[] = {
+  "AOP_INVALID",
+  "AOP_LIT",
+  "AOP_REG",
+  "AOP_DIR",
+  "AOP_SFR",
+  "AOP_STK",
+  "AOP_IMMD",
+  "AOP_STR",
+  "AOP_CRY",
+  "AOP_IY",
+  "AOP_HL",
+  "AOP_ACC",
+  "AOP_HLREG",
+  "AOP_SIMPLELIT",
+  "AOP_EXSTK",
+  "AOP_PAIRPT",
+  "AOP_DUMMY"
+};
+
+static bool
+isLastUse (iCode *ic, operand *op)
+{
+  bitVect *uses = bitVectCopy (OP_USES (op));
+
+  while (!bitVectIsZero (uses))
+    {
+      if (bitVectFirstBit (uses) == ic->key)
+        {
+          if (bitVectnBitsOn (uses) == 1)
+            {
+              return TRUE;
+            }
+          else
+            {
+              return FALSE;
+            }
+        }
+      bitVectUnSetBit (uses, bitVectFirstBit (uses));
+    }
+
+  return FALSE;
+}
+
 static PAIR_ID
 _getTempPairId(void)
 {
 static PAIR_ID
 _getTempPairId(void)
 {
@@ -252,14 +311,50 @@ _getTempPairName(void)
   return _pairs[_getTempPairId()].name;
 }
 
   return _pairs[_getTempPairId()].name;
 }
 
+static bool
+isPairInUse (PAIR_ID id, iCode *ic)
+{
+  if (id == PAIR_DE)
+    {
+      return bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
+    }
+  else if (id == PAIR_BC)
+    {
+      return bitVectBitValue (ic->rMask, B_IDX) || bitVectBitValue(ic->rMask, C_IDX);
+    }
+  else
+    {
+      wassertl (0, "Only implemented for DE and BC");
+      return TRUE;
+    }
+}
+
+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);
+    }
+  else
+    {
+      wassertl (0, "Only implemented for DE");
+      return TRUE;
+    }
+}
+
 static PAIR_ID
 getFreePairId (iCode *ic)
 {
 static PAIR_ID
 getFreePairId (iCode *ic)
 {
-  if (!(bitVectBitValue (ic->rMask, B_IDX) || bitVectBitValue(ic->rMask, C_IDX)))
+  if (!isPairInUse (PAIR_BC, ic))
     {
       return PAIR_BC;
     }
     {
       return PAIR_BC;
     }
-  else if (IS_Z80 && !(bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX)))
+  else if (IS_Z80 && !isPairInUse (PAIR_DE, ic))
     {
       return PAIR_DE;
     }
     {
       return PAIR_DE;
     }
@@ -306,9 +401,9 @@ _newLineNode (char *line)
 static void
 _vemit2 (const char *szFormat, va_list ap)
 {
 static void
 _vemit2 (const char *szFormat, va_list ap)
 {
-  char buffer[256];
+  char buffer[INITIAL_INLINEASM];
 
 
-  tvsprintf (buffer, szFormat, ap);
+  tvsprintf (buffer, sizeof(buffer), szFormat, ap);
 
   _tidyUp (buffer);
   _G.lines.current = (_G.lines.current ?
 
   _tidyUp (buffer);
   _G.lines.current = (_G.lines.current ?
@@ -316,6 +411,8 @@ _vemit2 (const char *szFormat, va_list ap)
              (_G.lines.head = _newLineNode (buffer)));
 
   _G.lines.current->isInline = _G.lines.isInline;
              (_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;
 }
 
 static void
 }
 
 static void
@@ -336,15 +433,28 @@ emitDebug (const char *szFormat,...)
   if (!DISABLE_DEBUG)
     {
       va_list ap;
   if (!DISABLE_DEBUG)
     {
       va_list ap;
-      
+
       va_start (ap, szFormat);
       va_start (ap, szFormat);
-      
+
       _vemit2 (szFormat, ap);
       _vemit2 (szFormat, ap);
-      
+
       va_end (ap);
     }
 }
 
       va_end (ap);
     }
 }
 
+/*-----------------------------------------------------------------*/
+/* z80_emitDebuggerSymbol - associate the current code location    */
+/*   with a debugger symbol                                        */
+/*-----------------------------------------------------------------*/
+void
+z80_emitDebuggerSymbol (char * debugSym)
+{
+  _G.lines.isDebug = 1;
+  emit2 ("%s !equ .", debugSym);
+  emit2 ("!global", debugSym);
+  _G.lines.isDebug = 0;
+}
+
 /*-----------------------------------------------------------------*/
 /* emit2 - writes the code into a file : for now it is simple    */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 /* emit2 - writes the code into a file : for now it is simple    */
 /*-----------------------------------------------------------------*/
@@ -375,13 +485,14 @@ _emit2 (const char *inst, const char *fmt,...)
                   (_G.lines.head = _newLineNode (lb)));
     }
   _G.lines.current->isInline = _G.lines.isInline;
                   (_G.lines.head = _newLineNode (lb)));
     }
   _G.lines.current->isInline = _G.lines.isInline;
+  _G.lines.current->ic = _G.current_iCode;
   va_end (ap);
 }
 
 static void
 _emitMove(const char *to, const char *from)
 {
   va_end (ap);
 }
 
 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);
     }
     {
       emit2("ld %s,%s", to, from);
     }
@@ -392,6 +503,35 @@ _emitMove(const char *to, const char *from)
     }
 }
 
     }
 }
 
+void
+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)
+    {
+    case AOP_EXSTK:
+    case AOP_STK:
+      emitDebug(";  aop_stk %d", aop->aopu.aop_stk);
+      break;
+    case AOP_REG:
+      for (i=aop->size-1;i>=0;i--)
+        *rbp++ = *(aop->aopu.aop_reg[i]->name);
+      *rbp = '\0';
+      emitDebug(";  reg = %s", regbuf);
+      break;
+    case AOP_PAIRPTR:
+      emitDebug(";  pairptr = (%s)", _pairs[aop->aopu.aop_pairId].name);
+        
+    default:
+      /* No information. */
+      break;
+    }
+}
+
 static void
 _moveA(const char *moveFrom)
 {
 static void
 _moveA(const char *moveFrom)
 {
@@ -480,6 +620,22 @@ isPair (asmop * aop)
   return (getPairId (aop) != PAIR_INVALID);
 }
 
   return (getPairId (aop) != PAIR_INVALID);
 }
 
+/** Returns TRUE if the registers used in aop cannot be split into high
+    and low halves */
+bool
+isUnsplitable (asmop * aop)
+{
+  switch (getPairId (aop))
+    {
+    case PAIR_IX:
+    case PAIR_IY:
+      return TRUE;
+    default:
+      return FALSE;
+    }
+  return FALSE;
+}
+
 bool
 isPtrPair (asmop * aop)
 {
 bool
 isPtrPair (asmop * aop)
 {
@@ -502,6 +658,30 @@ spillPair (PAIR_ID pairId)
   _G.pairs[pairId].base = NULL;
 }
 
   _G.pairs[pairId].base = NULL;
 }
 
+/* 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)
+        {
+        case 'h':
+        case 'l':
+          spillPair(PAIR_HL);
+          break;
+        case 'd':
+        case 'e':
+          spillPair(PAIR_DE);
+          break;
+        case 'b':
+        case 'c':
+          spillPair(PAIR_BC);
+          break;
+        }
+    }
+}
+
 /** Push a register pair onto the stack */
 void
 genPairPush (asmop * aop)
 /** Push a register pair onto the stack */
 void
 genPairPush (asmop * aop)
@@ -524,6 +704,39 @@ _pop (PAIR_ID pairId)
   spillPair (pairId);
 }
 
   spillPair (pairId);
 }
 
+void
+genMovePairPair (PAIR_ID srcPair, PAIR_ID dstPair)
+{
+  switch (dstPair)
+    {
+    case PAIR_IX:
+    case PAIR_IY:
+    case PAIR_AF:
+      _push(srcPair);
+      _pop(dstPair);
+      break;
+    case PAIR_BC:
+    case PAIR_DE:
+    case PAIR_HL:
+      if (srcPair == PAIR_IX || srcPair == PAIR_IY)
+        {
+          _push(srcPair);
+          _pop(dstPair);
+        }
+      else
+        {
+          emit2("ld %s,%s",_pairs[dstPair].l,_pairs[srcPair].l);
+          emit2("ld %s,%s",_pairs[dstPair].h,_pairs[srcPair].h);
+        }
+     default:
+       wassertl (0, "Tried to move a nonphysical pair");
+    }
+  _G.pairs[dstPair].last_type = _G.pairs[srcPair].last_type;
+  _G.pairs[dstPair].base = _G.pairs[srcPair].base;
+  _G.pairs[dstPair].offset = _G.pairs[srcPair].offset;
+}
+
+
 /*-----------------------------------------------------------------*/
 /* newAsmop - creates a new asmOp                                  */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 /* newAsmop - creates a new asmOp                                  */
 /*-----------------------------------------------------------------*/
@@ -554,7 +767,9 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
 
   /* if already has one */
   if (sym->aop)
 
   /* if already has one */
   if (sym->aop)
-    return sym->aop;
+    {
+      return sym->aop;
+    }
 
   /* Assign depending on the storage class */
   if (sym->onStack || sym->iaccess)
 
   /* Assign depending on the storage class */
   if (sym->onStack || sym->iaccess)
@@ -563,7 +778,7 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
          Normally everything is AOP_STK, but for offsets of < -128 or
          > 127 on the Z80 an extended stack pointer is used.
       */
          Normally everything is AOP_STK, but for offsets of < -128 or
          > 127 on the Z80 an extended stack pointer is used.
       */
-      if (IS_Z80 && (options.ommitFramePtr || sym->stack < INT8MIN || sym->stack > (int)(INT8MAX-getSize (sym->type))))
+      if (IS_Z80 && (_G.omitFramePtr || sym->stack < INT8MIN || sym->stack > (int)(INT8MAX-getSize (sym->type))))
         {
           emitDebug ("; AOP_EXSTK for %s", sym->rname);
           sym->aop = aop = newAsmop (AOP_EXSTK);
         {
           emitDebug ("; AOP_EXSTK for %s", sym->rname);
           sym->aop = aop = newAsmop (AOP_EXSTK);
@@ -588,18 +803,34 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
       return aop;
     }
 
       return aop;
     }
 
-  if (IS_GB)
+  if( IN_REGSP( space ))
+  { /*.p.t.20030716 minor restructure to add SFR support to the Z80 */
+    if (IS_GB)
     {
       /* if it is in direct space */
     {
       /* if it is in direct space */
-      if (IN_REGSP (space) && !requires_a)
-       {
-         sym->aop = aop = newAsmop (AOP_SFR);
-         aop->aopu.aop_dir = sym->rname;
-         aop->size = getSize (sym->type);
+      if( !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;
-       }
+        return aop;
+      }
     }
     }
+    else
+    { /*.p.t.20030716 adding SFR support to the Z80 port */
+      aop = newAsmop (AOP_SFR);
+      sym->aop          = aop;
+      aop->aopu.aop_dir = sym->rname;
+      aop->size         = getSize( sym->type );
+      aop->paged        = FUNC_REGBANK(sym->type);
+      aop->bcInUse      = isPairInUse( PAIR_BC, ic );
+      aop->deInUse      = isPairInUse( PAIR_DE, ic );
+      emitDebug( ";Z80 AOP_SFR for %s banked:%d bc:%d de:%d", sym->rname, FUNC_REGBANK(sym->type), aop->bcInUse, aop->deInUse );
+
+      return( aop );
+    }
+  }
 
   /* only remaining is far space */
   /* in which case DPTR gets the address */
 
   /* only remaining is far space */
   /* in which case DPTR gets the address */
@@ -791,12 +1022,24 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a)
 
   /* if already has a asmop then continue */
   if (op->aop)
 
   /* if already has a asmop then continue */
   if (op->aop)
-    return;
+    {
+      if (op->aop->type == AOP_SFR)
+        {
+          op->aop->bcInUse = isPairInUse( PAIR_BC, ic );
+          op->aop->deInUse = isPairInUse( PAIR_DE, ic );
+        }
+      return;
+    }
 
   /* if the underlying symbol has a aop */
   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
     {
       op->aop = OP_SYMBOL (op)->aop;
 
   /* if the underlying symbol has a aop */
   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
     {
       op->aop = OP_SYMBOL (op)->aop;
+      if (op->aop->type == AOP_SFR)
+        {
+          op->aop->bcInUse = isPairInUse( PAIR_BC, ic );
+          op->aop->deInUse = isPairInUse( PAIR_DE, ic );
+        }
       return;
     }
 
       return;
     }
 
@@ -882,9 +1125,21 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a)
          return;
        }
 
          return;
        }
 
-      /* else spill location  */
-      sym->aop = op->aop = aop =
-       aopForSym (ic, sym->usl.spillLoc, result, requires_a);
+      if (sym->usl.spillLoc)
+        {
+         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;
+        }
+      
+      /* else must be a dummy iTemp */
+      sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
       aop->size = getSize (sym->type);
       return;
     }
       aop->size = getSize (sym->type);
       return;
     }
@@ -922,6 +1177,11 @@ freeAsmop (operand * op, asmop * aaop, iCode * ic)
       _pop (aop->aopu.aop_pairId);
     }
 
       _pop (aop->aopu.aop_pairId);
     }
 
+  if (getPairId (aop) == PAIR_HL)
+    {
+      spillPair (PAIR_HL);
+    }
+
 dealloc:
   /* all other cases just dealloc */
   if (op)
 dealloc:
   /* all other cases just dealloc */
   if (op)
@@ -956,8 +1216,6 @@ isLitWord (asmop * aop)
 char *
 aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
 {
 char *
 aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
 {
-  char *s = buffer;
-
   /* depending on type */
   switch (aop->type)
     {
   /* depending on type */
   switch (aop->type)
     {
@@ -967,17 +1225,20 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
       /* PENDING: for re-target */
       if (with_hash)
         {
       /* PENDING: for re-target */
       if (with_hash)
         {
-          tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
+          tsprintf (buffer, sizeof(buffer), 
+                   "!hashedstr + %d", aop->aopu.aop_immd, offset);
         }
       else if (offset == 0)
         {
         }
       else if (offset == 0)
         {
-          tsprintf (s, "%s", aop->aopu.aop_immd);
+          tsprintf (buffer, sizeof(buffer),
+                   "%s", aop->aopu.aop_immd);
         }
       else
         {
         }
       else
         {
-          tsprintf (s, "%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(s));
+      return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
 
     case AOP_LIT:
       {
 
     case AOP_LIT:
       {
@@ -1002,9 +1263,9 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
               }
 
            if (with_hash)
               }
 
            if (with_hash)
-             tsprintf (buffer, "!immedword", v);
+             tsprintf (buffer, sizeof(buffer), "!immedword", v);
            else
            else
-             tsprintf (buffer, "!constword", v);
+             tsprintf (buffer, sizeof(buffer), "!constword", v);
 
             return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
          }
 
             return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
          }
@@ -1020,15 +1281,15 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
             /* it is type float */
             fl.f = (float) floatFromVal (val);
 
             /* it is type float */
             fl.f = (float) floatFromVal (val);
 
-#ifdef _BIG_ENDIAN
+#ifdef WORDS_BIGENDIAN
             i = fl.c[3-offset] | (fl.c[3-offset-1]<<8);
 #else
             i = fl.c[offset] | (fl.c[offset+1]<<8);
 #endif
            if (with_hash)
             i = fl.c[3-offset] | (fl.c[3-offset-1]<<8);
 #else
             i = fl.c[offset] | (fl.c[offset+1]<<8);
 #endif
            if (with_hash)
-             tsprintf (buffer, "!immedword", i);
+             tsprintf (buffer, sizeof(buffer), "!immedword", i);
            else
            else
-             tsprintf (buffer, "!constword", i);
+             tsprintf (buffer, sizeof(buffer), "!constword", i);
 
             return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
          }
 
             return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
          }
@@ -1133,8 +1394,36 @@ fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
   emit2 ("ld %s,!hashedstr", pair, l);
 }
 
   emit2 ("ld %s,!hashedstr", pair, l);
 }
 
+static PAIR_ID
+makeFreePairId (iCode *ic, bool *pisUsed)
+{
+  *pisUsed = FALSE;
+
+  if (ic != NULL)
+    {
+      if (!bitVectBitValue (ic->rMask, B_IDX) && !bitVectBitValue(ic->rMask, C_IDX))
+        {
+          return PAIR_BC;
+        }
+      else if (IS_Z80 && !bitVectBitValue (ic->rMask, D_IDX) && !bitVectBitValue(ic->rMask, E_IDX))
+        {
+          return PAIR_DE;
+        }
+      else
+        {
+          *pisUsed = TRUE;
+          return PAIR_HL;
+        }
+    }
+  else
+    {
+      *pisUsed = TRUE;
+      return PAIR_HL;
+    }
+}
+
 static void
 static void
-fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
+fetchPairLong (PAIR_ID pairId, asmop * aop, iCode *ic, int offset)
 {
     /* if this is remateriazable */
     if (isLitWord (aop)) {
 {
     /* if this is remateriazable */
     if (isLitWord (aop)) {
@@ -1186,19 +1475,29 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
               }
             else
               {
               }
             else
               {
-                _push (PAIR_HL);
+                bool isUsed;
+                PAIR_ID id = makeFreePairId (ic, &isUsed);
+                if (isUsed)
+                  _push (id);
                 /* Can't load into parts, so load into HL then exchange. */
                 /* Can't load into parts, so load into HL then exchange. */
-                emit2 ("ld %s,%s", _pairs[PAIR_HL].l, aopGet (aop, offset, FALSE));
-                emit2 ("ld %s,%s", _pairs[PAIR_HL].h, aopGet (aop, offset + 1, FALSE));
-                emit2 ("push hl");
+                emit2 ("ld %s,%s", _pairs[id].l, aopGet (aop, offset, FALSE));
+                emit2 ("ld %s,%s", _pairs[id].h, aopGet (aop, offset + 1, FALSE));
+                emit2 ("push %s", _pairs[id].name);
                 emit2 ("pop iy");
                 emit2 ("pop iy");
-                _pop (PAIR_HL);
+                if (isUsed)
+                  _pop (id);
               }
           }
               }
           }
-        else {
+        else if (isUnsplitable(aop))
+          {
+            emit2("push %s", _pairs[getPairId(aop)].name);
+            emit2("pop %s", _pairs[pairId].name);
+          }
+        else 
+          {
             emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
             emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
             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)
             spillPair (PAIR_HL);
         /* PENDING: check? */
         if (pairId == PAIR_HL)
             spillPair (PAIR_HL);
@@ -1208,7 +1507,7 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
 static void
 fetchPair (PAIR_ID pairId, asmop * aop)
 {
 static void
 fetchPair (PAIR_ID pairId, asmop * aop)
 {
-  fetchPairLong (pairId, aop, 0);
+  fetchPairLong (pairId, aop, NULL, 0);
 }
 
 static void
 }
 
 static void
@@ -1222,6 +1521,12 @@ setupPairFromSP (PAIR_ID id, int offset)
 {
   wassertl (id == PAIR_HL, "Setup relative to SP only implemented for HL");
 
 {
   wassertl (id == PAIR_HL, "Setup relative to SP only implemented for HL");
 
+  if (_G.preserveCarry)
+    {
+      _push (PAIR_AF);
+      offset += 2;
+    }
+  
   if (offset < INT8MIN || offset > INT8MAX)
     {
       emit2 ("ld hl,!immedword", offset);
   if (offset < INT8MIN || offset > INT8MAX)
     {
       emit2 ("ld hl,!immedword", offset);
@@ -1229,7 +1534,13 @@ setupPairFromSP (PAIR_ID id, int offset)
     }
   else
     {
     }
   else
     {
-      emit2 ("!ldahlsp", offset);
+          emit2 ("!ldahlsp", offset);
+    }
+
+  if (_G.preserveCarry)
+    {
+      _pop (PAIR_AF);
+      offset -= 2;
     }
 }
 
     }
 }
 
@@ -1265,11 +1576,15 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset)
         else
           {
             /* PENDING: Do this better. */
         else
           {
             /* PENDING: Do this better. */
+            if (_G.preserveCarry)
+              _push (PAIR_AF);
             sprintf (buffer, "%d", offset + _G.stack.pushed);
             emit2 ("ld %s,!hashedstr", _pairs[pairId].name, buffer);
             emit2 ("add %s,sp", _pairs[pairId].name);
             _G.pairs[pairId].last_type = aop->type;
             _G.pairs[pairId].offset = offset;
             sprintf (buffer, "%d", offset + _G.stack.pushed);
             emit2 ("ld %s,!hashedstr", _pairs[pairId].name, buffer);
             emit2 ("add %s,sp", _pairs[pairId].name);
             _G.pairs[pairId].last_type = aop->type;
             _G.pairs[pairId].offset = offset;
+            if (_G.preserveCarry)
+              _pop (PAIR_AF);
           }
       }
       break;
           }
       }
       break;
@@ -1278,6 +1593,7 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset)
       {
        /* Doesnt include _G.stack.pushed */
        int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
       {
        /* 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;
        if (aop->aopu.aop_stk > 0)
          {
            abso += _G.stack.param_offset;
@@ -1297,6 +1613,8 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset)
       }
 
     case AOP_PAIRPTR:
       }
 
     case AOP_PAIRPTR:
+      if (pairId != aop->aopu.aop_pairId)
+        genMovePairPair(aop->aopu.aop_pairId, pairId);
       adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, offset);
       break;
       
       adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, offset);
       break;
       
@@ -1319,55 +1637,83 @@ emitLabel (int key)
 static const char *
 aopGet (asmop * aop, int offset, bool bit16)
 {
 static const char *
 aopGet (asmop * aop, int offset, bool bit16)
 {
-  char *s = buffer;
+  // char *s = buffer;
 
   /* 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) 
     {
 
   /* 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) 
     {
-      tsprintf (s, "!zero");
-      return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+      tsprintf (buffer, sizeof(buffer), "!zero");
+      return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
     }
 
   /* depending on type */
   switch (aop->type)
     {
     }
 
   /* depending on type */
   switch (aop->type)
     {
+    case AOP_DUMMY:
+      tsprintf (buffer, sizeof(buffer), "!zero");
+      return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
+    
     case AOP_IMMD:
       /* PENDING: re-target */
       if (bit16)
     case AOP_IMMD:
       /* PENDING: re-target */
       if (bit16)
-       tsprintf (s, "!immedwords", aop->aopu.aop_immd);
+       tsprintf (buffer, sizeof(buffer), "!immedwords", aop->aopu.aop_immd);
       else
        switch (offset)
          {
          case 2:
       else
        switch (offset)
          {
          case 2:
-           tsprintf (s, "!bankimmeds", aop->aopu.aop_immd);
+           tsprintf (buffer, sizeof(buffer), "!bankimmeds", aop->aopu.aop_immd);
            break;
          case 1:
            break;
          case 1:
-           tsprintf (s, "!msbimmeds", aop->aopu.aop_immd);
+           tsprintf (buffer, sizeof(buffer), "!msbimmeds", aop->aopu.aop_immd);
            break;
          case 0:
            break;
          case 0:
-           tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
+           tsprintf (buffer, sizeof(buffer), "!lsbimmeds", aop->aopu.aop_immd);
            break;
          default:
            wassertl (0, "Fetching from beyond the limits of an immediate value.");
          }
 
            break;
          default:
            wassertl (0, "Fetching from beyond the limits of an immediate value.");
          }
 
-      return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+      return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
 
     case AOP_DIR:
       wassert (IS_GB);
       emit2 ("ld a,(%s+%d)", aop->aopu.aop_dir, offset);
 
     case AOP_DIR:
       wassert (IS_GB);
       emit2 ("ld a,(%s+%d)", aop->aopu.aop_dir, offset);
-      sprintf (s, "a");
+      SNPRINTF (buffer, sizeof(buffer), "a");
 
 
-      return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+      return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
 
     case AOP_SFR:
 
     case AOP_SFR:
-      wassert (IS_GB);
-      emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset);
-      sprintf (s, "a");
+      if( IS_GB )
+      {
+        // wassert (IS_GB);
+        emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset);
+        SNPRINTF (buffer, sizeof(buffer), "a");
+
+        return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
+      }
+      else
+      { /*.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);
+        }
+        else if( z80_opts.port_mode == 180 )
+        { /* z180 in0/out0 mode */
+          emit2( "in0 a,(%s)", aop->aopu.aop_dir );
+        }
+        else
+        { /* 8 bit mode */
+          emit2( "in a,(%s)", aop->aopu.aop_dir );
+        }
+        
+        SNPRINTF (buffer, sizeof(buffer), "a");
 
 
-      return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+        return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
+      }
 
     case AOP_REG:
       return aop->aopu.aop_reg[offset]->name;
 
     case AOP_REG:
       return aop->aopu.aop_reg[offset]->name;
@@ -1375,38 +1721,39 @@ aopGet (asmop * aop, int offset, bool bit16)
     case AOP_HL:
       wassert (IS_GB);
       setupPair (PAIR_HL, aop, offset);
     case AOP_HL:
       wassert (IS_GB);
       setupPair (PAIR_HL, aop, offset);
-      tsprintf (s, "!*hl");
+      tsprintf (buffer, sizeof(buffer), "!*hl");
 
 
-      return traceAlloc(&_G.trace.aops, Safe_strdup (s));
+      return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));
 
     case AOP_IY:
       wassert (IS_Z80);
       setupPair (PAIR_IY, aop, offset);
 
     case AOP_IY:
       wassert (IS_Z80);
       setupPair (PAIR_IY, aop, offset);
-      tsprintf (s, "!*iyx", offset);
+      tsprintf (buffer, sizeof(buffer), "!*iyx", offset);
 
 
-      return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+      return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
 
     case AOP_EXSTK:
       wassert (IS_Z80);
       setupPair (PAIR_IY, aop, offset);
 
     case AOP_EXSTK:
       wassert (IS_Z80);
       setupPair (PAIR_IY, aop, offset);
-      tsprintf (s, "!*iyx", offset, offset);
+      tsprintf (buffer, sizeof(buffer), "!*iyx", offset, offset);
 
 
-      return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+      return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
 
     case AOP_STK:
       if (IS_GB)
        {
          setupPair (PAIR_HL, aop, offset);
 
     case AOP_STK:
       if (IS_GB)
        {
          setupPair (PAIR_HL, aop, offset);
-         tsprintf (s, "!*hl");
+         tsprintf (buffer, sizeof(buffer), "!*hl");
        }
       else
        {
          if (aop->aopu.aop_stk >= 0)
            offset += _G.stack.param_offset;
        }
       else
        {
          if (aop->aopu.aop_stk >= 0)
            offset += _G.stack.param_offset;
-         tsprintf (s, "!*ixx", aop->aopu.aop_stk + offset);
+         tsprintf (buffer, sizeof(buffer),
+                   "!*ixx", aop->aopu.aop_stk + offset);
        }
 
        }
 
-      return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+      return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
 
     case AOP_CRY:
       wassertl (0, "Tried to fetch from a bit variable");
 
     case AOP_CRY:
       wassertl (0, "Tried to fetch from a bit variable");
@@ -1418,8 +1765,8 @@ aopGet (asmop * aop, int offset, bool bit16)
        }
       else
         {
        }
       else
         {
-          tsprintf(s, "!zero");
-          return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+          tsprintf(buffer, sizeof(buffer), "!zero");
+          return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
         }
 
     case AOP_HLREG:
         }
 
     case AOP_HLREG:
@@ -1434,9 +1781,10 @@ aopGet (asmop * aop, int offset, bool bit16)
         unsigned long v = aop->aopu.aop_simplelit;
         
         v >>= (offset * 8);
         unsigned long v = aop->aopu.aop_simplelit;
         
         v >>= (offset * 8);
-        tsprintf (s, "!immedbyte", (unsigned int) v & 0xff);
+        tsprintf (buffer, sizeof(buffer), 
+                 "!immedbyte", (unsigned int) v & 0xff);
         
         
-        return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+        return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
       }
     case AOP_STR:
       aop->coff = offset;
       }
     case AOP_STR:
       aop->coff = offset;
@@ -1444,9 +1792,17 @@ aopGet (asmop * aop, int offset, bool bit16)
 
     case AOP_PAIRPTR:
       setupPair (aop->aopu.aop_pairId, aop, offset);
 
     case AOP_PAIRPTR:
       setupPair (aop->aopu.aop_pairId, aop, offset);
-      sprintf (s, "(%s)", _pairs[aop->aopu.aop_pairId].name);
+      if (aop->aopu.aop_pairId==PAIR_IX)
+        SNPRINTF (buffer, sizeof(buffer), 
+                 "!*ixx", 0);
+      else if (aop->aopu.aop_pairId==PAIR_IY)
+        SNPRINTF (buffer, sizeof(buffer), 
+                 "!*iyx", 0);
+      else
+        SNPRINTF (buffer, sizeof(buffer), 
+                 "(%s)", _pairs[aop->aopu.aop_pairId].name);
 
 
-      return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+      return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
 
     default:
       break;
 
     default:
       break;
@@ -1502,13 +1858,17 @@ aopPut (asmop * aop, const char *s, int offset)
     }
 
   // PENDING
     }
 
   // PENDING
-  tsprintf(buffer2, s);
+  tsprintf(buffer2, sizeof(buffer2), s);
   s = buffer2;
 
   /* will assign value to value */
   /* depending on where it is ofcourse */
   switch (aop->type)
     {
   s = buffer2;
 
   /* will assign value to value */
   /* depending on where it is ofcourse */
   switch (aop->type)
     {
+    case AOP_DUMMY:
+      _moveA (s);  /* in case s is volatile */
+      break;
+      
     case AOP_DIR:
       /* Direct.  Hmmm. */
       wassert (IS_GB);
     case AOP_DIR:
       /* Direct.  Hmmm. */
       wassert (IS_GB);
@@ -1518,10 +1878,49 @@ aopPut (asmop * aop, const char *s, int offset)
       break;
 
     case AOP_SFR:
       break;
 
     case AOP_SFR:
-      wassert (IS_GB);
-      if (strcmp (s, "a"))
-       emit2 ("ld a,%s", s);
-      emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
+      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);
+      }
+      else
+      { /*.p.t.20030716 handling for i/o port read access for Z80 */
+        if( aop->paged )
+        { /* banked mode */
+          if( aop->bcInUse )  emit2( "push bc" );
+
+          emit2( "ld bc,#%s", aop->aopu.aop_dir );
+
+          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"    );
+          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 );
+        }
+      }
       break;
 
     case AOP_REG:
       break;
 
     case AOP_REG:
@@ -1530,6 +1929,7 @@ aopPut (asmop * aop, const char *s, int offset)
       else
        emit2 ("ld %s,%s",
               aop->aopu.aop_reg[offset]->name, s);
       else
        emit2 ("ld %s,%s",
               aop->aopu.aop_reg[offset]->name, s);
+      spillPairReg(aop->aopu.aop_reg[offset]->name);
       break;
 
     case AOP_IY:
       break;
 
     case AOP_IY:
@@ -1613,7 +2013,7 @@ aopPut (asmop * aop, const char *s, int offset)
       /* if bit variable */
       if (!aop->aopu.aop_dir)
        {
       /* if bit variable */
       if (!aop->aopu.aop_dir)
        {
-         emit2 ("ld a,#0");
+         emit2 ("ld a,!zero");
          emit2 ("rla");
        }
       else
          emit2 ("rla");
        }
       else
@@ -1629,6 +2029,7 @@ aopPut (asmop * aop, const char *s, int offset)
        {
          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:
       break;
 
     case AOP_ACC:
@@ -1642,18 +2043,27 @@ aopPut (asmop * aop, const char *s, int offset)
       else
        {
          if (strcmp (aop->aopu.aop_str[offset], s))
       else
        {
          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_HLREG:
       wassert (offset < 2);
       emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
        }
       break;
 
     case AOP_HLREG:
       wassert (offset < 2);
       emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
+      spillPairReg(aop->aopu.aop_str[offset]);
       break;
 
     case AOP_PAIRPTR:
       setupPair (aop->aopu.aop_pairId, aop, offset);
       break;
 
     case AOP_PAIRPTR:
       setupPair (aop->aopu.aop_pairId, aop, offset);
-      emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s);
+      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);
+      else
+        emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s);
       break;
 
     default:
       break;
 
     default:
@@ -1666,7 +2076,7 @@ aopPut (asmop * aop, const char *s, int offset)
 #define AOP(op) op->aop
 #define AOP_TYPE(op) AOP(op)->type
 #define AOP_SIZE(op) AOP(op)->size
 #define AOP(op) op->aop
 #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))
+#define AOP_NEEDSACC(x) (AOP(x) && ((AOP_TYPE(x) == AOP_CRY) || (AOP_TYPE(x) == AOP_SFR)))
 
 static void
 commitPair (asmop * aop, PAIR_ID id)
 
 static void
 commitPair (asmop * aop, PAIR_ID id)
@@ -1760,6 +2170,7 @@ 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");
           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);
         }
       else if ( getPairId ( AOP (result)) == PAIR_IY)
         {
         }
       else if ( getPairId ( AOP (result)) == PAIR_IY)
         {
@@ -1854,43 +2265,6 @@ _toBoolean (operand * oper)
     }
 }
 
     }
 }
 
-/*-----------------------------------------------------------------*/
-/* genNotFloat - generates not for float operations              */
-/*-----------------------------------------------------------------*/
-static void
-genNotFloat (operand * op, operand * res)
-{
-  int size, offset;
-  symbol *tlbl;
-
-  emitDebug ("; genNotFloat");
-
-  /* we will put 127 in the first byte of
-     the result */
-  aopPut (AOP (res), "!immedbyte", 0x7F);
-  size = AOP_SIZE (op) - 1;
-  offset = 1;
-
-  _moveA (aopGet (op->aop, offset++, FALSE));
-
-  while (size--)
-    {
-      emit2 ("or a,%s", aopGet (op->aop, offset++, FALSE));
-    }
-
-  tlbl = newiTempLabel (NULL);
-  aopPut (res->aop, "!one", 1);
-  emit2 ("!shortjp z !tlabel", tlbl->key + 100);
-  aopPut (res->aop, "!zero", 1);
-
-  emitLabel(tlbl->key + 100);
-
-  size = res->aop->size - 2;
-  offset = 2;
-  /* put zeros in the rest */
-  while (size--)
-    aopPut (res->aop, "!zero", offset++);
-}
 
 /*-----------------------------------------------------------------*/
 /* genNot - generate code for ! operation                          */
 
 /*-----------------------------------------------------------------*/
 /* genNot - generate code for ! operation                          */
@@ -1898,7 +2272,6 @@ genNotFloat (operand * op, operand * res)
 static void
 genNot (iCode * ic)
 {
 static void
 genNot (iCode * ic)
 {
-  sym_link *optype = operandType (IC_LEFT (ic));
 
   /* assign asmOps to operand & result */
   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
 
   /* assign asmOps to operand & result */
   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
@@ -1910,13 +2283,6 @@ genNot (iCode * ic)
       wassertl (0, "Tried to negate a bit");
     }
 
       wassertl (0, "Tried to negate a bit");
     }
 
-  /* if type float then do float */
-  if (IS_FLOAT (optype))
-    {
-      genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
-      goto release;
-    }
-
   _toBoolean (IC_LEFT (ic));
 
   /* Not of A:
   _toBoolean (IC_LEFT (ic));
 
   /* Not of A:
@@ -1926,7 +2292,6 @@ genNot (iCode * ic)
   emit2 ("sub a,!one");
   outBitC (IC_RESULT (ic));
 
   emit2 ("sub a,!one");
   outBitC (IC_RESULT (ic));
 
- release:
   /* release the aops */
   freeAsmop (IC_LEFT (ic), NULL, ic);
   freeAsmop (IC_RESULT (ic), NULL, ic);
   /* release the aops */
   freeAsmop (IC_LEFT (ic), NULL, ic);
   freeAsmop (IC_RESULT (ic), NULL, ic);
@@ -2001,7 +2366,7 @@ _gbz80_emitAddSubLongLong (iCode *ic, asmop *left, asmop *right, bool isAdd)
   aopPut ( AOP (IC_RESULT (ic)), "a", MSB16);
   aopPut ( AOP (IC_RESULT (ic)), "e", LSB);
 
   aopPut ( AOP (IC_RESULT (ic)), "a", MSB16);
   aopPut ( AOP (IC_RESULT (ic)), "e", LSB);
 
-  fetchPairLong (PAIR_DE, left, MSB24);
+  fetchPairLong (PAIR_DE, left, NULL, MSB24);
   aopGet (right, MSB24, FALSE);
 
   _pop (PAIR_AF);
   aopGet (right, MSB24, FALSE);
 
   _pop (PAIR_AF);
@@ -2198,7 +2563,8 @@ _saveRegsForCall(iCode *ic, int sendSetSize)
     bool bcInRet = FALSE, deInRet = FALSE;
     bitVect *rInUse;
 
     bool bcInRet = FALSE, deInRet = FALSE;
     bitVect *rInUse;
 
-    rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
+    rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), 
+                            z80_rUmaskForOp (IC_RESULT(ic)));
 
     deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
     bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
 
     deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
     bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
@@ -2290,11 +2656,11 @@ genIpush (iCode * ic)
        }
       if (size == 4)
        {
        }
       if (size == 4)
        {
-         fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
+         fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
          emit2 ("push hl");
          spillPair (PAIR_HL);
          _G.stack.pushed += 2;
          emit2 ("push hl");
          spillPair (PAIR_HL);
          _G.stack.pushed += 2;
-         fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
+         fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 0);
          emit2 ("push hl");
          spillPair (PAIR_HL);
          _G.stack.pushed += 2;
          emit2 ("push hl");
          spillPair (PAIR_HL);
          _G.stack.pushed += 2;
@@ -2433,10 +2799,9 @@ _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
 static void
 emitCall (iCode * ic, bool ispcall)
 {
 static void
 emitCall (iCode * ic, bool ispcall)
 {
+  bool bInRet, cInRet, dInRet, eInRet;
   sym_link *dtype = operandType (IC_LEFT (ic));
 
   sym_link *dtype = operandType (IC_LEFT (ic));
 
-  bitVect *rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
-
   /* if caller saves & we have not saved then */
   if (!ic->regsSaved)
     {
   /* if caller saves & we have not saved then */
   if (!ic->regsSaved)
     {
@@ -2581,77 +2946,92 @@ emitCall (iCode * ic, bool ispcall)
       else
        {
          spillCached ();
       else
        {
          spillCached ();
-         if (i > 6)
+         if (i > 8)
            {
            {
-             emit2 ("ld hl,#%d", i);
-             emit2 ("add hl,sp");
-             emit2 ("ld sp,hl");
+             emit2 ("ld iy,!immedword", i);
+             emit2 ("add iy,sp");
+             emit2 ("ld sp,iy");
            }
          else
            {
              while (i > 1)
                {
            }
          else
            {
              while (i > 1)
                {
-                 emit2 ("pop hl");
+                 emit2 ("pop af");
                  i -= 2;
                }
              if (i)
                  i -= 2;
                }
              if (i)
-               emit2 ("inc sp");
+                {
+                  emit2 ("inc sp");
+                }
            }
        }
     }
 
   spillCached ();
            }
        }
     }
 
   spillCached ();
-
-  if (_G.stack.pushedDE) 
+  if (IC_RESULT (ic))
+    {
+      bitVect *result = z80_rUmaskForOp (IC_RESULT (ic));
+      bInRet = bitVectBitValue(result, B_IDX);
+      cInRet = bitVectBitValue(result, C_IDX);
+      dInRet = bitVectBitValue(result, D_IDX);
+      eInRet = bitVectBitValue(result, E_IDX);
+    }
+  else
     {
     {
-      bool dInUse = bitVectBitValue(rInUse, D_IDX);
-      bool eInUse = bitVectBitValue(rInUse, E_IDX);
+      bInRet = FALSE;
+      cInRet = FALSE;
+      dInRet = FALSE;
+      eInRet = FALSE;
+    }
 
 
-      if (dInUse && eInUse) 
+  if (_G.stack.pushedDE) 
+    {
+      if (dInRet && eInRet)
         {
         {
-          _pop (PAIR_DE);
+          wassertl (0, "Shouldn't push DE if it's wiped out by the return");
         }
         }
-      else if (dInUse)
+      else if (dInRet)
         {
         {
-          _pop(PAIR_HL);
-          emit2 ("ld d,h");
+          /* Only restore E */
+          emit2 ("ld a,d");
+          _pop (PAIR_DE);
+          emit2 ("ld d,a");
         }
         }
-      else if (eInUse)
+      else if (eInRet)
         {
         {
-          _pop(PAIR_HL);
-          emit2 ("ld e,l");
+          /* Only restore D */
+          _pop (PAIR_AF);
+          emit2 ("ld d,a");
         }
       else
         {
         }
       else
         {
-          wassertl (0, "Neither D or E were in use but it was pushed.");
+          _pop (PAIR_DE);
         }
       _G.stack.pushedDE = FALSE;
     }
   
   if (_G.stack.pushedBC) 
     {
         }
       _G.stack.pushedDE = FALSE;
     }
   
   if (_G.stack.pushedBC) 
     {
-      bool bInUse = bitVectBitValue(rInUse, B_IDX);
-      bool cInUse = bitVectBitValue(rInUse, C_IDX);
-
-      // If both B and C are used in the return value, then we won't get
-      // here.
-      if (bInUse && cInUse) 
+      if (bInRet && cInRet)
         {
         {
-          _pop (PAIR_BC);
+          wassertl (0, "Shouldn't push BC if it's wiped out by the return");
         }
         }
-      else if (bInUse)
+      else if (bInRet)
         {
         {
-          _pop(PAIR_HL);
-          emit2 ("ld b,h");
+          /* Only restore C */
+          emit2 ("ld a,b");
+          _pop (PAIR_BC);
+          emit2 ("ld b,a");
         }
         }
-      else if (cInUse)
+      else if (cInRet)
         {
         {
-          _pop(PAIR_HL);
-          emit2 ("ld c,l");
+          /* Only restore B */
+          _pop (PAIR_AF);
+          emit2 ("ld b,a");
         }
       else
         {
         }
       else
         {
-          wassertl (0, "Neither B or C were in use but it was pushed.");
+          _pop (PAIR_BC);
         }
       _G.stack.pushedBC = FALSE;
     }
         }
       _G.stack.pushedBC = FALSE;
     }
@@ -2702,13 +3082,13 @@ extern set *publics;
 static void
 genFunction (iCode * ic)
 {
 static void
 genFunction (iCode * ic)
 {
+  bool stackParm;
+  
   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
   sym_link *ftype;
 
   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
   sym_link *ftype;
 
-#if CALLEE_SAVES
   bool bcInUse = FALSE;
   bool deInUse = FALSE;
   bool bcInUse = FALSE;
   bool deInUse = FALSE;
-#endif
 
   setArea (IFFUNC_NONBANKED (sym->type));
 
 
   setArea (IFFUNC_NONBANKED (sym->type));
 
@@ -2722,8 +3102,8 @@ genFunction (iCode * ic)
   
   /* Create the function header */
   emit2 ("!functionheader", sym->name);
   
   /* Create the function header */
   emit2 ("!functionheader", sym->name);
-  /* PENDING: portability. */
-  emit2 ("__%s_start:", sym->rname);
+  sprintf (buffer, "%s_start", sym->rname);
+  emit2 ("!labeldef", buffer);
   emit2 ("!functionlabeldef", sym->rname);
 
   if (options.profile) 
   emit2 ("!functionlabeldef", sym->rname);
 
   if (options.profile) 
@@ -2747,9 +3127,13 @@ genFunction (iCode * ic)
 
   _G.stack.param_offset = 0;
 
 
   _G.stack.param_offset = 0;
 
-#if CALLEE_SAVES
+  if (z80_opts.calleeSavesBC)
+    {
+      bcInUse = TRUE;
+    }
+
   /* Detect which registers are used. */
   /* Detect which registers are used. */
-  if (sym->regsUsed)
+  if (IFFUNC_CALLEESAVES(sym->type) && sym->regsUsed)
     {
       int i;
       for (i = 0; i < sym->regsUsed->size; i++)
     {
       int i;
       for (i = 0; i < sym->regsUsed->size; i++)
@@ -2782,7 +3166,7 @@ genFunction (iCode * ic)
       _G.stack.param_offset += 2;
     }
 
       _G.stack.param_offset += 2;
     }
 
-  _G.stack.pushedBC = bcInUse;
+  _G.calleeSaves.pushedBC = bcInUse;
 
   if (deInUse)
     {
 
   if (deInUse)
     {
@@ -2790,18 +3174,39 @@ genFunction (iCode * ic)
       _G.stack.param_offset += 2;
     }
 
       _G.stack.param_offset += 2;
     }
 
-  _G.stack.pushedDE = deInUse;
-#endif
+  _G.calleeSaves.pushedDE = deInUse;
 
   /* adjust the stack for the function */
   _G.stack.last = sym->stack;
 
   /* adjust the stack for the function */
   _G.stack.last = sym->stack;
-
-  if (sym->stack && IS_GB && sym->stack > -INT8MIN)
+  
+  stackParm = FALSE;
+  for (sym = setFirstItem (istack->syms); sym;
+       sym = setNextItem (istack->syms))
+    {
+      if (sym->_isparm && !IS_REGPARM (sym->etype))
+        {
+          stackParm = TRUE;
+          break;
+        }
+    }
+  sym = OP_SYMBOL (IC_LEFT (ic));
+  
+  _G.omitFramePtr = options.ommitFramePtr;
+  if (IS_Z80 && !stackParm && !sym->stack)
+    {
+      /* When the conflicts between AOP_EXSTK && AOP_HLREG are fixed, */
+      /* the above !sym->stack condition can be removed. -- EEP       */
+      if (sym->stack)
+        emit2 ("!ldaspsp", -sym->stack);
+      _G.omitFramePtr = TRUE;
+    }
+  else if (sym->stack && IS_GB && sym->stack > -INT8MIN)
     emit2 ("!enterxl", sym->stack);
   else if (sym->stack)
     emit2 ("!enterx", sym->stack);
     emit2 ("!enterxl", sym->stack);
   else if (sym->stack)
     emit2 ("!enterx", sym->stack);
-  else
+  else if( !FUNC_ISNAKED( sym->type )) /*.p.t.20030716 - now supporting Naked funcitons */
     emit2 ("!enter");
     emit2 ("!enter");
+
   _G.stack.offset = sym->stack;
 }
 
   _G.stack.offset = sym->stack;
 }
 
@@ -2824,7 +3229,12 @@ genEndFunction (iCode * ic)
 
       /* PENDING: calleeSave */
 
 
       /* PENDING: calleeSave */
 
-      if (_G.stack.offset && IS_GB && _G.stack.offset > INT8MAX)
+      if (IS_Z80 && _G.omitFramePtr)
+        {
+          if (_G.stack.offset)
+            emit2 ("!ldaspsp", _G.stack.offset);
+        }
+      else if (_G.stack.offset && IS_GB && _G.stack.offset > INT8MAX)
         {
           emit2 ("!leavexl", _G.stack.offset);
         }
         {
           emit2 ("!leavexl", _G.stack.offset);
         }
@@ -2832,24 +3242,22 @@ genEndFunction (iCode * ic)
         {
           emit2 ("!leavex", _G.stack.offset);
         }
         {
           emit2 ("!leavex", _G.stack.offset);
         }
-      else
+      else if( !FUNC_ISNAKED( sym->type )) /*.p.t.20030716 - now supporting Naked funcitons */
         {
           emit2 ("!leave");
         }
 
         {
           emit2 ("!leave");
         }
 
-#if CALLEE_SAVES
-      if (_G.stack.pushedDE) 
+      if (_G.calleeSaves.pushedDE) 
         {
           emit2 ("pop de");
         {
           emit2 ("pop de");
-          _G.stack.pushedDE = FALSE;
+          _G.calleeSaves.pushedDE = FALSE;
         }
 
         }
 
-      if (_G.stack.pushedDE
+      if (_G.calleeSaves.pushedBC
         {
           emit2 ("pop bc");
         {
           emit2 ("pop bc");
-          _G.stack.pushedDE = FALSE;
+          _G.calleeSaves.pushedBC = FALSE;
         }
         }
-#endif
 
       if (options.profile) 
         {
 
       if (options.profile) 
         {
@@ -2857,11 +3265,16 @@ genEndFunction (iCode * ic)
         }
 
 
         }
 
 
-      /* Both baned and non-banked just ret */
+      if (options.debug && currFunc)
+       {
+         debugFile->writeEndFunction (currFunc, ic, 1);
+       }
+      
+      /* Both banked and non-banked just ret */
       emit2 ("ret");
 
       emit2 ("ret");
 
-      /* PENDING: portability. */
-      emit2 ("__%s_end:", sym->rname);
+      sprintf (buffer, "%s_end", sym->rname);
+      emit2 ("!labeldef", buffer);
     }
   _G.flushStatics = 1;
   _G.stack.pushed = 0;
     }
   _G.flushStatics = 1;
   _G.stack.pushed = 0;
@@ -2889,6 +3302,9 @@ genRet (iCode * ic)
   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
   size = AOP_SIZE (IC_LEFT (ic));
 
   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
   size = AOP_SIZE (IC_LEFT (ic));
 
+  aopDump("IC_LEFT", AOP(IC_LEFT(ic)));
+
+  #if 0  
   if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
     {
       if (IS_GB)
   if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
     {
       if (IS_GB)
@@ -2900,12 +3316,17 @@ genRet (iCode * ic)
          emit2 ("ld hl,%s", l);
        }
     }
          emit2 ("ld hl,%s", l);
        }
     }
+  #endif
+  if (size==2)
+    {
+      fetchPair(IS_GB ? PAIR_DE : PAIR_HL, AOP (IC_LEFT (ic)));
+    }
   else
     {
       if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
        {
          fetchPair (PAIR_DE, AOP (IC_LEFT (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)), 2);
+         fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
        }
       else
        {
        }
       else
        {
@@ -2914,7 +3335,8 @@ genRet (iCode * ic)
              l = aopGet (AOP (IC_LEFT (ic)), offset,
                          FALSE);
              if (strcmp (_fReturn[offset], l))
              l = aopGet (AOP (IC_LEFT (ic)), offset,
                          FALSE);
              if (strcmp (_fReturn[offset], l))
-               emit2 ("ld %s,%s", _fReturn[offset++], l);
+               emit2 ("ld %s,%s", _fReturn[offset], l);
+              offset++;
            }
        }
     }
            }
        }
     }
@@ -3163,11 +3585,16 @@ setupToPreserveCarry (asmop *result, asmop *left, asmop *right)
       if (couldDestroyCarry (right) && couldDestroyCarry (result))
         {
           shiftIntoPair (0, right);
       if (couldDestroyCarry (right) && couldDestroyCarry (result))
         {
           shiftIntoPair (0, right);
-          shiftIntoPair (1, result);
+          /* check result again, in case right == result */
+          if (couldDestroyCarry (result))
+            shiftIntoPair (1, result);
         }
       else if (couldDestroyCarry (right))
         {
         }
       else if (couldDestroyCarry (right))
         {
-          shiftIntoPair (0, right);
+          if (getPairId (result) == PAIR_HL)
+            _G.preserveCarry = TRUE;
+          else
+            shiftIntoPair (0, right);
         }
       else if (couldDestroyCarry (result))
         {
         }
       else if (couldDestroyCarry (result))
         {
@@ -3201,7 +3628,7 @@ genPlus (iCode * ic)
      in ACC */
 
   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
      in ACC */
 
   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
-      (AOP_NEEDSACC (IC_LEFT (ic))) ||
+      (AOP_NEEDSACC (IC_RIGHT (ic))) ||
       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
     {
       operand *t = IC_RIGHT (ic);
       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
     {
       operand *t = IC_RIGHT (ic);
@@ -3293,7 +3720,7 @@ genPlus (iCode * ic)
   if (isPair (AOP (IC_RIGHT (ic))) && AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD && getPairId (AOP (IC_RIGHT (ic))) != PAIR_HL)
     {
       fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
   if (isPair (AOP (IC_RIGHT (ic))) && AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD && getPairId (AOP (IC_RIGHT (ic))) != PAIR_HL)
     {
       fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
-      emit2 ("add hl,%s ; 2", getPairName (AOP (IC_RIGHT (ic))));
+      emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
       spillCached();
       commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
       goto release;
       spillCached();
       commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
       goto release;
@@ -3369,7 +3796,7 @@ genPlus (iCode * ic)
           goto release;
         }
     }
           goto release;
         }
     }
-
+  
   setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
 
   while (size--)
   setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
 
   while (size--)
@@ -3398,6 +3825,7 @@ genPlus (iCode * ic)
     }
 
 release:
     }
 
 release:
+  _G.preserveCarry = FALSE;
   freeAsmop (IC_LEFT (ic), NULL, ic);
   freeAsmop (IC_RIGHT (ic), NULL, ic);
   freeAsmop (IC_RESULT (ic), NULL, ic);
   freeAsmop (IC_LEFT (ic), NULL, ic);
   freeAsmop (IC_RIGHT (ic), NULL, ic);
   freeAsmop (IC_RESULT (ic), NULL, ic);
@@ -3601,6 +4029,7 @@ genMinus (iCode * ic)
     }
 
 release:
     }
 
 release:
+  _G.preserveCarry = FALSE;
   freeAsmop (IC_LEFT (ic), NULL, ic);
   freeAsmop (IC_RIGHT (ic), NULL, ic);
   freeAsmop (IC_RESULT (ic), NULL, ic);
   freeAsmop (IC_LEFT (ic), NULL, ic);
   freeAsmop (IC_RIGHT (ic), NULL, ic);
   freeAsmop (IC_RESULT (ic), NULL, ic);
@@ -3616,11 +4045,14 @@ genMult (iCode * ic)
   int count, i;
   /* If true then the final operation should be a subtract */
   bool active = FALSE;
   int count, i;
   /* If true then the final operation should be a subtract */
   bool active = FALSE;
+  bool byteResult;
 
   /* Shouldn't occur - all done through function calls */
   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
   aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
 
   /* Shouldn't occur - all done through function calls */
   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 ||
       AOP_SIZE (IC_RIGHT (ic)) > 2 ||
 
   if (AOP_SIZE (IC_LEFT (ic)) > 2 ||
       AOP_SIZE (IC_RIGHT (ic)) > 2 ||
@@ -3643,17 +4075,21 @@ genMult (iCode * ic)
   //  wassertl (val > 0, "Multiply must be positive");
   wassertl (val != 1, "Can't multiply by 1");
 
   //  wassertl (val > 0, "Multiply must be positive");
   wassertl (val != 1, "Can't multiply by 1");
 
-  if (IS_Z80) {
+  if (IS_Z80 && isPairInUseNotInRet (PAIR_DE, ic)) {
     _push (PAIR_DE);
     _push (PAIR_DE);
+    _G.stack.pushedDE = TRUE;
   }
 
   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 ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic)))))
     {
       emit2 ("ld e,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE));
-      emit2 ("ld a,e");
-      emit2 ("rlc a");
-      emit2 ("sbc a,a");
-      emit2 ("ld d,a");
+      if (!byteResult)
+        {
+          emit2 ("ld a,e");
+          emit2 ("rlc a");
+          emit2 ("sbc a,a");
+          emit2 ("ld d,a");
+       }
     }
   else
     {
     }
   else
     {
@@ -3675,7 +4111,8 @@ genMult (iCode * ic)
           if (active == FALSE)
             {
               emit2 ("ld l,e");
           if (active == FALSE)
             {
               emit2 ("ld l,e");
-              emit2 ("ld h,d");
+              if (!byteResult)
+               emit2 ("ld h,d");
             }
           else
             {
             }
           else
             {
@@ -3688,12 +4125,16 @@ genMult (iCode * ic)
 
   spillCached();
 
 
   spillCached();
 
-  if (IS_Z80)
+  if (IS_Z80 && _G.stack.pushedDE)
     {
       _pop (PAIR_DE);
     {
       _pop (PAIR_DE);
+      _G.stack.pushedDE = FALSE;
     }
 
     }
 
-  commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
+  if (byteResult)
+    aopPut (AOP (IC_RESULT (ic)), _pairs[PAIR_HL].l, 0);
+  else
+    commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
 
   freeAsmop (IC_LEFT (ic), NULL, ic);
   freeAsmop (IC_RIGHT (ic), NULL, ic);
 
   freeAsmop (IC_LEFT (ic), NULL, ic);
   freeAsmop (IC_RIGHT (ic), NULL, ic);
@@ -3856,10 +4297,10 @@ _getPairIdName (PAIR_ID id)
                   // Save the flags
                   emit2 ("push af");
                   emit2 ("ld a,(de)");
                   // Save the flags
                   emit2 ("push af");
                   emit2 ("ld a,(de)");
-                  emit2 ("xor #0x80");
+                  emit2 ("xor !immedbyte", 0x80);
                   emit2 ("ld e,a");
                   emit2 ("ld a,(hl)");
                   emit2 ("ld e,a");
                   emit2 ("ld a,(hl)");
-                  emit2 ("xor #0x80");
+                  emit2 ("xor !immedbyte", 0x80);
                   emit2 ("ld d,a");
                   emit2 ("pop af");
                   emit2 ("ld a,e");
                   emit2 ("ld d,a");
                   emit2 ("pop af");
                   emit2 ("ld a,e");
@@ -3893,10 +4334,10 @@ _getPairIdName (PAIR_ID id)
                   // Save the flags
                   emit2 ("push af");
                   emit2 ("ld a,(hl)");
                   // Save the flags
                   emit2 ("push af");
                   emit2 ("ld a,(hl)");
-                  emit2 ("xor #0x80");
+                  emit2 ("xor !immedbyte", 0x80);
                   emit2 ("ld l,a");
                   emit2 ("ld a,%d(iy)", offset);
                   emit2 ("ld l,a");
                   emit2 ("ld a,%d(iy)", offset);
-                  emit2 ("xor #0x80");
+                  emit2 ("xor !immedbyte", 0x80);
                   emit2 ("ld h,a");
                   emit2 ("pop af");
                   emit2 ("ld a,l");
                   emit2 ("ld h,a");
                   emit2 ("pop af");
                   emit2 ("ld a,l");
@@ -4220,7 +4661,9 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
     }
 
   if (AOP_TYPE (right) == AOP_LIT)
     }
 
   if (AOP_TYPE (right) == AOP_LIT)
-    lit = (unsigned long) floatFromVal (AOP (right)->aopu.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 &&
 
   /* if the right side is a literal then anything goes */
   if (AOP_TYPE (right) == AOP_LIT &&
@@ -4345,11 +4788,9 @@ genCmpEq (iCode * ic, iCode * ifx)
       else
        {
          tlbl = newiTempLabel (NULL);
       else
        {
          tlbl = newiTempLabel (NULL);
-          emitDebug(";1");
          gencjneshort (left, right, tlbl);
          if (IC_TRUE (ifx))
            {
          gencjneshort (left, right, tlbl);
          if (IC_TRUE (ifx))
            {
-              emitDebug(";2");
              emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
              emitLabel (tlbl->key + 100);
            }
              emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
              emitLabel (tlbl->key + 100);
            }
@@ -4357,7 +4798,6 @@ genCmpEq (iCode * ic, iCode * ifx)
            {
              /* PENDING: do this better */
              symbol *lbl = newiTempLabel (NULL);
            {
              /* PENDING: do this better */
              symbol *lbl = newiTempLabel (NULL);
-              emitDebug(";3");
              emit2 ("!shortjp !tlabel", lbl->key + 100);
              emitLabel (tlbl->key + 100);
              emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
              emit2 ("!shortjp !tlabel", lbl->key + 100);
              emitLabel (tlbl->key + 100);
              emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
@@ -4564,7 +5004,7 @@ genAnd (iCode * ic, iCode * ifx)
 
   /* if left is a literal & right is not then exchange them */
   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
 
   /* if left is a literal & right is not then exchange them */
   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
-      AOP_NEEDSACC (left))
+      (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
     {
       operand *tmp = right;
       right = left;
     {
       operand *tmp = right;
       right = left;
@@ -4754,7 +5194,7 @@ genOr (iCode * ic, iCode * ifx)
 
   /* if left is a literal & right is not then exchange them */
   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
 
   /* if left is a literal & right is not then exchange them */
   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
-      AOP_NEEDSACC (left))
+      (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
     {
       operand *tmp = right;
       right = left;
     {
       operand *tmp = right;
       right = left;
@@ -4912,7 +5352,7 @@ genXor (iCode * ic, iCode * ifx)
 
   /* if left is a literal & right is not then exchange them */
   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
 
   /* if left is a literal & right is not then exchange them */
   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
-      AOP_NEEDSACC (left))
+      (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
     {
       operand *tmp = right;
       right = left;
     {
       operand *tmp = right;
       right = left;
@@ -4989,9 +5429,9 @@ genXor (iCode * ic, iCode * ifx)
                continue;
              else
                {
                continue;
              else
                {
-                 _moveA (aopGet (AOP (right), offset, FALSE));
+                 _moveA (aopGet (AOP (left), offset, FALSE));
                  emit2 ("xor a,%s",
                  emit2 ("xor a,%s",
-                           aopGet (AOP (left), offset, FALSE));
+                           aopGet (AOP (right), offset, FALSE));
                  aopPut (AOP (result), "a", offset);
                }
            }
                  aopPut (AOP (result), "a", offset);
                }
            }
@@ -5003,10 +5443,10 @@ genXor (iCode * ic, iCode * ifx)
                 }
              else
                {
                 }
              else
                {
-                 _moveA (aopGet (AOP (right), offset, FALSE));
+                 _moveA (aopGet (AOP (left), offset, FALSE));
                  emit2 ("xor a,%s",
                  emit2 ("xor a,%s",
-                           aopGet (AOP (left), offset, FALSE));
-                 aopPut (AOP (result), "a", 0);
+                           aopGet (AOP (right), offset, FALSE));
+                 aopPut (AOP (result), "a", offset);
                }
            }
        }
                }
            }
        }
@@ -5041,9 +5481,9 @@ genXor (iCode * ic, iCode * ifx)
               }
            else
              {
               }
            else
              {
-               _moveA (aopGet (AOP (right), offset, FALSE));
+               _moveA (aopGet (AOP (left), offset, FALSE));
                emit2 ("xor a,%s",
                emit2 ("xor a,%s",
-                         aopGet (AOP (left), offset, FALSE));
+                         aopGet (AOP (right), offset, FALSE));
              }
            aopPut (AOP (result), "a", offset);
          }
              }
            aopPut (AOP (result), "a", offset);
          }
@@ -5124,6 +5564,7 @@ genGetHbit (iCode * ic)
   operand *left, *result;
   left = IC_LEFT (ic);
   result = IC_RESULT (ic);
   operand *left, *result;
   left = IC_LEFT (ic);
   result = IC_RESULT (ic);
+
   aopOp (left, ic, FALSE, FALSE);
   aopOp (result, ic, FALSE, FALSE);
 
   aopOp (left, ic, FALSE, FALSE);
   aopOp (result, ic, FALSE, FALSE);
 
@@ -5138,8 +5579,7 @@ genGetHbit (iCode * ic)
   else
     {
       emit2 ("rlc a");
   else
     {
       emit2 ("rlc a");
-      /* PENDING: For re-target. */
-      emit2 ("and a,#1");
+      emit2 ("and a,!one");
       outAcc (result);
     }
 
       outAcc (result);
     }
 
@@ -5227,9 +5667,16 @@ shiftL2Left2Result (operand * left, int offl,
       movLeft2Result (left, offl, result, offr, 0);
       movLeft2Result (left, offl + 1, result, offr + 1, 0);
     }
       movLeft2Result (left, offl, result, offr, 0);
       movLeft2Result (left, offl + 1, result, offr + 1, 0);
     }
-  /* PENDING: for now just see if it'll work. */
-  /*if (AOP(result)->type == AOP_REG) { */
-  {
+
+  if (getPairId (AOP (result)) == PAIR_HL)
+    {
+      while (shCount--)
+       {
+         emit2 ("add hl,hl");
+       }
+    }
+  else
+    {
     int size = 2;
     int offset = 0;
     symbol *tlbl, *tlbl1;
     int size = 2;
     int offset = 0;
     symbol *tlbl, *tlbl1;
@@ -5238,34 +5685,56 @@ shiftL2Left2Result (operand * left, int offl,
     tlbl = newiTempLabel (NULL);
     tlbl1 = newiTempLabel (NULL);
 
     tlbl = newiTempLabel (NULL);
     tlbl1 = newiTempLabel (NULL);
 
-    /* Left is already in result - so now do the shift */
-    if (shCount > 1)
+    if (AOP (result)->type == AOP_REG)
       {
       {
-       emit2 ("ld a,!immedbyte+1", shCount);
-       emit2 ("!shortjp !tlabel", tlbl1->key + 100);
-       emitLabel (tlbl->key + 100);
+       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 (size--)
+    else
       {
       {
-       l = aopGet (AOP (result), offset, FALSE);
-
-        if (offset == 0)
-          {
-            emit2 ("sla %s", l);
-          }
-        else
-          {
-            emit2 ("rl %s", l);
-          }
+       /* 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);
+         }
 
 
-        offset++;
-      }
-    if (shCount > 1)
-      {
-       emitLabel (tlbl1->key + 100);
-       emit2 ("dec a");
-       emit2 ("!shortjp nz,!tlabel", 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);
+         }
       }
   }
 }
       }
   }
 }
@@ -5278,6 +5747,7 @@ AccRol (int shCount)
 {
   shCount &= 0x0007;           // shCount : 0..7
 
 {
   shCount &= 0x0007;           // shCount : 0..7
 
+#if 0
   switch (shCount)
     {
     case 0:
   switch (shCount)
     {
     case 0:
@@ -5313,6 +5783,43 @@ AccRol (int shCount)
       emit2 ("srl a");
       break;
     }
       emit2 ("srl a");
       break;
     }
+#else
+  switch (shCount)
+    {
+    case 0:
+      break;
+    case 1:
+      emit2 ("rlca");
+      break;
+    case 2:
+      emit2 ("rlca");
+      emit2 ("rlca");
+      break;
+    case 3:
+      emit2 ("rlca");
+      emit2 ("rlca");
+      emit2 ("rlca");
+      break;
+    case 4:
+      emit2 ("rlca");
+      emit2 ("rlca");
+      emit2 ("rlca");
+      emit2 ("rlca");
+      break;
+    case 5:
+      emit2 ("rrca");
+      emit2 ("rrca");
+      emit2 ("rrca");
+      break;
+    case 6:
+      emit2 ("rrca");
+      emit2 ("rrca");
+      break;
+    case 7:
+      emit2 ("rrca");
+      break;
+    }
+#endif
 }
 
 /*-----------------------------------------------------------------*/
 }
 
 /*-----------------------------------------------------------------*/
@@ -5699,9 +6206,19 @@ genRightShiftLiteral (operand * left,
       wassert (0);
     }
 
       wassert (0);
     }
 
-  else if (shCount >= (size * 8))
+  else if (shCount >= (size * 8)) {
+    const char *s;
+    if (!SPEC_USIGN(getSpec(operandType(left)))) {
+      _moveA(aopGet (AOP (left), 0, FALSE));
+      emit2 ("rlc a");
+      emit2 ("sbc a,a");
+      s=ACC_NAME;
+    } else {
+      s="!zero";
+    }
     while (size--)
     while (size--)
-      aopPut (AOP (result), "!zero", size);
+      aopPut (AOP (result), s, size);
+  }
   else
     {
       switch (size)
   else
     {
       switch (size)
@@ -5764,13 +6281,16 @@ genRightShift (iCode * ic)
       return;
     }
 
       return;
     }
 
+  emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
+  emit2 ("inc a");
+  freeAsmop (right, NULL, ic);
+
   aopOp (left, ic, FALSE, FALSE);
   aopOp (result, ic, FALSE, FALSE);
 
   /* now move the left to the result if they are not the
      same */
   aopOp (left, ic, FALSE, FALSE);
   aopOp (result, ic, FALSE, FALSE);
 
   /* now move the left to the result if they are not the
      same */
-  if (!sameRegs (AOP (left), AOP (result)) &&
-      AOP_SIZE (result) > 1)
+  if (!sameRegs (AOP (left), AOP (result)))
     {
 
       size = AOP_SIZE (result);
     {
 
       size = AOP_SIZE (result);
@@ -5783,10 +6303,6 @@ genRightShift (iCode * ic)
        }
     }
 
        }
     }
 
-  emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
-  emit2 ("inc a");
-  freeAsmop (right, NULL, ic);
-
   tlbl = newiTempLabel (NULL);
   tlbl1 = newiTempLabel (NULL);
   size = AOP_SIZE (result);
   tlbl = newiTempLabel (NULL);
   tlbl1 = newiTempLabel (NULL);
   size = AOP_SIZE (result);
@@ -5815,6 +6331,82 @@ genRightShift (iCode * ic)
   freeAsmop (result, NULL, ic);
 }
 
   freeAsmop (result, NULL, ic);
 }
 
+
+/*-----------------------------------------------------------------*/
+/* genUnpackBits - generates code for unpacking bits               */
+/*-----------------------------------------------------------------*/
+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 */
+
+  emitDebug ("; genUnpackBits");
+
+  etype = getSpec (operandType (result));
+  rsize = getSize (operandType (result));
+  blen = SPEC_BLEN (etype);
+  bstr = SPEC_BSTR (etype);
+
+  /* If the bitfield length is less than a byte */
+  if (blen < 8)
+    {
+      emit2 ("ld a,!*pair", _pairs[pair].name);
+      AccRsh (bstr);
+      emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - blen));
+      aopPut (AOP (result), "a", offset++);
+      goto finish;
+    }
+
+  /* TODO: what if pair == PAIR_DE ? */
+  if (getPairId (AOP (result)) == PAIR_HL)
+    {
+      wassertl (rsize == 2, "HL must be of size 2");
+      emit2 ("ld a,!*hl");
+      emit2 ("inc hl");
+      emit2 ("ld h,!*hl");
+      emit2 ("ld l,a");
+      emit2 ("ld a,h");
+      emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (16 - blen));
+      emit2 ("ld h,a");
+      spillPair (PAIR_HL);
+      return;
+    }
+
+  /* Bit field did not fit in a byte. Copy all
+     but the partial byte at the end.  */
+  for (rlen=blen;rlen>=8;rlen-=8)
+    {
+      emit2 ("ld a,!*pair", _pairs[pair].name);
+      aopPut (AOP (result), "a", offset++);
+      if (rlen>8)
+        {
+          emit2 ("inc %s", _pairs[pair].name);
+          _G.pairs[pair].offset++;
+        }
+    }
+
+  /* Handle the partial byte at the end */
+  if (rlen)
+    {
+      emit2 ("ld a,!*pair", _pairs[pair].name);
+      emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - rlen));
+      aopPut (AOP (result), "a", offset++);
+    }
+
+finish:
+  if (offset < rsize)
+    {
+      rsize -= offset;
+      while (rsize--)
+       aopPut (AOP (result), "!zero", offset++);
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* genGenPointerGet -  get value from generic pointer space        */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 /* genGenPointerGet -  get value from generic pointer space        */
 /*-----------------------------------------------------------------*/
@@ -5834,12 +6426,13 @@ genGenPointerGet (operand * left,
 
   size = AOP_SIZE (result);
 
 
   size = AOP_SIZE (result);
 
-  if (isPair (AOP (left)) && size == 1)
+  if (isPair (AOP (left)) && size == 1 && !IS_BITVAR (retype))
     {
       /* Just do it */
       if (isPtrPair (AOP (left)))
        {
     {
       /* Just do it */
       if (isPtrPair (AOP (left)))
        {
-         tsprintf (buffer, "!*pair", getPairName (AOP (left)));
+         tsprintf (buffer, sizeof(buffer), 
+                   "!*pair", getPairName (AOP (left)));
          aopPut (AOP (result), buffer, 0);
        }
       else
          aopPut (AOP (result), buffer, 0);
        }
       else
@@ -5851,17 +6444,19 @@ genGenPointerGet (operand * left,
       goto release;
     }
 
       goto release;
     }
 
-  if ( getPairId( AOP (left)) == PAIR_IY)
+  if (getPairId (AOP (left)) == PAIR_IY && !IS_BITVAR (retype))
     {
       /* Just do it */
       offset = 0;
       while (size--) 
         {
           char at[20];
     {
       /* Just do it */
       offset = 0;
       while (size--) 
         {
           char at[20];
-          tsprintf (at, "!*iyx", offset);
+          tsprintf (at, sizeof(at), "!*iyx", offset);
           aopPut (AOP (result), at, offset);
           offset++;
         }
           aopPut (AOP (result), at, offset);
           offset++;
         }
+      freeAsmop (left, NULL, ic);
       goto release;
     }
 
       goto release;
     }
 
@@ -5869,20 +6464,51 @@ genGenPointerGet (operand * left,
   /* if this is remateriazable */
   fetchPair (pair, AOP (left));
 
   /* if this is remateriazable */
   fetchPair (pair, AOP (left));
 
-  freeAsmop (left, NULL, ic);
-
   /* if bit then unpack */
   if (IS_BITVAR (retype))
     {
   /* if bit then unpack */
   if (IS_BITVAR (retype))
     {
-      wassert (0);
+      genUnpackBits (result, pair);
+      freeAsmop (left, NULL, ic);
+      goto release;
+      //wassert (0);
     }
     }
-  else if ( getPairId( AOP (result)) == PAIR_HL)
+  else if (getPairId (AOP (result)) == PAIR_HL)
     {
       wassertl (size == 2, "HL must be of size 2");
       emit2 ("ld a,!*hl");
       emit2 ("inc hl");
       emit2 ("ld h,!*hl");
       emit2 ("ld l,a");
     {
       wassertl (size == 2, "HL must be of size 2");
       emit2 ("ld a,!*hl");
       emit2 ("inc hl");
       emit2 ("ld h,!*hl");
       emit2 ("ld l,a");
+      spillPair (PAIR_HL);
+    }
+  else if (getPairId (AOP (left)) == PAIR_HL && !isLastUse (ic, left))
+    {
+      size = AOP_SIZE (result);
+      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++;
+           }
+       }
+      /* Fixup HL back down */
+      for (size = AOP_SIZE (result)-1; size; size--)
+        {
+          emit2 ("dec %s", _pairs[pair].name);
+        }
     }
   else
     {
     }
   else
     {
@@ -5892,7 +6518,8 @@ genGenPointerGet (operand * left,
       while (size--)
        {
          /* PENDING: make this better */
       while (size--)
        {
          /* PENDING: make this better */
-         if (!IS_GB && AOP (result)->type == AOP_REG)
+         if (!IS_GB && 
+              (AOP_TYPE (result) == AOP_REG || AOP_TYPE (result) == AOP_HLREG))
            {
              aopPut (AOP (result), "!*hl", offset++);
            }
            {
              aopPut (AOP (result), "!*hl", offset++);
            }
@@ -5909,6 +6536,8 @@ genGenPointerGet (operand * left,
        }
     }
 
        }
     }
 
+  freeAsmop (left, NULL, ic);
+
 release:
   freeAsmop (result, NULL, ic);
 }
 release:
   freeAsmop (result, NULL, ic);
 }
@@ -5941,6 +6570,149 @@ isRegOrLit (asmop * aop)
   return FALSE;
 }
 
   return FALSE;
 }
 
+
+/*-----------------------------------------------------------------*/
+/* genPackBits - generates code for packed bit storage             */
+/*-----------------------------------------------------------------*/
+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 */
+
+  emitDebug (";     genPackBits","");
+
+  blen = SPEC_BLEN (etype);
+  bstr = SPEC_BSTR (etype);
+
+  /* If the bitfield length is less than a byte */
+  if (blen < 8)
+    {
+      mask = ((unsigned char) (0xFF << (blen + 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 <<= bstr;
+          litval &= (~mask) & 0xff;
+          emit2 ("ld a,!*pair", _pairs[pair].name);
+          if ((mask|litval)!=0xff)
+            emit2 ("and a,!immedbyte", mask);
+          if (litval)
+            emit2 ("or a,!immedbyte", litval);
+          emit2 ("ld !*pair,a", _pairs[pair].name);
+          return;
+        }
+      else
+        {
+          /* Case with a bitfield length <8 and arbitrary source
+          */
+          _moveA (aopGet (AOP (right), 0, FALSE));
+          /* shift and mask source value */
+          AccLsh (bstr);
+          emit2 ("and a,!immedbyte", (~mask) & 0xff);
+
+          extraPair = getFreePairId(ic);
+          if (extraPair == PAIR_INVALID)
+            {
+              extraPair = PAIR_BC;
+              if (getPairId (AOP (right)) != PAIR_BC
+                  || !isLastUse (ic, right))
+                {
+                  _push (extraPair);
+                  needPopExtra = 1;
+                }
+            }
+          emit2 ("ld %s,a", _pairs[extraPair].l);
+          emit2 ("ld a,!*pair", _pairs[pair].name);
+
+          emit2 ("and a,!immedbyte", mask);
+          emit2 ("or a,%s", _pairs[extraPair].l);
+          emit2 ("ld !*pair,a", _pairs[pair].name);
+          if (needPopExtra)
+            _pop (extraPair);
+          return;
+        }
+    }
+
+  /* Bit length is greater than 7 bits. In this case, copy  */
+  /* all except the partial byte at the end                 */
+  for (rlen=blen;rlen>=8;rlen-=8)
+    {
+      emit2 ("ld a,%s", aopGet (AOP (right), offset++, FALSE) );
+      emit2 ("ld !*pair,a", _pairs[pair].name);
+      if (rlen>8)
+        {
+          emit2 ("inc %s", _pairs[pair].name);
+          _G.pairs[pair].offset++;
+        }
+    }
+
+  /* If there was a partial byte at the end */
+  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 >>= (blen-rlen);
+          litval &= (~mask) & 0xff;
+          emit2 ("ld a,!*pair", _pairs[pair].name);
+          if ((mask|litval)!=0xff)
+            emit2 ("and a,!immedbyte", mask);
+          if (litval)
+            emit2 ("or a,!immedbyte", litval);
+        }
+      else
+        {
+          /* Case with partial byte and arbitrary source
+          */
+          _moveA (aopGet (AOP (right), offset++, FALSE));
+          emit2 ("and a,!immedbyte", (~mask) & 0xff);
+
+          extraPair = getFreePairId(ic);
+          if (extraPair == PAIR_INVALID)
+            {
+              extraPair = getPairId (AOP (right));
+              if (!isLastUse (ic, right) || (extraPair == PAIR_INVALID))
+                extraPair = PAIR_BC;
+
+              if (getPairId (AOP (right)) != PAIR_BC
+                  || !isLastUse (ic, right))
+                {
+                  _push (extraPair);
+                  needPopExtra = 1;
+                }
+            }
+          emit2 ("ld %s,a", _pairs[extraPair].l);
+          emit2 ("ld a,!*pair", _pairs[pair].name);
+
+          emit2 ("and a,!immedbyte", mask);
+          emit2 ("or a,%s", _pairs[extraPair].l);
+          if (needPopExtra)
+            _pop (extraPair);
+
+        }
+      emit2 ("ld !*pair,a", _pairs[pair].name);
+    }
+}
+
+
 /*-----------------------------------------------------------------*/
 /* genGenPointerSet - stores the value into a pointer location        */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 /* genGenPointerSet - stores the value into a pointer location        */
 /*-----------------------------------------------------------------*/
@@ -5950,7 +6722,9 @@ genGenPointerSet (operand * right,
 {
   int size, offset;
   sym_link *retype = getSpec (operandType (right));
 {
   int size, offset;
   sym_link *retype = getSpec (operandType (right));
+  sym_link *letype = getSpec (operandType (result));
   PAIR_ID pairId = PAIR_HL;
   PAIR_ID pairId = PAIR_HL;
+  bool isBitvar;
   
   aopOp (result, ic, FALSE, FALSE);
   aopOp (right, ic, FALSE, FALSE);
   
   aopOp (result, ic, FALSE, FALSE);
   aopOp (right, ic, FALSE, FALSE);
@@ -5960,8 +6734,11 @@ genGenPointerSet (operand * right,
 
   size = AOP_SIZE (right);
 
 
   size = AOP_SIZE (right);
 
+  isBitvar = IS_BITVAR(retype) || IS_BITVAR(letype);
+  emitDebug("; isBitvar = %d", isBitvar);
+
   /* Handle the exceptions first */
   /* Handle the exceptions first */
-  if (isPair (AOP (result)) && size == 1)
+  if (isPair (AOP (result)) && size == 1 && !isBitvar)
     {
       /* Just do it */
       const char *l = aopGet (AOP (right), 0, FALSE);
     {
       /* Just do it */
       const char *l = aopGet (AOP (right), 0, FALSE);
@@ -5978,7 +6755,7 @@ genGenPointerSet (operand * right,
       goto release;
     }
   
       goto release;
     }
   
-  if ( getPairId( AOP (result)) == PAIR_IY)
+  if ( getPairId( AOP (result)) == PAIR_IY && !isBitvar)
     {
       /* Just do it */
       const char *l = aopGet (AOP (right), 0, FALSE);
     {
       /* Just do it */
       const char *l = aopGet (AOP (right), 0, FALSE);
@@ -5999,6 +6776,38 @@ genGenPointerSet (operand * right,
         }
       goto release;
     }
         }
       goto release;
     }
+  else if (getPairId (AOP (result)) == PAIR_HL && !isLastUse (ic, result)
+           && !isBitvar)
+    {
+      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++;
+       }
+
+      /* Fixup HL back down */
+      for (size = AOP_SIZE (right)-1; size; size--)
+        {
+          emit2 ("dec %s", _pairs[PAIR_HL].name);
+        }
+      goto release;
+    }
 
   /* if the operand is already in dptr
      then we do nothing else we move the value to dptr */
 
   /* if the operand is already in dptr
      then we do nothing else we move the value to dptr */
@@ -6006,13 +6815,15 @@ genGenPointerSet (operand * right,
     {
       fetchPair (pairId, AOP (result));
     }
     {
       fetchPair (pairId, AOP (result));
     }
-  /* so hl know contains the address */
+  /* so hl now contains the address */
   freeAsmop (result, NULL, ic);
 
   /* if bit then unpack */
   freeAsmop (result, NULL, ic);
 
   /* if bit then unpack */
-  if (IS_BITVAR (retype))
+  if (isBitvar)
     {
     {
-      wassert (0);
+      genPackBits ((IS_BITVAR (retype) ? retype : letype), right, pairId, ic);
+      goto release;
+      //wassert (0);
     }
   else
     {
     }
   else
     {
@@ -6138,14 +6949,14 @@ genAddrOf (iCode * ic)
        {
          /* if it has an offset  then we need to compute it */
          if (sym->stack > 0)
        {
          /* if it has an offset  then we need to compute it */
          if (sym->stack > 0)
-           emit2 ("ld hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
+           emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
          else
          else
-           emit2 ("ld hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
+           emit2 ("ld hl,!immedword", sym->stack + _G.stack.pushed + _G.stack.offset);
          emit2 ("add hl,sp");
        }
       else
        {
          emit2 ("add hl,sp");
        }
       else
        {
-         emit2 ("ld hl,#%s", sym->rname);
+         emit2 ("ld hl,!hashedstr", sym->rname);
        }
       commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
     }
        }
       commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
     }
@@ -6194,12 +7005,12 @@ genAssign (iCode * ic)
 
   if (AOP_TYPE (right) == AOP_LIT)
     {
 
   if (AOP_TYPE (right) == AOP_LIT)
     {
-    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+      lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
     }
 
   if (isPair (AOP (result)))
     {
     }
 
   if (isPair (AOP (result)))
     {
-      fetchPair (getPairId (AOP (result)), AOP (right));
+      fetchPairLong (getPairId (AOP (result)), AOP (right), ic, LSB);
     }
   else if ((size > 1) &&
           (AOP_TYPE (result) != AOP_REG) &&
     }
   else if ((size > 1) &&
           (AOP_TYPE (result) != AOP_REG) &&
@@ -6336,7 +7147,7 @@ static void
 genCast (iCode * ic)
 {
   operand *result = IC_RESULT (ic);
 genCast (iCode * ic)
 {
   operand *result = IC_RESULT (ic);
-  sym_link *ctype = operandType (IC_LEFT (ic));
+  sym_link *rtype = operandType (IC_RIGHT (ic));
   operand *right = IC_RIGHT (ic);
   int size, offset;
 
   operand *right = IC_RIGHT (ic);
   int size, offset;
 
@@ -6390,7 +7201,7 @@ genCast (iCode * ic)
   /* now depending on the sign of the destination */
   size = AOP_SIZE (result) - AOP_SIZE (right);
   /* Unsigned or not an integral type - right fill with zeros */
   /* now depending on the sign of the destination */
   size = AOP_SIZE (result) - AOP_SIZE (right);
   /* Unsigned or not an integral type - right fill with zeros */
-  if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
+  if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
     {
       while (size--)
        aopPut (AOP (result), "!zero", offset++);
     {
       while (size--)
        aopPut (AOP (result), "!zero", offset++);
@@ -6441,6 +7252,52 @@ genReceive (iCode * ic)
   freeAsmop (IC_RESULT (ic), NULL, ic);
 }
 
   freeAsmop (IC_RESULT (ic), NULL, ic);
 }
 
+/*-----------------------------------------------------------------*/
+/* genDummyRead - generate code for dummy read of volatiles        */
+/*-----------------------------------------------------------------*/
+static void
+genDummyRead (iCode * ic)
+{
+  operand *op;
+  int size, offset;
+
+  op = IC_RIGHT (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++;
+       }
+
+      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++;
+       }
+
+      freeAsmop (op, NULL, ic);
+    }
+}
+
 enum
   {
     /** Maximum number of bytes to emit per line. */
 enum
   {
     /** Maximum number of bytes to emit per line. */
@@ -6566,7 +7423,7 @@ _rleAppend(RLECTX *self, int c)
           /* Yes, worthwhile. */
           /* Commit whatever was in the buffer. */
           _rleCommit(self);
           /* Yes, worthwhile. */
           /* Commit whatever was in the buffer. */
           _rleCommit(self);
-          emit2(".db -%u,0x%02X", self->runLen, self->last);
+          emit2("!db !immed-%u,!immedbyte", self->runLen, self->last);
         }
       else
         {
         }
       else
         {
@@ -6591,7 +7448,7 @@ _rleAppend(RLECTX *self, int c)
           /* Commit whatever was in the buffer. */
           _rleCommit(self);
 
           /* Commit whatever was in the buffer. */
           _rleCommit(self);
 
-          emit2 (".db -%u,0x%02X", self->runLen, self->last);
+          emit2 ("!db !immed-%u,!immedbyte", self->runLen, self->last);
           self->runLen = 0;
         }
       self->runLen++;
           self->runLen = 0;
         }
       self->runLen++;
@@ -6634,13 +7491,26 @@ genArrayInit (iCode * ic)
     
   if (type && type->next)
     {
     
   if (type && type->next)
     {
-      elementSize = getSize(type->next);
+      if (IS_SPEC(type->next))
+        {
+          elementSize = getSize(type->next);
+        }
+      else if (IS_ARRAY(type->next) && type->next->next)
+        {
+          elementSize = getSize(type->next->next);
+        }
+      else
+        {
+          wassertl (0, "Can't determine element size in genArrayInit.");
+        }
     }
   else
     {
       wassertl (0, "Can't determine element size in genArrayInit.");
     }
 
     }
   else
     {
       wassertl (0, "Can't determine element size in genArrayInit.");
     }
 
+  wassertl ((elementSize > 0) && (elementSize <= 4), "Illegal element size in genArrayInit.");
+
   iLoop = IC_ARRAYILIST(ic);
   lastVal = (unsigned)-1;
 
   iLoop = IC_ARRAYILIST(ic);
   lastVal = (unsigned)-1;
 
@@ -6653,17 +7523,14 @@ genArrayInit (iCode * ic)
     {
       ix = iLoop->count;
 
     {
       ix = iLoop->count;
 
-      if (ix != 0)
+      for (i = 0; i < ix; i++)
         {
         {
-          for (i = 0; i < ix; i++)
+          for (eIndex = 0; eIndex < elementSize; eIndex++)
             {
             {
-              for (eIndex = 0; eIndex < elementSize; eIndex++)
-                {
-                  val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
-                  _rleAppend(&rle, val);
-                }
+              val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
+              _rleAppend(&rle, val);
             }
             }
-       }
+        }
        
       iLoop = iLoop->next;
     }
        
       iLoop = iLoop->next;
     }
@@ -6679,6 +7546,282 @@ genArrayInit (iCode * ic)
   freeAsmop (IC_LEFT(ic), NULL, ic);
 }
 
   freeAsmop (IC_LEFT(ic), NULL, ic);
 }
 
+static void
+_swap (PAIR_ID one, PAIR_ID two)
+{
+  if ((one == PAIR_DE && two == PAIR_HL) || (one == PAIR_HL && two == PAIR_DE))
+    {
+      emit2 ("ex de,hl");
+    }
+  else
+    {
+      emit2 ("ld a,%s", _pairs[one].l);
+      emit2 ("ld %s,%s", _pairs[one].l, _pairs[two].l);
+      emit2 ("ld %s,a", _pairs[two].l);
+      emit2 ("ld a,%s", _pairs[one].h);
+      emit2 ("ld %s,%s", _pairs[one].h, _pairs[two].h);
+      emit2 ("ld %s,a", _pairs[two].h);
+    }
+}
+
+/* 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)
+{
+  PAIR_ID ids[NUM_PAIRS][NUM_PAIRS];
+  PAIR_ID dest[3] = {
+    PAIR_BC, PAIR_HL, PAIR_DE
+  };
+  int i, j, nunity = 0;
+  memset (ids, PAIR_INVALID, sizeof (ids));
+
+  /* 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);
+      ids[dest[i]][getPairId (AOP (pparams[i]))] = TRUE;
+    }
+
+  /* Count the number of unity or iTemp assigns. */
+  for (i = 0; i < 3; i++) 
+    {
+      if (ids[dest[i]][dest[i]] == TRUE || ids[dest[i]][PAIR_INVALID] == TRUE)
+        {
+          nunity++;
+        }
+    }
+
+  if (nunity == 3)
+    {
+      /* Any order, fall through. */
+    }
+  else if (nunity == 2)
+    {
+      /* One is assigned.  Pull it out and assign. */
+      for (i = 0; i < 3; i++)
+        {
+          for (j = 0; j < NUM_PAIRS; j++)
+            {
+              if (ids[dest[i]][j] == TRUE)
+                {
+                  /* Found it.  See if it's the right one. */
+                  if (j == PAIR_INVALID || j == dest[i])
+                    {
+                      /* Keep looking. */
+                    }
+                  else
+                    {
+                      fetchPair(dest[i], AOP (pparams[i]));
+                      goto done;
+                    }
+                }
+            }
+        }
+    }
+  else if (nunity == 1)
+    {
+      /* Find the pairs to swap. */
+      for (i = 0; i < 3; i++)
+        {
+          for (j = 0; j < NUM_PAIRS; j++)
+            {
+              if (ids[dest[i]][j] == TRUE)
+                {
+                  if (j == PAIR_INVALID || j == dest[i])
+                    {
+                      /* Keep looking. */
+                    }
+                  else
+                    {
+                      _swap (j, dest[i]);
+                      goto done;
+                    }
+                }
+            }
+        }
+    }
+  else
+    {
+      int next = getPairId (AOP (pparams[0]));
+      emit2 ("push %s", _pairs[next].name);
+
+      if (next == dest[1])
+        {
+          fetchPair (dest[1], AOP (pparams[1]));
+          fetchPair (dest[2], AOP (pparams[2]));
+        }
+      else
+        {
+          fetchPair (dest[2], AOP (pparams[2]));
+          fetchPair (dest[1], AOP (pparams[1]));
+        }
+      emit2 ("pop %s", _pairs[dest[0]].name);
+    }
+ done:
+  /* Finally pull out all of the iTemps */
+  for (i = 0; i < 3; i++)
+    {
+      if (ids[dest[i]][PAIR_INVALID] == 1)
+        {
+          fetchPair (dest[i], AOP (pparams[i]));
+        }
+    }
+}
+
+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");
+  to = pparams[2];
+  from = pparams[1];
+  count = pparams[0];
+
+  deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX);
+
+  setupForBuiltin3 (ic, nParams, pparams);
+
+  emit2 ("ldir");
+
+  freeAsmop (count, NULL, ic->next->next);
+  freeAsmop (from, NULL, ic);
+
+  _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)) ||
+      IS_TRUE_SYMOP (IC_RESULT (ic)))
+    {
+      aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
+      movLeft2ResultLong (to, 0, IC_RESULT (ic), 0, 0, 2);
+      freeAsmop (IC_RESULT (ic), NULL, ic);
+    }
+
+  freeAsmop (to, NULL, ic->next);
+}
+
+/*-----------------------------------------------------------------*/
+/* genBuiltIn - calls the appropriate function to  generating code */
+/* for a built in function                                        */
+/*-----------------------------------------------------------------*/
+static void genBuiltIn (iCode *ic)
+{
+    operand *bi_parms[MAX_BUILTIN_ARGS];
+    int nbi_parms;
+    iCode *bi_iCode;
+    symbol *bif;
+
+    /* get all the arguments for a built in function */
+    bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
+
+    /* 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) 
+      {
+       genBuiltInMemcpy(bi_iCode, nbi_parms, bi_parms);
+      } 
+    else 
+      {
+       wassertl (0, "Unknown builtin function encountered");
+      }
+}
+
 /*-----------------------------------------------------------------*/
 /* genZ80Code - generate code for Z80 based controllers            */
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 /* genZ80Code - generate code for Z80 based controllers            */
 /*-----------------------------------------------------------------*/
@@ -6701,15 +7844,32 @@ genZ80Code (iCode * lic)
     }
 
   _G.lines.head = _G.lines.current = NULL;
     }
 
   _G.lines.head = _G.lines.current = NULL;
+  
+  /* if debug information required */
+  if (options.debug && currFunc)
+    {
+      debugFile->writeFunction (currFunc, lic);
+    }
 
   for (ic = lic; ic; ic = ic->next)
     {
 
   for (ic = lic; ic; ic = ic->next)
     {
+      _G.current_iCode = ic;
 
 
-      if (cln != ic->lineno)
+      if (ic->lineno && cln != ic->lineno)
        {
        {
-         emit2 ("; %s %d", ic->filename, 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;
        }
          cln = ic->lineno;
        }
+      if (options.iCodeInAsm) {
+       emit2 (";ic:%d: %s", ic->key, printILine(ic));
+      }
       /* if the result is marked as
          spilt and rematerializable or code for
          this has already been generated then
       /* if the result is marked as
          spilt and rematerializable or code for
          this has already been generated then
@@ -6946,15 +8106,28 @@ genZ80Code (iCode * lic)
          break;
 
        case SEND:
          break;
 
        case SEND:
-         emitDebug ("; addSet");
-         addSet (&_G.sendSet, ic);
+         if (ic->builtinSEND)
+            {
+              emitDebug ("; genBuiltIn");
+              genBuiltIn(ic);
+            }
+          else
+            {
+              emitDebug ("; addSet");
+              addSet (&_G.sendSet, ic);
+            }
          break;
 
        case ARRAYINIT:
          emitDebug ("; genArrayInit");
           genArrayInit(ic);
           break;
          break;
 
        case ARRAYINIT:
          emitDebug ("; genArrayInit");
           genArrayInit(ic);
           break;
-           
+
+       case DUMMY_READ_VOLATILE:
+         emitDebug ("; genDummyRead");
+         genDummyRead (ic);
+         break;
+
        default:
          ic = ic;
        }
        default:
          ic = ic;
        }
@@ -7022,7 +8195,7 @@ fetchLitSpecial (asmop * aop, bool negate, bool xor)
     v = 0-v;
   v &= 0xFFFF;
 
     v = 0-v;
   v &= 0xFFFF;
 
-  tsprintf (buffer, "!immedword", v);
+  tsprintf (buffer, sizeof(buffer), "!immedword", v);
   return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));
 }
 
   return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));
 }