Stopped a couple of warnings.
[fw/sdcc] / src / z80 / gen.c
index 8df72ac7df0b94bf827270e4bd7e96ee6e72d9ab..f065a37e76e2f74d4267f0b05ab92da52f16aa6c 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>
    IX is used as an index register to the top of the local variable
    area.  ix-0 is the top most local variable.
 */
+
+enum {
+  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];
-
-short rbank = -1;
-short inLine = 0;
-short debugLine = 0;
-short nregssaved = 0;
-extern int ptrRegReq;
-extern int nRegs;
 extern FILE *codeOutFile;
-set *sendSet = NULL;
 
 typedef enum
-{
+  {
     PAIR_INVALID,
     PAIR_AF,
     PAIR_BC,
@@ -110,21 +143,21 @@ typedef enum
     PAIR_IY,
     PAIR_IX,
     NUM_PAIRS
-} PAIR_ID;
+  } PAIR_ID;
 
 static struct
 {
-    const char *name;
-    const char *l;
-    const char *h;
+  const char *name;
+  const char *l;
+  const char *h;
 } _pairs[NUM_PAIRS] = {
-    {    "??", "?", "?" },
-    {    "af", "f", "a" },
-    {    "bc", "c", "b" },
-    {    "de", "e", "d" },
-    {    "hl", "l", "h" },
-    {    "iy", "iy.l?", "iy.h?" },
-    {    "ix", "ix.l?", "ix.h?" }
+  {    "??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
@@ -134,51 +167,92 @@ static struct
                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
                          IC_RESULT(x)->aop->type == AOP_STK )
 
-lineNode *lineHead = NULL;
-lineNode *lineCurr = NULL;
-
-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};
+enum 
+  {
+    LSB,
+    MSB16,
+    MSB24,
+    MSB32
+  };
 
-#define LSB     0
-#define MSB16   1
-#define MSB24   2
-#define MSB32   3
+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 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;
 
-/* Stack frame:
-   IX+4   param0  LH
-   IX+2   ret LH
-   IX+0   ix  LH
-   IX-2   temp0 LH
- */
+  struct 
+  {
+    lineNode *head;
+    lineNode *current;
+    int isInline;
+  } lines;
 
-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;
-    int receiveOffset;
-    bool flush_statics;
-    bool in_home;
-    const char *lastFunctionName;
-  }
-_G;
+} _G;
 
 static const char *aopGet (asmop * aop, int offset, bool bit16);
 
+static PAIR_ID
+_getTempPairId(void)
+{
+  if (IS_GB)
+    {
+      return PAIR_DE;
+    }
+  else
+    {
+      return PAIR_HL;
+    }
+}
+
+static const char *
+_getTempPairName(void)
+{
+  return _pairs[_getTempPairId()].name;
+}
+
+#if 0
+static const char *
+_getTempPairPart(int idx)
+{
+  wassertl (idx == LSB || idx == MSB16, "Invalid pair offset");
+  
+  if (idx == LSB)
+    {
+      return _pairs[_getTempPairId()].l;
+    }
+  else
+    {
+      return _pairs[_getTempPairId()].h;
+    }
+}
+#endif
+
 static void
 _tidyUp (char *buf)
 {
@@ -190,42 +264,65 @@ _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[INITIAL_INLINEASM];
@@ -245,35 +342,38 @@ 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);
 }
 
 static void
 _emitMove(const char *to, const char *from)
 {
-    if (strcasecmp(to, from) != 0) {
-        emit2("ld %s,%s", to, 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.
+  else 
+    {
+      // Optimise it out.
+      // Could leave this to the peephole, but sometimes the peephole is inhibited.
     }
 }
 
 static void
-_MoveA(const char *moveFrom)
+_moveA(const char *moveFrom)
 {
     // Let the peephole optimiser take care of redundent loads
     _emitMove(ACC_NAME, moveFrom);
 }
 
 static void
-_ClearCarry(void)
+_clearCarry(void)
 {
     emit2("xor a,a");
 }
@@ -379,7 +479,7 @@ isPtrPair (asmop * aop)
 void
 genPairPush (asmop * aop)
 {
-  emitcode ("push", "%s", getPairName (aop));
+  emit2 ("push %s", getPairName (aop));
 }
 
 
@@ -418,7 +518,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;
@@ -443,7 +543,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;
        }
     }
