* support/regression/tests/bug-460444.c: Added test case.
[fw/sdcc] / src / z80 / gen.c
index f52e8e4e183c748eee00f8e7f047a7b8fd08b340..c8c6df5cf302e736d0d4445091db587bf5852b40 100644 (file)
@@ -1,25 +1,7 @@
 /*-------------------------------------------------------------------------
   gen.c - Z80 specific code generator.
-
-  Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
-            ticks dhry  size
-  Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
-  Improved WORD push        22784 144 19AE
-  With label1 on        22694 144 197E
-  With label2 on        22743 144 198A
-  With label3 on        22776 144 1999
-  With label4 on        22776 144 1999
-  With all 'label' on       22661 144 196F
-  With loopInvariant on       20919 156 19AB
-  With loopInduction on       Breaks    198B
-  With all working on       20796 158 196C
-  Slightly better genCmp(signed)    20597 159 195B
-  Better reg packing, first peephole    20038 163 1873
-  With assign packing       19281 165 1849
-  5/3/00          17741 185 17B6
-  With reg params for mul and div   16234 202 162D
-
-  Michael Hope <michaelh@earthling.net> 2000
+     
+  Michael Hope <michaelh@juju.net.nz> 2000
   Based on the mcs51 generator -
       Sandeep Dutta . sandeep.dutta@usa.net (1998)
    and -  Jean-Louis VERN.jlvern@writeme.com (1999)
 
 -------------------------------------------------------------------------*/
 
+/*
+  Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
+                                       ticks dhry  size
+  Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
+  Improved WORD push                    22784 144 19AE
+  With label1 on                        22694 144 197E
+  With label2 on                        22743 144 198A
+  With label3 on                        22776 144 1999
+  With label4 on                        22776 144 1999
+  With all 'label' on                   22661 144 196F
+  With loopInvariant on                 20919 156 19AB
+  With loopInduction on                 Breaks    198B
+  With all working on                   20796 158 196C
+  Slightly better genCmp(signed)        20597 159 195B
+  Better reg packing, first peephole    20038 163 1873
+  With assign packing                   19281 165 1849
+  5/3/00                                17741 185 17B6
+  With reg params for mul and div       16234 202 162D
+
+  1. Starting again at 3 Aug 01         34965  93 219C
+   No asm strings
+   Includes long mul/div in code
+  2. Optimised memcpy for acc use       32102 102 226B
+  3. Optimised strcpy for acc use      27819 117 2237
+  3a Optimised memcpy fun
+  4. Optimised strcmp fun              21999 149 2294
+  5. Optimised strcmp further          21660 151 228C
+  6. Optimised memcpy by unroling      20885 157 2201
+  7. After turning loop induction on   19862 165 236D
+  8. Same as 7 but with more info      
+  9. With asm optimised strings                17030 192 2223
+
+  10 and below are with asm strings off.
+  
+  Apparent advantage of turning on regparams:
+  1.  Cost of push
+        Decent case is push of a constant 
+          - ld hl,#n; push hl: (10+11)*nargs
+  2.  Cost of pull from stack
+        Using asm with ld hl, etc
+          - ld hl,#2; add hl,sp; (ld bc,(hl); hl+=2)*nargs
+            10+11+(7+6+7+6)*nargs
+  3.  Cost of fixing stack
+          - pop hl*nargs
+            10*nargs
+  
+  So cost is (10+11+7+6+7+10)*nargs+10+11 
+      = 51*nargs+21
+      = 123 for mul, div, strcmp, strcpy
+  Saving of (98298+32766+32766+32766)*123 = 24181308
+  At 192 d/s for 682411768t, speed up to 199.  Hmm.
+*/
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "SDCCglue.h"
 #include "newalloc.h"
 
-/* this is the down and dirty file with all kinds of kludgy & hacky
+/* This is the down and dirty file with all kinds of kludgy & hacky
    stuff. This is what it is all about CODE GENERATION for a specific MCU.
    Some of the routines may be reusable, will have to see */
 
-static char *spname;
+/* Z80 calling convention description.
+   Parameters are passed right to left.  As the stack grows downwards,
+   the parameters are arranged in left to right in memory.
+   Parameters may be passed in the HL and DE registers with one
+   parameter per pair.
+   PENDING: What if the parameter is a long?
+   Everything is caller saves. i.e. the caller must save any registers
+   that it wants to preserve over the call.
+   GB: The return value is returned in DEHL.  DE is normally used as a
+   working register pair.  Caller saves allows it to be used for a
+   return value.
+   va args functions do not use register parameters.  All arguments
+   are passed on the stack.
+   IX is used as an index register to the top of the local variable
+   area.  ix-0 is the top most local variable.
+*/
+
+enum 
+{
+  /* Set to enable debugging trace statements in the output assembly code. */
+  DISABLE_DEBUG = 0
+};
+
 static char *_z80_return[] =
 {"l", "h", "e", "d"};
 static char *_gbz80_return[] =
 {"e", "d", "l", "h"};
+static char *_fReceive[] =
+  { "c", "b", "e", "d" };
+
 static char **_fReturn;
 static char **_fTmp;
 
-/* PENDING: messy */
-static char zero[20];
-
-static char *accUse[] =
-{"a"};
-static char *hlUse[] =
-{"l", "h"};
-short rbank = -1;
-short accInUse = 0;
-short inLine = 0;
-short debugLine = 0;
-short nregssaved = 0;
-extern int ptrRegReq;
-extern int nRegs;
 extern FILE *codeOutFile;
-set *sendSet = NULL;
 
+/** Enum covering all the possible register pairs.
+ */
 typedef enum
   {
     PAIR_INVALID,
+    PAIR_AF,
     PAIR_BC,
     PAIR_DE,
     PAIR_HL,
     PAIR_IY,
     PAIR_IX,
     NUM_PAIRS
-  }
-PAIR_ID;
+  } PAIR_ID;
 
 static struct
-  {
-    const char *name;
-    const char *l;
-    const char *h;
-  }
-_pairs[NUM_PAIRS] =
 {
-  {
-    "??", "?", "?"
-  }
-  ,
-  {
-    "bc", "c", "b"
-  }
-  ,
-  {
-    "de", "e", "d"
-  }
-  ,
-  {
-    "hl", "l", "h"
-  }
-  ,
-  {
-    "iy", "iy.l?", "iy.h?"
-  }
-  ,
-  {
-    "ix", "ix.l?", "ix.h?"
-  }
+  const char *name;
+  const char *l;
+  const char *h;
+} _pairs[NUM_PAIRS] = {
+  {    "??1", "?2", "?3" },
+  {    "af", "f", "a" },
+  {    "bc", "c", "b" },
+  {    "de", "e", "d" },
+  {    "hl", "l", "h" },
+  {    "iy", "iy.l?", "iy.h?" },
+  {    "ix", "ix.l?", "ix.h?" }
 };
 
+// PENDING
+#define ACC_NAME       _pairs[PAIR_AF].h
+
 #define RESULTONSTACK(x) \
                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
                          IC_RESULT(x)->aop->type == AOP_STK )
 
-#define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
-#define CLRC    emitcode("xor","a,a");
+enum 
+  {
+    LSB,
+    MSB16,
+    MSB24,
+    MSB32
+  };
 
-lineNode *lineHead = NULL;
-lineNode *lineCurr = NULL;
+/** Code generator persistent data.
+ */
+static struct 
+{
+  /** Used to optimised setting up of a pair by remebering what it
+      contains and adjusting instead of reloading where possible.
+  */
+  struct 
+  {
+    AOP_TYPE last_type;
+    const char *base;
+    int offset;
+  } pairs[NUM_PAIRS];
+  struct 
+  {
+    int last;
+    int pushed;
+    int param_offset;
+    int offset;
+    int pushedBC;
+    int pushedDE;
+  } stack;
+  int frameId;
+  int receiveOffset;
+  bool flushStatics;
+  bool in_home;
+  const char *lastFunctionName;
+
+  set *sendSet;
+
+  struct
+  {
+    /** TRUE if the registers have already been saved. */
+    bool saved;
+  } saves;
 
-static const unsigned char SLMask[] =
-{0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};
-static const unsigned char SRMask[] =
-{0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00};
+  struct 
+  {
+    lineNode *head;
+    lineNode *current;
+    int isInline;
+  } lines;
 
-#define LSB     0
-#define MSB16   1
-#define MSB24   2
-#define MSB32   3
+} _G;
 
-/* Stack frame:
-   IX+4   param0  LH
-   IX+2   ret LH
-   IX+0   ix  LH
-   IX-2   temp0 LH
- */
+static const char *aopGet (asmop * aop, int offset, bool bit16);
 
-static struct
-  {
-    struct
-      {
-       AOP_TYPE last_type;
-       const char *lit;
-       int offset;
-      }
-    pairs[NUM_PAIRS];
-    struct
-      {
-       int last;
-       int pushed;
-       int param_offset;
-       int offset;
-       int pushed_bc;
-       int pushed_de;
-      }
-    stack;
-    int frameId;
-    bool flush_statics;
-    bool in_home;
-  }
-_G;
+static PAIR_ID
+_getTempPairId(void)
+{
+  if (IS_GB)
+    {
+      return PAIR_DE;
+    }
+  else
+    {
+      return PAIR_HL;
+    }
+}
 
-static char *aopGet (asmop * aop, int offset, bool bit16);
+static const char *
+_getTempPairName(void)
+{
+  return _pairs[_getTempPairId()].name;
+}
 
 static void
 _tidyUp (char *buf)
@@ -200,45 +256,68 @@ _tidyUp (char *buf)
     }
   /* Change the first (and probably only) ' ' to a tab so
      everything lines up.
-   */
+  */
   while (*buf)
     {
       if (*buf == ' ')
-       {
-         *buf = '\t';
-         return;
-       }
+        {
+          *buf = '\t';
+          break;
+        }
       buf++;
     }
 }
 
 static void
-emit2 (const char *szFormat,...)
+_vemit2 (const char *szFormat, va_list ap)
 {
   char buffer[256];
+
+  tvsprintf (buffer, szFormat, ap);
+
+  _tidyUp (buffer);
+  _G.lines.current = (_G.lines.current ?
+             connectLine (_G.lines.current, newLineNode (buffer)) :
+             (_G.lines.head = newLineNode (buffer)));
+
+  _G.lines.current->isInline = _G.lines.isInline;
+}
+
+static void
+emit2 (const char *szFormat,...)
+{
   va_list ap;
 
   va_start (ap, szFormat);
 
-  tvsprintf (buffer, szFormat, ap);
+  _vemit2 (szFormat, ap);
 
-  _tidyUp (buffer);
-  lineCurr = (lineCurr ?
-             connectLine (lineCurr, newLineNode (buffer)) :
-             (lineHead = newLineNode (buffer)));
+  va_end (ap);
+}
 
-  lineCurr->isInline = inLine;
-  lineCurr->isDebug = debugLine;
+static void
+emitDebug (const char *szFormat,...)
+{
+  if (!DISABLE_DEBUG)
+    {
+      va_list ap;
+      
+      va_start (ap, szFormat);
+      
+      _vemit2 (szFormat, ap);
+      
+      va_end (ap);
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* emitcode - writes the code into a file : for now it is simple    */
+/* emit2 - writes the code into a file : for now it is simple    */
 /*-----------------------------------------------------------------*/
 void
-emitcode (const char *inst, const char *fmt,...)
+_emit2 (const char *inst, const char *fmt,...)
 {
   va_list ap;
-  char lb[MAX_INLINEASM];
+  char lb[INITIAL_INLINEASM];
   char *lbp = lb;
 
   va_start (ap, fmt);
@@ -255,33 +334,41 @@ emitcode (const char *inst, const char *fmt,...)
     lbp++;
 
   if (lbp && *lbp)
-    lineCurr = (lineCurr ?
-               connectLine (lineCurr, newLineNode (lb)) :
-               (lineHead = newLineNode (lb)));
-  lineCurr->isInline = inLine;
-  lineCurr->isDebug = debugLine;
+    {
+      _G.lines.current = (_G.lines.current ?
+                  connectLine (_G.lines.current, newLineNode (lb)) :
+                  (_G.lines.head = newLineNode (lb)));
+    }
+  _G.lines.current->isInline = _G.lines.isInline;
   va_end (ap);
 }
 
-/* Z80:
-   { "adjustsp",
-   "\tld hl,#-%d\n"
-   "\tadd hl,sp\n"
-   "\tld sp,hl"
-   }
-   { "prelude",
-   "push bc"
-   "push de"
-   "push ix"
-   "ld ix,#0"
-   "add ix,sp"
-   { "leave"
-   emitcode("ld", "sp,ix");
-   emitcode("pop", "ix");
-   emitcode("pop", "de");
-   }
-   }
- */
+static void
+_emitMove(const char *to, const char *from)
+{
+  if (strcasecmp(to, from) != 0) 
+    {
+      emit2("ld %s,%s", to, from);
+    }
+  else 
+    {
+      // Optimise it out.
+      // Could leave this to the peephole, but sometimes the peephole is inhibited.
+    }
+}
+
+static void
+_moveA(const char *moveFrom)
+{
+    // Let the peephole optimiser take care of redundent loads
+    _emitMove(ACC_NAME, moveFrom);
+}
+
+static void
+_clearCarry(void)
+{
+    emit2("xor a,a");
+}
 
 const char *
 getPairName (asmop * aop)
@@ -316,7 +403,7 @@ getPairName (asmop * aop)
          break;
        }
     }
-  wassert (0);
+  wassertl (0, "Tried to get the pair name of something that isn't a pair");
   return NULL;
 }
 
@@ -384,9 +471,22 @@ isPtrPair (asmop * aop)
 void
 genPairPush (asmop * aop)
 {
-  emitcode ("push", "%s", getPairName (aop));
+  emit2 ("push %s", getPairName (aop));
 }
 
+static void
+_push (PAIR_ID pairId)
+{
+  emit2 ("push %s", _pairs[pairId].name);
+  _G.stack.pushed += 2;
+}
+
+static void
+_pop (PAIR_ID pairId)
+{
+  emit2 ("pop %s", _pairs[pairId].name);
+  _G.stack.pushed -= 2;
+}
 
 /*-----------------------------------------------------------------*/
 /* newAsmop - creates a new asmOp                                  */
@@ -423,7 +523,7 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
   /* Assign depending on the storage class */
   if (sym->onStack || sym->iaccess)
     {
-      emitcode ("", "; AOP_STK for %s", sym->rname);
+      emitDebug ("; AOP_STK for %s", sym->rname);
       sym->aop = aop = newAsmop (AOP_STK);
       aop->size = getSize (sym->type);
       aop->aopu.aop_stk = sym->stack;
@@ -448,7 +548,7 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
          sym->aop = aop = newAsmop (AOP_SFR);
          aop->aopu.aop_dir = sym->rname;
          aop->size = getSize (sym->type);
-         emitcode ("", "; AOP_SFR for %s", sym->rname);
+         emitDebug ("; AOP_SFR for %s", sym->rname);
          return aop;
        }
     }
@@ -457,7 +557,7 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
   /* in which case DPTR gets the address */
   if (IS_GB)
     {
-      emitcode ("", "; AOP_HL for %s", sym->rname);
+      emitDebug ("; AOP_HL for %s", sym->rname);
       sym->aop = aop = newAsmop (AOP_HL);
     }
   else
@@ -694,24 +794,27 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a)
 
       if (sym->accuse)
        {
-         int i;
          if (sym->accuse == ACCUSE_A)
            {
              aop = op->aop = sym->aop = newAsmop (AOP_ACC);
              aop->size = getSize (sym->type);
-             for (i = 0; i < 2; i++)
-               aop->aopu.aop_str[i] = accUse[i];
+              wassertl(aop->size == 1, "Internal error: Caching in A, but too big to fit in A");
+
+              aop->aopu.aop_str[0] = _pairs[PAIR_AF].h;
            }
          else if (sym->accuse == ACCUSE_HL)
            {
              wassert (!IS_GB);
              aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
              aop->size = getSize (sym->type);
-             for (i = 0; i < 2; i++)
-               aop->aopu.aop_str[i] = hlUse[i];
+              wassertl(aop->size <= 2, "Internal error: Caching in HL, but too big to fit in HL");
+              aop->aopu.aop_str[0] = _pairs[PAIR_HL].l;
+              aop->aopu.aop_str[1] = _pairs[PAIR_HL].h;
            }
-         else
-           wassert (0);
+         else 
+              {
+                  wassertl (0, "Marked as being allocated into A or HL but is actually in neither");
+              }
          return;
        }
 
@@ -796,10 +899,6 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
   char *s = buffer;
   char *rs;
 
-#if 0
-  if (aop->size != 2 && aop->type != AOP_HL)
-    return NULL;
-#endif
   /* depending on type */
   switch (aop->type)
     {
@@ -808,12 +907,19 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
     case AOP_IMMD:
       /* PENDING: for re-target */
       if (with_hash)
-       tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
+        {
+          tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
+        }
+      else if (offset == 0)
+        {
+          tsprintf (s, "%s", aop->aopu.aop_immd);
+        }
       else
-       tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
-      rs = Safe_calloc (1, strlen (s) + 1);
-      strcpy (rs, s);
-      return rs;
+        {
+          tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
+        }
+      return gc_strdup(s);
+
     case AOP_LIT:
       {
        value *val = aop->aopu.aop_lit;
@@ -821,17 +927,27 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
        /* otherwise it is fairly simple */
        if (!IS_FLOAT (val->type))
          {
-           unsigned long v = floatFromVal (val);
+           unsigned long v = (unsigned long) floatFromVal (val);
 
            if (offset == 2)
-             v >>= 16;
+              {
+                v >>= 16;
+              }
+            else if (offset == 0)
+              {
+                // OK
+              }
+            else 
+              {
+                wassertl(0, "Encountered an invalid offset while fetching a literal");
+              }
 
            if (with_hash)
              tsprintf (buffer, "!immedword", v);
            else
              tsprintf (buffer, "!constword", v);
-           rs = Safe_calloc (1, strlen (buffer) + 1);
-           return strcpy (rs, buffer);
+
+            return gc_strdup(buffer);
          }
        else
          {
@@ -876,12 +992,12 @@ adjustPair (const char *pair, int *pold, int new)
 
   while (*pold < new)
     {
-      emitcode ("inc", "%s", pair);
+      emit2 ("inc %s", pair);
       (*pold)++;
     }
   while (*pold > new)
     {
-      emitcode ("dec", "%s", pair);
+      emit2 ("dec %s", pair);
       (*pold)--;
     }
 }
@@ -890,7 +1006,7 @@ static void
 spillPair (PAIR_ID pairId)
 {
   _G.pairs[pairId].last_type = AOP_INVALID;
-  _G.pairs[pairId].lit = NULL;
+  _G.pairs[pairId].base = NULL;
 }
 
 static void
@@ -905,6 +1021,7 @@ requiresHL (asmop * aop)
 {
   switch (aop->type)
     {
+    case AOP_IY:
     case AOP_HL:
     case AOP_STK:
       return TRUE;
@@ -913,34 +1030,14 @@ requiresHL (asmop * aop)
     }
 }
 
-static char *
-fetchLitSpecial (asmop * aop, bool negate, bool xor)
-{
-  unsigned long v;
-  value *val = aop->aopu.aop_lit;
-
-  wassert (aop->type == AOP_LIT);
-  wassert (!IS_FLOAT (val->type));
-
-  v = floatFromVal (val);
-
-  if (xor)
-    v ^= 0x8000;
-  if (negate)
-    v = -v;
-  v &= 0xFFFF;
-
-  tsprintf (buffer, "!immedword", v);
-  return gc_strdup (buffer);
-}
-
 static void
 fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
 {
-  const char *l;
+  const char *l, *base;
   const char *pair = _pairs[pairId].name;
-  l = aopGetLitWordLong (left, 0, FALSE);
-  wassert (l && pair);
+  l = aopGetLitWordLong (left, offset, FALSE);
+  base = aopGetLitWordLong (left, 0, FALSE);
+  wassert (l && pair && base);
 
   if (isPtr (pair))
     {
@@ -948,7 +1045,7 @@ fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
        {
          if (_G.pairs[pairId].last_type == left->type)
            {
-             if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
+             if (_G.pairs[pairId].base && !strcmp (_G.pairs[pairId].base, base))
                {
                  if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
                    {
@@ -963,74 +1060,59 @@ fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
            }
        }
       _G.pairs[pairId].last_type = left->type;
-      _G.pairs[pairId].lit = gc_strdup (l);
-      _G.pairs[pairId].offset = offset;
-    }
-  if (IS_GB && pairId == PAIR_DE && 0)
-    {
-      if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
-       {
-         if (abs (_G.pairs[pairId].offset - offset) < 3)
-           {
-             adjustPair (pair, &_G.pairs[pairId].offset, offset);
-             return;
-           }
-       }
-      _G.pairs[pairId].last_type = left->type;
-      _G.pairs[pairId].lit = gc_strdup (l);
+      _G.pairs[pairId].base = gc_strdup (base);
       _G.pairs[pairId].offset = offset;
     }
   /* Both a lit on the right and a true symbol on the left */
-  if (offset)
-    emit2 ("ld %s,!hashedstr + %u", pair, l, offset);
-  else
-    emit2 ("ld %s,!hashedstr", pair, l);
+  emit2 ("ld %s,!hashedstr", pair, l);
 }
 
 static void
 fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
 {
-  /* if this is remateriazable */
-  if (isLitWord (aop))
-    {
-      fetchLitPair (pairId, aop, offset);
-    }
-  else
-    {                          /* we need to get it byte by byte */
-      if (pairId == PAIR_HL && IS_GB && requiresHL (aop))
-       {
-         aopGet (aop, offset, FALSE);
-         switch (aop->size)
-           {
-           case 1:
-             emit2 ("ld l,!*hl");
-             emit2 ("ld h,!immedbyte", 0);
-             break;
-           case 2:
-             emit2 ("!ldahli");
-             emit2 ("ld h,!*hl");
-             emit2 ("ld l,a");
-             break;
-           default:
-             emit2 ("; WARNING: mlh woosed out.  This code is invalid.");
-           }
-       }
-      else if (IS_Z80 && aop->type == AOP_IY)
-       {
-         /* Instead of fetching relative to IY, just grab directly
-            from the address IY refers to */
-         char *l = aopGetLitWordLong (aop, offset, FALSE);
-         wassert (l);
-         emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
-       }
-      else
-       {
-         emitcode ("ld", "%s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
-         emitcode ("ld", "%s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
-       }
-      /* PENDING: check? */
-      if (pairId == PAIR_HL)
-       spillPair (PAIR_HL);
+    /* if this is remateriazable */
+    if (isLitWord (aop)) {
+        fetchLitPair (pairId, aop, offset);
+    }
+    else {
+        /* we need to get it byte by byte */
+        if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
+            aopGet (aop, offset, FALSE);
+            switch (aop->size - offset) {
+            case 1:
+                emit2 ("ld l,!*hl");
+                emit2 ("ld h,!immedbyte", 0);
+                            break;
+            case 2:
+              // PENDING: Requires that you are only fetching two bytes.
+            case 4:
+                emit2 ("!ldahli");
+                emit2 ("ld h,!*hl");
+                emit2 ("ld l,a");
+                break;
+            default:
+              wassertl (0, "Attempted to fetch too much data into HL");
+              break;
+            }
+        }
+        else if (IS_Z80 && aop->type == AOP_IY) {
+            /* Instead of fetching relative to IY, just grab directly
+               from the address IY refers to */
+            char *l = aopGetLitWordLong (aop, offset, FALSE);
+            wassert (l);
+            emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
+
+            if (aop->size < 2) {
+                emit2("ld %s,!zero", _pairs[pairId].h);
+            }
+        }
+        else {
+            emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
+            emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
+        }
+        /* PENDING: check? */
+        if (pairId == PAIR_HL)
+            spillPair (PAIR_HL);
     }
 }
 
@@ -1097,17 +1179,19 @@ emitLabel (int key)
 /*-----------------------------------------------------------------*/
 /* aopGet - for fetching value of the aop                          */
 /*-----------------------------------------------------------------*/
-static char *
+static const char *
 aopGet (asmop * aop, int offset, bool bit16)
 {
   char *s = buffer;
-  char *rs;
 
   /* 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)
-    return zero;
+      aop->type != AOP_LIT) 
+    {
+      tsprintf (s, "!zero");
+      return gc_strdup(s);
+    }
 
   /* depending on type */
   switch (aop->type)
@@ -1129,27 +1213,24 @@ aopGet (asmop * aop, int offset, bool bit16)
            tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
            break;
          default:
-           wassert (0);
+           wassertl (0, "Fetching from beyond the limits of an immediate value.");
          }
-      rs = Safe_calloc (1, strlen (s) + 1);
-      strcpy (rs, s);
-      return rs;
+
+      return gc_strdup(s);
 
     case AOP_DIR:
       wassert (IS_GB);
-      emitcode ("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
+      emit2 ("ld a,(%s+%d)", aop->aopu.aop_dir, offset);
       sprintf (s, "a");
-      rs = Safe_calloc (1, strlen (s) + 1);
-      strcpy (rs, s);
-      return rs;
+
+      return gc_strdup(s);
 
     case AOP_SFR:
       wassert (IS_GB);
-      emitcode ("ldh", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
+      emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset);
       sprintf (s, "a");
-      rs = Safe_calloc (1, strlen (s) + 1);
-      strcpy (rs, s);
-      return rs;
+
+      return gc_strdup(s);
 
     case AOP_REG:
       return aop->aopu.aop_reg[offset]->name;
@@ -1158,15 +1239,15 @@ aopGet (asmop * aop, int offset, bool bit16)
       wassert (IS_GB);
       setupPair (PAIR_HL, aop, offset);
       tsprintf (s, "!*hl");
+
       return gc_strdup (s);
 
     case AOP_IY:
       wassert (IS_Z80);
       setupPair (PAIR_IY, aop, offset);
       tsprintf (s, "!*iyx", offset);
-      rs = Safe_calloc (1, strlen (s) + 1);
-      strcpy (rs, s);
-      return rs;
+
+      return gc_strdup(s);
 
     case AOP_STK:
       if (IS_GB)
@@ -1178,21 +1259,24 @@ aopGet (asmop * aop, int offset, bool bit16)
        {
          if (aop->aopu.aop_stk >= 0)
            offset += _G.stack.param_offset;
-         tsprintf (s, "!*ixx ; x", aop->aopu.aop_stk + offset);
+         tsprintf (s, "!*ixx", aop->aopu.aop_stk + offset);
        }
-      rs = Safe_calloc (1, strlen (s) + 1);
-      strcpy (rs, s);
-      return rs;
+
+      return gc_strdup(s);
 
     case AOP_CRY:
-      wassert (0);
+      wassertl (0, "Tried to fetch from a bit variable");
 
     case AOP_ACC:
       if (!offset)
        {
          return "a";
        }
-      return "!zero";
+      else
+        {
+          tsprintf(s, "!zero");
+          return gc_strdup(s);
+        }
 
     case AOP_HLREG:
       wassert (offset < 2);
@@ -1201,9 +1285,19 @@ aopGet (asmop * aop, int offset, bool bit16)
     case AOP_LIT:
       return aopLiteral (aop->aopu.aop_lit, offset);
 
+    case AOP_SIMPLELIT:
+      {
+        unsigned long v = aop->aopu.aop_simplelit;
+        
+        v >>= (offset * 8);
+        tsprintf (s, "!immedbyte", (unsigned int) v & 0xff);
+        
+        return gc_strdup(s);
+      }
     case AOP_STR:
       aop->coff = offset;
       return aop->aopu.aop_str[offset];
+
     default:
       break;
     }
@@ -1248,6 +1342,8 @@ canAssignToPtr (const char *s)
 static void
 aopPut (asmop * aop, const char *s, int offset)
 {
+  char buffer2[256];
+
   if (aop->size && offset > (aop->size - 1))
     {
       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
@@ -1255,6 +1351,10 @@ aopPut (asmop * aop, const char *s, int offset)
       exit (0);
     }
 
+  // PENDING
+  tsprintf(buffer2, s);
+  s = buffer2;
+
   /* will assign value to value */
   /* depending on where it is ofcourse */
   switch (aop->type)
@@ -1263,15 +1363,15 @@ aopPut (asmop * aop, const char *s, int offset)
       /* Direct.  Hmmm. */
       wassert (IS_GB);
       if (strcmp (s, "a"))
-       emitcode ("ld", "a,%s", s);
-      emitcode ("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
+       emit2 ("ld a,%s", s);
+      emit2 ("ld (%s+%d),a", aop->aopu.aop_dir, offset);
       break;
 
     case AOP_SFR:
       wassert (IS_GB);
       if (strcmp (s, "a"))
-       emitcode ("ld", "a,%s", s);
-      emitcode ("ldh", "(%s+%d),a", aop->aopu.aop_dir, offset);
+       emit2 ("ld a,%s", s);
+      emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
       break;
 
     case AOP_REG:
@@ -1349,7 +1449,7 @@ aopPut (asmop * aop, const char *s, int offset)
       else
        {
          /* In bit space but not in C - cant happen */
-         wassert (0);
+         wassertl (0, "Tried to write into a bit variable");
        }
       break;
 
@@ -1357,7 +1457,7 @@ aopPut (asmop * aop, const char *s, int offset)
       aop->coff = offset;
       if (strcmp (aop->aopu.aop_str[offset], s))
        {
-         emitcode ("ld", "%s,%s", aop->aopu.aop_str[offset], s);
+         emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
        }
       break;
 
@@ -1367,13 +1467,12 @@ aopPut (asmop * aop, const char *s, int offset)
        break;
       if (offset > 0)
        {
-
-         emitcode ("", "; Error aopPut AOP_ACC");
+          wassertl (0, "Tried to access past the end of A");
        }
       else
        {
          if (strcmp (aop->aopu.aop_str[offset], s))
-           emitcode ("ld", "%s,%s", aop->aopu.aop_str[offset], s);
+           emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
        }
       break;
 
@@ -1422,7 +1521,7 @@ getDataSize (operand * op)
   if (size == 3)
     {
       /* pointer */
-      wassert (0);
+      wassertl (0, "Somehow got a three byte data pointer");
     }
   return size;
 }
@@ -1434,7 +1533,7 @@ static void
 movLeft2Result (operand * left, int offl,
                operand * result, int offr, int sign)
 {
-  char *l;
+  const char *l;
   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
     {
       l = aopGet (AOP (left), offl, FALSE);
@@ -1445,7 +1544,11 @@ movLeft2Result (operand * left, int offl,
        }
       else
        {
-         wassert (0);
+          if (getDataSize (left) == offl + 1)
+            {
+              emit2 ("ld a,%s", l);
+              aopPut (AOP (result), "a", offr);
+            }
        }
     }
 }
@@ -1466,7 +1569,7 @@ outAcc (operand * result)
       /* unsigned or positive */
       while (size--)
        {
-         aopPut (AOP (result), zero, offset++);
+         aopPut (AOP (result), "!zero", offset++);
        }
     }
 }
@@ -1479,8 +1582,7 @@ outBitCLong (operand * result, bool swap_sense)
   /* if the result is bit */
   if (AOP_TYPE (result) == AOP_CRY)
     {
-      emitcode ("", "; Note: outBitC form 1");
-      aopPut (AOP (result), "blah", 0);
+      wassertl (0, "Tried to write carry to a bit");
     }
   else
     {
@@ -1502,23 +1604,23 @@ outBitC (operand * result)
 /* toBoolean - emit code for orl a,operator(sizeop)                */
 /*-----------------------------------------------------------------*/
 void
-toBoolean (operand * oper)
+_toBoolean (operand * oper)
 {
   int size = AOP_SIZE (oper);
   int offset = 0;
   if (size > 1)
     {
-      emitcode ("ld", "a,%s", aopGet (AOP (oper), offset++, FALSE));
+      emit2 ("ld a,%s", aopGet (AOP (oper), offset++, FALSE));
       size--;
       while (size--)
-       emitcode ("or", "a,%s", aopGet (AOP (oper), offset++, FALSE));
+       emit2 ("or a,%s", aopGet (AOP (oper), offset++, FALSE));
     }
   else
     {
       if (AOP (oper)->type != AOP_ACC)
        {
-         CLRC;
-         emitcode ("or", "a,%s", aopGet (AOP (oper), 0, FALSE));
+         _clearCarry();
+         emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE));
        }
     }
 }
@@ -1538,16 +1640,16 @@ genNot (iCode * ic)
   /* if in bit space then a special case */
   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to negate a bit");
     }
 
   /* if type float then do float */
   if (IS_FLOAT (optype))
     {
-      wassert (0);
+      wassertl (0, "Tried to negate a float");
     }
 
-  toBoolean (IC_LEFT (ic));
+  _toBoolean (IC_LEFT (ic));
 
   /* Not of A:
      If A == 0, !A = 1
@@ -1580,15 +1682,15 @@ genCpl (iCode * ic)
   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Left and the result are in bit space");
     }
 
   size = AOP_SIZE (IC_RESULT (ic));
   while (size--)
     {
-      char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
-      MOVA (l);
-      emitcode ("cpl", "");
+      const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
+      _moveA (l);
+      emit2("cpl");
       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
     }
 
@@ -1597,6 +1699,59 @@ genCpl (iCode * ic)
   freeAsmop (IC_RESULT (ic), NULL, ic);
 }
 
+static void
+_gbz80_emitAddSubLongLong (iCode *ic, asmop *left, asmop *right, bool isAdd)
+{
+  /* Logic:
+       ld de,right.lw
+       setup hl to left
+       de = hl - de
+       push flags
+       store de into result
+       pop flags
+       ld de,right.hw
+       setup hl
+       de = hl -de
+       store de into result
+  */
+  const char *first = isAdd ? "add" : "sub";
+  const char *later = isAdd ? "adc" : "sbc";
+
+  wassertl (IS_GB, "Code is only relevent to the gbz80");
+  wassertl (AOP( IC_RESULT (ic))->size == 4, "Only works for four bytes");
+
+  fetchPair (PAIR_DE, left);
+
+  emit2 ("ld a,e");
+  emit2 ("%s a,%s", first, aopGet( right, LSB, FALSE));
+  emit2 ("ld e,a");
+  emit2 ("ld a,d");
+  emit2 ("%s a,%s", later, aopGet( right, MSB16, FALSE));
+
+  _push (PAIR_AF);
+  aopPut ( AOP (IC_RESULT (ic)), "a", MSB16);
+  aopPut ( AOP (IC_RESULT (ic)), "e", LSB);
+
+  fetchPairLong (PAIR_DE, left, MSB24);
+  aopGet (right, MSB24, FALSE);
+
+  _pop (PAIR_AF);
+  emit2 ("ld a,e");
+  emit2 ("%s a,%s", later, aopGet( right, MSB24, FALSE));
+  emit2 ("ld e,a");
+  emit2 ("ld a,d");
+  emit2 ("%s a,%s", later, aopGet( right, MSB32, FALSE));
+
+  aopPut ( AOP (IC_RESULT (ic)), "a", MSB32);
+  aopPut ( AOP (IC_RESULT (ic)), "e", MSB24);
+}
+
+static void
+_gbz80_emitAddSubLong (iCode *ic, bool isAdd)
+{
+  _gbz80_emitAddSubLongLong (ic, AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)), isAdd);
+}
+
 /*-----------------------------------------------------------------*/
 /* genUminus - unary minus code generation                         */
 /*-----------------------------------------------------------------*/