@@ -452,7 +552,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
@@ -689,14 +789,13 @@ 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);
               wassertl(aop->size == 1, "Internal error: Caching in A, but too big to fit in A");
 
-              aop->aopu.aop_str[i] = _pairs[PAIR_AF].h;
+              aop->aopu.aop_str[0] = _pairs[PAIR_AF].h;
            }
          else if (sym->accuse == ACCUSE_HL)
            {
@@ -795,10 +894,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)
     {
@@ -810,9 +905,9 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
        tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
       else
        tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
-      rs = Safe_calloc (1, strlen (s) + 1);
-      strcpy (rs, s);
-      return rs;
+
+      return gc_strdup(s);
+
     case AOP_LIT:
       {
        value *val = aop->aopu.aop_lit;
@@ -823,14 +918,24 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
            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
          {
@@ -875,12 +980,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)--;
     }
 }
@@ -913,33 +1018,12 @@ 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 = (unsigned long) floatFromVal (val);
-
-  if (xor)
-    v ^= 0x8000;
-  if (negate)
-    v = 0-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 *pair = _pairs[pairId].name;
-  l = aopGetLitWordLong (left, 0, FALSE);
+  l = aopGetLitWordLong (left, offset, FALSE);
   wassert (l && pair);
 
   if (isPtr (pair))
@@ -981,10 +1065,7 @@ fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
       _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
@@ -998,18 +1079,21 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
         /* we need to get it byte by byte */
         if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
             aopGet (aop, offset, FALSE);
-            switch (aop->size) {
+            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:
-                emit2 ("; WARNING: mlh woosed out.  This code is invalid.");
+              wassertl (0, "Attempted to fetch too much data into HL");
+              break;
             }
         }
         else if (IS_Z80 && aop->type == AOP_IY) {
@@ -1024,8 +1108,8 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
             }
         }
         else {
-            emitcode ("ld", "%s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
-            emitcode ("ld", "%s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
+            emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
+            emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
         }
         /* PENDING: check? */
         if (pairId == PAIR_HL)
@@ -1100,13 +1184,15 @@ 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)
@@ -1130,25 +1216,22 @@ aopGet (asmop * aop, int offset, bool bit16)
          default:
            wassert (0);
          }
-      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;
@@ -1157,15 +1240,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)
@@ -1177,11 +1260,10 @@ 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);
@@ -1191,7 +1273,11 @@ aopGet (asmop * aop, int offset, bool bit16)
        {
          return "a";
        }
-      return "!zero";
+      else
+        {
+          tsprintf(s, "!zero");
+          return gc_strdup(s);
+        }
 
     case AOP_HLREG:
       wassert (offset < 2);
@@ -1203,6 +1289,7 @@ aopGet (asmop * aop, int offset, bool bit16)
     case AOP_STR:
       aop->coff = offset;
       return aop->aopu.aop_str[offset];
+
     default:
       break;
     }
@@ -1247,6 +1334,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__,
@@ -1254,6 +1343,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)
@@ -1262,15 +1355,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:
@@ -1356,7 +1449,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,12 +1460,12 @@ aopPut (asmop * aop, const char *s, int offset)
       if (offset > 0)
        {
 
-         emitcode ("", "; Error aopPut AOP_ACC");
+         emitDebug ("; Error aopPut AOP_ACC");
        }
       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;
 
@@ -1465,7 +1558,7 @@ outAcc (operand * result)
       /* unsigned or positive */
       while (size--)
        {
-         aopPut (AOP (result), zero, offset++);
+         aopPut (AOP (result), "!zero", offset++);
        }
     }
 }
@@ -1478,7 +1571,7 @@ outBitCLong (operand * result, bool swap_sense)
   /* if the result is bit */
   if (AOP_TYPE (result) == AOP_CRY)
     {
-      emitcode ("", "; Note: outBitC form 1");
+      emitDebug ("; Note: outBitC form 1");
       aopPut (AOP (result), "blah", 0);
     }
   else
@@ -1501,23 +1594,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)
        {
-         _ClearCarry();
-         emitcode ("or", "a,%s", aopGet (AOP (oper), 0, FALSE));
+         _clearCarry();
+         emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE));
        }
     }
 }
@@ -1546,7 +1639,7 @@ genNot (iCode * ic)
       wassert (0);
     }
 
-  toBoolean (IC_LEFT (ic));
+  _toBoolean (IC_LEFT (ic));
 
   /* Not of A:
      If A == 0, !A = 1
@@ -1586,7 +1679,7 @@ genCpl (iCode * ic)
   while (size--)
     {
       const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
-      _MoveA (l);
+      _moveA (l);
       emit2("cpl");
       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
     }
@@ -1631,7 +1724,7 @@ genUminus (iCode * ic)
   /* otherwise subtract from zero */
   size = AOP_SIZE (IC_LEFT (ic));
   offset = 0;
-  _ClearCarry();
+  _clearCarry();
   while (size--)
     {
       const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
@@ -1693,8 +1786,7 @@ assignResultValue (operand * oper)
       _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);
     }
@@ -1707,6 +1799,73 @@ 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;
+
+#if 1
+    rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
+#else
+    if (IC_RESULT(ic))
+      {
+        rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), z80_rUmaskForOp (IC_RESULT(ic)));
+      }
+    else 
+      {
+        /* Has no result, so in use is all of in use */
+        rInUse = ic->rMask;
+      }
+#endif
+
+    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  */
 /*-----------------------------------------------------------------*/
@@ -1720,45 +1879,37 @@ genIpush (iCode * ic)
      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);
@@ -1768,14 +1919,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;
@@ -1783,11 +1934,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;
@@ -1806,8 +1957,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++;
        }
     }
@@ -1833,14 +1984,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--);
        }
@@ -1849,22 +2000,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->rMask, D_IDX))
-       ret++;
-      if (bitVectBitValue (ic->rMask, 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
@@ -1887,12 +2046,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);
@@ -1904,117 +2071,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)
@@ -2027,16 +2158,15 @@ 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));
+         emitDebug ("; Special case where the pCall is to a constant");
+         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 +2195,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 ||
@@ -2083,6 +2216,7 @@ emitCall (iCode * ic, bool ispcall)
   if (ic->parmBytes)
     {
       int i = ic->parmBytes;
+
       _G.stack.pushed -= i;
       if (IS_GB)
        {
@@ -2093,25 +2227,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;
+    }
 }
 
 /*-----------------------------------------------------------------*/
@@ -2162,51 +2348,58 @@ genFunction (iCode * ic)
   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
   sym_link *fetype;
 
-  nregssaved = 0;
-  // PENDING: HACK
-  _G.receiveOffset = 0;
+#if CALLEE_SAVES
+  bool bcInUse = FALSE;
+  bool deInUse = FALSE;
+#endif
 
   setArea (IS_NONBANKED (sym->etype));
 
+  /* PENDING: Reset the receive offset as it doesn't seem to get reset anywhere
+     else.
+  */
+  _G.receiveOffset = 0;
+
+#if 0
   /* PENDING: hack */
   if (!IS_STATIC (sym->etype))
     {
       addSetIfnotP (&publics, sym);
     }
+#endif
 
+  /* Record the last function name for debugging. */
   _G.lastFunctionName = sym->rname;
-
-  /* create the function header */
+  
+  /* 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;
 
-  /* PENDING: BUG: We don't detect if DE or BC are used in a send set.
-     For now assume the worst and always save.
-  */
-  _G.stack.pushed_bc = 1;
-  _G.stack.pushed_de = 1;
-
+#if CALLEE_SAVES
+  /* Detect which registers are used. */
   if (sym->regsUsed)
     {
       int i;
@@ -2218,28 +2411,38 @@ 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;
@@ -2270,35 +2473,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;
 }
@@ -2328,11 +2538,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
@@ -2349,7 +2559,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);
            }
        }
     }
@@ -2402,7 +2612,7 @@ genPlusIncr (iCode * ic)
   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
     return FALSE;
 
-  emitcode ("", "; genPlusIncr");
+  emitDebug ("; genPlusIncr");
 
   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
 
@@ -2417,7 +2627,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)
@@ -2432,7 +2642,7 @@ genPlusIncr (iCode * ic)
        }
       while (icount--)
        {
-         emitcode ("inc", "%s", getPairName (AOP (IC_RESULT (ic))));
+         emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic))));
        }
       return TRUE;
     }
@@ -2453,7 +2663,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);
@@ -2474,7 +2684,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;
     }
 
@@ -2553,7 +2765,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));
 
@@ -2561,16 +2773,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;
        }
     }