@@ -1615,7 +1770,7 @@ genUminus (iCode * ic)
   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Left and right are in bit space");
       goto release;
     }
 
@@ -1625,17 +1780,28 @@ genUminus (iCode * ic)
   /* if float then do float stuff */
   if (IS_FLOAT (optype))
     {
-      wassert (0);
+      wassertl (0, "Tried to do a unary minus on a float");
       goto release;
     }
 
   /* otherwise subtract from zero */
   size = AOP_SIZE (IC_LEFT (ic));
+
+  if (AOP_SIZE (IC_RESULT (ic)) == 4 && IS_GB)
+    {
+      /* Create a new asmop with value zero */
+      asmop *azero = newAsmop (AOP_SIMPLELIT);
+      azero->aopu.aop_simplelit = 0;
+      azero->size = size;
+      _gbz80_emitAddSubLongLong (ic, azero, AOP (IC_LEFT (ic)), FALSE);
+      goto release;
+    }
+
   offset = 0;
-  CLRC;
+  _clearCarry();
   while (size--)
     {
-      char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
+      const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
       emit2 ("ld a,!zero");
       emit2 ("sbc a,%s", l);
       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
@@ -1657,21 +1823,6 @@ release:
   freeAsmop (IC_RESULT (ic), NULL, ic);
 }
 
-static void
-_push (PAIR_ID pairId)
-{
-  emit2 ("push %s", _pairs[pairId].name);
-  _G.stack.pushed += 2;
-}
-
-static void
-_pop (PAIR_ID pairId)
-{
-  emit2 ("pop %s", _pairs[pairId].name);
-  _G.stack.pushed -= 2;
-}
-
-
 /*-----------------------------------------------------------------*/
 /* assignResultValue -               */
 /*-----------------------------------------------------------------*/
@@ -1681,21 +1832,16 @@ assignResultValue (operand * oper)
   int size = AOP_SIZE (oper);
   bool topInA = 0;
 
-  wassert (size <= 4);
+  wassertl (size <= 4, "Got a result that is bigger than four bytes");
   topInA = requiresHL (AOP (oper));
 
-#if 0
-  if (!IS_GB)
-    wassert (size <= 2);
-#endif
   if (IS_GB && size == 4 && requiresHL (AOP (oper)))
     {
       /* We do it the hard way here. */
       _push (PAIR_HL);
       aopPut (AOP (oper), _fReturn[0], 0);
       aopPut (AOP (oper), _fReturn[1], 1);
-      emitcode ("pop", "de");
-      _G.stack.pushed -= 2;
+      _pop (PAIR_DE);
       aopPut (AOP (oper), _fReturn[0], 2);
       aopPut (AOP (oper), _fReturn[1], 3);
     }
@@ -1708,6 +1854,61 @@ assignResultValue (operand * oper)
     }
 }
 
+static void
+_saveRegsForCall(iCode *ic, int sendSetSize)
+{
+  /* Rules:
+      o Stack parameters are pushed before this function enters
+      o DE and BC may be used in this function.
+      o HL and DE may be used to return the result.
+      o HL and DE may be used to send variables.
+      o DE and BC may be used to store the result value.
+      o HL may be used in computing the sent value of DE
+      o The iPushes for other parameters occur before any addSets
+
+     Logic: (to be run inside the first iPush or if none, before sending)
+      o Compute if DE and/or BC are in use over the call
+      o Compute if DE is used in the send set
+      o Compute if DE and/or BC are used to hold the result value
+      o If (DE is used, or in the send set) and is not used in the result, push.
+      o If BC is used and is not in the result, push
+      o 
+      o If DE is used in the send set, fetch
+      o If HL is used in the send set, fetch
+      o Call
+      o ...
+  */
+  if (_G.saves.saved == FALSE) {
+    bool deInUse, bcInUse;
+    bool deSending;
+    bool bcInRet = FALSE, deInRet = FALSE;
+    bitVect *rInUse;
+
+    rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
+
+    deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
+    bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
+
+    deSending = (sendSetSize > 1);
+
+    emitDebug ("; _saveRegsForCall: sendSetSize: %u deInUse: %u bcInUse: %u deSending: %u", sendSetSize, deInUse, bcInUse, deSending);
+
+    if (bcInUse && bcInRet == FALSE) {
+      _push(PAIR_BC);
+      _G.stack.pushedBC = TRUE;
+    }
+    if (deInUse && deInRet == FALSE) {
+      _push(PAIR_DE);
+      _G.stack.pushedDE = TRUE;
+    }
+
+    _G.saves.saved = TRUE;
+  }
+  else {
+    /* Already saved. */
+  }
+}
+
 /*-----------------------------------------------------------------*/
 /* genIpush - genrate code for pushing this gets a little complex  */
 /*-----------------------------------------------------------------*/
@@ -1715,51 +1916,43 @@ static void
 genIpush (iCode * ic)
 {
   int size, offset = 0;
-  char *l;
+  const char *l;
 
   /* if this is not a parm push : ie. it is spill push
      and spill push is always done on the local stack */
   if (!ic->parmPush)
     {
-      /* and the item is spilt then do nothing */
-      if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
-       return;
-
-      aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
-      size = AOP_SIZE (IC_LEFT (ic));
-      /* push it on the stack */
-      if (isPair (AOP (IC_LEFT (ic))))
-       {
-         emitcode ("push", getPairName (AOP (IC_LEFT (ic))));
-         _G.stack.pushed += 2;
-       }
-      else
-       {
-         offset = size;
-         while (size--)
-           {
-             /* Simple for now - load into A and PUSH AF */
-             if (AOP (IC_LEFT (ic))->type == AOP_IY)
-               {
-                 char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
-                 wassert (l);
-                 emit2 ("ld a,(%s)", l);
-               }
-             else
-               {
-                 l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
-                 emit2 ("ld a,%s", l);
-               }
-             emit2 ("push af");
-             emit2 ("inc sp");
-             _G.stack.pushed++;
-           }
-       }
+      wassertl(0, "Encountered an unsupported spill push.");
       return;
     }
 
-  /* Hmmm... what about saving the currently used registers
-     at this point? */
+  if (_G.saves.saved == FALSE) {
+    /* Caller saves, and this is the first iPush. */
+    /* Scan ahead until we find the function that we are pushing parameters to.
+       Count the number of addSets on the way to figure out what registers
+       are used in the send set.
+    */
+    int nAddSets = 0;
+    iCode *walk = ic->next;
+    
+    while (walk) {
+      if (walk->op == SEND) {
+        nAddSets++;
+      }
+      else if (walk->op == CALL || walk->op == PCALL) {
+        /* Found it. */
+        break;
+      }
+      else {
+        /* Keep looking. */
+      }
+      walk = walk->next;
+    }
+    _saveRegsForCall(walk, nAddSets);
+  }
+  else {
+    /* Already saved by another iPush. */
+  }
 
   /* then do the push */
   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
@@ -1769,14 +1962,14 @@ genIpush (iCode * ic)
   if (isPair (AOP (IC_LEFT (ic))))
     {
       _G.stack.pushed += 2;
-      emitcode ("push", "%s", getPairName (AOP (IC_LEFT (ic))));
+      emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
     }
   else
     {
       if (size == 2)
        {
          fetchHL (AOP (IC_LEFT (ic)));
-         emitcode ("push", "hl");
+         emit2 ("push hl");
          spillPair (PAIR_HL);
          _G.stack.pushed += 2;
          goto release;
@@ -1784,11 +1977,11 @@ genIpush (iCode * ic)
       if (size == 4)
        {
          fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
-         emitcode ("push", "hl");
+         emit2 ("push hl");
          spillPair (PAIR_HL);
          _G.stack.pushed += 2;
          fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
-         emitcode ("push", "hl");
+         emit2 ("push hl");
          spillPair (PAIR_HL);
          _G.stack.pushed += 2;
          goto release;
@@ -1807,8 +2000,8 @@ genIpush (iCode * ic)
              l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
              emit2 ("ld a,%s", l);
            }
-         emitcode ("push", "af");
-         emitcode ("inc", "sp");
+         emit2 ("push af");
+         emit2 ("inc sp");
          _G.stack.pushed++;
        }
     }
@@ -1834,14 +2027,14 @@ genIpop (iCode * ic)
   offset = (size - 1);
   if (isPair (AOP (IC_LEFT (ic))))
     {
-      emitcode ("pop", getPairName (AOP (IC_LEFT (ic))));
+      emit2 ("pop %s", getPairName (AOP (IC_LEFT (ic))));
     }
   else
     {
       while (size--)
        {
-         emitcode ("dec", "sp");
-         emitcode ("pop", "hl");
+         emit2 ("dec sp");
+         emit2 ("pop hl");
          spillPair (PAIR_HL);
          aopPut (AOP (IC_LEFT (ic)), "l", offset--);
        }
@@ -1850,22 +2043,30 @@ genIpop (iCode * ic)
   freeAsmop (IC_LEFT (ic), NULL, ic);
 }
 
-static int
-_isPairUsed (iCode * ic, PAIR_ID pairId)
+/* This is quite unfortunate */
+static void
+setArea (int inHome)
 {
-  int ret = 0;
-  switch (pairId)
-    {
-    case PAIR_DE:
-      if (bitVectBitValue (ic->rUsed, D_IDX))
-       ret++;
-      if (bitVectBitValue (ic->rUsed, E_IDX))
-       ret++;
-      break;
-    default:
-      wassert (0);
-    }
-  return ret;
+  /*
+    static int lastArea = 0;
+
+     if (_G.in_home != inHome) {
+     if (inHome) {
+     const char *sz = port->mem.code_name;
+     port->mem.code_name = "HOME";
+     emit2("!area", CODE_NAME);
+     port->mem.code_name = sz;
+     }
+     else
+     emit2("!area", CODE_NAME); */
+  _G.in_home = inHome;
+  //    }
+}
+
+static bool
+isInHome (void)
+{
+  return _G.in_home;
 }
 
 static int
@@ -1888,12 +2089,20 @@ _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
        {
          if (pairId == PAIR_DE)
            {
-             emit2 ("; name %s", aop->aopu.aop_reg[i]->name);
+             emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
              if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
                ret++;
              if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
                ret++;
            }
+          else if (pairId == PAIR_BC)
+            {
+             emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
+             if (!strcmp (aop->aopu.aop_reg[i]->name, "c"))
+               ret++;
+             if (!strcmp (aop->aopu.aop_reg[i]->name, "b"))
+               ret++;
+            }
          else
            {
              wassert (0);
@@ -1905,117 +2114,81 @@ _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
   return ret;
 }
 
-/* This is quite unfortunate */
-static void
-setArea (int inHome)
-{
-  static int lastArea = 0;
-
-  /*
-     if (_G.in_home != inHome) {
-     if (inHome) {
-     const char *sz = port->mem.code_name;
-     port->mem.code_name = "HOME";
-     emit2("!area", CODE_NAME);
-     port->mem.code_name = sz;
-     }
-     else
-     emit2("!area", CODE_NAME); */
-  _G.in_home = inHome;
-  //    }
-}
-
-static bool
-isInHome (void)
-{
-  return _G.in_home;
-}
-
 /** Emit the code for a call statement
  */
 static void
 emitCall (iCode * ic, bool ispcall)
 {
-  int pushed_de = 0;
   sym_link *detype = getSpec (operandType (IC_LEFT (ic)));
 
+  bitVect *rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
+
   /* if caller saves & we have not saved then */
   if (!ic->regsSaved)
     {
       /* PENDING */
     }
 
+  _saveRegsForCall(ic, _G.sendSet ? elementsInSet(_G.sendSet) : 0);
+
   /* if send set is not empty then assign */
-  if (sendSet)
+  if (_G.sendSet)
     {
       iCode *sic;
       int send = 0;
-      int n = elementsInSet (sendSet);
-      if (IS_Z80 && n == 2 && _isPairUsed (ic, PAIR_DE))
-       {
-         /* Only push de if it is used and if it's not used
-            in the return value */
-         /* Panic if partly used */
-         if (_opUsesPair (IC_RESULT (ic), ic, PAIR_DE) == 1)
-           {
-             emit2 ("; Warning: de crossover");
-           }
-         else if (!_opUsesPair (IC_RESULT (ic), ic, PAIR_DE))
-           {
-             /* Store away de */
-             _push (PAIR_DE);
-             pushed_de = 1;
-           }
-       }
-      /* PENDING: HACK */
-      if (IS_Z80 && n == 2)
-       {
-         /* Want to load HL first, then DE as HL may = DE */
-         sic = setFirstItem (sendSet);
-         sic = setNextItem (sendSet);
-         aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
-         fetchPair (PAIR_HL, AOP (IC_LEFT (sic)));
-         send++;
-         freeAsmop (IC_LEFT (sic), NULL, sic);
-         sic = setFirstItem (sendSet);
-         aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
-         fetchPair (PAIR_DE, AOP (IC_LEFT (sic)));
-         send++;
-         freeAsmop (IC_LEFT (sic), NULL, sic);
-       }
-      else
-       {
-         for (sic = setFirstItem (sendSet); sic;
-              sic = setNextItem (sendSet))
-           {
-             int size;
-             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
-             size = AOP_SIZE (IC_LEFT (sic));
-             wassert (size <= 2);
-             /* Always send in pairs */
-             switch (send)
-               {
-               case 0:
-                 if (IS_Z80 && n == 1)
-                   fetchPair (PAIR_HL, AOP (IC_LEFT (sic)));
-                 else
-                   fetchPair (PAIR_DE, AOP (IC_LEFT (sic)));
-                 break;
-               case 1:
-                 fetchPair (PAIR_HL, AOP (IC_LEFT (sic)));
-                 break;
-               default:
-                 /* Send set too big */
-                 wassert (0);
-               }
-             send++;
-             freeAsmop (IC_LEFT (sic), NULL, sic);
-           }
-       }
-      sendSet = NULL;
-      if (pushed_de)
-       {
-       }
+      int nSend = elementsInSet(_G.sendSet);
+      bool swapped = FALSE;
+
+      int _z80_sendOrder[] = {
+        PAIR_BC, PAIR_DE
+      };
+
+      if (nSend > 1) {
+        /* Check if the parameters are swapped.  If so route through hl instead. */
+        wassertl (nSend == 2, "Pedantic check.  Code only checks for the two send items case.");
+
+        sic = setFirstItem(_G.sendSet);
+        sic = setNextItem(_G.sendSet);
+
+        if (_opUsesPair (IC_LEFT(sic), sic, _z80_sendOrder[0])) {
+          /* The second send value is loaded from one the one that holds the first
+             send, i.e. it is overwritten. */
+          /* Cache the first in HL, and load the second from HL instead. */
+          emit2 ("ld h,%s", _pairs[_z80_sendOrder[0]].h);
+          emit2 ("ld l,%s", _pairs[_z80_sendOrder[0]].l);
+
+          swapped = TRUE;
+        }
+      }
+
+      for (sic = setFirstItem (_G.sendSet); sic;
+           sic = setNextItem (_G.sendSet))
+        {
+          int size;
+          aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
+
+          size = AOP_SIZE (IC_LEFT (sic));
+          wassertl (size <= 2, "Tried to send a parameter that is bigger than two bytes");
+          wassertl (_z80_sendOrder[send] != PAIR_INVALID, "Tried to send more parameters than we have registers for");
+
+          // PENDING: Mild hack
+          if (swapped == TRUE && send == 1) {
+            if (size > 1) {
+              emit2 ("ld %s,h", _pairs[_z80_sendOrder[send]].h);
+            }
+            else {
+              emit2 ("ld %s,!zero", _pairs[_z80_sendOrder[send]].h);
+            }
+            emit2 ("ld %s,l", _pairs[_z80_sendOrder[send]].l);
+          }
+          else {
+            fetchPair(_z80_sendOrder[send], AOP (IC_LEFT (sic)));
+          }
+
+          send++;
+          freeAsmop (IC_LEFT (sic), NULL, sic);
+        }
+      _G.sendSet = NULL;
     }
 
   if (ispcall)
@@ -2028,15 +2201,14 @@ emitCall (iCode * ic, bool ispcall)
 
       if (isLitWord (AOP (IC_LEFT (ic))))
        {
-         emitcode ("", "; Special case where the pCall is to a constant");
-         emitcode ("call", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
+         emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
        }
       else
        {
          symbol *rlbl = newiTempLabel (NULL);
          spillPair (PAIR_HL);
          emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
-         emitcode ("push", "hl");
+         emit2 ("push hl");
          _G.stack.pushed += 2;
 
          fetchHL (AOP (IC_LEFT (ic)));
@@ -2065,6 +2237,9 @@ emitCall (iCode * ic, bool ispcall)
     }
   spillCached ();
 
+  /* Mark the regsiters as restored. */
+  _G.saves.saved = FALSE;
+
   /* if we need assign a result value */
   if ((IS_ITEMP (IC_RESULT (ic)) &&
        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
@@ -2072,9 +2247,7 @@ emitCall (iCode * ic, bool ispcall)
       IS_TRUE_SYMOP (IC_RESULT (ic)))
     {
 
-      accInUse++;
       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
-      accInUse--;
 
       assignResultValue (IC_RESULT (ic));
 
@@ -2082,9 +2255,10 @@ emitCall (iCode * ic, bool ispcall)
     }
 
   /* adjust the stack for parameters if required */
-  if (IC_LEFT (ic)->parmBytes)
+  if (ic->parmBytes)
     {
-      int i = IC_LEFT (ic)->parmBytes;
+      int i = ic->parmBytes;
+
       _G.stack.pushed -= i;
       if (IS_GB)
        {
@@ -2095,25 +2269,77 @@ emitCall (iCode * ic, bool ispcall)
          spillCached ();
          if (i > 6)
            {
-             emitcode ("ld", "hl,#%d", i);
-             emitcode ("add", "hl,sp");
-             emitcode ("ld", "sp,hl");
+             emit2 ("ld hl,#%d", i);
+             emit2 ("add hl,sp");
+             emit2 ("ld sp,hl");
            }
          else
            {
              while (i > 1)
                {
-                 emitcode ("pop", "hl");
+                 emit2 ("pop hl");
                  i -= 2;
                }
              if (i)
-               emitcode ("inc", "sp");
+               emit2 ("inc sp");
            }
          spillCached ();
        }
     }
-  if (pushed_de)
-    _pop (PAIR_DE);
+
+  if (_G.stack.pushedDE) 
+    {
+      bool dInUse = bitVectBitValue(rInUse, D_IDX);
+      bool eInUse = bitVectBitValue(rInUse, E_IDX);
+
+      if (dInUse && eInUse) 
+        {
+          _pop (PAIR_DE);
+        }
+      else if (dInUse)
+        {
+          _pop(PAIR_HL);
+          emit2 ("ld d,h");
+        }
+      else if (eInUse)
+        {
+          _pop(PAIR_HL);
+          emit2 ("ld e,l");
+        }
+      else
+        {
+          wassertl (0, "Neither D or E were in use but it was pushed.");
+        }
+      _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) 
+        {
+          _pop (PAIR_BC);
+        }
+      else if (bInUse)
+        {
+          _pop(PAIR_HL);
+          emit2 ("ld b,h");
+        }
+      else if (cInUse)
+        {
+          _pop(PAIR_HL);
+          emit2 ("ld c,l");
+        }
+      else
+        {
+          wassertl (0, "Neither B or C were in use but it was pushed.");
+        }
+      _G.stack.pushedBC = FALSE;
+    }
 }
 
 /*-----------------------------------------------------------------*/
@@ -2122,7 +2348,6 @@ emitCall (iCode * ic, bool ispcall)
 static void
 genCall (iCode * ic)
 {
-  sym_link *detype = getSpec (operandType (IC_LEFT (ic)));
   emitCall (ic, FALSE);
 }
 
@@ -2165,39 +2390,50 @@ genFunction (iCode * ic)
   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
   sym_link *fetype;
 
-  nregssaved = 0;
+#if CALLEE_SAVES
+  bool bcInUse = FALSE;
+  bool deInUse = FALSE;
+#endif
+
   setArea (IS_NONBANKED (sym->etype));
 
-  /* PENDING: hack */
-  if (!IS_STATIC (sym->etype))
-    {
-      addSetIfnotP (&publics, sym);
-    }
+  /* PENDING: Reset the receive offset as it doesn't seem to get reset anywhere
+     else.
+  */
+  _G.receiveOffset = 0;
 
-  /* create the function header */
+  /* Record the last function name for debugging. */
+  _G.lastFunctionName = sym->rname;
+  
+  /* Create the function header */
   emit2 ("!functionheader", sym->name);
   /* PENDING: portability. */
   emit2 ("__%s_start:", sym->rname);
   emit2 ("!functionlabeldef", sym->rname);
 
+  if (options.profile) 
+    {
+      emit2 ("!profileenter");
+    }
+
   fetype = getSpec (operandType (IC_LEFT (ic)));
 
   /* if critical function then turn interrupts off */
   if (SPEC_CRTCL (fetype))
     emit2 ("!di");
 
-  /* if this is an interrupt service routine then
-     save acc, b, dpl, dph  */
+  /* if this is an interrupt service routine then save all potentially used registers. */
   if (IS_ISR (sym->etype))
     {
       emit2 ("!pusha");
     }
+
   /* PENDING: callee-save etc */
 
-  /* If BC or DE are used, then push */
-  _G.stack.pushed_bc = 0;
-  _G.stack.pushed_de = 0;
   _G.stack.param_offset = 0;
+
+#if CALLEE_SAVES
+  /* Detect which registers are used. */
   if (sym->regsUsed)
     {
       int i;
@@ -2209,28 +2445,39 @@ genFunction (iCode * ic)
                {
                case C_IDX:
                case B_IDX:
-                 _G.stack.pushed_bc = 1;
+                  bcInUse = TRUE;
                  break;
                case D_IDX:
                case E_IDX:
-                 if (IS_Z80)
-                   _G.stack.pushed_de = 1;
+                 if (IS_Z80) {
+                    deInUse = TRUE;
+                  }
+                  else {
+                    /* Other systems use DE as a temporary. */
+                  }
                  break;
                }
            }
        }
-      if (_G.stack.pushed_bc)
-       {
-         emit2 ("push bc");
-         _G.stack.param_offset += 2;
-       }
-      if (_G.stack.pushed_de)
-       {
-         emit2 ("push de");
-         _G.stack.param_offset += 2;
-       }
     }
 
+  if (bcInUse) 
+    {
+      emit2 ("push bc");
+      _G.stack.param_offset += 2;
+    }
+
+  _G.stack.pushedBC = bcInUse;
+
+  if (deInUse)
+    {
+      emit2 ("push de");
+      _G.stack.param_offset += 2;
+    }
+
+  _G.stack.pushedDE = deInUse;
+#endif
+
   /* adjust the stack for the function */
   _G.stack.last = sym->stack;
 
@@ -2251,7 +2498,7 @@ genEndFunction (iCode * ic)
 
   if (IS_ISR (sym->etype))
     {
-      wassert (0);
+      wassertl (0, "Tried to close an interrupt support function");
     }
   else
     {
@@ -2260,35 +2507,42 @@ genEndFunction (iCode * ic)
 
       /* PENDING: calleeSave */
 
-      /* if debug then send end of function */
-      if (options.debug && currFunc)
-       {
-         debugLine = 1;
-         emitcode ("", "C$%s$%d$%d$%d ==.",
-                   FileBaseName (ic->filename), currFunc->lastLine,
-                   ic->level, ic->block);
-         if (IS_STATIC (currFunc->etype))
-           emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
-         else
-           emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
-         debugLine = 0;
-       }
       if (_G.stack.offset)
-       emit2 ("!leavex", _G.stack.offset);
+        {
+          emit2 ("!leavex", _G.stack.offset);
+        }
       else
-       emit2 ("!leave");
+        {
+          emit2 ("!leave");
+        }
+
+#if CALLEE_SAVES
+      if (_G.stack.pushedDE) 
+        {
+          emit2 ("pop de");
+          _G.stack.pushedDE = FALSE;
+        }
+
+      if (_G.stack.pushedDE) 
+        {
+          emit2 ("pop bc");
+          _G.stack.pushedDE = FALSE;
+        }
+#endif
+
+      if (options.profile) 
+        {
+          emit2 ("!profileexit");
+        }
+
 
-      if (_G.stack.pushed_de)
-       emit2 ("pop de");
-      if (_G.stack.pushed_bc)
-       emit2 ("pop bc");
       /* Both baned and non-banked just ret */
       emit2 ("ret");
 
       /* PENDING: portability. */
       emit2 ("__%s_end:", sym->rname);
     }
-  _G.flush_statics = 1;
+  _G.flushStatics = 1;
   _G.stack.pushed = 0;
   _G.stack.offset = 0;
 }