@@ -2580,7 +2793,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;
     }
 
@@ -2646,7 +2859,7 @@ genPlus (iCode * ic)
            }
          else if (size == 4)
            {
-             emit2 ("; WARNING: This add is probably broken.\n");
+              // Fall through
            }
        }
     }
@@ -2655,7 +2868,7 @@ genPlus (iCode * ic)
     {
       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
        {
-         _MoveA (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));
@@ -2665,7 +2878,7 @@ genPlus (iCode * ic)
        }
       else
        {
-         _MoveA (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));
@@ -2704,32 +2917,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;
     }
 
@@ -2739,10 +2932,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)
@@ -2753,7 +2963,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;
     }
 
@@ -2838,7 +3048,10 @@ genMinus (iCode * ic)
            }
          else if (size == 4)
            {
-             emit2 ("; WARNING: This sub is probably broken.\n");
+              /* Anything could be on the stack, and we can't afford
+                 to setup the base pointer as that may nuke the carry.
+              */
+             emitDebug ("; WARNING: This sub is probably broken.\n");
            }
        }
     }
@@ -2846,14 +3059,14 @@ genMinus (iCode * ic)
   /* if literal, add a,#-lit, else normal subb */
   while (size--)
     {
-      _MoveA (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
@@ -2965,7 +3178,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"))
     {
@@ -2975,7 +3188,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);
 
@@ -2983,11 +3196,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 <
  */
@@ -3017,23 +3232,26 @@ 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 0
+          // PENDING: Doesn't work around zero
+
          /* 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))
+         if (IS_GB && size == 2 && (AOP_TYPE (right) == AOP_LIT || AOP_TYPE (left) == AOP_LIT))
            {
              PAIR_ID id = PAIR_DE;
              asmop *lit = AOP (right);
@@ -3067,6 +3285,7 @@ genCmp (operand * left, operand * right,
              emit2 ("add hl,%s", _getPairIdName (id));
              goto release;
            }
+#endif
          if (AOP_TYPE (right) == AOP_LIT)
            {
              lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
@@ -3076,19 +3295,19 @@ genCmp (operand * left, operand * right,
                  if (!sign)
                    {
                      /* No sign so it's always false */
-                     _ClearCarry();
+                     _clearCarry();
                    }
                  else
                    {
                      /* Just load in the top most bit */
-                     _MoveA (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;
                }
@@ -3106,9 +3325,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)
@@ -3120,34 +3339,34 @@ 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)
-               _ClearCarry();
+               _clearCarry();
            }
          else
            {
-             _ClearCarry();
+             _clearCarry();
            }
          while (size--)
            {
              /* Do a long subtract */
              if (!sign || size)
                {
-                 _MoveA (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 ("sbc a,%s", _fTmp[1]);
                }
              else
                {
                  /* Subtract through, propagating the carry */
-                 emitcode ("sbc", "a,%s ; 2", aopGet (AOP (right), offset++, FALSE));
+                 emit2 ("sbc a,%s", aopGet (AOP (right), offset++, FALSE));
                }
            }
        }
@@ -3257,19 +3476,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);
        }
@@ -3277,11 +3496,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++;
            }
@@ -3295,14 +3514,14 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
     {
       while (size--)
        {
-         _MoveA (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++;
@@ -3314,8 +3533,8 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
       /* PENDING: is this required? */
       while (size--)
        {
-         _MoveA (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++;
        }
@@ -3336,7 +3555,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);
 }
 
@@ -3352,7 +3571,7 @@ genCmpEq (iCode * ic, iCode * ifx)
   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
 
-  emit2("; genCmpEq: left %u, right %u, result %u\n", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
+  emitDebug ("; genCmpEq: left %u, right %u, result %u\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.
@@ -3477,9 +3696,9 @@ genAndOp (iCode * ic)
   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);
     }
@@ -3514,9 +3733,9 @@ genOrOp (iCode * ic)
   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);
     }
@@ -3587,10 +3806,10 @@ genAnd (iCode * ic, iCode * ifx)
   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
 
 #ifdef DEBUG_TYPE
-  emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
+  emitDebug ("; Type res[%d] = l[%d]&r[%d]",
            AOP_TYPE (result),
            AOP_TYPE (left), AOP_TYPE (right));
-  emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
+  emitDebug ("; Size res[%d] = l[%d]&r[%d]",
            AOP_SIZE (result),
            AOP_SIZE (left), AOP_SIZE (right));
 #endif
@@ -3642,12 +3861,12 @@ genAnd (iCode * ic, iCode * ifx)
       if (posbit)
        {
          posbit--;
-         _MoveA (aopGet (AOP (left), posbit >> 3, FALSE));
+         _moveA (aopGet (AOP (left), posbit >> 3, FALSE));
          // bit = left & 2^n
          if (size)
            {
              wassert (0);
-             emitcode ("mov", "c,acc.%d", posbit & 0x07);
+             emit2 ("mov c,acc.%d", posbit & 0x07);
            }
          // if(left &  2^n)
          else
@@ -3671,23 +3890,23 @@ genAnd (iCode * ic, iCode * ifx)
          if (size)
            {
              wassert (0);
-             emitcode ("setb", "c");
+             emit2 ("setb c");
            }
          while (sizel--)
            {
              if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
                {
-                 _MoveA (aopGet (AOP (left), offset, FALSE));
+                 _moveA (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);
+                     emit2 ("jb acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
                    }
                  else
                    {
                      if (bytelit != 0x0FFL)
-                       emitcode ("and", "a,%s",
+                       emit2 ("and a,%s",
                                  aopGet (AOP (right), offset, FALSE));
                      else
                        /* For the flags */
@@ -3700,7 +3919,7 @@ genAnd (iCode * ic, iCode * ifx)
          // bit = left & literal
          if (size)
            {
-             emitcode ("clr", "c");
+             emit2 ("clr c");
              emit2 ("!tlabeldef", tlbl->key + 100);
            }
          // if(left & literal)
@@ -3727,11 +3946,11 @@ genAnd (iCode * ic, iCode * ifx)
              else
                {
                  if (bytelit == 0)
-                   aopPut (AOP (result), zero, offset);
+                   aopPut (AOP (result), "!zero", offset);
                  else
                    {
-                     _MoveA (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);
                    }
@@ -3746,8 +3965,8 @@ genAnd (iCode * ic, iCode * ifx)
                }
              else
                {
-                 _MoveA (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);
                }
@@ -3778,18 +3997,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
                {
-                 _MoveA (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);
@@ -3819,10 +4038,10 @@ genOr (iCode * ic, iCode * ifx)
   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
 
 #if 1
-  emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
+  emitDebug ("; Type res[%d] = l[%d]&r[%d]",
            AOP_TYPE (result),
            AOP_TYPE (left), AOP_TYPE (right));
-  emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
+  emitDebug ("; Size res[%d] = l[%d]&r[%d]",
            AOP_SIZE (result),
            AOP_SIZE (left), AOP_SIZE (right));
 #endif
@@ -3882,8 +4101,8 @@ genOr (iCode * ic, iCode * ifx)
                continue;
              else
                {
-                 _MoveA (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);
                }
@@ -3891,11 +4110,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
                {
-                 _MoveA (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);
                }
@@ -3927,11 +4146,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
              {
-               _MoveA (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);
@@ -4016,20 +4235,22 @@ genXor (iCode * ic, iCode * ifx)
                continue;
              else
                {
-                 _MoveA (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
                {
-                 _MoveA (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);
                }
@@ -4060,14 +4281,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
              {
-               _MoveA (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);
          }
@@ -4087,7 +4309,7 @@ genInline (iCode * ic)
 {
   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));
@@ -4098,7 +4320,7 @@ genInline (iCode * ic)
       if (*bp == '\n')
        {
          *bp++ = '\0';
-         emitcode (bp1, "");
+         emit2 (bp1);
          bp1 = bp;
        }
       else
@@ -4108,7 +4330,7 @@ genInline (iCode * ic)
              bp++;
              *bp = '\0';
              bp++;
-             emitcode (bp1, "");
+             emit2 (bp1);
              bp1 = bp;
            }
          else
@@ -4116,9 +4338,9 @@ genInline (iCode * ic)
        }
     }
   if (bp1 != bp)
-    emitcode (bp1, "");
-  /*     emitcode("",buffer); */
-  inLine -= (!options.asmpeep);
+    emit2 (bp1);
+  _G.lines.isInline -= (!options.asmpeep);
+
 }
 
 /*-----------------------------------------------------------------*/
@@ -4139,53 +4361,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 <= 2)
     {
-      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;
-      const 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);
     }
 }
 
@@ -4226,16 +4492,19 @@ shiftL2Left2Result (operand * left, int offl,
        emitLabel (tlbl->key + 100);
       }
 
-    emitcode ("or", "a,a");
+    emit2 ("or a,a");
     while (size--)
       {
-       l = aopGet (AOP (result), offset++, FALSE);
-       emitcode ("rl", "%s", l);
+       l = aopGet (AOP (result), offset, FALSE);
+
+       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);
       }
   }