@@ -2299,7 +2553,7 @@ genEndFunction (iCode * ic)
 static void
 genRet (iCode * ic)
 {
-  char *l;
+    const char *l;
   /* Errk.  This is a hack until I can figure out how
      to cause dehl to spill on a call */
   int size, offset = 0;
@@ -2318,11 +2572,11 @@ genRet (iCode * ic)
     {
       if (IS_GB)
        {
-         emitcode ("ld", "de,%s", l);
+         emit2 ("ld de,%s", l);
        }
       else
        {
-         emitcode ("ld", "hl,%s", l);
+         emit2 ("ld hl,%s", l);
        }
     }
   else
@@ -2339,7 +2593,7 @@ genRet (iCode * ic)
              l = aopGet (AOP (IC_LEFT (ic)), offset,
                          FALSE);
              if (strcmp (_fReturn[offset], l))
-               emitcode ("ld", "%s,%s", _fReturn[offset++], l);
+               emit2 ("ld %s,%s", _fReturn[offset++], l);
            }
        }
     }
@@ -2392,9 +2646,9 @@ genPlusIncr (iCode * ic)
   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
     return FALSE;
 
-  emitcode ("", "; genPlusIncr");
+  emitDebug ("; genPlusIncr");
 
-  icount = floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+  icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
 
   /* If result is a pair */
   if (resultId != PAIR_INVALID)
@@ -2407,7 +2661,7 @@ genPlusIncr (iCode * ic)
       if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
        {
          fetchPair (resultId, AOP (IC_RIGHT (ic)));
-         emitcode ("add", "hl,%s", getPairName (AOP (IC_LEFT (ic))));
+         emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
          return TRUE;
        }
       if (icount > 5)
@@ -2422,7 +2676,7 @@ genPlusIncr (iCode * ic)
        }
       while (icount--)
        {
-         emitcode ("inc", "%s", getPairName (AOP (IC_RESULT (ic))));
+         emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic))));
        }
       return TRUE;
     }
@@ -2443,7 +2697,7 @@ genPlusIncr (iCode * ic)
       tlbl = newiTempLabel (NULL);
       while (size--)
        {
-         emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
+         emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
          if (size)
            {
              emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
@@ -2464,7 +2718,9 @@ genPlusIncr (iCode * ic)
   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
     {
       while (icount--)
-       emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
+        {
+          emit2 ("inc %s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
+        }
       return TRUE;
     }
 
@@ -2481,7 +2737,7 @@ outBitAcc (operand * result)
   /* if the result is a bit */
   if (AOP_TYPE (result) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to write A into a bit");
     }
   else
     {
@@ -2527,7 +2783,7 @@ genPlus (iCode * ic)
       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
     {
       /* Cant happen */
-      wassert (0);
+      wassertl (0, "Tried to add two bits");
     }
 
   /* if left in bit space & right literal */
@@ -2535,7 +2791,7 @@ genPlus (iCode * ic)
       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
     {
       /* Can happen I guess */
-      wassert (0);
+      wassertl (0, "Tried to add a bit to a literal");
     }
 
   /* if I can do an increment instead
@@ -2543,7 +2799,7 @@ genPlus (iCode * ic)
   if (genPlusIncr (ic) == TRUE)
     goto release;
 
-  emit2 ("; genPlusIncr failed");
+  emitDebug ("; Can't optimise plus by inc, falling back to the normal way");
 
   size = getDataSize (IC_RESULT (ic));
 
@@ -2551,16 +2807,17 @@ genPlus (iCode * ic)
   if (isPair (AOP (IC_RESULT (ic))))
     {
       char *left, *right;
-
       left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
       right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
-      if (left && right)
+
+      if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT && AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT &&
+          left && right)
        {
          /* It's a pair */
          /* PENDING: fix */
          char buffer[100];
          sprintf (buffer, "#(%s + %s)", left, right);
-         emitcode ("ld", "%s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
+         emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
          goto release;
        }
     }
@@ -2570,7 +2827,7 @@ genPlus (iCode * ic)
       /* Fetch into HL then do the add */
       spillPair (PAIR_HL);
       fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
-      emitcode ("add", "hl,%s", getPairName (AOP (IC_RIGHT (ic))));
+      emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
       goto release;
     }
 
@@ -2634,18 +2891,22 @@ genPlus (iCode * ic)
              commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
              goto release;
            }
-         else if (size == 4)
-           {
-             emit2 ("; WARNING: This add is probably broken.\n");
-           }
        }
+      if (size == 4)
+        {
+          /* Be paranoid on the GB with 4 byte variables due to how C
+             can be trashed by lda hl,n(sp).
+          */
+          _gbz80_emitAddSubLong (ic, TRUE);
+          goto release;
+        }
     }
 
   while (size--)
     {
       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
        {
-         MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
+         _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
          if (offset == 0)
            emit2 ("add a,%s",
                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
@@ -2655,7 +2916,7 @@ genPlus (iCode * ic)
        }
       else
        {
-         MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
+         _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
          if (offset == 0)
            emit2 ("add a,%s",
                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
@@ -2694,32 +2955,12 @@ genMinusDec (iCode * ic)
 
   size = getDataSize (IC_RESULT (ic));
 
-#if 0
-  /* if increment 16 bits in register */
-  if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
-      (size > 1) &&
-      (icount == 1))
-    {
-      symbol *tlbl = newiTempLabel (NULL);
-      emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE));
-      emitcode ("jp", "np," LABEL_STR, tlbl->key + 100);
-
-      emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE));
-      if (size == 4)
-       {
-         wassert (0);
-       }
-      emitLabel (tlbl->key + 100);
-      return TRUE;
-    }
-#endif
-
   /* if decrement 16 bits in register */
   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
       (size > 1) && isPair (AOP (IC_RESULT (ic))))
     {
       while (icount--)
-       emitcode ("dec", "%s", getPairName (AOP (IC_RESULT (ic))));
+       emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
       return TRUE;
     }
 
@@ -2729,10 +2970,27 @@ genMinusDec (iCode * ic)
       movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
       movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
       while (icount--)
-       emitcode ("dec", "%s", getPairName (AOP (IC_RESULT (ic))));
+       emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
+      return TRUE;
+    }
+
+  /* if increment 16 bits in register */
+  if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
+      (size == 2)
+      )
+    {
+      fetchPair (_getTempPairId(), AOP (IC_RESULT (ic)));
+
+      while (icount--) {
+        emit2 ("dec %s", _getTempPairName());
+      }
+
+      commitPair (AOP (IC_RESULT (ic)), _getTempPairId());
+
       return TRUE;
     }
 
+
   /* if the sizes are greater than 1 then we cannot */
   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
       AOP_SIZE (IC_LEFT (ic)) > 1)
@@ -2743,7 +3001,7 @@ genMinusDec (iCode * ic)
   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
     {
       while (icount--)
-       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
+       emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
       return TRUE;
     }
 