@@ -4254,34 +4523,34 @@ AccRol (int shCount)
     case 0:
       break;
     case 1:
-      emitcode ("rl", "a");
+      emit2 ("rl a");
       break;
     case 2:
-      emitcode ("rl", "a");
-      emitcode ("rl", "a");
+      emit2 ("rl a");
+      emit2 ("rl a");
       break;
     case 3:
-      emitcode ("rl", "a");
-      emitcode ("rl", "a");
-      emitcode ("rl", "a");
+      emit2 ("rl a");
+      emit2 ("rl a");
+      emit2 ("rl a");
       break;
     case 4:
-      emitcode ("rl", "a");
-      emitcode ("rl", "a");
-      emitcode ("rl", "a");
-      emitcode ("rl", "a");
+      emit2 ("rl a");
+      emit2 ("rl a");
+      emit2 ("rl a");
+      emit2 ("rl a");
       break;
     case 5:
-      emitcode ("rr", "a");
-      emitcode ("rr", "a");
-      emitcode ("rr", "a");
+      emit2 ("rr a");
+      emit2 ("rr a");
+      emit2 ("rr a");
       break;
     case 6:
-      emitcode ("rr", "a");
-      emitcode ("rr", "a");
+      emit2 ("rr a");
+      emit2 ("rr a");
       break;
     case 7:
-      emitcode ("rr", "a");
+      emit2 ("rr a");
       break;
     }
 }
@@ -4292,16 +4561,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
        {
@@ -4322,7 +4596,7 @@ shiftL1Left2Result (operand * left, int offl,
 {
   const char *l;
   l = aopGet (AOP (left), offl, FALSE);
-  _MoveA (l);
+  _moveA (l);
   /* shift left accumulator */
   AccLsh (shCount);
   aopPut (AOP (result), "a", offr);
@@ -4348,18 +4622,18 @@ genlshTwo (operand * result, operand * left, int shCount)
          if (shCount)
            {
              movLeft2Result (left, LSB, result, MSB16, 0);
-             aopPut (AOP (result), zero, 0);
+             aopPut (AOP (result), "!zero", 0);
              shiftL1Left2Result (left, MSB16, 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 */
@@ -4405,7 +4679,7 @@ genLeftShiftLiteral (operand * left,
   size = getSize (operandType (result));
 
 #if VIEW_SIZE
-  emitcode ("; shift left ", "result %d, left %d", size,
+  emitDebug ("; shift left  result %d, left %d", size,
            AOP_SIZE (left));
 #endif
 
@@ -4415,9 +4689,13 @@ genLeftShiftLiteral (operand * left,
       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)
@@ -4429,7 +4707,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);
@@ -4468,8 +4746,8 @@ 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);
@@ -4509,14 +4787,16 @@ genLeftShift (iCode * ic)
   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
   emitLabel (tlbl->key + 100);
   l = aopGet (AOP (result), offset, FALSE);
-  emitcode ("or", "a,a");
+
+  emit2 ("or a,a");
+
   while (size--)
     {
       l = aopGet (AOP (result), offset++, FALSE);
-      emitcode ("rl", "%s", l);
+      emit2 ("rl %s", l);
     }
   emitLabel (tlbl1->key + 100);
-  emitcode ("dec", "a");
+  emit2 ("dec a");
   emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
 
   freeAsmop (left, NULL, ic);
@@ -4527,7 +4807,7 @@ 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);
@@ -4537,19 +4817,24 @@ genrshOne (operand * result, operand * left, int shCount)
   wassert (shCount < 8);
 
   l = aopGet (AOP (left), 0, FALSE);
+
+  emit2 ("or a,a");
+
   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
     {
-      _MoveA (l);
+      _moveA (l);
       while (shCount--)
        {
-         emitcode ("srl", "a");
+         emit2 ("%s a", is_signed ? "sra" : "srl");
        }
       aopPut (AOP (result), "a", 0);
     }
@@ -4561,6 +4846,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 */
@@ -4578,7 +4868,7 @@ shiftR1Left2Result (operand * left, int offl,
                    operand * result, int offr,
                    int shCount, int sign)
 {
-  _MoveA (aopGet (AOP (left), offl, FALSE));
+  _moveA (aopGet (AOP (left), offl, FALSE));
   if (sign)
     {
       wassert (0);
@@ -4610,7 +4900,7 @@ genrshTwo (operand * result, operand * left,
        {
          movLeft2Result (left, MSB16, result, LSB, sign);
        }
-      aopPut (AOP (result), zero, 1);
+      aopPut (AOP (result), "!zero", 1);
     }
   /*  1 <= shCount <= 7 */
   else
@@ -4626,7 +4916,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;
@@ -4638,7 +4929,7 @@ genRightShiftLiteral (operand * left,
 
   size = getSize (operandType (result));
 
-  emitcode ("; shift right ", "result %d, left %d", size,
+  emitDebug ("; shift right  result %d, left %d", size,
            AOP_SIZE (left));
 
   /* I suppose that the left size >= result size */
@@ -4649,23 +4940,23 @@ 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);
@@ -4709,7 +5000,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;
     }
 
@@ -4732,8 +5023,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);
@@ -4748,17 +5039,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);
@@ -4897,7 +5187,7 @@ genGenPointerSet (operand * right,
        }
       else
        {
-         _MoveA (l);
+         _moveA (l);
          emit2 ("ld !*pair,a", pair);
        }
       goto release;
@@ -4931,12 +5221,12 @@ genGenPointerSet (operand * right,
            }
          else
            {
-             _MoveA (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++;
@@ -4979,7 +5269,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 */
@@ -5027,8 +5317,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
        {
@@ -5044,14 +5334,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);
@@ -5076,7 +5366,7 @@ genAssign (iCode * ic)
   /* 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
@@ -5087,7 +5377,7 @@ 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;
     }
 
@@ -5124,7 +5414,7 @@ genAssign (iCode * ic)
            {
              if (!fXored && size > 1)
                {
-                 emitcode ("xor", "a,a");
+                 emit2 ("xor a,a");
                  fXored = TRUE;
                }
              if (fXored)
@@ -5133,7 +5423,7 @@ genAssign (iCode * ic)
                }
              else
                {
-                 aopPut (AOP (result), zero, offset);
+                 aopPut (AOP (result), "!zero", offset);
                }
            }
          else
@@ -5146,8 +5436,8 @@ 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. */
-      _MoveA (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);
     }
@@ -5158,7 +5448,7 @@ genAssign (iCode * ic)
          /* PENDING: do this check better */
          if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
            {
-             _MoveA (aopGet (AOP (right), offset, FALSE));
+             _moveA (aopGet (AOP (right), offset, FALSE));
              aopPut (AOP (result), "a", offset);
            }
          else
@@ -5187,18 +5477,18 @@ genJumpTab (iCode * ic)
   /* 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 */
@@ -5280,17 +5570,17 @@ 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 :{ */
         const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
                        FALSE);
-      _MoveA (l);
-      emitcode ("", "; genCast: sign extend untested.");
-      emitcode ("rla", "");
-      emitcode ("sbc", "a,a");
+      _moveA (l);
+      emitDebug ("; genCast: sign extend untested.");
+      emit2 ("rla ");
+      emit2 ("sbc a,a");
       while (size--)
        aopPut (AOP (result), "a", offset++);
     }
@@ -5322,13 +5612,253 @@ genReceive (iCode * ic)
         size = AOP_SIZE(IC_RESULT(ic));
 
         for (i = 0; i < size; i++) {
-            aopPut(AOP(IC_RESULT(ic)), _fReturn[_G.receiveOffset++], 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            */
 /*-----------------------------------------------------------------*/
@@ -5349,36 +5879,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;
-    }
+  _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
@@ -5392,22 +5901,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;
 
@@ -5422,83 +5931,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;
 
@@ -5513,66 +6022,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;
 
@@ -5580,46 +6090,50 @@ 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); */
@@ -5631,7 +6145,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 */
@@ -5639,12 +6153,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);
+}
+
+
+*/