@@ -2768,7 +3026,7 @@ genMinus (iCode * ic)
   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to subtract two bits");
       goto release;
     }
 
@@ -2826,24 +3084,28 @@ genMinus (iCode * ic)
              aopPut (AOP (IC_RESULT (ic)), "e", 0);
              goto release;
            }
-         else if (size == 4)
-           {
-             emit2 ("; WARNING: This sub is probably broken.\n");
-           }
        }
+      if (size == 4)
+        {
+          /* Be paranoid on the GB with 4 byte variables due to how C
+             can be trashed by lda hl,n(sp).
+          */
+          _gbz80_emitAddSubLong (ic, FALSE);
+          goto release;
+        }
     }
 
   /* if literal, add a,#-lit, else normal subb */
   while (size--)
     {
-      MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
+      _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
        {
          if (!offset)
-           emitcode ("sub", "a,%s",
+           emit2 ("sub a,%s",
                      aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
          else
-           emitcode ("sbc", "a,%s",
+           emit2 ("sbc a,%s",
                      aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
        }
       else
@@ -2860,7 +3122,9 @@ genMinus (iCode * ic)
   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
       AOP_SIZE (IC_LEFT (ic)) == 3 &&
       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
-    wassert (0);
+    {
+      wassertl (0, "Tried to subtract on a long pointer");
+    }
 
 release:
   freeAsmop (IC_LEFT (ic), NULL, ic);
@@ -2875,7 +3139,7 @@ static void
 genMult (iCode * ic)
 {
   /* Shouldn't occur - all done through function calls */
-  wassert (0);
+  wassertl (0, "Multiplication is handled through support function calls");
 }
 
 /*-----------------------------------------------------------------*/
@@ -2885,7 +3149,7 @@ static void
 genDiv (iCode * ic)
 {
   /* Shouldn't occur - all done through function calls */
-  wassert (0);
+  wassertl (0, "Division is handled through support function calls");
 }
 
 /*-----------------------------------------------------------------*/
@@ -2955,7 +3219,7 @@ genIfxJump (iCode * ic, char *jval)
   /* Z80 can do a conditional long jump */
   if (!strcmp (jval, "a"))
     {
-      emitcode ("or", "a,a");
+      emit2 ("or a,a");
     }
   else if (!strcmp (jval, "c"))
     {
@@ -2965,7 +3229,7 @@ genIfxJump (iCode * ic, char *jval)
     }
   else
     {
-      emitcode ("bit", "%s,a", jval);
+      emit2 ("bit %s,a", jval);
     }
   emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
 
@@ -2973,11 +3237,13 @@ genIfxJump (iCode * ic, char *jval)
   ic->generated = 1;
 }
 
+#if DISABLED
 static const char *
 _getPairIdName (PAIR_ID id)
 {
   return _pairs[id].name;
 }
+#endif
 
 /** Generic compare for > or <
  */
@@ -2994,7 +3260,7 @@ genCmp (operand * left, operand * right,
       AOP_TYPE (right) == AOP_CRY)
     {
       /* Cant happen on the Z80 */
-      wassert (0);
+      wassertl (0, "Tried to compare two bits");
     }
   else
     {
@@ -3007,56 +3273,58 @@ genCmp (operand * left, operand * right,
       if ((size == 1) &&
          (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
        {
-         emitcode ("ld", "a,%s", aopGet (AOP (left), offset, FALSE));
+         emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
          if (sign)
            {
              emit2 ("xor a,!immedbyte", 0x80);
              emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
            }
          else
-           emitcode ("cp", "%s", aopGet (AOP (right), offset, FALSE));
-       }
+           emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
+       }
+      else if (size == 4 && IS_GB && requiresHL(AOP(right)) && requiresHL(AOP(left)))
+        {
+          // On the Gameboy we can't afford to adjust HL as it may trash the carry.
+          // Pull left into DE and right into HL
+          aopGet (AOP(left), LSB, FALSE);
+          emit2 ("ld d,h");
+          emit2 ("ld e,l");
+          aopGet (AOP(right), LSB, FALSE);
+
+          while (size--)
+            {
+              if (size == 0 && sign)
+                {
+                  // Highest byte when signed needs the bits flipped
+                  // Save the flags
+                  emit2 ("push af");
+                  emit2 ("ld a,(de)");
+                  emit2 ("xor #0x80");
+                  emit2 ("ld e,a");
+                  emit2 ("ld a,(hl)");
+                  emit2 ("xor #0x80");
+                  emit2 ("ld d,a");
+                  emit2 ("pop af");
+                  emit2 ("ld a,e");
+                  emit2 ("%s a,d", offset == 0 ? "sub" : "sbc");
+                }
+              else
+                {
+                  emit2 ("ld a,(de)");
+                  emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc");
+                }
+              
+              if (size != 0)
+                {
+                  emit2 ("inc hl");
+                  emit2 ("inc de");
+                }
+              offset++;
+            }
+          spillPair (PAIR_HL);
+        }
       else
        {
-         /* Special cases:
-            On the GB:
-            If the left or the right is a lit:
-            Load -lit into HL, add to right via, check sense.
-          */
-         if (size == 2 && (AOP_TYPE (right) == AOP_LIT || AOP_TYPE (left) == AOP_LIT))
-           {
-             PAIR_ID id = PAIR_DE;
-             asmop *lit = AOP (right);
-             asmop *op = AOP (left);
-             swap_sense = TRUE;
-
-             if (AOP_TYPE (left) == AOP_LIT)
-               {
-                 swap_sense = FALSE;
-                 lit = AOP (left);
-                 op = AOP (right);
-               }
-             if (sign)
-               {
-                 emit2 ("ld e,%s", aopGet (op, 0, 0));
-                 emit2 ("ld a,%s", aopGet (op, 1, 0));
-                 emit2 ("xor a,!immedbyte", 0x80);
-                 emit2 ("ld d,a");
-               }
-             else
-               {
-                 id = getPairId (op);
-                 if (id == PAIR_INVALID)
-                   {
-                     fetchPair (PAIR_DE, op);
-                     id = PAIR_DE;
-                   }
-               }
-             spillPair (PAIR_HL);
-             emit2 ("ld hl,%s", fetchLitSpecial (lit, TRUE, sign));
-             emit2 ("add hl,%s", _getPairIdName (id));
-             goto release;
-           }
          if (AOP_TYPE (right) == AOP_LIT)
            {
              lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
@@ -3066,19 +3334,19 @@ genCmp (operand * left, operand * right,
                  if (!sign)
                    {
                      /* No sign so it's always false */
-                     CLRC;
+                     _clearCarry();
                    }
                  else
                    {
                      /* Just load in the top most bit */
-                     MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
+                     _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
                      if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
                        {
                          genIfxJump (ifx, "7");
                          return;
                        }
                      else
-                       emitcode ("rlc", "a");
+                       emit2 ("rlc a");
                    }
                  goto release;
                }
@@ -3096,9 +3364,9 @@ genCmp (operand * left, operand * right,
                }
              else
                {
-                 emitcode ("ld", "a,%s", aopGet (AOP (left), size - 1, FALSE));
+                 emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE));
                  emit2 ("xor a,!immedbyte", 0x80);
-                 emitcode ("ld", "%s,a", _fTmp[0]);
+                 emit2 ("ld %s,a", _fTmp[0]);
                  fDidXor = TRUE;
                }
              if (AOP_TYPE (right) == AOP_LIT)
@@ -3110,34 +3378,28 @@ genCmp (operand * left, operand * right,
                }
              else
                {
-                 emitcode ("ld", "a,%s", aopGet (AOP (right), size - 1, FALSE));
+                 emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE));
                  emit2 ("xor a,!immedbyte", 0x80);
-                 emitcode ("ld", "%s,a", _fTmp[1]);
+                 emit2 ("ld %s,a", _fTmp[1]);
                  fDidXor = TRUE;
                }
-             if (!fDidXor)
-               CLRC;
-           }
-         else
-           {
-             CLRC;
            }
          while (size--)
            {
              /* Do a long subtract */
              if (!sign || size)
                {
-                 MOVA (aopGet (AOP (left), offset, FALSE));
+                 _moveA (aopGet (AOP (left), offset, FALSE));
                }
              if (sign && size == 0)
                {
-                 emitcode ("ld", "a,%s", _fTmp[0]);
-                 emitcode ("sbc", "a,%s", _fTmp[1]);
+                 emit2 ("ld a,%s", _fTmp[0]);
+                 emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", _fTmp[1]);
                }
              else
                {
                  /* Subtract through, propagating the carry */
-                 emitcode ("sbc", "a,%s ; 2", aopGet (AOP (right), offset++, FALSE));
+                 emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset++, FALSE));
                }
            }
        }
@@ -3247,19 +3509,19 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
     {
       if (lit == 0)
        {
-         emitcode ("ld", "a,%s", aopGet (AOP (left), offset, FALSE));
+         emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
          if (size > 1)
            {
              size--;
              offset++;
              while (size--)
                {
-                 emitcode ("or", "a,%s", aopGet (AOP (left), offset, FALSE));
+                 emit2 ("or a,%s", aopGet (AOP (left), offset, FALSE));
                }
            }
          else
            {
-             emitcode ("or", "a,a");
+             emit2 ("or a,a");
            }
          emit2 ("jp nz,!tlabel", lbl->key + 100);
        }
@@ -3267,11 +3529,11 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
        {
          while (size--)
            {
-             emitcode ("ld", "a,%s ; 2", aopGet (AOP (left), offset, FALSE));
+             emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
              if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
-               emitcode ("or", "a,a");
+               emit2 ("or a,a");
              else
-               emitcode ("cp", "a,%s", aopGet (AOP (right), offset, FALSE));
+               emit2 ("cp a,%s", aopGet (AOP (right), offset, FALSE));
              emit2 ("jp nz,!tlabel", lbl->key + 100);
              offset++;
            }
@@ -3285,14 +3547,14 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
     {
       while (size--)
        {
-         MOVA (aopGet (AOP (left), offset, FALSE));
+         _moveA (aopGet (AOP (left), offset, FALSE));
          if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
              ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
            /* PENDING */
            emit2 ("jp nz,!tlabel", lbl->key + 100);
          else
            {
-             emitcode ("cp", "%s ; 4", aopGet (AOP (right), offset, FALSE));
+             emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
              emit2 ("jp nz,!tlabel", lbl->key + 100);
            }
          offset++;
@@ -3304,8 +3566,8 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
       /* PENDING: is this required? */
       while (size--)
        {
-         MOVA (aopGet (AOP (right), offset, FALSE));
-         emitcode ("cp", "%s ; 5", aopGet (AOP (left), offset, FALSE));
+         _moveA (aopGet (AOP (right), offset, FALSE));
+         emit2 ("cp %s", aopGet (AOP (left), offset, FALSE));
          emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
          offset++;
        }
@@ -3326,7 +3588,7 @@ gencjne (operand * left, operand * right, symbol * lbl)
   emit2 ("ld a,!one");
   emit2 ("!shortjp !tlabel", tlbl->key + 100);
   emitLabel (lbl->key + 100);
-  emitcode ("xor", "a,a");
+  emit2 ("xor a,a");
   emitLabel (tlbl->key + 100);
 }
 
@@ -3342,6 +3604,8 @@ genCmpEq (iCode * ic, iCode * ifx)
   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
 
+  emitDebug ("; genCmpEq: left %u, right %u, result %u\n", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
+
   /* Swap operands if it makes the operation easier. ie if:
      1.  Left is a literal.
    */
@@ -3359,7 +3623,7 @@ genCmpEq (iCode * ic, iCode * ifx)
       if (AOP_TYPE (left) == AOP_CRY &&
          ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
        {
-         wassert (0);
+         wassertl (0, "Tried to compare two bits");
        }
       else
        {
@@ -3389,7 +3653,7 @@ genCmpEq (iCode * ic, iCode * ifx)
   if (AOP_TYPE (left) == AOP_CRY &&
       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
     {
-      wassert (0);
+      wassertl (0, "Tried to compare a bit to either a literal or another bit");
     }
   else
     {
@@ -3460,14 +3724,14 @@ genAndOp (iCode * ic)
   if (AOP_TYPE (left) == AOP_CRY &&
       AOP_TYPE (right) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to and two bits");
     }
   else
     {
       tlbl = newiTempLabel (NULL);
-      toBoolean (left);
+      _toBoolean (left);
       emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
-      toBoolean (right);
+      _toBoolean (right);
       emitLabel (tlbl->key + 100);
       outBitAcc (result);
     }
@@ -3497,14 +3761,14 @@ genOrOp (iCode * ic)
   if (AOP_TYPE (left) == AOP_CRY &&
       AOP_TYPE (right) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to OR two bits");
     }
   else
     {
       tlbl = newiTempLabel (NULL);
-      toBoolean (left);
+      _toBoolean (left);
       emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
-      toBoolean (right);
+      _toBoolean (right);
       emitLabel (tlbl->key + 100);
       outBitAcc (result);
     }
@@ -3574,15 +3838,6 @@ genAnd (iCode * ic, iCode * ifx)
   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
 
-#ifdef DEBUG_TYPE
-  emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
-           AOP_TYPE (result),
-           AOP_TYPE (left), AOP_TYPE (right));
-  emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
-           AOP_SIZE (result),
-           AOP_SIZE (left), AOP_SIZE (right));
-#endif
-
   /* 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))
@@ -3615,7 +3870,7 @@ genAnd (iCode * ic, iCode * ifx)
 
   if (AOP_TYPE (left) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to perform an AND with a bit as an operand");
       goto release;
     }
 
@@ -3625,80 +3880,46 @@ genAnd (iCode * ic, iCode * ifx)
       (AOP_TYPE (result) == AOP_CRY) &&
       (AOP_TYPE (left) != AOP_CRY))
     {
-      int posbit = isLiteralBit (lit);
-      /* left &  2^n */
-      if (posbit)
-       {
-         posbit--;
-         MOVA (aopGet (AOP (left), posbit >> 3, FALSE));
-         // bit = left & 2^n
-         if (size)
-           {
-             wassert (0);
-             emitcode ("mov", "c,acc.%d", posbit & 0x07);
-           }
-         // if(left &  2^n)
-         else
-           {
-             if (ifx)
-               {
-                 sprintf (buffer, "%d", posbit & 0x07);
-                 genIfxJump (ifx, buffer);
-               }
-             else
-               {
-                 wassert (0);
-               }
-             goto release;
-           }
-       }
-      else
-       {
-         symbol *tlbl = newiTempLabel (NULL);
-         int sizel = AOP_SIZE (left);
-         if (size)
-           {
-             wassert (0);
-             emitcode ("setb", "c");
-           }
-         while (sizel--)
-           {
-             if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
-               {
-                 MOVA (aopGet (AOP (left), offset, FALSE));
-                 // byte ==  2^n ?
-                 if ((posbit = isLiteralBit (bytelit)) != 0)
-                   {
-                     wassert (0);
-                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
-                   }
-                 else
-                   {
-                     if (bytelit != 0x0FFL)
-                       emitcode ("and", "a,%s",
-                                 aopGet (AOP (right), offset, FALSE));
-                     else
-                       /* For the flags */
-                       emit2 ("or a,a");
-                     emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
-                   }
-               }
+      symbol *tlbl = newiTempLabel (NULL);
+      int sizel = AOP_SIZE (left);
+      if (size)
+        {
+          /* PENDING: Test case for this. */
+          emit2 ("scf");
+        }
+      while (sizel--)
+        {
+          if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
+            {
+              _moveA (aopGet (AOP (left), offset, FALSE));
+              if (bytelit != 0x0FFL)
+                {
+                  emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
+                }
+              else
+                {
+                  /* For the flags */
+                  emit2 ("or a,a");
+                }
+              emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+            }
              offset++;
-           }
-         // bit = left & literal
-         if (size)
-           {
-             emitcode ("clr", "c");
-             emit2 ("!tlabeldef", tlbl->key + 100);
-           }
-         // if(left & literal)
-         else
-           {
-             if (ifx)
-               jmpTrueOrFalse (ifx, tlbl);
-             goto release;
-           }
-       }
+        }
+      // bit = left & literal
+      if (size)
+        {
+          emit2 ("clr c");
+          emit2 ("!tlabeldef", tlbl->key + 100);
+        }
+      // if(left & literal)
+      else
+        {
+          if (ifx)
+            {
+              jmpTrueOrFalse (ifx, tlbl);
+            }
+          goto release;
+        }
       outBitC (result);
       goto release;
     }
@@ -3715,11 +3936,11 @@ genAnd (iCode * ic, iCode * ifx)
              else
                {
                  if (bytelit == 0)
-                   aopPut (AOP (result), zero, offset);
+                   aopPut (AOP (result), "!zero", offset);
                  else
                    {
-                     MOVA (aopGet (AOP (left), offset, FALSE));
-                     emitcode ("and", "a,%s",
+                     _moveA (aopGet (AOP (left), offset, FALSE));
+                     emit2 ("and a,%s",
                                aopGet (AOP (right), offset, FALSE));
                      aopPut (AOP (left), "a", offset);
                    }
@@ -3730,12 +3951,12 @@ genAnd (iCode * ic, iCode * ifx)
            {
              if (AOP_TYPE (left) == AOP_ACC)
                {
-                 wassert (0);
+                 wassertl (0, "Tried to perform an AND where the left operand is allocated into A");
                }
              else
                {
-                 MOVA (aopGet (AOP (left), offset, FALSE));
-                 emitcode ("and", "a,%s",
+                 _moveA (aopGet (AOP (left), offset, FALSE));
+                 emit2 ("and a,%s",
                            aopGet (AOP (right), offset, FALSE));
                  aopPut (AOP (left), "a", offset);
                }
@@ -3747,7 +3968,7 @@ genAnd (iCode * ic, iCode * ifx)
       // left & result in different registers
       if (AOP_TYPE (result) == AOP_CRY)
        {
-         wassert (0);
+         wassertl (0, "Tried to AND where the result is in carry");
        }
       else
        {
@@ -3766,18 +3987,18 @@ genAnd (iCode * ic, iCode * ifx)
                    }
                  else if (bytelit == 0)
                    {
-                     aopPut (AOP (result), zero, offset);
+                     aopPut (AOP (result), "!zero", offset);
                      continue;
                    }
                }
              // faster than result <- left, anl result,right
              // and better if result is SFR
              if (AOP_TYPE (left) == AOP_ACC)
-               emitcode ("and", "a,%s", aopGet (AOP (right), offset, FALSE));
+               emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
              else
                {
-                 MOVA (aopGet (AOP (left), offset, FALSE));
-                 emitcode ("and", "a,%s",
+                 _moveA (aopGet (AOP (left), offset, FALSE));
+                 emit2 ("and a,%s",
                            aopGet (AOP (right), offset, FALSE));
                }
              aopPut (AOP (result), "a", offset);
@@ -3801,20 +4022,12 @@ genOr (iCode * ic, iCode * ifx)
   operand *left, *right, *result;
   int size, offset = 0;
   unsigned long lit = 0L;
+  int bytelit = 0;
 
   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
 
-#if 1
-  emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
-           AOP_TYPE (result),
-           AOP_TYPE (left), AOP_TYPE (right));
-  emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
-           AOP_SIZE (result),
-           AOP_SIZE (left), AOP_SIZE (right));
-#endif
-
   /* 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))
@@ -3847,15 +4060,39 @@ genOr (iCode * ic, iCode * ifx)
 
   if (AOP_TYPE (left) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to OR where left is a bit");
       goto release;
     }
 
+  // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
+  // bit = val | 0xZZ     - size = 1, ifx = FALSE -
   if ((AOP_TYPE (right) == AOP_LIT) &&
       (AOP_TYPE (result) == AOP_CRY) &&
       (AOP_TYPE (left) != AOP_CRY))
     {
-      wassert (0);
+      symbol *tlbl = newiTempLabel (NULL);
+      int sizel = AOP_SIZE (left);
+
+      if (size)
+        {
+          wassertl (0, "Result is assigned to a bit");
+        }
+      /* PENDING: Modeled after the AND code which is inefficent. */
+      while (sizel--)
+        {
+          bytelit = (lit >> (offset * 8)) & 0x0FFL;
+
+          _moveA (aopGet (AOP (left), offset, FALSE));
+          /* OR with any literal is the same as OR with itself. */
+          emit2 ("or a,a");
+          emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+
+          offset++;
+        }
+      if (ifx)
+        {
+          jmpTrueOrFalse (ifx, tlbl);
+        }
       goto release;
     }
 
@@ -3870,8 +4107,8 @@ genOr (iCode * ic, iCode * ifx)
                continue;
              else
                {
-                 MOVA (aopGet (AOP (left), offset, FALSE));
-                 emitcode ("or", "a,%s",
+                 _moveA (aopGet (AOP (left), offset, FALSE));
+                 emit2 ("or a,%s",
                            aopGet (AOP (right), offset, FALSE));
                  aopPut (AOP (result), "a", offset);
                }
@@ -3879,11 +4116,11 @@ genOr (iCode * ic, iCode * ifx)
          else
            {
              if (AOP_TYPE (left) == AOP_ACC)
-               emitcode ("or", "a,%s", aopGet (AOP (right), offset, FALSE));
+               emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
              else
                {
-                 MOVA (aopGet (AOP (left), offset, FALSE));
-                 emitcode ("or", "a,%s",
+                 _moveA (aopGet (AOP (left), offset, FALSE));
+                 emit2 ("or a,%s",
                            aopGet (AOP (right), offset, FALSE));
                  aopPut (AOP (result), "a", offset);
                }
@@ -3895,7 +4132,7 @@ genOr (iCode * ic, iCode * ifx)
       // left & result in different registers
       if (AOP_TYPE (result) == AOP_CRY)
        {
-         wassert (0);
+         wassertl (0, "Result of OR is in a bit");
        }
       else
        for (; (size--); offset++)
@@ -3915,11 +4152,11 @@ genOr (iCode * ic, iCode * ifx)
            // faster than result <- left, anl result,right
            // and better if result is SFR
            if (AOP_TYPE (left) == AOP_ACC)
-             emitcode ("or", "a,%s", aopGet (AOP (right), offset, FALSE));
+             emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
            else
              {
-               MOVA (aopGet (AOP (left), offset, FALSE));
-               emitcode ("or", "a,%s",
+               _moveA (aopGet (AOP (left), offset, FALSE));
+               emit2 ("or a,%s",
                          aopGet (AOP (right), offset, FALSE));
              }
            aopPut (AOP (result), "a", offset);
@@ -3981,15 +4218,39 @@ genXor (iCode * ic, iCode * ifx)
 
   if (AOP_TYPE (left) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to XOR a bit");
       goto release;
     }
 
+  // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
+  // bit = val & 0xZZ     - size = 1, ifx = FALSE -
   if ((AOP_TYPE (right) == AOP_LIT) &&
       (AOP_TYPE (result) == AOP_CRY) &&
       (AOP_TYPE (left) != AOP_CRY))
     {
-      wassert (0);
+      symbol *tlbl = newiTempLabel (NULL);
+      int sizel = AOP_SIZE (left);
+
+      if (size)
+        {
+          /* PENDING: Test case for this. */
+          wassertl (0, "Tried to XOR left against a literal with the result going into a bit");
+        }
+      while (sizel--)
+        {
+          _moveA (aopGet (AOP (left), offset, FALSE));
+          emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
+          emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+          offset++;
+        }
+      if (ifx)
+        {
+          jmpTrueOrFalse (ifx, tlbl);
+        }
+      else
+        {
+          wassertl (0, "Result of XOR was destined for a bit");
+        }
       goto release;
     }
 
@@ -4004,20 +4265,22 @@ genXor (iCode * ic, iCode * ifx)
                continue;
              else
                {
-                 MOVA (aopGet (AOP (right), offset, FALSE));
-                 emitcode ("xor", "a,%s",
+                 _moveA (aopGet (AOP (right), offset, FALSE));
+                 emit2 ("xor a,%s",
                            aopGet (AOP (left), offset, FALSE));
-                 aopPut (AOP (result), "a", 0);
+                 aopPut (AOP (result), "a", offset);
                }
            }
          else
            {
              if (AOP_TYPE (left) == AOP_ACC)
-               emitcode ("xor", "a,%s", aopGet (AOP (right), offset, FALSE));
+                {
+                  emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
+                }
              else
                {
-                 MOVA (aopGet (AOP (right), offset, FALSE));
-                 emitcode ("xor", "a,%s",
+                 _moveA (aopGet (AOP (right), offset, FALSE));
+                 emit2 ("xor a,%s",
                            aopGet (AOP (left), offset, FALSE));
                  aopPut (AOP (result), "a", 0);
                }
@@ -4029,7 +4292,7 @@ genXor (iCode * ic, iCode * ifx)
       // left & result in different registers
       if (AOP_TYPE (result) == AOP_CRY)
        {
-         wassert (0);
+         wassertl (0, "Result of XOR is in a bit");
        }
       else
        for (; (size--); offset++)
@@ -4048,14 +4311,15 @@ genXor (iCode * ic, iCode * ifx)
              }
            // faster than result <- left, anl result,right
            // and better if result is SFR
-           if (AOP_TYPE (left) == AOP_ACC)
-             emitcode ("xor", "a,%s", aopGet (AOP (right), offset, FALSE));
+           if (AOP_TYPE (left) == AOP_ACC) 
+              {
+                emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
+              }
            else
              {
-               MOVA (aopGet (AOP (right), offset, FALSE));
-               emitcode ("xor", "a,%s",
+               _moveA (aopGet (AOP (right), offset, FALSE));
+               emit2 ("xor a,%s",
                          aopGet (AOP (left), offset, FALSE));
-               aopPut (AOP (result), "a", 0);
              }
            aopPut (AOP (result), "a", offset);
          }
@@ -4073,11 +4337,11 @@ release:
 static void
 genInline (iCode * ic)
 {
-  char buffer[MAX_INLINEASM];
-  char *bp = buffer;
-  char *bp1 = buffer;
+  char *buffer, *bp, *bp1;
 
-  inLine += (!options.asmpeep);
+  _G.lines.isInline += (!options.asmpeep);
+
+  buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
   strcpy (buffer, IC_INLINE (ic));
 
   /* emit each line as a code */
@@ -4086,7 +4350,7 @@ genInline (iCode * ic)
       if (*bp == '\n')
        {
          *bp++ = '\0';
-         emitcode (bp1, "");
+         emit2 (bp1);
          bp1 = bp;
        }
       else
@@ -4096,7 +4360,7 @@ genInline (iCode * ic)
              bp++;
              *bp = '\0';
              bp++;
-             emitcode (bp1, "");
+             emit2 (bp1);
              bp1 = bp;
            }
          else
@@ -4104,9 +4368,9 @@ genInline (iCode * ic)
        }
     }
   if (bp1 != bp)
-    emitcode (bp1, "");
-  /*     emitcode("",buffer); */
-  inLine -= (!options.asmpeep);
+    emit2 (bp1);
+  _G.lines.isInline -= (!options.asmpeep);
+
 }
 
 /*-----------------------------------------------------------------*/
@@ -4127,53 +4391,97 @@ genRLC (iCode * ic)
   wassert (0);
 }
 
+/*-----------------------------------------------------------------*/
+/* genGetHbit - generates code get highest order bit               */
+/*-----------------------------------------------------------------*/
+static void
+genGetHbit (iCode * ic)
+{
+  operand *left, *result;
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+  aopOp (left, ic, FALSE, FALSE);
+  aopOp (result, ic, FALSE, FALSE);
+
+  /* get the highest order byte into a */
+  emit2("ld a,%s", aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
+
+  if (AOP_TYPE (result) == AOP_CRY)
+    {
+      emit2 ("rl a");
+      outBitC (result);
+    }
+  else
+    {
+      emit2 ("rlc a");
+      /* PENDING: For re-target. */
+      emit2 ("and a,#1");
+      outAcc (result);
+    }
+
+
+  freeAsmop (left, NULL, ic);
+  freeAsmop (result, NULL, ic);
+}
+
+static void
+emitRsh2 (asmop *aop, int size, int is_signed)
+{
+  int offset = 0;
+
+  while (size--)
+    {
+      const char *l = aopGet (aop, size, FALSE);
+      if (offset == 0)
+        {
+          emit2 ("%s %s", is_signed ? "sra" : "srl", l);
+        }
+      else
+        {
+          emit2 ("rr %s", l);
+        }
+      offset++;
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* shiftR2Left2Result - shift right two bytes from left to result  */
 /*-----------------------------------------------------------------*/
 static void
 shiftR2Left2Result (operand * left, int offl,
                    operand * result, int offr,
-                   int shCount, int sign)
+                   int shCount, int is_signed)
 {
+  int size = 2;
+  symbol *tlbl, *tlbl1;
+
   movLeft2Result (left, offl, result, offr, 0);
   movLeft2Result (left, offl + 1, result, offr + 1, 0);
 
-  if (sign)
+  /*  if (AOP(result)->type == AOP_REG) { */
+  
+  tlbl = newiTempLabel (NULL);
+  tlbl1 = newiTempLabel (NULL);
+
+  /* Left is already in result - so now do the shift */
+  if (shCount <= 4)
     {
-      wassert (0);
+      while (shCount--)
+        {
+          emitRsh2 (AOP (result), size, is_signed);
+        }
     }
   else
     {
-      /*  if (AOP(result)->type == AOP_REG) { */
-      int size = 2;
-      int offset = 0;
-      symbol *tlbl, *tlbl1;
-      char *l;
-
-      tlbl = newiTempLabel (NULL);
-      tlbl1 = newiTempLabel (NULL);
+      emit2 ("ld a,!immedbyte+1", shCount);
+      emit2 ("!shortjp !tlabel", tlbl1->key + 100);
+      emitLabel (tlbl->key + 100);
 
-      /* Left is already in result - so now do the shift */
-      if (shCount > 1)
-       {
-         emit2 ("ld a,!immedbyte+1", shCount);
-         emit2 ("!shortjp !tlabel", tlbl1->key + 100);
-         emitLabel (tlbl->key + 100);
-       }
+      emitRsh2 (AOP (result), size, is_signed);
 
-      emitcode ("or", "a,a");
-      offset = size;
-      while (size--)
-       {
-         l = aopGet (AOP (result), --offset, FALSE);
-         emitcode ("rr", "%s", l);
-       }
-      if (shCount > 1)
-       {
-         emitLabel (tlbl1->key + 100);
-         emitcode ("dec", "a");
-         emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
-       }
+      emitLabel (tlbl1->key + 100);
+      emit2 ("dec a");
+      emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
     }
 }
 
@@ -4201,7 +4509,7 @@ shiftL2Left2Result (operand * left, int offl,
     int size = 2;
     int offset = 0;
     symbol *tlbl, *tlbl1;
-    char *l;
+    const char *l;
 
     tlbl = newiTempLabel (NULL);
     tlbl1 = newiTempLabel (NULL);
@@ -4214,16 +4522,25 @@ shiftL2Left2Result (operand * left, int offl,
        emitLabel (tlbl->key + 100);
       }
 
-    emitcode ("or", "a,a");
     while (size--)
       {
-       l = aopGet (AOP (result), offset++, FALSE);
-       emitcode ("rl", "%s", l);
+       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);
-       emitcode ("dec", "a");
+       emit2 ("dec a");
        emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
       }
   }
@@ -4242,34 +4559,34 @@ AccRol (int shCount)
     case 0:
       break;
     case 1:
-      emitcode ("rl", "a");
+      emit2 ("sla a");
       break;
     case 2:
-      emitcode ("rl", "a");
-      emitcode ("rl", "a");
+      emit2 ("sla a");
+      emit2 ("rl a");
       break;
     case 3:
-      emitcode ("rl", "a");
-      emitcode ("rl", "a");
-      emitcode ("rl", "a");
+      emit2 ("sla a");
+      emit2 ("rl a");
+      emit2 ("rl a");
       break;
     case 4:
-      emitcode ("rl", "a");
-      emitcode ("rl", "a");
-      emitcode ("rl", "a");
-      emitcode ("rl", "a");
+      emit2 ("sla a");
+      emit2 ("rl a");
+      emit2 ("rl a");
+      emit2 ("rl a");
       break;
     case 5:
-      emitcode ("rr", "a");
-      emitcode ("rr", "a");
-      emitcode ("rr", "a");
+      emit2 ("srl a");
+      emit2 ("rr a");
+      emit2 ("rr a");
       break;
     case 6:
-      emitcode ("rr", "a");
-      emitcode ("rr", "a");
+      emit2 ("srl a");
+      emit2 ("rr a");
       break;
     case 7:
-      emitcode ("rr", "a");
+      emit2 ("srl a");
       break;
     }
 }
@@ -4280,16 +4597,21 @@ AccRol (int shCount)
 static void
 AccLsh (int shCount)
 {
+  static const unsigned char SLMask[] =
+    {
+      0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00
+    };
+
   if (shCount != 0)
     {
       if (shCount == 1)
        {
-         emitcode ("add", "a,a");
+         emit2 ("add a,a");
        }
       else if (shCount == 2)
        {
-         emitcode ("add", "a,a");
-         emitcode ("add", "a,a");
+         emit2 ("add a,a");
+         emit2 ("add a,a");
        }
       else
        {
@@ -4308,9 +4630,9 @@ static void
 shiftL1Left2Result (operand * left, int offl,
                    operand * result, int offr, int shCount)
 {
-  char *l;
+  const char *l;
   l = aopGet (AOP (left), offl, FALSE);
-  MOVA (l);
+  _moveA (l);
   /* shift left accumulator */
   AccLsh (shCount);
   aopPut (AOP (result), "a", offr);
@@ -4336,18 +4658,18 @@ genlshTwo (operand * result, operand * left, int shCount)
          if (shCount)
            {
              movLeft2Result (left, LSB, result, MSB16, 0);
-             aopPut (AOP (result), zero, 0);
-             shiftL1Left2Result (left, MSB16, result, MSB16, shCount);
+             aopPut (AOP (result), "!zero", 0);
+             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
            }
          else
            {
              movLeft2Result (left, LSB, result, MSB16, 0);
-             aopPut (AOP (result), zero, 0);
+             aopPut (AOP (result), "!zero", 0);
            }
        }
       else
        {
-         aopPut (AOP (result), zero, LSB);
+         aopPut (AOP (result), "!zero", LSB);
        }
     }
   /*  1 <= shCount <= 7 */
@@ -4392,20 +4714,19 @@ genLeftShiftLiteral (operand * left,
 
   size = getSize (operandType (result));
 
-#if VIEW_SIZE
-  emitcode ("; shift left ", "result %d, left %d", size,
-           AOP_SIZE (left));
-#endif
-
   /* I suppose that the left size >= result size */
   if (shCount == 0)
     {
       wassert (0);
     }
 
-  else if (shCount >= (size * 8))
-    while (size--)
-      aopPut (AOP (result), zero, size);
+  else if (shCount >= (size * 8)) 
+    {
+      while (size--)
+        {
+          aopPut (AOP (result), "!zero", size);
+        }
+    }
   else
     {
       switch (size)
@@ -4417,7 +4738,7 @@ genLeftShiftLiteral (operand * left,
          genlshTwo (result, left, shCount);
          break;
        case 4:
-         wassert (0);
+         wassertl (0, "Shifting of longs is currently unsupported");
          break;
        default:
          wassert (0);
@@ -4434,7 +4755,7 @@ static void
 genLeftShift (iCode * ic)
 {
   int size, offset;
-  char *l;
+  const char *l;
   symbol *tlbl, *tlbl1;
   operand *left, *right, *result;
 
@@ -4456,15 +4777,15 @@ genLeftShift (iCode * ic)
      count in B : Note: we take only the lower order byte since
      shifting more that 32 bits make no sense anyway, ( the largest
      size of an object can be only 32 bits ) */
-  emitcode ("ld", "a,%s", aopGet (AOP (right), 0, FALSE));
-  emitcode ("inc", "a");
+  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 */
-#if 1
+
   if (!sameRegs (AOP (left), AOP (result)))
     {
 
@@ -4477,17 +4798,6 @@ genLeftShift (iCode * ic)
          offset++;
        }
     }
-#else
-  size = AOP_SIZE (result);
-  offset = 0;
-  while (size--)
-    {
-      l = aopGet (AOP (left), offset, FALSE);
-      aopPut (AOP (result), l, offset);
-      offset++;
-    }
-#endif
-
 
   tlbl = newiTempLabel (NULL);
   size = AOP_SIZE (result);
@@ -4497,14 +4807,23 @@ genLeftShift (iCode * ic)
   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
   emitLabel (tlbl->key + 100);
   l = aopGet (AOP (result), offset, FALSE);
-  emitcode ("or", "a,a");
+
   while (size--)
     {
-      l = aopGet (AOP (result), offset++, FALSE);
-      emitcode ("rl", "%s", l);
+      l = aopGet (AOP (result), offset, FALSE);
+
+      if (offset == 0)
+        {
+          emit2 ("sla %s", l);
+        }
+      else
+        {
+          emit2 ("rl %s", l);
+        }
+      offset++;
     }
   emitLabel (tlbl1->key + 100);
-  emitcode ("dec", "a");
+  emit2 ("dec a");
   emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
 
   freeAsmop (left, NULL, ic);
@@ -4515,29 +4834,32 @@ genLeftShift (iCode * ic)
 /* genrshOne - left shift two bytes by known amount != 0           */
 /*-----------------------------------------------------------------*/
 static void
-genrshOne (operand * result, operand * left, int shCount)
+genrshOne (operand * result, operand * left, int shCount, int is_signed)
 {
   /* Errk */
   int size = AOP_SIZE (result);
-  char *l;
+  const char *l;
 
   wassert (size == 1);
   wassert (shCount < 8);
 
   l = aopGet (AOP (left), 0, FALSE);
+
   if (AOP (result)->type == AOP_REG)
     {
       aopPut (AOP (result), l, 0);
       l = aopGet (AOP (result), 0, FALSE);
       while (shCount--)
-       emitcode ("srl", "%s", l);
+        {
+          emit2 ("%s %s", is_signed ? "sra" : "srl", l);
+        }
     }
   else
     {
-      MOVA (l);
+      _moveA (l);
       while (shCount--)
        {
-         emitcode ("srl", "a");
+         emit2 ("%s a", is_signed ? "sra" : "srl");
        }
       aopPut (AOP (result), "a", 0);
     }
@@ -4549,6 +4871,11 @@ genrshOne (operand * result, operand * left, int shCount)
 static void
 AccRsh (int shCount)
 {
+  static const unsigned char SRMask[] =
+    {
+      0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
+    };
+
   if (shCount != 0)
     {
       /* rotate right accumulator */
@@ -4566,10 +4893,13 @@ shiftR1Left2Result (operand * left, int offl,
                    operand * result, int offr,
                    int shCount, int sign)
 {
-  MOVA (aopGet (AOP (left), offl, FALSE));
+  _moveA (aopGet (AOP (left), offl, FALSE));
   if (sign)
     {
-      wassert (0);
+      while (shCount--)
+       {
+         emit2 ("%s a", sign ? "sra" : "srl");
+       }
     }
   else
     {
@@ -4598,7 +4928,19 @@ genrshTwo (operand * result, operand * left,
        {
          movLeft2Result (left, MSB16, result, LSB, sign);
        }
-      aopPut (AOP (result), zero, 1);
+      if (sign)
+        {
+          /* Sign extend the result */
+          _moveA(aopGet (AOP (result), 0, FALSE));
+          emit2 ("rlc a");
+          emit2 ("sbc a,a");
+
+          aopPut (AOP (result), ACC_NAME, MSB16);
+        }
+      else
+        {
+          aopPut (AOP (result), "!zero", 1);
+        }
     }
   /*  1 <= shCount <= 7 */
   else
@@ -4614,7 +4956,8 @@ static void
 genRightShiftLiteral (operand * left,
                      operand * right,
                      operand * result,
-                     iCode * ic)
+                     iCode * ic,
+                      int sign)
 {
   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
   int size;
@@ -4626,9 +4969,6 @@ genRightShiftLiteral (operand * left,
 
   size = getSize (operandType (result));
 
-  emitcode ("; shift right ", "result %d, left %d", size,
-           AOP_SIZE (left));
-
   /* I suppose that the left size >= result size */
   if (shCount == 0)
     {
@@ -4637,23 +4977,22 @@ genRightShiftLiteral (operand * left,
 
   else if (shCount >= (size * 8))
     while (size--)
-      aopPut (AOP (result), zero, size);
+      aopPut (AOP (result), "!zero", size);
   else
     {
       switch (size)
        {
        case 1:
-         genrshOne (result, left, shCount);
+         genrshOne (result, left, shCount, sign);
          break;
        case 2:
-         /* PENDING: sign support */
-         genrshTwo (result, left, shCount, FALSE);
+         genrshTwo (result, left, shCount, sign);
          break;
        case 4:
-         wassert (0);
+         wassertl (0, "Asked to shift right a long which should be a function call");
          break;
        default:
-         wassert (0);
+         wassertl (0, "Entered default case in right shift delegate");
        }
     }
   freeAsmop (left, NULL, ic);
@@ -4669,7 +5008,7 @@ genRightShift (iCode * ic)
   operand *right, *left, *result;
   sym_link *retype;
   int size, offset, first = 1;
-  char *l;
+  const char *l;
   bool is_signed;
 
   symbol *tlbl, *tlbl1;
@@ -4697,7 +5036,7 @@ genRightShift (iCode * ic)
      as efficiently as possible */
   if (AOP_TYPE (right) == AOP_LIT)
     {
-      genRightShiftLiteral (left, right, result, ic);
+      genRightShiftLiteral (left, right, result, ic, is_signed);
       return;
     }
 
@@ -4720,8 +5059,8 @@ genRightShift (iCode * ic)
        }
     }
 
-  emitcode ("ld", "a,%s", aopGet (AOP (right), 0, FALSE));
-  emitcode ("inc", "a");
+  emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
+  emit2 ("inc a");
   freeAsmop (right, NULL, ic);
 
   tlbl = newiTempLabel (NULL);
@@ -4736,17 +5075,16 @@ genRightShift (iCode * ic)
       l = aopGet (AOP (result), offset--, FALSE);
       if (first)
        {
-         if (is_signed)
-           emitcode ("sra", "%s", l);
-         else
-           emitcode ("srl", "%s", l);
+          emit2 ("%s %s", is_signed ? "sra" : "srl", l);
          first = 0;
        }
       else
-       emitcode ("rr", "%s", l);
+        {
+          emit2 ("rr %s", l);
+        }
     }
   emitLabel (tlbl1->key + 100);
-  emitcode ("dec", "a");
+  emit2 ("dec a");
   emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
 
   freeAsmop (left, NULL, ic);
@@ -4877,7 +5215,7 @@ genGenPointerSet (operand * right,
   if (isPair (AOP (result)) && (AOP_SIZE (right) == 1))
     {
       /* Just do it */
-      char *l = aopGet (AOP (right), 0, FALSE);
+      const char *l = aopGet (AOP (right), 0, FALSE);
       const char *pair = getPairName (AOP (result));
       if (canAssignToPtr (l) && isPtr (pair))
        {
@@ -4885,7 +5223,7 @@ genGenPointerSet (operand * right,
        }
       else
        {
-         MOVA (l);
+         _moveA (l);
          emit2 ("ld !*pair,a", pair);
        }
       goto release;
@@ -4912,19 +5250,19 @@ genGenPointerSet (operand * right,
 
       while (size--)
        {
-         char *l = aopGet (AOP (right), offset, FALSE);
+         const char *l = aopGet (AOP (right), offset, FALSE);
          if (isRegOrLit (AOP (right)) && !IS_GB)
            {
              emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
            }
          else
            {
-             MOVA (l);
+             _moveA (l);
              emit2 ("ld !*pair,a", _pairs[pairId].name);
            }
          if (size)
            {
-             emitcode ("inc", _pairs[pairId].name);
+             emit2 ("inc %s", _pairs[pairId].name);
              _G.pairs[pairId].offset++;
            }
          offset++;
@@ -4967,7 +5305,7 @@ genIfx (iCode * ic, iCode * popIc)
 
   /* get the value into acc */
   if (AOP_TYPE (cond) != AOP_CRY)
-    toBoolean (cond);
+    _toBoolean (cond);
   else
     isbit = 1;
   /* the result is now in the accumulator */
@@ -5015,8 +5353,8 @@ genAddrOf (iCode * ic)
            {
              emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
            }
-         emitcode ("ld", "d,h");
-         emitcode ("ld", "e,l");
+         emit2 ("ld d,h");
+         emit2 ("ld e,l");
        }
       else
        {
@@ -5032,14 +5370,14 @@ genAddrOf (iCode * ic)
        {
          /* if it has an offset  then we need to compute it */
          if (sym->stack > 0)
-           emitcode ("ld", "hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
+           emit2 ("ld hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
          else
-           emitcode ("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
-         emitcode ("add", "hl,sp");
+           emit2 ("ld hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
+         emit2 ("add hl,sp");
        }
       else
        {
-         emitcode ("ld", "hl,#%s", sym->rname);
+         emit2 ("ld hl,#%s", sym->rname);
        }
       aopPut (AOP (IC_RESULT (ic)), "l", 0);
       aopPut (AOP (IC_RESULT (ic)), "h", 1);
@@ -5060,14 +5398,12 @@ genAssign (iCode * ic)
   result = IC_RESULT (ic);
   right = IC_RIGHT (ic);
 
-#if 1
   /* Dont bother assigning if they are the same */
   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
     {
-      emitcode ("", "; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
+      emitDebug ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
       return;
     }
-#endif
 
   aopOp (right, ic, FALSE, FALSE);
   aopOp (result, ic, TRUE, FALSE);
@@ -5075,14 +5411,14 @@ genAssign (iCode * ic)
   /* if they are the same registers */
   if (sameRegs (AOP (right), AOP (result)))
     {
-      emitcode ("", "; (registers are the same)");
+      emitDebug ("; (registers are the same)");
       goto release;
     }
 
   /* if the result is a bit */
   if (AOP_TYPE (result) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to assign to a bit");
     }
 
   /* general case */
@@ -5112,7 +5448,7 @@ genAssign (iCode * ic)
            {
              if (!fXored && size > 1)
                {
-                 emitcode ("xor", "a,a");
+                 emit2 ("xor a,a");
                  fXored = TRUE;
                }
              if (fXored)
@@ -5121,7 +5457,7 @@ genAssign (iCode * ic)
                }
              else
                {
-                 aopPut (AOP (result), zero, offset);
+                 aopPut (AOP (result), "!zero", offset);
                }
            }
          else
@@ -5134,11 +5470,33 @@ genAssign (iCode * ic)
   else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
     {
       /* Special case.  Load into a and d, then load out. */
-      MOVA (aopGet (AOP (right), 0, FALSE));
-      emitcode ("ld", "e,%s", aopGet (AOP (right), 1, FALSE));
+      _moveA (aopGet (AOP (right), 0, FALSE));
+      emit2 ("ld e,%s", aopGet (AOP (right), 1, FALSE));
       aopPut (AOP (result), "a", 0);
       aopPut (AOP (result), "e", 1);
     }
+  else if (size == 4 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
+    {
+      /* Special case - simple memcpy */
+      aopGet (AOP (right), LSB, FALSE);
+      emit2 ("ld d,h");
+      emit2 ("ld e,l");
+      aopGet (AOP (result), LSB, FALSE);
+
+      while (size--)
+        {
+          emit2 ("ld a,(de)");
+          /* Peephole will optimise this. */
+          emit2 ("ld (hl),a");
+
+          if (size != 0)
+            {
+              emit2 ("inc hl");
+              emit2 ("inc de");
+            }
+        }
+      spillPair (PAIR_HL);
+    }
   else
     {
       while (size--)
@@ -5146,7 +5504,7 @@ genAssign (iCode * ic)
          /* PENDING: do this check better */
          if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
            {
-             MOVA (aopGet (AOP (right), offset, FALSE));
+             _moveA (aopGet (AOP (right), offset, FALSE));
              aopPut (AOP (result), "a", offset);
            }
          else
@@ -5169,24 +5527,24 @@ static void
 genJumpTab (iCode * ic)
 {
   symbol *jtab;
-  char *l;
+  const char *l;
 
   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
   /* get the condition into accumulator */
   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
   if (!IS_GB)
-    emitcode ("push", "de");
-  emitcode ("ld", "e,%s", l);
+    emit2 ("push de");
+  emit2 ("ld e,%s", l);
   emit2 ("ld d,!zero");
   jtab = newiTempLabel (NULL);
   spillCached ();
   emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
-  emitcode ("add", "hl,de");
-  emitcode ("add", "hl,de");
-  emitcode ("add", "hl,de");
+  emit2 ("add hl,de");
+  emit2 ("add hl,de");
+  emit2 ("add hl,de");
   freeAsmop (IC_JTCOND (ic), NULL, ic);
   if (!IS_GB)
-    emitcode ("pop", "de");
+    emit2 ("pop de");
   emit2 ("jp !*hl");
   emitLabel (jtab->key + 100);
   /* now generate the jump labels */
@@ -5216,7 +5574,7 @@ genCast (iCode * ic)
   /* if the result is a bit */
   if (AOP_TYPE (result) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to cast to a bit");
     }
 
   /* if they are the same size : or less */
@@ -5240,16 +5598,7 @@ genCast (iCode * ic)
       goto release;
     }
 
-  /* PENDING: should be OK. */
-#if 0
-  /* if the result is of type pointer */
-  if (IS_PTR (ctype))
-    {
-      wassert (0);
-    }
-#endif
-
-  /* so we now know that the size of destination is greater
+  /* So we now know that the size of destination is greater
      than the size of the source */
   /* we move to result for the size of source */
   size = AOP_SIZE (right);
@@ -5268,17 +5617,16 @@ genCast (iCode * ic)
   if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
     {
       while (size--)
-       aopPut (AOP (result), zero, offset++);
+       aopPut (AOP (result), "!zero", offset++);
     }
   else
     {
       /* we need to extend the sign :{ */
-      char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
+        const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
                        FALSE);
-      MOVA (l);
-      emitcode ("", "; genCast: sign extend untested.");
-      emitcode ("rla", "");
-      emitcode ("sbc", "a,a");
+      _moveA (l);
+      emit2 ("rla ");
+      emit2 ("sbc a,a");
       while (size--)
        aopPut (AOP (result), "a", offset++);
     }
@@ -5302,15 +5650,261 @@ genReceive (iCode * ic)
     }
   else
     {
-      accInUse++;
-      aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
-      accInUse--;
-      assignResultValue (IC_RESULT (ic));
+        // PENDING: HACK
+        int size;
+        int i;
+
+        aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
+        size = AOP_SIZE(IC_RESULT(ic));
+
+        for (i = 0; i < size; i++) {
+            aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
+       }
     }
 
   freeAsmop (IC_RESULT (ic), NULL, ic);
 }
 
+enum
+  {
+    /** Maximum number of bytes to emit per line. */
+    DBEMIT_MAX_RUN = 8
+  };
+
+/** Context for the byte output chunker. */
+typedef struct
+{
+  unsigned char buffer[DBEMIT_MAX_RUN];
+  int pos;
+} DBEMITCTX;
+
+
+/** Flushes a byte chunker by writing out all in the buffer and
+    reseting. 
+*/
+static void
+_dbFlush(DBEMITCTX *self)
+{
+  char line[256];
+
+  if (self->pos > 0)
+    {
+      int i;
+      sprintf(line, ".db 0x%02X", self->buffer[0]);
+
+      for (i = 1; i < self->pos; i++)
+        {
+          sprintf(line + strlen(line), ", 0x%02X", self->buffer[i]);
+        }
+      emit2(line);
+    }
+  self->pos = 0;
+}
+
+/** Write out another byte, buffering until a decent line is
+    generated.
+*/
+static void
+_dbEmit(DBEMITCTX *self, int c)
+{
+  if (self->pos == DBEMIT_MAX_RUN)
+    {
+      _dbFlush(self);
+    }
+  self->buffer[self->pos++] = c;
+}
+
+/** Context for a simple run length encoder. */
+typedef struct
+{
+  unsigned last;
+  unsigned char buffer[128];
+  int pos;
+  /** runLen may be equivalent to pos. */
+  int runLen;
+} RLECTX;
+
+enum
+  {
+    RLE_CHANGE_COST = 4,
+    RLE_MAX_BLOCK = 127
+  };
+
+/** Flush the buffer of a run length encoder by writing out the run or
+    data that it currently contains.
+*/
+static void
+_rleCommit(RLECTX *self)
+{
+  int i;
+  if (self->pos != 0)
+    {
+      DBEMITCTX db;
+      memset(&db, 0, sizeof(db));
+          
+      emit2(".db %u", self->pos);
+      
+      for (i = 0; i < self->pos; i++)
+        {
+          _dbEmit(&db, self->buffer[i]);
+        }
+      _dbFlush(&db);
+    }
+  /* Reset */
+  self->pos = 0;
+}
+
+/* Encoder design:
+   Can get either a run or a block of random stuff.
+   Only want to change state if a good run comes in or a run ends.
+   Detecting run end is easy.
+   Initial state?
+
+   Say initial state is in run, len zero, last zero.  Then if you get a
+   few zeros then something else then a short run will be output.
+   Seems OK.  While in run mode, keep counting.  While in random mode,
+   keep a count of the run.  If run hits margin, output all up to run,
+   restart, enter run mode.
+*/
+
+/** Add another byte into the run length encoder, flushing as
+    required.  The run length encoder uses the Amiga IFF style, where
+    a block is prefixed by its run length.  A positive length means
+    the next n bytes pass straight through.  A negative length means
+    that the next byte is repeated -n times.  A zero terminates the
+    chunks.
+*/
+static void
+_rleAppend(RLECTX *self, int c)
+{
+  int i;
+
+  if (c != self->last)
+    {
+      /* The run has stopped.  See if it is worthwhile writing it out
+         as a run.  Note that the random data comes in as runs of
+         length one.
+      */
+      if (self->runLen > RLE_CHANGE_COST)
+        {
+          /* Yes, worthwhile. */
+          /* Commit whatever was in the buffer. */
+          _rleCommit(self);
+          emit2(".db -%u,0x%02X", self->runLen, self->last);
+        }
+      else
+        {
+          /* Not worthwhile.  Append to the end of the random list. */
+          for (i = 0; i < self->runLen; i++)
+            {
+              if (self->pos >= RLE_MAX_BLOCK)
+                {
+                  /* Commit. */
+                  _rleCommit(self);
+                }
+              self->buffer[self->pos++] = self->last;
+            }
+        }
+      self->runLen = 1;
+      self->last = c;
+    }
+  else
+    {
+      if (self->runLen >= RLE_MAX_BLOCK)
+        {
+          /* Commit whatever was in the buffer. */
+          _rleCommit(self);
+
+          emit2 (".db -%u,0x%02X", self->runLen, self->last);
+          self->runLen = 0;
+        }
+      self->runLen++;
+    }
+}
+
+static void
+_rleFlush(RLECTX *self)
+{
+  _rleAppend(self, -1);
+  _rleCommit(self);
+  self->pos = 0;
+  self->last = 0;
+  self->runLen = 0;
+}
+
+/** genArrayInit - Special code for initialising an array with constant
+   data.
+*/
+static void
+genArrayInit (iCode * ic)
+{
+  literalList *iLoop;
+  int         ix;
+  int         elementSize = 0, eIndex, i;
+  unsigned    val, lastVal;
+  sym_link    *type;
+  RLECTX      rle;
+
+  memset(&rle, 0, sizeof(rle));
+
+  aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
+
+  if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
+    {
+      /* Emit the support function call and the destination address. */
+      emit2("call __initrleblock");
+      emit2(".dw %s", aopGetWord (AOP(IC_LEFT(ic)), 0));
+    }
+  else
+    {
+      wassertl (0, "Unexpected operand to genArrayInit.\n");
+    }
+    
+  type = operandType(IC_LEFT(ic));
+    
+  if (type && type->next)
+    {
+      elementSize = getSize(type->next);
+    }
+  else
+    {
+      wassertl (0, "Can't determine element size in genArrayInit.");
+    }
+
+  iLoop = IC_ARRAYILIST(ic);
+  lastVal = (unsigned)-1;
+
+  /* Feed all the bytes into the run length encoder which will handle
+     the actual output.
+     This works well for mixed char data, and for random int and long
+     data.
+  */
+  while (iLoop)
+    {
+      ix = iLoop->count;
+
+      if (ix != 0)
+        {
+          for (i = 0; i < ix; i++)
+            {
+              for (eIndex = 0; eIndex < elementSize; eIndex++)
+                {
+                  val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
+                  _rleAppend(&rle, val);
+                }
+            }
+       }
+       
+      iLoop = iLoop->next;
+    }
+
+  _rleFlush(&rle);
+  /* Mark the end of the run. */
+  emit2(".db 0");
+
+  freeAsmop (IC_LEFT(ic), NULL, ic);
+}
+
 /*-----------------------------------------------------------------*/
 /* genZ80Code - generate code for Z80 based controllers            */
 /*-----------------------------------------------------------------*/
@@ -5331,39 +5925,15 @@ genZ80Code (iCode * lic)
       _fReturn = _z80_return;
       _fTmp = _z80_return;
     }
-  tsprintf (zero, "!zero");
-
-  lineHead = lineCurr = NULL;
-
-  /* if debug information required */
-  if (options.debug && currFunc)
-    {
-      cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
-      debugLine = 1;
-      if (IS_STATIC (currFunc->etype))
-       emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
-      else
-       emitcode ("", "G$%s$0$0 ==.", currFunc->name);
-      debugLine = 0;
-    }
-  /* stack pointer name */
-  spname = "sp";
 
+  _G.lines.head = _G.lines.current = NULL;
 
   for (ic = lic; ic; ic = ic->next)
     {
 
       if (cln != ic->lineno)
        {
-         if (options.debug)
-           {
-             debugLine = 1;
-             emitcode ("", "C$%s$%d$%d$%d ==.",
-                       FileBaseName (ic->filename), ic->lineno,
-                       ic->level, ic->block);
-             debugLine = 0;
-           }
-         emitcode (";", "%s %d", ic->filename, ic->lineno);
+         emit2 ("; %s %d", ic->filename, ic->lineno);
          cln = ic->lineno;
        }
       /* if the result is marked as
@@ -5377,22 +5947,22 @@ genZ80Code (iCode * lic)
       switch (ic->op)
        {
        case '!':
-         emitcode ("", "; genNot");
+         emitDebug ("; genNot");
          genNot (ic);
          break;
 
        case '~':
-         emitcode ("", "; genCpl");
+         emitDebug ("; genCpl");
          genCpl (ic);
          break;
 
        case UNARYMINUS:
-         emitcode ("", "; genUminus");
+         emitDebug ("; genUminus");
          genUminus (ic);
          break;
 
        case IPUSH:
-         emitcode ("", "; genIpush");
+         emitDebug ("; genIpush");
          genIpush (ic);
          break;
 
@@ -5407,83 +5977,83 @@ genZ80Code (iCode * lic)
              ic->next->op == IFX &&
              regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
            {
-             emitcode ("", "; genIfx");
+              emitDebug ("; genIfx");
              genIfx (ic->next, ic);
            }
          else
            {
-             emitcode ("", "; genIpop");
+             emitDebug ("; genIpop");
              genIpop (ic);
            }
          break;
 
        case CALL:
-         emitcode ("", "; genCall");
+         emitDebug ("; genCall");
          genCall (ic);
          break;
 
        case PCALL:
-         emitcode ("", "; genPcall");
+         emitDebug ("; genPcall");
          genPcall (ic);
          break;
 
        case FUNCTION:
-         emitcode ("", "; genFunction");
+         emitDebug ("; genFunction");
          genFunction (ic);
          break;
 
        case ENDFUNCTION:
-         emitcode ("", "; genEndFunction");
+         emitDebug ("; genEndFunction");
          genEndFunction (ic);
          break;
 
        case RETURN:
-         emitcode ("", "; genRet");
+         emitDebug ("; genRet");
          genRet (ic);
          break;
 
        case LABEL:
-         emitcode ("", "; genLabel");
+         emitDebug ("; genLabel");
          genLabel (ic);
          break;
 
        case GOTO:
-         emitcode ("", "; genGoto");
+         emitDebug ("; genGoto");
          genGoto (ic);
          break;
 
        case '+':
-         emitcode ("", "; genPlus");
+         emitDebug ("; genPlus");
          genPlus (ic);
          break;
 
        case '-':
-         emitcode ("", "; genMinus");
+         emitDebug ("; genMinus");
          genMinus (ic);
          break;
 
        case '*':
-         emitcode ("", "; genMult");
+         emitDebug ("; genMult");
          genMult (ic);
          break;
 
        case '/':
-         emitcode ("", "; genDiv");
+         emitDebug ("; genDiv");
          genDiv (ic);
          break;
 
        case '%':
-         emitcode ("", "; genMod");
+         emitDebug ("; genMod");
          genMod (ic);
          break;
 
        case '>':
-         emitcode ("", "; genCmpGt");
+         emitDebug ("; genCmpGt");
          genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
          break;
 
        case '<':
-         emitcode ("", "; genCmpLt");
+         emitDebug ("; genCmpLt");
          genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
          break;
 
@@ -5498,66 +6068,67 @@ genZ80Code (iCode * lic)
          break;
 
        case EQ_OP:
-         emitcode ("", "; genCmpEq");
+         emitDebug ("; genCmpEq");
          genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
          break;
 
        case AND_OP:
-         emitcode ("", "; genAndOp");
+         emitDebug ("; genAndOp");
          genAndOp (ic);
          break;
 
        case OR_OP:
-         emitcode ("", "; genOrOp");
+         emitDebug ("; genOrOp");
          genOrOp (ic);
          break;
 
        case '^':
-         emitcode ("", "; genXor");
+         emitDebug ("; genXor");
          genXor (ic, ifxForOp (IC_RESULT (ic), ic));
          break;
 
        case '|':
-         emitcode ("", "; genOr");
+         emitDebug ("; genOr");
          genOr (ic, ifxForOp (IC_RESULT (ic), ic));
          break;
 
        case BITWISEAND:
-         emitcode ("", "; genAnd");
+         emitDebug ("; genAnd");
          genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
          break;
 
        case INLINEASM:
-         emitcode ("", "; genInline");
+         emitDebug ("; genInline");
          genInline (ic);
          break;
 
        case RRC:
-         emitcode ("", "; genRRC");
+         emitDebug ("; genRRC");
          genRRC (ic);
          break;
 
        case RLC:
-         emitcode ("", "; genRLC");
+         emitDebug ("; genRLC");
          genRLC (ic);
          break;
 
        case GETHBIT:
-         emitcode ("", "; genHBIT");
-         wassert (0);
+         emitDebug ("; genGetHBIT");
+         genGetHbit (ic);
+          break;
 
        case LEFT_OP:
-         emitcode ("", "; genLeftShift");
+         emitDebug ("; genLeftShift");
          genLeftShift (ic);
          break;
 
        case RIGHT_OP:
-         emitcode ("", "; genRightShift");
+         emitDebug ("; genRightShift");
          genRightShift (ic);
          break;
 
        case GET_VALUE_AT_ADDRESS:
-         emitcode ("", "; genPointerGet");
+         emitDebug ("; genPointerGet");
          genPointerGet (ic);
          break;
 
@@ -5565,50 +6136,52 @@ genZ80Code (iCode * lic)
 
          if (POINTER_SET (ic))
            {
-             emitcode ("", "; genAssign (pointer)");
+             emitDebug ("; genAssign (pointer)");
              genPointerSet (ic);
            }
          else
            {
-             emitcode ("", "; genAssign");
+             emitDebug ("; genAssign");
              genAssign (ic);
            }
          break;
 
        case IFX:
-         emitcode ("", "; genIfx");
+          emitDebug ("; genIfx");
          genIfx (ic, NULL);
          break;
 
        case ADDRESS_OF:
-         emitcode ("", "; genAddrOf");
+         emitDebug ("; genAddrOf");
          genAddrOf (ic);
          break;
 
        case JUMPTABLE:
-         emitcode ("", "; genJumpTab");
+         emitDebug ("; genJumpTab");
          genJumpTab (ic);
          break;
 
        case CAST:
-         emitcode ("", "; genCast");
+         emitDebug ("; genCast");
          genCast (ic);
          break;
 
        case RECEIVE:
-         emitcode ("", "; genReceive");
+         emitDebug ("; genReceive");
          genReceive (ic);
          break;
 
        case SEND:
-         emitcode ("", "; addSet");
-         addSet (&sendSet, ic);
+         emitDebug ("; addSet");
+         addSet (&_G.sendSet, ic);
          break;
 
+       case ARRAYINIT:
+          genArrayInit(ic);
+          break;
+           
        default:
          ic = ic;
-         /*      piCode(ic,stdout); */
-
        }
     }
 
@@ -5616,7 +6189,7 @@ genZ80Code (iCode * lic)
   /* now we are ready to call the
      peep hole optimizer */
   if (!options.nopeep)
-    peepHole (&lineHead);
+    peepHole (&_G.lines.head);
 
   /* This is unfortunate */
   /* now do the actual printing */
@@ -5624,12 +6197,56 @@ genZ80Code (iCode * lic)
     FILE *fp = codeOutFile;
     if (isInHome () && codeOutFile == code->oFile)
       codeOutFile = home->oFile;
-    printLine (lineHead, codeOutFile);
-    if (_G.flush_statics)
+    printLine (_G.lines.head, codeOutFile);
+    if (_G.flushStatics)
       {
        flushStatics ();
-       _G.flush_statics = 0;
+       _G.flushStatics = 0;
       }
     codeOutFile = fp;
   }
 }
+
+/*
+  Attic
+static int
+_isPairUsed (iCode * ic, PAIR_ID pairId)
+{
+  int ret = 0;
+  switch (pairId)
+    {
+    case PAIR_DE:
+      if (bitVectBitValue (ic->rMask, D_IDX))
+       ret++;
+      if (bitVectBitValue (ic->rMask, E_IDX))
+       ret++;
+      break;
+    default:
+      wassert (0);
+    }
+  return ret;
+}
+
+static char *
+fetchLitSpecial (asmop * aop, bool negate, bool xor)
+{
+  unsigned long v;
+  value *val = aop->aopu.aop_lit;
+
+  wassert (aop->type == AOP_LIT);
+  wassert (!IS_FLOAT (val->type));
+
+  v = (unsigned long) floatFromVal (val);
+
+  if (xor)
+    v ^= 0x8000;
+  if (negate)
+    v = 0-v;
+  v &= 0xFFFF;
+
+  tsprintf (buffer, "!immedword", v);
+  return gc_strdup (buffer);
+}
+
+
+*/