Added support for gsinit packing.
[fw/sdcc] / src / z80 / gen.c
index 9e325cd561c582f97a4f5a017eaea92cb60de633..0482186cb9c36f3596c5acae63522b2ff97086d6 100644 (file)
@@ -2,39 +2,54 @@
   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
-
-  Michael Hope <michaelh@earthling.net>        2000
-  Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998)
-                           and -  Jean-Louis VERN.jlvern@writeme.com (1999)
-        
+                                       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
+
+  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)
+
   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 2, or (at your option) any
   later version.
-  
+
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
-  
+
+
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-  
+
   In other words, you are welcome to use, share and improve this program.
   You are forbidden to forbid anyone else to use, share and improve
   what you give them.   Help stamp out software-hoarding!
 #endif
 
 #include "z80.h"
+#include "SDCCglobl.h"
 #include "SDCCpeeph.h"
 #include "gen.h"
 #include "SDCCglue.h"
+#include "newalloc.h"
 
 /* this is the down and dirty file with all kinds of kludgy & hacky
    stuff. This is what it is all about CODE GENERATION for a specific MCU.
    Some of the routines may be reusable, will have to see */
 
-static char *zero = "#0x00";
-static char *one  = "#0x01";
-static char *spname ;
-static char *_z80_return[] = {"l", "h", "e", "d" };
-static char *_gbz80_return[] = { "e", "d", "l", "h" };
+/* Z80 calling convention description.
+   Parameters are passed right to left.  As the stack grows downwards,
+   the parameters are arranged in left to right in memory.
+   Parameters may be passed in the HL and DE registers with one
+   parameter per pair.
+   PENDING: What if the parameter is a long?
+   Everything is caller saves. i.e. the caller must save any registers
+   that it wants to preserve over the call.
+   The return value is returned in DEHL.  DE is normally used as a
+   working register pair.  Caller saves allows it to be used for a
+   return value.
+   va args functions do not use register parameters.  All arguments
+   are passed on the stack.
+   IX is used as an index register to the top of the local variable
+   area.  ix-0 is the top most local variable.
+*/
+
+enum {
+  DISABLE_DEBUG = 1
+};
+
+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;
 
-static char *accUse[] = {"a" };
-short rbank = -1;
-short accInUse = 0 ;
-short inLine = 0;
-short debugLine = 0;
-short nregssaved = 0;
-extern int ptrRegReq ;
-extern int nRegs;
 extern FILE *codeOutFile;
-set *sendSet = NULL;
+
+typedef enum
+  {
+    PAIR_INVALID,
+    PAIR_AF,
+    PAIR_BC,
+    PAIR_DE,
+    PAIR_HL,
+    PAIR_IY,
+    PAIR_IX,
+    NUM_PAIRS
+  } PAIR_ID;
+
+static struct
+{
+  const char *name;
+  const char *l;
+  const char *h;
+} _pairs[NUM_PAIRS] = {
+  {    "??1", "?2", "?3" },
+  {    "af", "f", "a" },
+  {    "bc", "c", "b" },
+  {    "de", "e", "d" },
+  {    "hl", "l", "h" },
+  {    "iy", "iy.l?", "iy.h?" },
+  {    "ix", "ix.l?", "ix.h?" }
+};
+
+// PENDING
+#define ACC_NAME       _pairs[PAIR_AF].h
+
 #define RESULTONSTACK(x) \
                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
                          IC_RESULT(x)->aop->type == AOP_STK )
 
-#define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
-#define CLRC    emitcode("xor","a,a");
+enum 
+  {
+    LSB,
+    MSB16,
+    MSB24,
+    MSB32
+  };
+
+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;
+
+  struct 
+  {
+    lineNode *head;
+    lineNode *current;
+    int isInline;
+  } lines;
+
+} _G;
+
+static const char *aopGet (asmop * aop, int offset, bool bit16);
+
+static void
+_tidyUp (char *buf)
+{
+  /* Clean up the line so that it is 'prettier' */
+  if (strchr (buf, ':'))
+    {
+      /* Is a label - cant do anything */
+      return;
+    }
+  /* Change the first (and probably only) ' ' to a tab so
+     everything lines up.
+  */
+  while (*buf)
+    {
+      if (*buf == ' ')
+        {
+          *buf = '\t';
+          break;
+        }
+      buf++;
+    }
+}
 
-#define LABEL_STR      "%05d$"
+static void
+_vemit2 (const char *szFormat, va_list ap)
+{
+  char buffer[256];
 
-lineNode *lineHead = NULL;
-lineNode *lineCurr = NULL;
+  tvsprintf (buffer, szFormat, ap);
 
-unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
-0xE0, 0xC0, 0x80, 0x00};
-unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
-0x07, 0x03, 0x01, 0x00};
+  _tidyUp (buffer);
+  _G.lines.current = (_G.lines.current ?
+             connectLine (_G.lines.current, newLineNode (buffer)) :
+             (_G.lines.head = newLineNode (buffer)));
 
-static int _lastStack = 0;
-static int _pushed = 0;
-static int _spoffset;
+  _G.lines.current->isInline = _G.lines.isInline;
+}
 
-#define LSB     0
-#define MSB16   1
-#define MSB24   2
-#define MSB32   3
+static void
+emit2 (const char *szFormat,...)
+{
+  va_list ap;
 
-/* Stack frame:
+  va_start (ap, szFormat);
 
-   IX+4                param0  LH
-   IX+2                ret     LH
-   IX+0                ix      LH
-   IX-2                temp0   LH
-*/
+  _vemit2 (szFormat, ap);
+
+  va_end (ap);
+}
+
+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, ...)
+void
+_emit2 (const char *inst, const char *fmt,...)
 {
-    va_list ap;
-    char lb[MAX_INLINEASM];  
-    char *lbp = lb;
+  va_list ap;
+  char lb[INITIAL_INLINEASM];
+  char *lbp = lb;
+
+  va_start (ap, fmt);
+
+  if (*inst != '\0')
+    {
+      sprintf (lb, "%s\t", inst);
+      vsprintf (lb + (strlen (lb)), fmt, ap);
+    }
+  else
+    vsprintf (lb, fmt, ap);
+
+  while (isspace (*lbp))
+    lbp++;
 
-    va_start(ap,fmt);   
+  if (lbp && *lbp)
+    {
+      _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);
+}
 
-    if (*inst != '\0') {
-        sprintf(lb,"%s\t",inst);
-        vsprintf(lb+(strlen(lb)),fmt,ap);
-    }  else 
-        vsprintf(lb,fmt,ap);
+static void
+_emitMove(const char *to, const char *from)
+{
+  if (strcasecmp(to, from) != 0) 
+    {
+      emit2("ld %s,%s", to, from);
+    }
+  else 
+    {
+      // Optimise it out.
+      // Could leave this to the peephole, but sometimes the peephole is inhibited.
+    }
+}
 
-    while (isspace(*lbp)) lbp++;
+static void
+_moveA(const char *moveFrom)
+{
+    // Let the peephole optimiser take care of redundent loads
+    _emitMove(ACC_NAME, moveFrom);
+}
 
-    if (lbp && *lbp) 
-        lineCurr = (lineCurr ?
-                    connectLine(lineCurr,newLineNode(lb)) :
-                    (lineHead = newLineNode(lb)));
-    lineCurr->isInline = inLine;
-    lineCurr->isDebug  = debugLine;
-    va_end(ap);
+static void
+_clearCarry(void)
+{
+    emit2("xor a,a");
 }
 
-const char *getPairName(asmop *aop)
+const char *
+getPairName (asmop * aop)
 {
-    if (aop->type == AOP_REG) {
-       switch (aop->aopu.aop_reg[0]->rIdx) {
+  if (aop->type == AOP_REG)
+    {
+      switch (aop->aopu.aop_reg[0]->rIdx)
+       {
        case C_IDX:
-           return "bc";
-           break;
+         return "bc";
+         break;
        case E_IDX:
-           return "de";
-           break;
+         return "de";
+         break;
        case L_IDX:
-           return "hl";
-           break;
+         return "hl";
+         break;
        }
     }
-    else if (aop->type == AOP_STR) {
-       switch (*aop->aopu.aop_str[0]) {
+  else if (aop->type == AOP_STR)
+    {
+      switch (*aop->aopu.aop_str[0])
+       {
        case 'c':
-           return "bc";
-           break;
+         return "bc";
+         break;
        case 'e':
-           return "de";
-           break;
+         return "de";
+         break;
        case 'l':
-           return "hl";
-           break;
+         return "hl";
+         break;
        }
     }
-    assert(0);
-    return NULL;
+  wassert (0);
+  return NULL;
 }
 
-/** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
-bool isPair(asmop *aop)
+static PAIR_ID
+getPairId (asmop * aop)
 {
-    if (aop->size == 2) {
-       if (aop->type == AOP_REG) {
-           if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
-               return TRUE;
+  if (aop->size == 2)
+    {
+      if (aop->type == AOP_REG)
+       {
+         if ((aop->aopu.aop_reg[0]->rIdx == C_IDX) && (aop->aopu.aop_reg[1]->rIdx == B_IDX))
+           {
+             return PAIR_BC;
            }
-           if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
-               return TRUE;
+         if ((aop->aopu.aop_reg[0]->rIdx == E_IDX) && (aop->aopu.aop_reg[1]->rIdx == D_IDX))
+           {
+             return PAIR_DE;
            }
-           if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
-               return TRUE;
+         if ((aop->aopu.aop_reg[0]->rIdx == L_IDX) && (aop->aopu.aop_reg[1]->rIdx == H_IDX))
+           {
+             return PAIR_HL;
            }
        }
-       if (aop->type == AOP_STR) {
-           if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
-               return TRUE;
+      if (aop->type == AOP_STR)
+       {
+         if (!strcmp (aop->aopu.aop_str[0], "c") && !strcmp (aop->aopu.aop_str[1], "b"))
+           {
+             return PAIR_BC;
            }
-           if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
-               return TRUE;
+         if (!strcmp (aop->aopu.aop_str[0], "e") && !strcmp (aop->aopu.aop_str[1], "d"))
+           {
+             return PAIR_DE;
            }
-           if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
-               return TRUE;
+         if (!strcmp (aop->aopu.aop_str[0], "l") && !strcmp (aop->aopu.aop_str[1], "h"))
+           {
+             return PAIR_HL;
            }
        }
     }
-    return FALSE;
+  return PAIR_INVALID;
 }
 
+/** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
+bool
+isPair (asmop * aop)
+{
+  return (getPairId (aop) != PAIR_INVALID);
+}
+
+bool
+isPtrPair (asmop * aop)
+{
+  PAIR_ID pairId = getPairId (aop);
+  switch (pairId)
+    {
+    case PAIR_HL:
+    case PAIR_IY:
+    case PAIR_IX:
+      return TRUE;
+    default:
+      return FALSE;
+    }
+}
 /** Push a register pair onto the stack */
-void genPairPush(asmop *aop)
+void
+genPairPush (asmop * aop)
 {
-    emitcode("push", "%s", getPairName(aop));
+  emit2 ("push %s", getPairName (aop));
 }
 
+
 /*-----------------------------------------------------------------*/
 /* newAsmop - creates a new asmOp                                  */
 /*-----------------------------------------------------------------*/
-static asmop *newAsmop (short type)
+static asmop *
+newAsmop (short type)
 {
-    asmop *aop;
+  asmop *aop;
 
-    ALLOC(aop,sizeof(asmop));
-    aop->type = type;
-    return aop;
+  aop = Safe_calloc (1, sizeof (asmop));
+  aop->type = type;
+  return aop;
 }
 
 /*-----------------------------------------------------------------*/
 /* aopForSym - for a true symbol                                   */
 /*-----------------------------------------------------------------*/
-static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
+static asmop *
+aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
 {
-    asmop *aop;
-    memmap *space= SPEC_OCLS(sym->etype);
+  asmop *aop;
+  memmap *space;
 
-    /* if already has one */
-    if (sym->aop)
-        return sym->aop;
+  wassert (ic);
+  wassert (sym);
+  wassert (sym->etype);
 
-    /* Assign depending on the storage class */
-    if (sym->onStack || sym->iaccess) {
-        sym->aop = aop = newAsmop(AOP_STK);
-        aop->size = getSize(sym->type);
+  space = SPEC_OCLS (sym->etype);
 
-       aop->aopu.aop_stk = sym->stack;
-        return aop;
+  /* if already has one */
+  if (sym->aop)
+    return sym->aop;
+
+  /* Assign depending on the storage class */
+  if (sym->onStack || sym->iaccess)
+    {
+      emitDebug ("; AOP_STK for %s", sym->rname);
+      sym->aop = aop = newAsmop (AOP_STK);
+      aop->size = getSize (sym->type);
+      aop->aopu.aop_stk = sym->stack;
+      return aop;
     }
 
-    /* special case for a function */
-    if (IS_FUNC(sym->type)) {   
-        sym->aop = aop = newAsmop(AOP_IMMD);    
-        ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
-        strcpy(aop->aopu.aop_immd,sym->rname);
-        aop->size = 2;
-        return aop;
+  /* special case for a function */
+  if (IS_FUNC (sym->type))
+    {
+      sym->aop = aop = newAsmop (AOP_IMMD);
+      aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
+      strcpy (aop->aopu.aop_immd, sym->rname);
+      aop->size = 2;
+      return aop;
     }
 
-    if (IS_GB) {
-       /* if it is in direct space */
-       if (IN_DIRSPACE(space)) {
-           sym->aop = aop = newAsmop (AOP_DIR);
-           aop->aopu.aop_dir = sym->rname ;
-           aop->size = getSize(sym->type);
-           emitcode("", "; AOP_DIR for %s", sym->rname);
-           return aop;
+  if (IS_GB)
+    {
+      /* if it is in direct space */
+      if (IN_REGSP (space) && !requires_a)
+       {
+         sym->aop = aop = newAsmop (AOP_SFR);
+         aop->aopu.aop_dir = sym->rname;
+         aop->size = getSize (sym->type);
+         emitDebug ("; AOP_SFR for %s", sym->rname);
+         return aop;
        }
     }
 
-    /* only remaining is far space */
-    /* in which case DPTR gets the address */
-    sym->aop = aop = newAsmop(AOP_IY);
-    if (!IS_GB)
-       emitcode ("ld","iy,#%s ; a", sym->rname);
-    aop->size = getSize(sym->type);
-    aop->aopu.aop_dir = sym->rname;
+  /* only remaining is far space */
+  /* in which case DPTR gets the address */
+  if (IS_GB)
+    {
+      emitDebug ("; AOP_HL for %s", sym->rname);
+      sym->aop = aop = newAsmop (AOP_HL);
+    }
+  else
+    {
+      sym->aop = aop = newAsmop (AOP_IY);
+    }
+  aop->size = getSize (sym->type);
+  aop->aopu.aop_dir = sym->rname;
 
-    /* if it is in code space */
-    if (IN_CODESPACE(space))
-        aop->code = 1;
+  /* if it is in code space */
+  if (IN_CODESPACE (space))
+    aop->code = 1;
 
-    return aop;     
+  return aop;
 }
 
 /*-----------------------------------------------------------------*/
 /* aopForRemat - rematerialzes an object                           */
 /*-----------------------------------------------------------------*/
-static asmop *aopForRemat (symbol *sym)
+static asmop *
+aopForRemat (symbol * sym)
 {
-    char *s = buffer;   
-    iCode *ic = sym->rematiCode;
-    asmop *aop = newAsmop(AOP_IMMD);
+  char *s = buffer;
+  iCode *ic = sym->rematiCode;
+  asmop *aop = newAsmop (AOP_IMMD);
 
-    while (1) {
-        /* if plus or minus print the right hand side */
-        if (ic->op == '+' || ic->op == '-') {
-            sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
-                    ic->op );
-            s += strlen(s);
-            ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
-            continue ;
-        }
-        /* we reached the end */
-        sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
-        break;
+  while (1)
+    {
+      /* if plus or minus print the right hand side */
+      if (ic->op == '+' || ic->op == '-')
+       {
+         /* PENDING: for re-target */
+         sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
+                  ic->op);
+         s += strlen (s);
+         ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+         continue;
+       }
+      /* we reached the end */
+      sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
+      break;
     }
 
-    ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
-    strcpy(aop->aopu.aop_immd,buffer);    
-    return aop;        
+  aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
+  strcpy (aop->aopu.aop_immd, buffer);
+  return aop;
 }
 
 /*-----------------------------------------------------------------*/
 /* regsInCommon - two operands have some registers in common       */
 /*-----------------------------------------------------------------*/
-bool regsInCommon (operand *op1, operand *op2)
+bool
+regsInCommon (operand * op1, operand * op2)
 {
-    symbol *sym1, *sym2;
-    int i;
+  symbol *sym1, *sym2;
+  int i;
 
-    /* if they have registers in common */
-    if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
-        return FALSE ;
+  /* if they have registers in common */
+  if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
+    return FALSE;
 
-    sym1 = OP_SYMBOL(op1);
-    sym2 = OP_SYMBOL(op2);
+  sym1 = OP_SYMBOL (op1);
+  sym2 = OP_SYMBOL (op2);
 
-    if (sym1->nRegs == 0 || sym2->nRegs == 0)
-        return FALSE ;
+  if (sym1->nRegs == 0 || sym2->nRegs == 0)
+    return FALSE;
 
-    for (i = 0 ; i < sym1->nRegs ; i++) {
-        int j;
-        if (!sym1->regs[i])
-            continue ;
+  for (i = 0; i < sym1->nRegs; i++)
+    {
+      int j;
+      if (!sym1->regs[i])
+       continue;
 
-        for (j = 0 ; j < sym2->nRegs ;j++ ) {
-            if (!sym2->regs[j])
-                continue ;
+      for (j = 0; j < sym2->nRegs; j++)
+       {
+         if (!sym2->regs[j])
+           continue;
 
-            if (sym2->regs[j] == sym1->regs[i])
-                return TRUE ;
-        }
+         if (sym2->regs[j] == sym1->regs[i])
+           return TRUE;
+       }
     }
 
-    return FALSE ;
+  return FALSE;
 }
 
 /*-----------------------------------------------------------------*/
 /* operandsEqu - equivalent                                        */
 /*-----------------------------------------------------------------*/
-bool operandsEqu ( operand *op1, operand *op2)
+bool
+operandsEqu (operand * op1, operand * op2)
 {
-    symbol *sym1, *sym2;
+  symbol *sym1, *sym2;
 
-    /* if they not symbols */
-    if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
-        return FALSE;
+  /* if they not symbols */
+  if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
+    return FALSE;
 
-    sym1 = OP_SYMBOL(op1);
-    sym2 = OP_SYMBOL(op2);
+  sym1 = OP_SYMBOL (op1);
+  sym2 = OP_SYMBOL (op2);
 
-    /* if both are itemps & one is spilt
-       and the other is not then false */
-    if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
-       sym1->isspilt != sym2->isspilt )
-       return FALSE ;
+  /* if both are itemps & one is spilt
+     and the other is not then false */
+  if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
+      sym1->isspilt != sym2->isspilt)
+    return FALSE;
 
-    /* if they are the same */
-    if (sym1 == sym2)
-        return 1;
+  /* if they are the same */
+  if (sym1 == sym2)
+    return 1;
 
-    if (strcmp(sym1->rname,sym2->rname) == 0)
-        return 2;
+  if (strcmp (sym1->rname, sym2->rname) == 0)
+    return 2;
 
 
-    /* if left is a tmp & right is not */
-    if (IS_ITEMP(op1)  && 
-        !IS_ITEMP(op2) &&
-        sym1->isspilt  &&
-        (sym1->usl.spillLoc == sym2))
-        return 3;
+  /* if left is a tmp & right is not */
+  if (IS_ITEMP (op1) &&
+      !IS_ITEMP (op2) &&
+      sym1->isspilt &&
+      (sym1->usl.spillLoc == sym2))
+    return 3;
 
-    if (IS_ITEMP(op2)  && 
-        !IS_ITEMP(op1) &&
-        sym2->isspilt  &&
-       sym1->level > 0 &&
-        (sym2->usl.spillLoc == sym1))
-        return 4;
+  if (IS_ITEMP (op2) &&
+      !IS_ITEMP (op1) &&
+      sym2->isspilt &&
+      sym1->level > 0 &&
+      (sym2->usl.spillLoc == sym1))
+    return 4;
 
-    return FALSE;
+  return FALSE;
 }
 
 /*-----------------------------------------------------------------*/
 /* sameRegs - two asmops have the same registers                   */
 /*-----------------------------------------------------------------*/
-bool sameRegs (asmop *aop1, asmop *aop2 )
+bool
+sameRegs (asmop * aop1, asmop * aop2)
 {
-    int i;
+  int i;
+
+  if (aop1->type == AOP_SFR ||
+      aop2->type == AOP_SFR)
+    return FALSE;
 
-    if (aop1 == aop2)
-        return TRUE ;
+  if (aop1 == aop2)
+    return TRUE;
 
-    if (aop1->type != AOP_REG ||
-        aop2->type != AOP_REG )
-        return FALSE ;
+  if (aop1->type != AOP_REG ||
+      aop2->type != AOP_REG)
+    return FALSE;
 
-    if (aop1->size != aop2->size)
-        return FALSE ;
+  if (aop1->size != aop2->size)
+    return FALSE;
 
-    for (i = 0 ; i < aop1->size ; i++ )
-        if (aop1->aopu.aop_reg[i] !=
-            aop2->aopu.aop_reg[i] )
-            return FALSE ;
+  for (i = 0; i < aop1->size; i++)
+    if (aop1->aopu.aop_reg[i] !=
+       aop2->aopu.aop_reg[i])
+      return FALSE;
 
-    return TRUE ;
+  return TRUE;
 }
 
 /*-----------------------------------------------------------------*/
 /* aopOp - allocates an asmop for an operand  :                    */
 /*-----------------------------------------------------------------*/
-static void aopOp (operand *op, iCode *ic, bool result)
+static void
+aopOp (operand * op, iCode * ic, bool result, bool requires_a)
 {
-    asmop *aop;
-    symbol *sym;
-    int i;
+  asmop *aop;
+  symbol *sym;
+  int i;
 
-    if (!op)
-        return ;
+  if (!op)
+    return;
 
-    /* if this a literal */
-    if (IS_OP_LITERAL(op)) {
-        op->aop = aop = newAsmop(AOP_LIT);
-        aop->aopu.aop_lit = op->operand.valOperand;
-        aop->size = getSize(operandType(op));
-        return;
+  /* if this a literal */
+  if (IS_OP_LITERAL (op))
+    {
+      op->aop = aop = newAsmop (AOP_LIT);
+      aop->aopu.aop_lit = op->operand.valOperand;
+      aop->size = getSize (operandType (op));
+      return;
     }
 
-    /* if already has a asmop then continue */
-    if (op->aop)
-        return ;
+  /* if already has a asmop then continue */
+  if (op->aop)
+    return;
 
-    /* if the underlying symbol has a aop */
-    if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
-        op->aop = OP_SYMBOL(op)->aop;
-        return;
+  /* if the underlying symbol has a aop */
+  if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
+    {
+      op->aop = OP_SYMBOL (op)->aop;
+      return;
     }
 
-    /* if this is a true symbol */
-    if (IS_TRUE_SYMOP(op)) {    
-        op->aop = aopForSym(ic,OP_SYMBOL(op),result);
-        return ;
+  /* if this is a true symbol */
+  if (IS_TRUE_SYMOP (op))
+    {
+      op->aop = aopForSym (ic, OP_SYMBOL (op), result, requires_a);
+      return;
     }
 
-    /* this is a temporary : this has
-    only four choices :
-    a) register
-    b) spillocation
-    c) rematerialize 
-    d) conditional   
-    e) can be a return use only */
+  /* this is a temporary : this has
+     only four choices :
+     a) register
+     b) spillocation
+     c) rematerialize
+     d) conditional
+     e) can be a return use only */
 
-    sym = OP_SYMBOL(op);
+  sym = OP_SYMBOL (op);
 
-    /* if the type is a conditional */
-    if (sym->regType == REG_CND) {
-        aop = op->aop = sym->aop = newAsmop(AOP_CRY);
-        aop->size = 0;
-        return;
+  /* if the type is a conditional */
+  if (sym->regType == REG_CND)
+    {
+      aop = op->aop = sym->aop = newAsmop (AOP_CRY);
+      aop->size = 0;
+      return;
     }
 
-    /* if it is spilt then two situations
-    a) is rematerialize 
-    b) has a spill location */
-    if (sym->isspilt || sym->nRegs == 0) {
-        /* rematerialize it NOW */
-        if (sym->remat) {
-            sym->aop = op->aop = aop =
-                                      aopForRemat (sym);
-            aop->size = getSize(sym->type);
-            return;
-        }
+  /* if it is spilt then two situations
+     a) is rematerialize
+     b) has a spill location */
+  if (sym->isspilt || sym->nRegs == 0)
+    {
+      /* rematerialize it NOW */
+      if (sym->remat)
+       {
+         sym->aop = op->aop = aop =
+           aopForRemat (sym);
+         aop->size = getSize (sym->type);
+         return;
+       }
 
-       if (sym->accuse) {
-           int i;
-            aop = op->aop = sym->aop = newAsmop(AOP_ACC);
-            aop->size = getSize(sym->type);
-            for ( i = 0 ; i < 2 ; i++ )
-                aop->aopu.aop_str[i] = accUse[i];
-            return;  
-       }
-
-        if (sym->ruonly ) {
-            int i;
-            aop = op->aop = sym->aop = newAsmop(AOP_STR);
-            aop->size = getSize(sym->type);
-            for ( i = 0 ; i < 4 ; i++ )
-                aop->aopu.aop_str[i] = "xx"; /*_fReturn[i];*/
-            return;
-        }
+      if (sym->accuse)
+       {
+         if (sym->accuse == ACCUSE_A)
+           {
+             aop = op->aop = sym->aop = newAsmop (AOP_ACC);
+             aop->size = getSize (sym->type);
+              wassertl(aop->size == 1, "Internal error: Caching in A, but too big to fit in A");
+
+              aop->aopu.aop_str[0] = _pairs[PAIR_AF].h;
+           }
+         else if (sym->accuse == ACCUSE_HL)
+           {
+             wassert (!IS_GB);
+             aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
+             aop->size = getSize (sym->type);
+              wassertl(aop->size <= 2, "Internal error: Caching in HL, but too big to fit in HL");
+              aop->aopu.aop_str[0] = _pairs[PAIR_HL].l;
+              aop->aopu.aop_str[1] = _pairs[PAIR_HL].h;
+           }
+         else 
+              {
+                  wassert (0);
+              }
+         return;
+       }
+
+      if (sym->ruonly)
+       {
+         int i;
+         aop = op->aop = sym->aop = newAsmop (AOP_STR);
+         aop->size = getSize (sym->type);
+         for (i = 0; i < 4; i++)
+           aop->aopu.aop_str[i] = _fReturn[i];
+         return;
+       }
 
-        /* else spill location  */
-        sym->aop = op->aop = aop = 
-                                  aopForSym(ic,sym->usl.spillLoc,result);
-        aop->size = getSize(sym->type);
-        return;
+      /* else spill location  */
+      sym->aop = op->aop = aop =
+       aopForSym (ic, sym->usl.spillLoc, result, requires_a);
+      aop->size = getSize (sym->type);
+      return;
     }
 
-    /* must be in a register */
-    sym->aop = op->aop = aop = newAsmop(AOP_REG);
-    aop->size = sym->nRegs;
-    for ( i = 0 ; i < sym->nRegs ;i++)
-        aop->aopu.aop_reg[i] = sym->regs[i];
+  /* must be in a register */
+  sym->aop = op->aop = aop = newAsmop (AOP_REG);
+  aop->size = sym->nRegs;
+  for (i = 0; i < sym->nRegs; i++)
+    aop->aopu.aop_reg[i] = sym->regs[i];
 }
 
 /*-----------------------------------------------------------------*/
 /* freeAsmop - free up the asmop given to an operand               */
 /*----------------------------------------------------------------*/
-static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
-{   
-    asmop *aop ;
-
-    if (!op)
-        aop = aaop;
-    else 
-        aop = op->aop;
+static void
+freeAsmop (operand * op, asmop * aaop, iCode * ic)
+{
+  asmop *aop;
 
-    if (!aop)
-        return ;
+  if (!op)
+    aop = aaop;
+  else
+    aop = op->aop;
 
-    if (aop->freed)
-        goto dealloc; 
+  if (!aop)
+    return;
 
-    aop->freed = 1;
+  if (aop->freed)
+    goto dealloc;
 
-    switch (aop->type) {
-    case AOP_STK :
-       break;
-    }
+  aop->freed = 1;
 
 dealloc:
-    /* all other cases just dealloc */
-    if (op ) {
-        op->aop = NULL;
-        if (IS_SYMOP(op)) {
-            OP_SYMBOL(op)->aop = NULL;    
-            /* if the symbol has a spill */
-           if (SPIL_LOC(op))
-                SPIL_LOC(op)->aop = NULL;
-        }
+  /* all other cases just dealloc */
+  if (op)
+    {
+      op->aop = NULL;
+      if (IS_SYMOP (op))
+       {
+         OP_SYMBOL (op)->aop = NULL;
+         /* if the symbol has a spill */
+         if (SPIL_LOC (op))
+           SPIL_LOC (op)->aop = NULL;
+       }
     }
 }
 
-char *aopGetWordLong(asmop *aop, int offset, bool with_hash)
+bool
+isLitWord (asmop * aop)
 {
-    char *s = buffer ;
-    char *rs;
+  /*    if (aop->size != 2)
+     return FALSE; */
+  switch (aop->type)
+    {
+    case AOP_IMMD:
+    case AOP_LIT:
+      return TRUE;
+    default:
+      return FALSE;
+    }
+}
 
-    if (aop->size != 2)
-       return NULL;
-    assert(offset == 0);
+char *
+aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
+{
+  char *s = buffer;
+  char *rs;
 
-    /* depending on type */
-    switch (aop->type) {
+  /* depending on type */
+  switch (aop->type)
+    {
+    case AOP_HL:
+    case AOP_IY:
     case AOP_IMMD:
-       sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd);
-       ALLOC_ATOMIC(rs,strlen(s)+1);
-       strcpy(rs,s);   
-       return rs;
-       
-    case AOP_LIT: {
-       value * val = aop->aopu.aop_lit;
+      /* PENDING: for re-target */
+      if (with_hash)
+       tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
+      else
+       tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
+
+      return gc_strdup(s);
+
+    case AOP_LIT:
+      {
+       value *val = aop->aopu.aop_lit;
        /* if it is a float then it gets tricky */
        /* otherwise it is fairly simple */
-       if (!IS_FLOAT(val->type)) {
-           unsigned long v = floatFromVal(val);
+       if (!IS_FLOAT (val->type))
+         {
+           unsigned long v = (unsigned long) floatFromVal (val);
+
+           if (offset == 2)
+              {
+                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);
 
-           sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v);
-           ALLOC_ATOMIC(rs,strlen(buffer)+1);
-           return strcpy (rs,buffer);
-       }
-       assert(0);
-       return NULL;
-    }
+            return gc_strdup(buffer);
+         }
+       else
+         {
+           /* A float */
+           Z80_FLOAT f;
+           convertFloat (&f, floatFromVal (val));
+           if (with_hash)
+             tsprintf (buffer, "!immedword", f.w[offset / 2]);
+           else
+             tsprintf (buffer, "!constword", f.w[offset / 2]);
+           rs = Safe_calloc (1, strlen (buffer) + 1);
+           return strcpy (rs, buffer);
+         }
+      }
+    default:
+      return NULL;
     }
-    return NULL;
 }
 
-char *aopGetWord(asmop *aop, int offset)
+char *
+aopGetWord (asmop * aop, int offset)
 {
-    return aopGetWordLong(aop, offset, TRUE);
+  return aopGetLitWordLong (aop, offset, TRUE);
 }
 
-/*-----------------------------------------------------------------*/
-/* aopGet - for fetching value of the aop                          */
-/*-----------------------------------------------------------------*/
-static char *aopGet (asmop *aop, int offset, bool bit16)
+bool
+isPtr (const char *s)
 {
-    char *s = buffer ;
-    char *rs;
-
-    /* offset is greater than size then zero */
-    if (offset > (aop->size - 1) &&
-        aop->type != AOP_LIT)
-        return zero;
-
-    /* depending on type */
-    switch (aop->type) {
-    case AOP_IMMD:
-       if (bit16) 
-           sprintf (s,"#%s",aop->aopu.aop_immd);
-       else
-           if (offset) {
-               assert(offset == 1);
-               sprintf(s,"#>%s",
-                       aop->aopu.aop_immd);
-           }
-           else
-               sprintf(s,"#<%s",
-                       aop->aopu.aop_immd);
-       ALLOC_ATOMIC(rs,strlen(s)+1);
-       strcpy(rs,s);   
-       return rs;
-       
-    case AOP_DIR:
-       assert(IS_GB);
-       emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
-       sprintf(s, "a");
-       ALLOC_ATOMIC(rs,strlen(s)+1);
-       strcpy(rs,s);   
-       return rs;
-       
-    case AOP_REG:
-       return aop->aopu.aop_reg[offset]->name;
-
-    case AOP_IY:
-       sprintf(s,"%d(iy)", offset);
-       ALLOC_ATOMIC(rs,strlen(s)+1);
-       strcpy(rs,s);   
-       return rs;
+  if (!strcmp (s, "hl"))
+    return TRUE;
+  if (!strcmp (s, "ix"))
+    return TRUE;
+  if (!strcmp (s, "iy"))
+    return TRUE;
+  return FALSE;
+}
 
-    case AOP_STK:
-       if (IS_GB) {
-           /* We cant really optimise this as we cant afford to
-              change the flags.
-           */
-           emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset);
-           sprintf(s, "(hl)");
-       }
-       else {
-           sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
-       }
-       ALLOC_ATOMIC(rs,strlen(s)+1);
-       strcpy(rs,s);   
-       return rs;
-       
-    case AOP_CRY:
-       assert(0);
-       
-    case AOP_ACC:
-       if (!offset) {
-           return "a";
-       }
-       return "#0x00";
+static void
+adjustPair (const char *pair, int *pold, int new)
+{
+  wassert (pair);
 
-    case AOP_LIT:
-       return aopLiteral (aop->aopu.aop_lit,offset);
-       
-    case AOP_STR:
-       aop->coff = offset;
-       return aop->aopu.aop_str[offset];
+  while (*pold < new)
+    {
+      emit2 ("inc %s", pair);
+      (*pold)++;
+    }
+  while (*pold > new)
+    {
+      emit2 ("dec %s", pair);
+      (*pold)--;
     }
-
-    fprintf(stderr, "Type %u\n", aop->type);
-
-    werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-           "aopget got unsupported aop->type");
-    exit(0);
 }
 
-bool isRegString(char *s)
+static void
+spillPair (PAIR_ID pairId)
 {
-    if (!strcmp(s, "b") ||
-       !strcmp(s, "c") ||
-       !strcmp(s, "d") ||
-       !strcmp(s, "e") ||
-       !strcmp(s, "a") ||
-       !strcmp(s, "h") ||
-       !strcmp(s, "l"))
-       return TRUE;
-    return FALSE;
+  _G.pairs[pairId].last_type = AOP_INVALID;
+  _G.pairs[pairId].lit = NULL;
 }
 
-bool isConstant(char *s)
+static void
+spillCached (void)
 {
-    return  (*s == '#');
+  spillPair (PAIR_HL);
+  spillPair (PAIR_IY);
 }
 
-bool canAssignToPtr(char *s)
+static bool
+requiresHL (asmop * aop)
 {
-    if (isRegString(s))
-       return TRUE;
-    if (isConstant(s))
-       return TRUE;
-    return FALSE;
+  switch (aop->type)
+    {
+    case AOP_IY:
+    case AOP_HL:
+    case AOP_STK:
+      return TRUE;
+    default:
+      return FALSE;
+    }
 }
 
-/*-----------------------------------------------------------------*/
-/* aopPut - puts a string for a aop                                */
-/*-----------------------------------------------------------------*/
-static void aopPut (asmop *aop, char *s, int offset)
+static char *
+fetchLitSpecial (asmop * aop, bool negate, bool xor)
 {
-    if (aop->size && offset > ( aop->size - 1)) {
-        werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-               "aopPut got offset > aop->size");
-        exit(0);
-    }
+  unsigned long v;
+  value *val = aop->aopu.aop_lit;
 
-    /* will assign value to value */
-    /* depending on where it is ofcourse */
-    switch (aop->type) {
-    case AOP_DIR:
-       /* Direct.  Hmmm. */
-       assert(IS_GB);
-       emitcode("ld", "a,%s", s);
-       emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
-       break;
-       
-    case AOP_REG:
-       /* Dont bother if it's a ld x,x */
-       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
-           emitcode("ld","%s,%s",
-                    aop->aopu.aop_reg[offset]->name,s);
-       }
-       break;
-       
-    case AOP_IY:
-       assert(!IS_GB);
-       if (!canAssignToPtr(s)) {
-           emitcode("ld", "a,%s", s);
-           emitcode("ld", "%d(iy),a", offset);
-       }
-       else
-           emitcode("ld", "%d(iy),%s", offset, s);
-       break;
-       
-    case AOP_STK:
-       if (IS_GB) {
-           if (!strcmp("(hl)", s)) {
-               emitcode("ld", "a,(hl)");
-               s = "a";
-           }
-           emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset);
-           if (!canAssignToPtr(s)) {
-               emitcode("ld", "a,%s", s);
-               emitcode("ld", "(hl),a");
-           }
-           else
-               emitcode("ld", "(hl),%s", s);
-       }
-       else {
-           if (!canAssignToPtr(s)) {
-               emitcode("ld", "a,%s", s);
-               emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
-           }
-           else
-               emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
-       }
-       break;
-       
-    case AOP_CRY:
-       /* if bit variable */
-       if (!aop->aopu.aop_dir) {
-           emitcode("ld", "a,#0");
-           emitcode("rla", "");
-       } else {
-           /* In bit space but not in C - cant happen */
-           assert(0);
-       }
-       break;
-       
-    case AOP_STR:
-       aop->coff = offset;
-       if (strcmp(aop->aopu.aop_str[offset],s)) {
-           emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
-       }
-       break;
-       
-    case AOP_ACC:
-       aop->coff = offset;
-       if (!offset && (strcmp(s,"acc") == 0))
-           break;
-       if (offset>0) {
-           
-           emitcode("", "; Error aopPut AOP_ACC");
-       }
-       else {
-           if (strcmp(aop->aopu.aop_str[offset],s))
-               emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
-       }
-       break;
+  wassert (aop->type == AOP_LIT);
+  wassert (!IS_FLOAT (val->type));
 
-    default :
-       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-              "aopPut got unsupported aop->type");
-       exit(0);    
-    }    
-}
+  v = (unsigned long) floatFromVal (val);
 
-#define AOP(op) op->aop
-#define AOP_TYPE(op) AOP(op)->type
-#define AOP_SIZE(op) AOP(op)->size
-#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
+  if (xor)
+    v ^= 0x8000;
+  if (negate)
+    v = 0-v;
+  v &= 0xFFFF;
 
-/*-----------------------------------------------------------------*/
-/* getDataSize - get the operand data size                         */
-/*-----------------------------------------------------------------*/
-int getDataSize(operand *op)
-{
-    int size;
-    size = AOP_SIZE(op);
-    if(size == 3) {
-        /* pointer */
-       assert(0);
-    }
-    return size;
+  tsprintf (buffer, "!immedword", v);
+  return gc_strdup (buffer);
 }
 
-/*-----------------------------------------------------------------*/
-/* movLeft2Result - move byte from left to result                  */
-/*-----------------------------------------------------------------*/
-static void movLeft2Result (operand *left, int offl,
-                            operand *result, int offr, int sign)
+static void
+fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
 {
-    char *l;
-    if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
-        l = aopGet(AOP(left),offl,FALSE);
+  const char *l;
+  const char *pair = _pairs[pairId].name;
+  l = aopGetLitWordLong (left, offset, FALSE);
+  wassert (l && pair);
 
-       if (!sign) {
-           aopPut(AOP(result),l,offr);
+  if (isPtr (pair))
+    {
+      if (pairId == PAIR_HL || pairId == PAIR_IY)
+       {
+         if (_G.pairs[pairId].last_type == left->type)
+           {
+             if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
+               {
+                 if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
+                   {
+                     adjustPair (pair, &_G.pairs[pairId].offset, offset);
+                     return;
+                   }
+                 if (pairId == PAIR_IY && abs (offset) < 127)
+                   {
+                     return;
+                   }
+               }
+           }
        }
-       else {
-           assert(0);
-        }
+      _G.pairs[pairId].last_type = left->type;
+      _G.pairs[pairId].lit = gc_strdup (l);
+      _G.pairs[pairId].offset = offset;
     }
-}
-
-
-/** Put Acc into a register set 
- */
-void outAcc(operand *result)
-{
-    int size, offset;
-    size = getDataSize(result);
-    if (size){
-        aopPut(AOP(result),"a",0);
-        size--;
-        offset = 1;
-        /* unsigned or positive */
-        while (size--){
-            aopPut(AOP(result),zero,offset++);
-        }
+  if (IS_GB && pairId == PAIR_DE && 0)
+    {
+      if (_G.pairs[pairId].lit && !strcmp (_G.pairs[pairId].lit, l))
+       {
+         if (abs (_G.pairs[pairId].offset - offset) < 3)
+           {
+             adjustPair (pair, &_G.pairs[pairId].offset, offset);
+             return;
+           }
+       }
+      _G.pairs[pairId].last_type = left->type;
+      _G.pairs[pairId].lit = gc_strdup (l);
+      _G.pairs[pairId].offset = offset;
     }
+  /* Both a lit on the right and a true symbol on the left */
+  emit2 ("ld %s,!hashedstr", pair, l);
 }
 
-/** Take the value in carry and put it into a register
- */
-void outBitC(operand *result)
+static void
+fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
 {
-    /* if the result is bit */
-    if (AOP_TYPE(result) == AOP_CRY) {
-       emitcode("", "; Note: outBitC form 1");
-        aopPut(AOP(result),"blah",0);
+    /* if this is remateriazable */
+    if (isLitWord (aop)) {
+        fetchLitPair (pairId, aop, offset);
     }
     else {
-       emitcode("ld", "a,#0");
-       emitcode("rla", "");
-        outAcc(result);
-    }
-}
-
-/*-----------------------------------------------------------------*/
-/* toBoolean - emit code for orl a,operator(sizeop)                */
-/*-----------------------------------------------------------------*/
-void toBoolean(operand *oper)
-{
-    int size = AOP_SIZE(oper);
-    int offset = 0;
-    if (size>1) {
-       emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
-       size--;
-       while (size--) 
-           emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
-    }
-    else {
-       if (AOP(oper)->type != AOP_ACC) {
-           CLRC;
-           emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
-       }
+        /* we need to get it byte by byte */
+        if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
+            aopGet (aop, offset, FALSE);
+            switch (aop->size) {
+            case 1:
+                emit2 ("ld l,!*hl");
+                emit2 ("ld h,!immedbyte", 0);
+                            break;
+            case 2:
+                emit2 ("!ldahli");
+                emit2 ("ld h,!*hl");
+                emit2 ("ld l,a");
+                break;
+            default:
+                emitDebug ("; WARNING: mlh woosed out.  This code is invalid.");
+            }
+        }
+        else if (IS_Z80 && aop->type == AOP_IY) {
+            /* Instead of fetching relative to IY, just grab directly
+               from the address IY refers to */
+            char *l = aopGetLitWordLong (aop, offset, FALSE);
+            wassert (l);
+            emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
+
+            if (aop->size < 2) {
+                emit2("ld %s,!zero", _pairs[pairId].h);
+            }
+        }
+        else {
+            emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
+            emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
+        }
+        /* PENDING: check? */
+        if (pairId == PAIR_HL)
+            spillPair (PAIR_HL);
     }
 }
 
-/*-----------------------------------------------------------------*/
-/* genNot - generate code for ! operation                          */
-/*-----------------------------------------------------------------*/
-static void genNot (iCode *ic)
+static void
+fetchPair (PAIR_ID pairId, asmop * aop)
 {
-    link *optype = operandType(IC_LEFT(ic));
+  fetchPairLong (pairId, aop, 0);
+}
 
-    /* assign asmOps to operand & result */
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
+static void
+fetchHL (asmop * aop)
+{
+  fetchPair (PAIR_HL, aop);
+}
 
-    /* if in bit space then a special case */
-    if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
-       assert(0);
-    }
+static void
+setupPair (PAIR_ID pairId, asmop * aop, int offset)
+{
+  assert (pairId == PAIR_HL || pairId == PAIR_IY);
 
-    /* if type float then do float */
-    if (IS_FLOAT(optype)) {
-       assert(0);
+  switch (aop->type)
+    {
+    case AOP_IY:
+      fetchLitPair (pairId, aop, 0);
+      break;
+    case AOP_HL:
+      fetchLitPair (pairId, aop, offset);
+      _G.pairs[pairId].offset = offset;
+      break;
+    case AOP_STK:
+      {
+       /* Doesnt include _G.stack.pushed */
+       int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
+       if (aop->aopu.aop_stk > 0)
+         {
+           abso += _G.stack.param_offset;
+         }
+       assert (pairId == PAIR_HL);
+       /* In some cases we can still inc or dec hl */
+       if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
+         {
+           adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
+         }
+       else
+         {
+           emit2 ("!ldahlsp", abso + _G.stack.pushed);
+         }
+       _G.pairs[pairId].offset = abso;
+       break;
+      }
+    default:
+      wassert (0);
     }
+  _G.pairs[pairId].last_type = aop->type;
+}
 
-    toBoolean(IC_LEFT(ic));
-
-    /* Not of A:
-       If A == 0, !A = 1
-       else A = 0
-       So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
-    emitcode("sub", "a,#0x01");
-    outBitC(IC_RESULT(ic));
-
-    /* release the aops */
-    freeAsmop(IC_LEFT(ic),NULL,ic);
-    freeAsmop(IC_RESULT(ic),NULL,ic);
+static void
+emitLabel (int key)
+{
+  emit2 ("!tlabeldef", key);
+  spillCached ();
 }
 
 /*-----------------------------------------------------------------*/
-/* genCpl - generate code for complement                           */
+/* aopGet - for fetching value of the aop                          */
 /*-----------------------------------------------------------------*/
-static void genCpl (iCode *ic)
+static const char *
+aopGet (asmop * aop, int offset, bool bit16)
 {
-    int offset = 0;
-    int size ;
+  char *s = buffer;
 
+  /* offset is greater than size then zero */
+  /* PENDING: this seems a bit screwed in some pointer cases. */
+  if (offset > (aop->size - 1) &&
+      aop->type != AOP_LIT) 
+    {
+      tsprintf (s, "!zero");
+      return gc_strdup(s);
+    }
 
-    /* assign asmOps to operand & result */
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
-
-    /* if both are in bit space then 
-    a special case */
-    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
-        AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
-       assert(0);
-    } 
+  /* depending on type */
+  switch (aop->type)
+    {
+    case AOP_IMMD:
+      /* PENDING: re-target */
+      if (bit16)
+       tsprintf (s, "!immedwords", aop->aopu.aop_immd);
+      else
+       switch (offset)
+         {
+         case 2:
+           tsprintf (s, "!bankimmeds", aop->aopu.aop_immd);
+           break;
+         case 1:
+           tsprintf (s, "!msbimmeds", aop->aopu.aop_immd);
+           break;
+         case 0:
+           tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
+           break;
+         default:
+           wassert (0);
+         }
 
-    size = AOP_SIZE(IC_RESULT(ic));
-    while (size--) {
-        char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
-        MOVA(l);       
-        emitcode("cpl","");
-        aopPut(AOP(IC_RESULT(ic)),"a",offset++);
-    }
+      return gc_strdup(s);
 
-    /* release the aops */
-    freeAsmop(IC_LEFT(ic),NULL,ic);
-    freeAsmop(IC_RESULT(ic),NULL,ic);
-}
+    case AOP_DIR:
+      wassert (IS_GB);
+      emit2 ("ld a,(%s+%d)", aop->aopu.aop_dir, offset);
+      sprintf (s, "a");
 
-/*-----------------------------------------------------------------*/
-/* genUminus - unary minus code generation                         */
-/*-----------------------------------------------------------------*/
-static void genUminus (iCode *ic)
-{
-    int offset ,size ;
-    link *optype, *rtype;
+      return gc_strdup(s);
 
-    /* assign asmops */
-    aopOp(IC_LEFT(ic),ic,FALSE);
-    aopOp(IC_RESULT(ic),ic,TRUE);
+    case AOP_SFR:
+      wassert (IS_GB);
+      emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset);
+      sprintf (s, "a");
 
-    /* if both in bit space then special
-    case */
-    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
-        AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
-       assert(0);
-        goto release;
-    } 
+      return gc_strdup(s);
 
-    optype = operandType(IC_LEFT(ic));
-    rtype = operandType(IC_RESULT(ic));
+    case AOP_REG:
+      return aop->aopu.aop_reg[offset]->name;
 
-    /* if float then do float stuff */
-    if (IS_FLOAT(optype)) {
-       assert(0);
-        goto release;
-    }
+    case AOP_HL:
+      wassert (IS_GB);
+      setupPair (PAIR_HL, aop, offset);
+      tsprintf (s, "!*hl");
 
-    /* otherwise subtract from zero */
-    size = AOP_SIZE(IC_LEFT(ic));
-    offset = 0 ;
-    CLRC ;
-    while(size--) {
-        char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
-       emitcode("ld", "a,#0");
-       emitcode("sbc","a,%s",l);
-        aopPut(AOP(IC_RESULT(ic)),"a",offset++);
-    }
+      return gc_strdup (s);
 
-    /* if any remaining bytes in the result */
-    /* we just need to propagate the sign   */
-    if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
-        emitcode("rlc","a");
-        emitcode("sbc","a,a");
-        while (size--) 
-            aopPut(AOP(IC_RESULT(ic)),"a",offset++);
-    }       
+    case AOP_IY:
+      wassert (IS_Z80);
+      setupPair (PAIR_IY, aop, offset);
+      tsprintf (s, "!*iyx", offset);
 
-release:
-    /* release the aops */
-    freeAsmop(IC_LEFT(ic),NULL,ic);
-    freeAsmop(IC_RESULT(ic),NULL,ic);
-}
+      return gc_strdup(s);
 
-static bool requiresHL(asmop *aop)
-{
-    switch (aop->type) {
     case AOP_STK:
-       return TRUE;
+      if (IS_GB)
+       {
+         setupPair (PAIR_HL, aop, offset);
+         tsprintf (s, "!*hl");
+       }
+      else
+       {
+         if (aop->aopu.aop_stk >= 0)
+           offset += _G.stack.param_offset;
+         tsprintf (s, "!*ixx", aop->aopu.aop_stk + offset);
+       }
+
+      return gc_strdup(s);
+
+    case AOP_CRY:
+      wassert (0);
+
+    case AOP_ACC:
+      if (!offset)
+       {
+         return "a";
+       }
+      else
+        {
+          tsprintf(s, "!zero");
+          return gc_strdup(s);
+        }
+
+    case AOP_HLREG:
+      wassert (offset < 2);
+      return aop->aopu.aop_str[offset];
+
+    case AOP_LIT:
+      return aopLiteral (aop->aopu.aop_lit, offset);
+
+    case AOP_STR:
+      aop->coff = offset;
+      return aop->aopu.aop_str[offset];
+
     default:
-       return FALSE;
+      break;
     }
+  wassertl (0, "aopget got unsupported aop->type");
+  exit (0);
 }
 
-/*-----------------------------------------------------------------*/
-/* assignResultValue -                                            */
-/*-----------------------------------------------------------------*/
-void assignResultValue(operand * oper)
+bool
+isRegString (const char *s)
 {
-    int offset = 0;
-    int size = AOP_SIZE(oper);
-
-    assert(size <= 2);
+  if (!strcmp (s, "b") ||
+      !strcmp (s, "c") ||
+      !strcmp (s, "d") ||
+      !strcmp (s, "e") ||
+      !strcmp (s, "a") ||
+      !strcmp (s, "h") ||
+      !strcmp (s, "l"))
+    return TRUE;
+  return FALSE;
+}
 
-    while (size--) {
-       aopPut(AOP(oper),_fReturn[offset],offset);
-       offset++;
-    }
+bool
+isConstant (const char *s)
+{
+  /* This is a bit of a hack... */
+  return (*s == '#' || *s == '$');
 }
 
-static void fetchHL(asmop *aop)
+bool
+canAssignToPtr (const char *s)
 {
-    if (IS_GB && requiresHL(aop)) {
-       emitcode("ld", "a,%s", aopGet(aop, 0, FALSE));
-       emitcode("ld", "h,%s", aopGet(aop, 1, FALSE));
-       emitcode("ld", "l,a");
-    }
-    else {
-       emitcode("ld", "l,%s", aopGet(aop, 0, FALSE));
-       emitcode("ld", "h,%s", aopGet(aop, 1, FALSE));
-    }
+  if (isRegString (s))
+    return TRUE;
+  if (isConstant (s))
+    return TRUE;
+  return FALSE;
 }
 
 /*-----------------------------------------------------------------*/
-/* genIpush - genrate code for pushing this gets a little complex  */
+/* aopPut - puts a string for a aop                                */
 /*-----------------------------------------------------------------*/
-static void genIpush (iCode *ic)
+static void
+aopPut (asmop * aop, const char *s, int offset)
 {
-    int size, offset = 0 ;
-    char *l;
+  char buffer2[256];
 
+  if (aop->size && offset > (aop->size - 1))
+    {
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+             "aopPut got offset > aop->size");
+      exit (0);
+    }
 
-    /* if this is not a parm push : ie. it is spill push 
-       and spill push is always done on the local stack */
-    if (!ic->parmPush) {
-        /* and the item is spilt then do nothing */
-        if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
-            return ;
+  // PENDING
+  tsprintf(buffer2, s);
+  s = buffer2;
 
-        aopOp(IC_LEFT(ic),ic,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))));
-           _pushed += 2;
-       }
-       else {
-           offset = size;
-           while (size--) {
-               l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
-               /* Simple for now - load into A and PUSH AF */
-               emitcode("ld", "a,%s", l);
-               emitcode("push", "af");
-               emitcode("inc", "sp");
-               _pushed++;
-           }
-       }
-       return ;        
-    }
+  /* will assign value to value */
+  /* depending on where it is ofcourse */
+  switch (aop->type)
+    {
+    case AOP_DIR:
+      /* Direct.  Hmmm. */
+      wassert (IS_GB);
+      if (strcmp (s, "a"))
+       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"))
+       emit2 ("ld a,%s", s);
+      emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
+      break;
 
-    /* Hmmm... what about saving the currently used registers
-       at this point? */
+    case AOP_REG:
+      if (!strcmp (s, "!*hl"))
+       emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
+      else
+       emit2 ("ld %s,%s",
+              aop->aopu.aop_reg[offset]->name, s);
+      break;
 
-    /* then do the push */
-    aopOp(IC_LEFT(ic),ic,FALSE);
+    case AOP_IY:
+      wassert (!IS_GB);
+      setupPair (PAIR_IY, aop, offset);
+      if (!canAssignToPtr (s))
+       {
+         emit2 ("ld a,%s", s);
+         emit2 ("ld !*iyx,a", offset);
+       }
+      else
+       emit2 ("ld !*iyx,%s", offset, s);
+      break;
+
+    case AOP_HL:
+      wassert (IS_GB);
+      /* PENDING: for re-target */
+      if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
+       {
+         emit2 ("ld a,!*hl");
+         s = "a";
+       }
+      setupPair (PAIR_HL, aop, offset);
 
-    size = AOP_SIZE(IC_LEFT(ic));
+      emit2 ("ld !*hl,%s", s);
+      break;
 
-    if (isPair(AOP(IC_LEFT(ic)))) {
-       _pushed+=2;
-       emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
-    }
-    else {
-       if (size == 2) {
-           char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
-           if (s) {
-               emitcode("ld", "hl,%s", s);
-               emitcode("push", "hl");
-               _pushed+=2;
+    case AOP_STK:
+      if (IS_GB)
+       {
+         /* PENDING: re-target */
+         if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
+           {
+             emit2 ("ld a,!*hl");
+             s = "a";
            }
-           else {
-               /* Optimise here - load into HL then push HL */
-               fetchHL(AOP(IC_LEFT(ic)));
-               emitcode("push", "hl");
-               _pushed += 2;
+         setupPair (PAIR_HL, aop, offset);
+         if (!canAssignToPtr (s))
+           {
+             emit2 ("ld a,%s", s);
+             emit2 ("ld !*hl,a");
            }
-           goto release;
+         else
+           emit2 ("ld !*hl,%s", s);
        }
-       offset = size;
-       while (size--) {
-           l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
-           emitcode("ld", "a,%s", l);
-           emitcode("push", "af");
-           emitcode("inc", "sp");
-           _pushed++;
-       }       
-    }
- release:
-    freeAsmop(IC_LEFT(ic),NULL,ic);
-}
+      else
+       {
+         if (aop->aopu.aop_stk >= 0)
+           offset += _G.stack.param_offset;
+         if (!canAssignToPtr (s))
+           {
+             emit2 ("ld a,%s", s);
+             emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
+           }
+         else
+           emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
+       }
+      break;
 
-/*-----------------------------------------------------------------*/
-/* genIpop - recover the registers: can happen only for spilling   */
-/*-----------------------------------------------------------------*/
-static void genIpop (iCode *ic)
-{
-    int size,offset ;
+    case AOP_CRY:
+      /* if bit variable */
+      if (!aop->aopu.aop_dir)
+       {
+         emit2 ("ld a,#0");
+         emit2 ("rla");
+       }
+      else
+       {
+         /* In bit space but not in C - cant happen */
+         wassert (0);
+       }
+      break;
 
+    case AOP_STR:
+      aop->coff = offset;
+      if (strcmp (aop->aopu.aop_str[offset], s))
+       {
+         emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
+       }
+      break;
 
-    /* if the temp was not pushed then */
-    if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
-        return ;
+    case AOP_ACC:
+      aop->coff = offset;
+      if (!offset && (strcmp (s, "acc") == 0))
+       break;
+      if (offset > 0)
+       {
 
-    aopOp(IC_LEFT(ic),ic,FALSE);
-    size = AOP_SIZE(IC_LEFT(ic));
-    offset = (size-1);
-    if (isPair(AOP(IC_LEFT(ic)))) {
-       emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
-    }
-    else {
-       while (size--) {
-           emitcode("dec", "sp");
-           emitcode("pop", "hl");
-           aopPut(AOP(IC_LEFT(ic)), "l", offset--);
+         emitDebug ("; Error aopPut AOP_ACC");
        }
+      else
+       {
+         if (strcmp (aop->aopu.aop_str[offset], s))
+           emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
+       }
+      break;
+
+    case AOP_HLREG:
+      wassert (offset < 2);
+      emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
+      break;
+
+    default:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+             "aopPut got unsupported aop->type");
+      exit (0);
     }
+}
+
+#define AOP(op) op->aop
+#define AOP_TYPE(op) AOP(op)->type
+#define AOP_SIZE(op) AOP(op)->size
+#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
 
-    freeAsmop(IC_LEFT(ic),NULL,ic);
+static void
+commitPair (asmop * aop, PAIR_ID id)
+{
+  if (id == PAIR_HL && requiresHL (aop))
+    {
+      emit2 ("ld a,l");
+      emit2 ("ld d,h");
+      aopPut (aop, "a", 0);
+      aopPut (aop, "d", 1);
+    }
+  else
+    {
+      aopPut (aop, _pairs[id].l, 0);
+      aopPut (aop, _pairs[id].h, 1);
+    }
 }
 
-/** Emit the code for a call statement 
- */
-static void emitCall (iCode *ic, bool ispcall)
+/*-----------------------------------------------------------------*/
+/* getDataSize - get the operand data size                         */
+/*-----------------------------------------------------------------*/
+int
+getDataSize (operand * op)
 {
-    /* if caller saves & we have not saved then */
-    if (!ic->regsSaved) {
-       /* PENDING */
+  int size;
+  size = AOP_SIZE (op);
+  if (size == 3)
+    {
+      /* pointer */
+      wassert (0);
     }
+  return size;
+}
 
-    /* if send set is not empty then assign */
-    if (sendSet) {
-       iCode *sic ;
+/*-----------------------------------------------------------------*/
+/* movLeft2Result - move byte from left to result                  */
+/*-----------------------------------------------------------------*/
+static void
+movLeft2Result (operand * left, int offl,
+               operand * result, int offr, int sign)
+{
+    const char *l;
+  if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
+    {
+      l = aopGet (AOP (left), offl, FALSE);
 
-       for (sic = setFirstItem(sendSet) ; sic ; 
-            sic = setNextItem(sendSet)) {
-           int size, offset = 0;
-           aopOp(IC_LEFT(sic),sic,FALSE);
-           size = AOP_SIZE(IC_LEFT(sic));
-           while (size--) {
-               char *l = aopGet(AOP(IC_LEFT(sic)),offset,
-                               FALSE);
-               if (strcmp(l, _fReturn[offset]))
-                   emitcode("ld","%s,%s",
-                            _fReturn[offset],
-                            l);
-               offset++;
-           }
-           freeAsmop (IC_LEFT(sic),NULL,sic);
+      if (!sign)
+       {
+         aopPut (AOP (result), l, offr);
+       }
+      else
+       {
+         wassert (0);
        }
-       sendSet = NULL;
     }
+}
 
-    if (ispcall) {
-       symbol *rlbl = newiTempLabel(NULL);
-
-       emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
-       emitcode("push", "hl");
 
-       aopOp(IC_LEFT(ic),ic,FALSE);
-       emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
-       emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
-       freeAsmop(IC_LEFT(ic),NULL,ic); 
-       
-       emitcode("jp", "(hl)");
-       emitcode("","%05d$:",(rlbl->key+100));
-    }
-    else {
-       /* make the call */
-       emitcode("call", "%s", (OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
-                               OP_SYMBOL(IC_LEFT(ic))->rname :
-                               OP_SYMBOL(IC_LEFT(ic))->name));
+/** Put Acc into a register set
+ */
+void
+outAcc (operand * result)
+{
+  int size, offset;
+  size = getDataSize (result);
+  if (size)
+    {
+      aopPut (AOP (result), "a", 0);
+      size--;
+      offset = 1;
+      /* unsigned or positive */
+      while (size--)
+       {
+         aopPut (AOP (result), "!zero", offset++);
+       }
     }
+}
 
-    /* if we need assign a result value */
-    if ((IS_ITEMP(IC_RESULT(ic)) && 
-         (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
-          OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
-        IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
-
-        accInUse++;
-        aopOp(IC_RESULT(ic),ic,FALSE);
-        accInUse--;
-
-       assignResultValue(IC_RESULT(ic));
-               
-        freeAsmop(IC_RESULT(ic),NULL, ic);
+/** Take the value in carry and put it into a register
+ */
+void
+outBitCLong (operand * result, bool swap_sense)
+{
+  /* if the result is bit */
+  if (AOP_TYPE (result) == AOP_CRY)
+    {
+      emitDebug ("; Note: outBitC form 1");
+      aopPut (AOP (result), "blah", 0);
     }
-
-    /* adjust the stack for parameters if required */
-    if (IC_LEFT(ic)->parmBytes) {
-       int i = IC_LEFT(ic)->parmBytes;
-       _pushed -= i;
-       if (i>6) {
-           emitcode("ld", "hl,#%d", i);
-           emitcode("add", "hl,sp");
-           emitcode("ld", "sp,hl");
-       }
-       else {
-           while (i>1) {
-               emitcode("pop", "hl");
-               i-=2;
-           }
-           if (i) 
-               emitcode("inc", "sp");
-       }
+  else
+    {
+      emit2 ("ld a,!zero");
+      emit2 ("rla");
+      if (swap_sense)
+       emit2 ("xor a,!immedbyte", 1);
+      outAcc (result);
     }
-
 }
 
-/*-----------------------------------------------------------------*/
-/* genCall - generates a call statement                            */
-/*-----------------------------------------------------------------*/
-static void genCall (iCode *ic)
+void
+outBitC (operand * result)
 {
-    emitCall(ic, FALSE);
+  outBitCLong (result, FALSE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genPcall - generates a call by pointer statement                */
+/* toBoolean - emit code for orl a,operator(sizeop)                */
 /*-----------------------------------------------------------------*/
-static void genPcall (iCode *ic)
+void
+_toBoolean (operand * oper)
 {
-    emitCall(ic, TRUE);
+  int size = AOP_SIZE (oper);
+  int offset = 0;
+  if (size > 1)
+    {
+      emit2 ("ld a,%s", aopGet (AOP (oper), offset++, FALSE));
+      size--;
+      while (size--)
+       emit2 ("or a,%s", aopGet (AOP (oper), offset++, FALSE));
+    }
+  else
+    {
+      if (AOP (oper)->type != AOP_ACC)
+       {
+         _clearCarry();
+         emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE));
+       }
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* resultRemat - result  is rematerializable                       */
+/* genNot - generate code for ! operation                          */
 /*-----------------------------------------------------------------*/
-static int resultRemat (iCode *ic)
+static void
+genNot (iCode * ic)
 {
-    if (SKIP_IC(ic) || ic->op == IFX)
-        return 0;
+  sym_link *optype = operandType (IC_LEFT (ic));
+
+  /* assign asmOps to operand & result */
+  aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
+  aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
+
+  /* if in bit space then a special case */
+  if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
+    {
+      wassert (0);
+    }
 
-    if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
-        symbol *sym = OP_SYMBOL(IC_RESULT(ic));
-        if (sym->remat && !POINTER_SET(ic)) 
-            return 1;
+  /* if type float then do float */
+  if (IS_FLOAT (optype))
+    {
+      wassert (0);
     }
 
-    return 0;
+  _toBoolean (IC_LEFT (ic));
+
+  /* Not of A:
+     If A == 0, !A = 1
+     else A = 0
+     So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
+  emit2 ("sub a,!one");
+  outBitC (IC_RESULT (ic));
+
+  /* release the aops */
+  freeAsmop (IC_LEFT (ic), NULL, ic);
+  freeAsmop (IC_RESULT (ic), NULL, ic);
 }
 
 /*-----------------------------------------------------------------*/
-/* genFunction - generated code for function entry                 */
+/* genCpl - generate code for complement                           */
 /*-----------------------------------------------------------------*/
-static void genFunction (iCode *ic)
+static void
+genCpl (iCode * ic)
 {
-    symbol *sym;
-    link *fetype;
+  int offset = 0;
+  int size;
 
-    nregssaved = 0;
-    /* create the function header */
-    emitcode(";","-----------------------------------------");
-    emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
-    emitcode(";","-----------------------------------------");
 
-    emitcode("","%s:",sym->rname);
-    fetype = getSpec(operandType(IC_LEFT(ic)));
+  /* assign asmOps to operand & result */
+  aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
+  aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
 
-    /* if critical function then turn interrupts off */
-    if (SPEC_CRTCL(fetype))
-        emitcode("di","");
-
-    /* if this is an interrupt service routine then
-    save acc, b, dpl, dph  */
-    if (IS_ISR(sym->etype)) {
-       emitcode("push", "af");
-       emitcode("push", "bc");
-       emitcode("push", "de");
-       emitcode("push", "hl");
+  /* if both are in bit space then
+     a special case */
+  if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
+      AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
+    {
+      wassert (0);
     }
-    /* PENDING: callee-save etc */
 
-    /* adjust the stack for the function */
-    emitcode("push", "bc");
-    if (!IS_GB) {
-       emitcode("push", "de");
-       emitcode("push", "ix");
-       emitcode("ld", "ix,#0");
-       emitcode("add", "ix,sp");
+  size = AOP_SIZE (IC_RESULT (ic));
+  while (size--)
+    {
+      const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
+      _moveA (l);
+      emit2("cpl");
+      aopPut (AOP (IC_RESULT (ic)), "a", offset++);
     }
 
-    _lastStack = sym->stack;
-
-    if (sym->stack) {
-       emitcode("ld", "hl,#-%d", sym->stack);
-       emitcode("add", "hl,sp");
-       emitcode("ld", "sp,hl");
-    }
-    _spoffset = sym->stack;
+  /* release the aops */
+  freeAsmop (IC_LEFT (ic), NULL, ic);
+  freeAsmop (IC_RESULT (ic), NULL, ic);
 }
 
 /*-----------------------------------------------------------------*/
-/* genEndFunction - generates epilogue for functions               */
+/* genUminus - unary minus code generation                         */
 /*-----------------------------------------------------------------*/
-static void genEndFunction (iCode *ic)
+static void
+genUminus (iCode * ic)
 {
-    symbol *sym = OP_SYMBOL(IC_LEFT(ic));
+  int offset, size;
+  sym_link *optype, *rtype;
 
-    if (IS_ISR(sym->etype)) {
-       assert(0);
-    }
-    else {
-        if (SPEC_CRTCL(sym->etype))
-            emitcode("ei", "");
-       
-       /* PENDING: calleeSave */
-
-       /* if debug then send end of function */
-       if (options.debug && currFunc) { 
-           debugLine = 1;
-           emitcode("","C$%s$%d$%d$%d ==.",
-                    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 (!IS_GB) {
-           emitcode("ld", "sp,ix");
-           emitcode("pop", "ix");
-           emitcode("pop", "de");
-       }
-       emitcode("pop", "bc");
-       emitcode("ret", "");
+  /* assign asmops */
+  aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
+  aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
+
+  /* if both in bit space then special
+     case */
+  if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
+      AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
+    {
+      wassert (0);
+      goto release;
     }
 
-}
+  optype = operandType (IC_LEFT (ic));
+  rtype = operandType (IC_RESULT (ic));
 
-/*-----------------------------------------------------------------*/
-/* genRet - generate code for return statement                     */
-/*-----------------------------------------------------------------*/
-static void genRet (iCode *ic)
-{
-    char *l;
-    /* Errk.  This is a hack until I can figure out how
-       to cause dehl to spill on a call */
-    int size,offset = 0;
-    
-    /* if we have no return value then
-       just generate the "ret" */
-    if (!IC_LEFT(ic)) 
-       goto jumpret;       
-    
-    /* we have something to return then
-       move the return value into place */
-    aopOp(IC_LEFT(ic),ic,FALSE);
-    size = AOP_SIZE(IC_LEFT(ic));
-    
-    if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
-           emitcode("ld", "hl,%s", l);
+  /* if float then do float stuff */
+  if (IS_FLOAT (optype))
+    {
+      wassert (0);
+      goto release;
     }
-    else {
-       while (size--) {
-           l = aopGet(AOP(IC_LEFT(ic)),offset,
-                      FALSE);
-           if (strcmp(_fReturn[offset],l))
-               emitcode("ld","%s,%s", _fReturn[offset++],l);
-       }
+
+  /* otherwise subtract from zero */
+  size = AOP_SIZE (IC_LEFT (ic));
+  offset = 0;
+  _clearCarry();
+  while (size--)
+    {
+      const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
+      emit2 ("ld a,!zero");
+      emit2 ("sbc a,%s", l);
+      aopPut (AOP (IC_RESULT (ic)), "a", offset++);
     }
-    freeAsmop (IC_LEFT(ic),NULL,ic);
-    
- jumpret:
-       /* generate a jump to the return label
-          if the next is not the return statement */
-    if (!(ic->next && ic->next->op == LABEL &&
-         IC_LABEL(ic->next) == returnLabel))
-       
-       emitcode("jp",  LABEL_STR ,(returnLabel->key+100));
+
+  /* if any remaining bytes in the result */
+  /* we just need to propagate the sign   */
+  if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
+    {
+      emit2 ("rlc a");
+      emit2 ("sbc a,a");
+      while (size--)
+       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+    }
+
+release:
+  /* release the aops */
+  freeAsmop (IC_LEFT (ic), NULL, ic);
+  freeAsmop (IC_RESULT (ic), NULL, ic);
 }
 
-/*-----------------------------------------------------------------*/
-/* genLabel - generates a label                                    */
-/*-----------------------------------------------------------------*/
-static void genLabel (iCode *ic)
+static void
+_push (PAIR_ID pairId)
 {
-    /* special case never generate */
-    if (IC_LABEL(ic) == entryLabel)
-        return ;
-
-    emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
+  emit2 ("push %s", _pairs[pairId].name);
+  _G.stack.pushed += 2;
 }
 
-/*-----------------------------------------------------------------*/
-/* genGoto - generates a ljmp                                      */
-/*-----------------------------------------------------------------*/
-static void genGoto (iCode *ic)
+static void
+_pop (PAIR_ID pairId)
 {
-    emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
+  emit2 ("pop %s", _pairs[pairId].name);
+  _G.stack.pushed -= 2;
 }
 
+
 /*-----------------------------------------------------------------*/
-/* genPlusIncr :- does addition with increment if possible         */
+/* assignResultValue -               */
 /*-----------------------------------------------------------------*/
-static bool genPlusIncr (iCode *ic)
+void
+assignResultValue (operand * oper)
 {
-    unsigned int icount ;
-    unsigned int size = getDataSize(IC_RESULT(ic));
-    
-    /* will try to generate an increment */
-    /* if the right side is not a literal 
-       we cannot */
-    if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
-        return FALSE;
-    
-    emitcode("", "; genPlusIncr");
+  int size = AOP_SIZE (oper);
+  bool topInA = 0;
 
-    icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
+  wassert (size <= 4);
+  topInA = requiresHL (AOP (oper));
 
-    /* If result is a pair */
-    if (isPair(AOP(IC_RESULT(ic)))) {
-       char *left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
-       if (left) {
-           /* Both a lit on the right and a true symbol on the left */
-           emitcode("ld", "%s,#%s + %d", getPairName(AOP(IC_RESULT(ic))), left, icount);
-           return TRUE;
+#if 0
+  if (!IS_GB)
+    wassert (size <= 2);
+#endif
+  if (IS_GB && size == 4 && requiresHL (AOP (oper)))
+    {
+      /* We do it the hard way here. */
+      _push (PAIR_HL);
+      aopPut (AOP (oper), _fReturn[0], 0);
+      aopPut (AOP (oper), _fReturn[1], 1);
+      emit2 ("pop de");
+      _G.stack.pushed -= 2;
+      aopPut (AOP (oper), _fReturn[0], 2);
+      aopPut (AOP (oper), _fReturn[1], 3);
+    }
+  else
+    {
+      while (size--)
+       {
+         aopPut (AOP (oper), _fReturn[size], size);
        }
     }
+}
 
-    /* if the literal value of the right hand side
-       is greater than 4 then it is not worth it */
-    if (icount > 4)
-        return FALSE ;
+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;
 
-    /* Inc a pair */
-    if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
-       isPair(AOP(IC_RESULT(ic)))) {
-       while (icount--) {
-           emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
-       }
-       return TRUE;
+#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 increment 16 bits in register */
-    if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
-        (size > 1) &&
-        (icount == 1)) {
-        symbol *tlbl = newiTempLabel(NULL);
-       emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
-       emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
-    
-       emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
-       if(size == 4) {
-           assert(0);
-       }
-       emitcode("", LABEL_STR ":",tlbl->key+100);
-        return TRUE;
+    if (deInUse && deInRet == FALSE) {
+      _push(PAIR_DE);
+      _G.stack.pushedDE = TRUE;
     }
 
-    /* If result is a pair */
-    if (isPair(AOP(IC_RESULT(ic)))) {
-       movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
-       movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
-       while (icount--)
-           emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
-       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   )
-        return FALSE ;
-    
-    /* we can if the aops of the left & result match or
-       if they are in registers and the registers are the
-       same */
-    if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
-       while (icount--)
-           emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
-       
-        return TRUE ;
-    }
-    
-    return FALSE ;
-}
-
-/*-----------------------------------------------------------------*/
-/* outBitAcc - output a bit in acc                                 */
-/*-----------------------------------------------------------------*/
-void outBitAcc(operand *result)
-{
-    symbol *tlbl = newiTempLabel(NULL);
-    /* if the result is a bit */
-    if (AOP_TYPE(result) == AOP_CRY){
-       assert(0);
-    }
-    else {
-        emitcode("jp","z," LABEL_STR ,tlbl->key+100);
-        emitcode("ld","a,%s",one);
-        emitcode("", LABEL_STR ":",tlbl->key+100);
-        outAcc(result);
-    }
-}
+    _G.saves.saved = TRUE;
+  }
+  else {
+    /* Already saved. */
+  }
+}
 
 /*-----------------------------------------------------------------*/
-/* genPlus - generates code for addition                           */
+/* genIpush - genrate code for pushing this gets a little complex  */
 /*-----------------------------------------------------------------*/
-static void genPlus (iCode *ic)
+static void
+genIpush (iCode * ic)
 {
-    int size, offset = 0;
+  int size, offset = 0;
+  const char *l;
 
-    /* special cases :- */
+  /* if this is not a parm push : ie. it is spill push
+     and spill push is always done on the local stack */
+  if (!ic->parmPush)
+    {
+      wassertl(0, "Encountered an unsupported spill push.");
+      return;
+    }
 
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RIGHT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
+  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. */
+  }
 
-    /* Swap the left and right operands if:
+  /* then do the push */
+  aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
 
-       if literal, literal on the right or
-       if left requires ACC or right is already
-       in ACC */
+  size = AOP_SIZE (IC_LEFT (ic));
 
-    if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
-       (AOP_NEEDSACC(IC_LEFT(ic))) ||
-       AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
-        operand *t = IC_RIGHT(ic);
-        IC_RIGHT(ic) = IC_LEFT(ic);
-        IC_LEFT(ic) = t;
+  if (isPair (AOP (IC_LEFT (ic))))
+    {
+      _G.stack.pushed += 2;
+      emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
     }
-
-    /* if both left & right are in bit
-    space */
-    if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
-        AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
-       /* Cant happen */
-       assert(0);
+  else
+    {
+      if (size == 2)
+       {
+         fetchHL (AOP (IC_LEFT (ic)));
+         emit2 ("push hl");
+         spillPair (PAIR_HL);
+         _G.stack.pushed += 2;
+         goto release;
+       }
+      if (size == 4)
+       {
+         fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
+         emit2 ("push hl");
+         spillPair (PAIR_HL);
+         _G.stack.pushed += 2;
+         fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
+         emit2 ("push hl");
+         spillPair (PAIR_HL);
+         _G.stack.pushed += 2;
+         goto release;
+       }
+      offset = size;
+      while (size--)
+       {
+         if (AOP (IC_LEFT (ic))->type == AOP_IY)
+           {
+             char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
+             wassert (l);
+             emit2 ("ld a,(%s)", l);
+           }
+         else
+           {
+             l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
+             emit2 ("ld a,%s", l);
+           }
+         emit2 ("push af");
+         emit2 ("inc sp");
+         _G.stack.pushed++;
+       }
     }
+release:
+  freeAsmop (IC_LEFT (ic), NULL, ic);
+}
 
-    /* if left in bit space & right literal */
-    if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
-        AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
-       /* Can happen I guess */
-       assert(0);
-    }
+/*-----------------------------------------------------------------*/
+/* genIpop - recover the registers: can happen only for spilling   */
+/*-----------------------------------------------------------------*/
+static void
+genIpop (iCode * ic)
+{
+  int size, offset;
 
-    /* if I can do an increment instead
-    of add then GOOD for ME */
-    if (genPlusIncr (ic) == TRUE)
-        goto release;   
 
-    size = getDataSize(IC_RESULT(ic));
+  /* if the temp was not pushed then */
+  if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
+    return;
 
-    /* Special case when left and right are constant */
-    if (isPair(AOP(IC_RESULT(ic)))) {
-       char *left, *right;
-       
-       left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
-       right = aopGetWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
-       if (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);
-           goto release;
-       }
-    }
-
-    while(size--) {
-       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
-           MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
-           if(offset == 0)
-               emitcode("add","a,%s",
-                        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
-           else
-               emitcode("adc","a,%s",
-                        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
-       } else {
-           MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
-           if(offset == 0)
-               emitcode("add","a,%s",
-                        aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
-           else
-               emitcode("adc","a,%s",
-                        aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
+  aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
+  size = AOP_SIZE (IC_LEFT (ic));
+  offset = (size - 1);
+  if (isPair (AOP (IC_LEFT (ic))))
+    {
+      emit2 ("pop %s", getPairName (AOP (IC_LEFT (ic))));
+    }
+  else
+    {
+      while (size--)
+       {
+         emit2 ("dec sp");
+         emit2 ("pop hl");
+         spillPair (PAIR_HL);
+         aopPut (AOP (IC_LEFT (ic)), "l", offset--);
        }
-        aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
     }
 
-    /* Some kind of pointer arith. */
-    if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
-       AOP_SIZE(IC_LEFT(ic)) == 3   &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
-       assert(0);
-
-     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
-       AOP_SIZE(IC_RIGHT(ic)) == 3   &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
-        assert(0);
+  freeAsmop (IC_LEFT (ic), NULL, ic);
+}
 
-   
-release:
-    freeAsmop(IC_LEFT(ic),NULL,ic);
-    freeAsmop(IC_RIGHT(ic),NULL,ic);
-    freeAsmop(IC_RESULT(ic),NULL,ic);
-    
+/* 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;
+  //    }
 }
 
-/*-----------------------------------------------------------------*/
-/* genMinusDec :- does subtraction with deccrement if possible     */
-/*-----------------------------------------------------------------*/
-static bool genMinusDec (iCode *ic)
+static bool
+isInHome (void)
 {
-    unsigned int icount ;
-    unsigned int size = getDataSize(IC_RESULT(ic));
+  return _G.in_home;
+}
 
-    /* will try to generate an increment */
-    /* if the right side is not a literal we cannot */
-    if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
-        return FALSE ;
+static int
+_opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
+{
+  int ret = 0;
+  asmop *aop;
+  symbol *sym = OP_SYMBOL (op);
 
-    /* if the literal value of the right hand side
-    is greater than 4 then it is not worth it */
-    if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
-        return FALSE;
+  if (sym->isspilt || sym->nRegs == 0)
+    return 0;
 
-    size = getDataSize(IC_RESULT(ic));
+  aopOp (op, ic, FALSE, FALSE);
 
-#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) {
-           assert(0);
+  aop = AOP (op);
+  if (aop->type == AOP_REG)
+    {
+      int i;
+      for (i = 0; i < aop->size; i++)
+       {
+         if (pairId == PAIR_DE)
+           {
+             emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
+             if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
+               ret++;
+             if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
+               ret++;
+           }
+          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);
+           }
        }
-       emitcode("", LABEL_STR ":",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))));
-        return TRUE;
-    }
+  freeAsmop (IC_LEFT (ic), NULL, ic);
+  return ret;
+}
 
-    /* If result is a pair */
-    if (isPair(AOP(IC_RESULT(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))));
-       return TRUE;
-    }
+/** Emit the code for a call statement
+ */
+static void
+emitCall (iCode * ic, bool ispcall)
+{
+  sym_link *detype = getSpec (operandType (IC_LEFT (ic)));
 
-    /* if the sizes are greater than 1 then we cannot */
-    if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
-        AOP_SIZE(IC_LEFT(ic)) > 1   )
-        return FALSE ;
+  bitVect *rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
 
-    /* we can if the aops of the left & result match or if they are in
-       registers and the registers are the same */
-    if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
-        while (icount--) 
-            emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
-        return TRUE ;
+  /* if caller saves & we have not saved then */
+  if (!ic->regsSaved)
+    {
+      /* PENDING */
     }
 
-    return FALSE ;
-}
+  _saveRegsForCall(ic, _G.sendSet ? elementsInSet(_G.sendSet) : 0);
 
-/*-----------------------------------------------------------------*/
-/* genMinus - generates code for subtraction                       */
-/*-----------------------------------------------------------------*/
-static void genMinus (iCode *ic)
-{
-    int size, offset = 0;
-    unsigned long lit = 0L;
+  /* if send set is not empty then assign */
+  if (_G.sendSet)
+    {
+      iCode *sic;
+      int send = 0;
+      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;
+    }
 
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RIGHT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
+  if (ispcall)
+    {
+      if (IS_BANKEDCALL (detype))
+       {
+         werror (W_INDIR_BANKED);
+       }
+      aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
 
-    /* special cases :- */
-    /* if both left & right are in bit space */
-    if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
-        AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
-       assert(0);
-        goto release ;
+      if (isLitWord (AOP (IC_LEFT (ic))))
+       {
+         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));
+         emit2 ("push hl");
+         _G.stack.pushed += 2;
+
+         fetchHL (AOP (IC_LEFT (ic)));
+         emit2 ("jp !*hl");
+         emit2 ("!tlabeldef", (rlbl->key + 100));
+         _G.stack.pushed -= 2;
+       }
+      freeAsmop (IC_LEFT (ic), NULL, ic);
+    }
+  else
+    {
+      char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
+      OP_SYMBOL (IC_LEFT (ic))->rname :
+      OP_SYMBOL (IC_LEFT (ic))->name;
+      if (IS_BANKEDCALL (detype))
+       {
+         emit2 ("call banked_call");
+         emit2 ("!dws", name);
+         emit2 ("!dw !bankimmeds", name);
+       }
+      else
+       {
+         /* make the call */
+         emit2 ("call %s", name);
+       }
     }
+  spillCached ();
+
+  /* Mark the regsiters as restored. */
+  _G.saves.saved = FALSE;
 
-    /* if I can do an decrement instead of subtract then GOOD for ME */
-    if (genMinusDec (ic) == TRUE)
-        goto release;   
+  /* if we need assign a result value */
+  if ((IS_ITEMP (IC_RESULT (ic)) &&
+       (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
+       OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
+      IS_TRUE_SYMOP (IC_RESULT (ic)))
+    {
 
-    size = getDataSize(IC_RESULT(ic));   
+      aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
 
-    if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
-    }
-    else{
-        lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
-        lit = - (long)lit;
+      assignResultValue (IC_RESULT (ic));
+
+      freeAsmop (IC_RESULT (ic), NULL, ic);
     }
 
+  /* adjust the stack for parameters if required */
+  if (ic->parmBytes)
+    {
+      int i = ic->parmBytes;
 
-    /* if literal, add a,#-lit, else normal subb */
-    while (size--) {
-       MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));    
-       if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
-           if (!offset)
-               emitcode("sub","a,%s",
-                        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
-           else
-               emitcode("sbc","a,%s",
-                        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
-       }
-       else{
-           /* first add without previous c */
-           if (!offset)
-               emitcode("add","a,#0x%02x",
-                        (unsigned int)(lit & 0x0FFL));
-           else
-               emitcode("adc","a,#0x%02x",
-                        (unsigned int)((lit >> (offset*8)) & 0x0FFL));
+      _G.stack.pushed -= i;
+      if (IS_GB)
+       {
+         emit2 ("!ldaspsp", i);
+       }
+      else
+       {
+         spillCached ();
+         if (i > 6)
+           {
+             emit2 ("ld hl,#%d", i);
+             emit2 ("add hl,sp");
+             emit2 ("ld sp,hl");
+           }
+         else
+           {
+             while (i > 1)
+               {
+                 emit2 ("pop hl");
+                 i -= 2;
+               }
+             if (i)
+               emit2 ("inc sp");
+           }
+         spillCached ();
        }
-       aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
     }
-    
-    if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
-       AOP_SIZE(IC_LEFT(ic)) == 3   &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
-       assert(0);
 
-release:
-    freeAsmop(IC_LEFT(ic),NULL,ic);
-    freeAsmop(IC_RIGHT(ic),NULL,ic);
-    freeAsmop(IC_RESULT(ic),NULL,ic);
+  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;
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* genMult - generates code for multiplication                     */
+/* genCall - generates a call statement                            */
 /*-----------------------------------------------------------------*/
-static void genMult (iCode *ic)
+static void
+genCall (iCode * ic)
 {
-    /* Shouldn't occur - all done through function calls */
-    assert(0);
+  emitCall (ic, FALSE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genDiv - generates code for division                            */
+/* genPcall - generates a call by pointer statement                */
 /*-----------------------------------------------------------------*/
-static void genDiv (iCode *ic)
+static void
+genPcall (iCode * ic)
 {
-    /* Shouldn't occur - all done through function calls */
-    assert(0);
+  emitCall (ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genMod - generates code for division                            */
+/* resultRemat - result  is rematerializable                       */
 /*-----------------------------------------------------------------*/
-static void genMod (iCode *ic)
+static int
+resultRemat (iCode * ic)
 {
-    /* Shouldn't occur - all done through function calls */
-    assert(0);
+  if (SKIP_IC (ic) || ic->op == IFX)
+    return 0;
+
+  if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
+    {
+      symbol *sym = OP_SYMBOL (IC_RESULT (ic));
+      if (sym->remat && !POINTER_SET (ic))
+       return 1;
+    }
+
+  return 0;
 }
 
+extern set *publics;
+
 /*-----------------------------------------------------------------*/
-/* genIfxJump :- will create a jump depending on the ifx           */
+/* genFunction - generated code for function entry                 */
 /*-----------------------------------------------------------------*/
-static void genIfxJump (iCode *ic, char *jval)
+static void
+genFunction (iCode * ic)
 {
-    symbol *jlbl ;
-    const char *inst;
+  symbol *sym = OP_SYMBOL (IC_LEFT (ic));
+  sym_link *fetype;
 
-    /* if true label then we jump if condition
-    supplied is true */
-    if ( IC_TRUE(ic) ) {
-        jlbl = IC_TRUE(ic);
-       if (!strcmp(jval, "a")) {
-           inst = "nz";
-       }
-       else if (!strcmp(jval, "c")) {
-           inst = "c";
-       }
-       else {
-           /* The buffer contains the bit on A that we should test */
-           inst = "nz";
-       }
-    }
-    else {
-        /* false label is present */
-        jlbl = IC_FALSE(ic) ;
-       if (!strcmp(jval, "a")) {
-           inst = "z";
-       }
-       else if (!strcmp(jval, "c")) {
-           inst = "nc";
-       }
-       else {
-           /* The buffer contains the bit on A that we should test */
-           inst = "z";
-       }
-    }
-    /* Z80 can do a conditional long jump */
-    if (!strcmp(jval, "a")) {
-       emitcode("or", "a,a");
+#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);
     }
-    else if (!strcmp(jval, "c")) {
+#endif
+
+  /* Record the last function name for debugging. */
+  _G.lastFunctionName = sym->rname;
+  
+  /* Create the function header */
+  emit2 ("!functionheader", sym->name);
+  /* PENDING: portability. */
+  emit2 ("__%s_start:", sym->rname);
+  emit2 ("!functionlabeldef", sym->rname);
+
+  if (options.profile) 
+    {
+      emit2 ("!profileenter");
     }
-    else {
-       emitcode("bit", "%s,a", jval);
+
+  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 all potentially used registers. */
+  if (IS_ISR (sym->etype))
+    {
+      emit2 ("!pusha");
     }
-    emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
 
-    /* mark the icode as generated */
-    ic->generated = 1;
-}
+  /* PENDING: callee-save etc */
 
-/** Generic compare for > or <
- */
-static void genCmp (operand *left,operand *right,
-                    operand *result, iCode *ifx, int sign)
-{
-    int size, offset = 0 ;
-    unsigned long lit = 0L;
-
-    /* if left & right are bit variables */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right) == AOP_CRY ) {
-       /* Cant happen on the Z80 */
-       assert(0);
-    } else {
-        /* subtract right from left if at the
-        end the carry flag is set then we know that
-        left is greater than right */
-        size = max(AOP_SIZE(left),AOP_SIZE(right));
-
-        /* if unsigned char cmp with lit, just compare */
-        if((size == 1) && 
-           (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
-           emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
-           if (sign) {
-               emitcode("xor", "a,#0x80");
-               emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
-           }
-           else 
-               emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE));
-        } 
-       else {
-            if(AOP_TYPE(right) == AOP_LIT) {
-                lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
-                /* optimize if(x < 0) or if(x >= 0) */
-                if (lit == 0L){
-                    if (!sign) {
-                       /* No sign so it's always false */
-                        CLRC;
-                    }
-                    else{
-                       /* Just load in the top most bit */
-                        MOVA(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");
-                    }
-                    goto release;
-                }
-            }
-           if (sign) {
-               /* First setup h and l contaning the top most bytes XORed */
-               bool fDidXor = FALSE;
-               if (AOP_TYPE(left) == AOP_LIT){
-                   unsigned long lit = (unsigned long)
-                       floatFromVal(AOP(left)->aopu.aop_lit);
-                   emitcode("ld", "%s,#0x%02x", _fTmp[0],
-                            0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
-               }
-               else {
-                   emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
-                   emitcode("xor", "a,#0x80");
-                   emitcode("ld", "%s,a", _fTmp[0]);
-                   fDidXor = TRUE;
-               }
-               if (AOP_TYPE(right) == AOP_LIT) {
-                   unsigned long lit = (unsigned long)
-                       floatFromVal(AOP(right)->aopu.aop_lit);
-                   emitcode("ld", "%s,#0x%02x", _fTmp[1],
-                            0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
-               }
-               else {
-                   emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
-                   emitcode("xor", "a,#0x80");
-                   emitcode("ld", "%s,a", _fTmp[1]);
-                   fDidXor = TRUE;
-               }
-               if (!fDidXor)
-                   CLRC;
-           }
-           else {
-               CLRC;
-           }
-            while (size--) {
-               /* Do a long subtract */
-               if (!sign || size) 
-                   MOVA(aopGet(AOP(left),offset,FALSE));
-                if (sign && size == 0) {
-                   emitcode("ld", "a,%s", _fTmp[0]);
-                   emitcode("sbc", "a,%s", _fTmp[1]);
-               }
-               else {
-                   /* Subtract through, propagating the carry */
-                   emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
+  _G.stack.param_offset = 0;
+
+#if CALLEE_SAVES
+  /* Detect which registers are used. */
+  if (sym->regsUsed)
+    {
+      int i;
+      for (i = 0; i < sym->regsUsed->size; i++)
+       {
+         if (bitVectBitValue (sym->regsUsed, i))
+           {
+             switch (i)
+               {
+               case C_IDX:
+               case B_IDX:
+                  bcInUse = TRUE;
+                 break;
+               case D_IDX:
+               case E_IDX:
+                 if (IS_Z80) {
+                    deInUse = TRUE;
+                  }
+                  else {
+                    /* Other systems use DE as a temporary. */
+                  }
+                 break;
                }
-            }
-        }
+           }
+       }
     }
 
-release:
-    if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
-        outBitC(result);
-    } else {
-        /* if the result is used in the next
-        ifx conditional branch then generate
-        code a little differently */
-        if (ifx )
-            genIfxJump (ifx,"c");
-        else
-            outBitC(result);
-        /* leave the result in acc */
+  if (bcInUse) 
+    {
+      emit2 ("push bc");
+      _G.stack.param_offset += 2;
     }
-}
 
-/*-----------------------------------------------------------------*/
-/* genCmpGt :- greater than comparison                             */
-/*-----------------------------------------------------------------*/
-static void genCmpGt (iCode *ic, iCode *ifx)
-{
-    operand *left, *right, *result;
-    link *letype , *retype;
-    int sign ;
+  _G.stack.pushedBC = bcInUse;
 
-    left = IC_LEFT(ic);
-    right= IC_RIGHT(ic);
-    result = IC_RESULT(ic);
+  if (deInUse)
+    {
+      emit2 ("push de");
+      _G.stack.param_offset += 2;
+    }
 
-    letype = getSpec(operandType(left));
-    retype =getSpec(operandType(right));
-    sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
-    /* assign the amsops */
-    aopOp (left,ic,FALSE);
-    aopOp (right,ic,FALSE);
-    aopOp (result,ic,TRUE);
+  _G.stack.pushedDE = deInUse;
+#endif
 
-    genCmp(right, left, result, ifx, sign);
+  /* adjust the stack for the function */
+  _G.stack.last = sym->stack;
 
-    freeAsmop(left,NULL,ic);
-    freeAsmop(right,NULL,ic);
-    freeAsmop(result,NULL,ic);
+  if (sym->stack)
+    emit2 ("!enterx", sym->stack);
+  else
+    emit2 ("!enter");
+  _G.stack.offset = sym->stack;
 }
 
 /*-----------------------------------------------------------------*/
-/* genCmpLt - less than comparisons                                */
+/* genEndFunction - generates epilogue for functions               */
 /*-----------------------------------------------------------------*/
-static void genCmpLt (iCode *ic, iCode *ifx)
+static void
+genEndFunction (iCode * ic)
 {
-    operand *left, *right, *result;
-    link *letype , *retype;
-    int sign ;
-
-    left = IC_LEFT(ic);
-    right= IC_RIGHT(ic);
-    result = IC_RESULT(ic);
+  symbol *sym = OP_SYMBOL (IC_LEFT (ic));
 
-    letype = getSpec(operandType(left));
-    retype =getSpec(operandType(right));
-    sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
-
-    /* assign the amsops */
-    aopOp (left,ic,FALSE);
-    aopOp (right,ic,FALSE);
-    aopOp (result,ic,TRUE);
+  if (IS_ISR (sym->etype))
+    {
+      wassert (0);
+    }
+  else
+    {
+      if (SPEC_CRTCL (sym->etype))
+       emit2 ("!ei");
 
-    genCmp(left, right, result, ifx, sign);
+      /* PENDING: calleeSave */
 
-    freeAsmop(left,NULL,ic);
-    freeAsmop(right,NULL,ic);
-    freeAsmop(result,NULL,ic);
-}
+      if (_G.stack.offset)
+        {
+          emit2 ("!leavex", _G.stack.offset);
+        }
+      else
+        {
+          emit2 ("!leave");
+        }
 
-/*-----------------------------------------------------------------*/
-/* gencjneshort - compare and jump if not equal                    */
-/*-----------------------------------------------------------------*/
-static void gencjneshort(operand *left, operand *right, symbol *lbl)
-{
-    int size = max(AOP_SIZE(left),AOP_SIZE(right));
-    int offset = 0;
-    unsigned long lit = 0L;
-
-    /* Swap the left and right if it makes the computation easier */
-    if (AOP_TYPE(left) == AOP_LIT) {
-        operand *t = right;
-        right = left;
-        left = t;
-    }
-
-    if(AOP_TYPE(right) == AOP_LIT)
-        lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
-
-    /* if the right side is a literal then anything goes */
-    if (AOP_TYPE(right) == AOP_LIT &&
-        AOP_TYPE(left) != AOP_DIR ) {
-        while (size--) {
-           emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
-           if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
-               emitcode("or", "a,a");
-           else 
-               emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
-            emitcode("jp", "nz," LABEL_STR , lbl->key+100);
-            offset++;
+#if CALLEE_SAVES
+      if (_G.stack.pushedDE) 
+        {
+          emit2 ("pop de");
+          _G.stack.pushedDE = FALSE;
         }
-    }
-    /* if the right side is in a register or in direct space or
-    if the left is a pointer register & right is not */    
-    else if (AOP_TYPE(right) == AOP_REG ||
-             AOP_TYPE(right) == AOP_DIR || 
-             (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
-        while (size--) {
-            MOVA(aopGet(AOP(left),offset,FALSE));
-            if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
-               ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
-               /* PENDING */
-                emitcode("jp","nz," LABEL_STR ,lbl->key+100);
-            else {
-               emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
-               emitcode("jp", "nz," LABEL_STR , lbl->key+100);
-           }
-            offset++;
+
+      if (_G.stack.pushedDE) 
+        {
+          emit2 ("pop bc");
+          _G.stack.pushedDE = FALSE;
         }
-    } else {
-        /* right is a pointer reg need both a & b */
-       /* PENDING: is this required? */
-        while(size--) {
-            char *l = aopGet(AOP(left),offset,FALSE);
-            MOVA(aopGet(AOP(right),offset,FALSE));
-           emitcode("cp", "%s ; 5", l);
-           emitcode("jr", "nz," LABEL_STR, lbl->key+100);
-            offset++;
+#endif
+
+      if (options.profile) 
+        {
+          emit2 ("!profileexit");
         }
+
+
+      /* Both baned and non-banked just ret */
+      emit2 ("ret");
+
+      /* PENDING: portability. */
+      emit2 ("__%s_end:", sym->rname);
     }
+  _G.flushStatics = 1;
+  _G.stack.pushed = 0;
+  _G.stack.offset = 0;
 }
 
 /*-----------------------------------------------------------------*/
-/* gencjne - compare and jump if not equal                         */
+/* genRet - generate code for return statement                     */
 /*-----------------------------------------------------------------*/
-static void gencjne(operand *left, operand *right, symbol *lbl)
+static void
+genRet (iCode * ic)
 {
-    symbol *tlbl  = newiTempLabel(NULL);
+    const char *l;
+  /* Errk.  This is a hack until I can figure out how
+     to cause dehl to spill on a call */
+  int size, offset = 0;
+
+  /* if we have no return value then
+     just generate the "ret" */
+  if (!IC_LEFT (ic))
+    goto jumpret;
+
+  /* we have something to return then
+     move the return value into place */
+  aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
+  size = AOP_SIZE (IC_LEFT (ic));
+
+  if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
+    {
+      if (IS_GB)
+       {
+         emit2 ("ld de,%s", l);
+       }
+      else
+       {
+         emit2 ("ld hl,%s", l);
+       }
+    }
+  else
+    {
+      if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
+       {
+         fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
+         fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
+       }
+      else
+       {
+         while (size--)
+           {
+             l = aopGet (AOP (IC_LEFT (ic)), offset,
+                         FALSE);
+             if (strcmp (_fReturn[offset], l))
+               emit2 ("ld %s,%s", _fReturn[offset++], l);
+           }
+       }
+    }
+  freeAsmop (IC_LEFT (ic), NULL, ic);
 
-    gencjneshort(left, right, lbl);
+jumpret:
+  /* generate a jump to the return label
+     if the next is not the return statement */
+  if (!(ic->next && ic->next->op == LABEL &&
+       IC_LABEL (ic->next) == returnLabel))
 
-    /* PENDING: ?? */
-    emitcode("ld","a,%s",one);
-    emitcode("jp", LABEL_STR ,tlbl->key+100);
-    emitcode("", LABEL_STR ":",lbl->key+100);
-    emitcode("xor","a,a");
-    emitcode("", LABEL_STR ":",tlbl->key+100);
+    emit2 ("jp !tlabel", returnLabel->key + 100);
 }
 
 /*-----------------------------------------------------------------*/
-/* genCmpEq - generates code for equal to                          */
+/* genLabel - generates a label                                    */
 /*-----------------------------------------------------------------*/
-static void genCmpEq (iCode *ic, iCode *ifx)
+static void
+genLabel (iCode * ic)
 {
-    operand *left, *right, *result;
-
-    aopOp((left=IC_LEFT(ic)),ic,FALSE);
-    aopOp((right=IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,TRUE);
-
-    /* Swap operands if it makes the operation easier. ie if:
-       1.  Left is a literal.
-    */
-    if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
-        operand *t = IC_RIGHT(ic);
-        IC_RIGHT(ic) = IC_LEFT(ic);
-        IC_LEFT(ic) = t;
-    }
-
-    if (ifx && !AOP_SIZE(result)){
-        symbol *tlbl;
-        /* if they are both bit variables */
-        if (AOP_TYPE(left) == AOP_CRY &&
-            ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
-           assert(0);
-        } else {
-            tlbl = newiTempLabel(NULL);
-            gencjneshort(left, right, tlbl);
-            if ( IC_TRUE(ifx) ) {
-                emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
-                emitcode("", LABEL_STR ":",tlbl->key+100);                
-            } else {
-               /* PENDING: do this better */
-                symbol *lbl = newiTempLabel(NULL);
-                emitcode("jp", LABEL_STR ,lbl->key+100);
-                emitcode("", LABEL_STR ":",tlbl->key+100);                
-                emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
-                emitcode("", LABEL_STR ":",lbl->key+100);             
-            }
-        }
-        /* mark the icode as generated */
-        ifx->generated = 1;
-        goto release ;
-    }
-
-    /* if they are both bit variables */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
-       assert(0);
-    } else {
-        gencjne(left,right,newiTempLabel(NULL));    
-        if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
-           assert(0);
-        }
-        if (ifx) {
-           genIfxJump(ifx,"a");
-           goto release;
-        }
-        /* if the result is used in an arithmetic operation
-        then put the result in place */
-        if (AOP_TYPE(result) != AOP_CRY) {
-            outAcc(result);
-       }
-        /* leave the result in acc */
-    }
+  /* special case never generate */
+  if (IC_LABEL (ic) == entryLabel)
+    return;
 
-release:
-    freeAsmop(left,NULL,ic);
-    freeAsmop(right,NULL,ic);
-    freeAsmop(result,NULL,ic);
+  emitLabel (IC_LABEL (ic)->key + 100);
 }
 
 /*-----------------------------------------------------------------*/
-/* ifxForOp - returns the icode containing the ifx for operand     */
+/* genGoto - generates a ljmp                                      */
 /*-----------------------------------------------------------------*/
-static iCode *ifxForOp ( operand *op, iCode *ic )
+static void
+genGoto (iCode * ic)
 {
-    /* if true symbol then needs to be assigned */
-    if (IS_TRUE_SYMOP(op))
-        return NULL ;
-
-    /* if this has register type condition and
-    the next instruction is ifx with the same operand
-    and live to of the operand is upto the ifx only then */
-    if (ic->next &&
-        ic->next->op == IFX &&
-        IC_COND(ic->next)->key == op->key &&
-        OP_SYMBOL(op)->liveTo <= ic->next->seq )
-        return ic->next;
-
-    return NULL;
+  emit2 ("jp !tlabel", IC_LABEL (ic)->key + 100);
 }
 
 /*-----------------------------------------------------------------*/
-/* genAndOp - for && operation                                     */
+/* genPlusIncr :- does addition with increment if possible         */
 /*-----------------------------------------------------------------*/
-static void genAndOp (iCode *ic)
+static bool
+genPlusIncr (iCode * ic)
 {
-    operand *left,*right, *result;
-    symbol *tlbl;
+  unsigned int icount;
+  unsigned int size = getDataSize (IC_RESULT (ic));
+  PAIR_ID resultId = getPairId (AOP (IC_RESULT (ic)));
+
+  /* will try to generate an increment */
+  /* if the right side is not a literal
+     we cannot */
+  if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
+    return FALSE;
+
+  emitDebug ("; genPlusIncr");
 
-    /* note here that && operations that are in an if statement are
-       taken away by backPatchLabels only those used in arthmetic
-       operations remain */
-    aopOp((left=IC_LEFT(ic)),ic,FALSE);
-    aopOp((right=IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,FALSE);
+  icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
 
-    /* if both are bit variables */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right) == AOP_CRY ) {
-       assert(0);
-    } else {
-        tlbl = newiTempLabel(NULL);
-        toBoolean(left);    
-        emitcode("jp","z," LABEL_STR ,tlbl->key+100);
-        toBoolean(right);
-        emitcode("", LABEL_STR ":",tlbl->key+100);
-        outBitAcc(result);
+  /* If result is a pair */
+  if (resultId != PAIR_INVALID)
+    {
+      if (isLitWord (AOP (IC_LEFT (ic))))
+       {
+         fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
+         return TRUE;
+       }
+      if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
+       {
+         fetchPair (resultId, AOP (IC_RIGHT (ic)));
+         emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
+         return TRUE;
+       }
+      if (icount > 5)
+       return FALSE;
+      /* Inc a pair */
+      if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
+       {
+         if (icount > 2)
+           return FALSE;
+         movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
+         movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
+       }
+      while (icount--)
+       {
+         emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic))));
+       }
+      return TRUE;
     }
 
-    freeAsmop(left,NULL,ic);
-    freeAsmop(right,NULL,ic);
-    freeAsmop(result,NULL,ic);
-}
+  /* if the literal value of the right hand side
+     is greater than 4 then it is not worth it */
+  if (icount > 4)
+    return FALSE;
 
-/*-----------------------------------------------------------------*/
-/* genOrOp - for || operation                                      */
-/*-----------------------------------------------------------------*/
-static void genOrOp (iCode *ic)
-{
-    operand *left,*right, *result;
-    symbol *tlbl;
+  /* if increment 16 bits in register */
+  if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
+      size > 1 &&
+      icount == 1
+    )
+    {
+      int offset = 0;
+      symbol *tlbl = NULL;
+      tlbl = newiTempLabel (NULL);
+      while (size--)
+       {
+         emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
+         if (size)
+           {
+             emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+           }
+       }
+      emitLabel (tlbl->key + 100);
+      return TRUE;
+    }
 
-    /* note here that || operations that are in an
-       if statement are taken away by backPatchLabels
-       only those used in arthmetic operations remain */
-    aopOp((left=IC_LEFT(ic)),ic,FALSE);
-    aopOp((right=IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,FALSE);
+  /* if the sizes are greater than 1 then we cannot */
+  if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
+      AOP_SIZE (IC_LEFT (ic)) > 1)
+    return FALSE;
 
-    /* if both are bit variables */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right) == AOP_CRY ) {
-       assert(0);
-    } else {
-        tlbl = newiTempLabel(NULL);
-        toBoolean(left);
-        emitcode("jp","nz," LABEL_STR,tlbl->key+100);
-        toBoolean(right);
-        emitcode("", LABEL_STR,tlbl->key+100);
-        outBitAcc(result);
+  /* we can if the aops of the left & result match or
+     if they are in registers and the registers are the
+     same */
+  if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
+    {
+      while (icount--)
+        {
+          emit2 ("inc %s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
+        }
+      return TRUE;
     }
 
-    freeAsmop(left,NULL,ic);
-    freeAsmop(right,NULL,ic);
-    freeAsmop(result,NULL,ic);
+  return FALSE;
 }
 
 /*-----------------------------------------------------------------*/
-/* isLiteralBit - test if lit == 2^n                               */
+/* outBitAcc - output a bit in acc                                 */
 /*-----------------------------------------------------------------*/
-int isLiteralBit(unsigned long lit)
+void
+outBitAcc (operand * result)
 {
-    unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
-    0x100L,0x200L,0x400L,0x800L,
-    0x1000L,0x2000L,0x4000L,0x8000L,
-    0x10000L,0x20000L,0x40000L,0x80000L,
-    0x100000L,0x200000L,0x400000L,0x800000L,
-    0x1000000L,0x2000000L,0x4000000L,0x8000000L,
-    0x10000000L,0x20000000L,0x40000000L,0x80000000L};
-    int idx;
-    
-    for(idx = 0; idx < 32; idx++)
-        if(lit == pw[idx])
-            return idx+1;
-    return 0;
+  symbol *tlbl = newiTempLabel (NULL);
+  /* if the result is a bit */
+  if (AOP_TYPE (result) == AOP_CRY)
+    {
+      wassert (0);
+    }
+  else
+    {
+      emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
+      emit2 ("ld a,!one");
+      emitLabel (tlbl->key + 100);
+      outAcc (result);
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* genAnd  - code for and                                          */
+/* genPlus - generates code for addition                           */
 /*-----------------------------------------------------------------*/
-static void genAnd (iCode *ic, iCode *ifx)
+static void
+genPlus (iCode * ic)
 {
-    operand *left, *right, *result;
-    int size, offset=0;  
-    unsigned long lit = 0L;
-    int bytelit = 0;
+  int size, offset = 0;
 
-    aopOp((left = IC_LEFT(ic)),ic,FALSE);
-    aopOp((right= IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,TRUE);
+  /* special cases :- */
 
-#ifdef DEBUG_TYPE
-    emitcode("","; Type res[%d] = l[%d]&r[%d]",
-             AOP_TYPE(result),
-             AOP_TYPE(left), AOP_TYPE(right));
-    emitcode("","; Size res[%d] = l[%d]&r[%d]",
-             AOP_SIZE(result),
-             AOP_SIZE(left), AOP_SIZE(right));
-#endif
+  aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
+  aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
+  aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
 
-    /* if left is a literal & right is not then exchange them */
-    if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
-       AOP_NEEDSACC(left)) {
-        operand *tmp = right ;
-        right = left;
-        left = tmp;
-    }
-
-    /* if result = right then exchange them */
-    if(sameRegs(AOP(result),AOP(right))){
-        operand *tmp = right ;
-        right = left;
-        left = tmp;
-    }
-
-    /* if right is bit then exchange them */
-    if (AOP_TYPE(right) == AOP_CRY &&
-        AOP_TYPE(left) != AOP_CRY){
-        operand *tmp = right ;
-        right = left;
-        left = tmp;
-    }
-    if(AOP_TYPE(right) == AOP_LIT)
-        lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
-
-    size = AOP_SIZE(result);
-
-    if (AOP_TYPE(left) == AOP_CRY){
-       assert(0);
-        goto release ;
-    }
-
-    // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
-    // bit = val & 0xZZ     - size = 1, ifx = FALSE -
-    if((AOP_TYPE(right) == AOP_LIT) &&
-       (AOP_TYPE(result) == AOP_CRY) &&
-       (AOP_TYPE(left) != AOP_CRY)) {
-        int posbit = isLiteralBit(lit);
-        /* left &  2^n */
-        if(posbit){
-            posbit--;
-            MOVA(aopGet(AOP(left),posbit>>3,FALSE));
-            // bit = left & 2^n
-            if(size) {
-               assert(0);
-                emitcode("mov","c,acc.%d",posbit&0x07);
-           }
-            // if(left &  2^n)
-            else{
-                if (ifx) {
-                    sprintf(buffer, "%d", posbit&0x07);
-                    genIfxJump(ifx, buffer);
-                }
-               else {
-                   assert(0);
-               }
-                goto release;
-            }
-        } else {
-            symbol *tlbl = newiTempLabel(NULL);
-            int sizel = AOP_SIZE(left);
-            if(size) {
-               assert(0);
-                emitcode("setb","c");
-           }
-            while(sizel--){
-                if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
-                    MOVA( aopGet(AOP(left),offset,FALSE));
-                    // byte ==  2^n ?
-                    if((posbit = isLiteralBit(bytelit)) != 0) {
-                       assert(0);
-                        emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
-                   }
-                    else{
-                        if(bytelit != 0x0FFL)
-                            emitcode("and","a,%s",
-                                     aopGet(AOP(right),offset,FALSE));
-                        emitcode("jr","nz, %05d$",tlbl->key+100);
-                    }
-                }
-                offset++;
-            }
-            // bit = left & literal
-            if (size){
-                emitcode("clr","c");
-                emitcode("","%05d$:",tlbl->key+100);
-            }
-            // if(left & literal)
-            else{
-                if(ifx)
-#if 0
-                    jmpTrueOrFalse(ifx, tlbl);
-#else
-               assert(0);
-#endif
-                goto release ;
-            }
-        }
-        outBitC(result);
-        goto release ;
-    }
-
-    /* if left is same as result */
-    if(sameRegs(AOP(result),AOP(left))){
-        for(;size--; offset++) {
-            if(AOP_TYPE(right) == AOP_LIT){
-                if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
-                    continue;
-                else {
-                   if (bytelit == 0)
-                       aopPut(AOP(result),zero,offset);
-                   else {
-                       MOVA(aopGet(AOP(left),offset,FALSE));
-                       emitcode("and","a,%s",
-                                aopGet(AOP(right),offset,FALSE));
-                       emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
-                   }
-               }
+  /* Swap the left and right operands if:
 
-            } else {
-               if (AOP_TYPE(left) == AOP_ACC) {
-                   assert(0);
-               }
-               else {
-                   MOVA(aopGet(AOP(right),offset,FALSE));
-                   emitcode("and","%s,a",
-                            aopGet(AOP(left),offset,FALSE));
+     if literal, literal on the right or
+     if left requires ACC or right is already
+     in ACC */
+
+  if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
+      (AOP_NEEDSACC (IC_LEFT (ic))) ||
+      AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
+    {
+      operand *t = IC_RIGHT (ic);
+      IC_RIGHT (ic) = IC_LEFT (ic);
+      IC_LEFT (ic) = t;
+    }
+
+  /* if both left & right are in bit
+     space */
+  if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
+      AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
+    {
+      /* Cant happen */
+      wassert (0);
+    }
+
+  /* if left in bit space & right literal */
+  if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
+      AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
+    {
+      /* Can happen I guess */
+      wassert (0);
+    }
+
+  /* if I can do an increment instead
+     of add then GOOD for ME */
+  if (genPlusIncr (ic) == TRUE)
+    goto release;
+
+  emitDebug ("; genPlusIncr failed");
+
+  size = getDataSize (IC_RESULT (ic));
+
+  /* Special case when left and right are constant */
+  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)
+       {
+         /* It's a pair */
+         /* PENDING: fix */
+         char buffer[100];
+         sprintf (buffer, "#(%s + %s)", left, right);
+         emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
+         goto release;
+       }
+    }
+
+  if (isPair (AOP (IC_RIGHT (ic))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
+    {
+      /* Fetch into HL then do the add */
+      spillPair (PAIR_HL);
+      fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
+      emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
+      goto release;
+    }
+
+  /* Special case:
+     ld hl,sp+n trashes C so we cant afford to do it during an
+     add with stack based varibles.  Worst case is:
+     ld  hl,sp+left
+     ld  a,(hl)
+     ld  hl,sp+right
+     add (hl)
+     ld  hl,sp+result
+     ld  (hl),a
+     ld  hl,sp+left+1
+     ld  a,(hl)
+     ld  hl,sp+right+1
+     adc (hl)
+     ld  hl,sp+result+1
+     ld  (hl),a
+     So you cant afford to load up hl if either left, right, or result
+     is on the stack (*sigh*)  The alt is:
+     ld  hl,sp+left
+     ld  de,(hl)
+     ld  hl,sp+right
+     ld  hl,(hl)
+     add hl,de
+     ld  hl,sp+result
+     ld  (hl),hl
+     Combinations in here are:
+     * If left or right are in bc then the loss is small - trap later
+     * If the result is in bc then the loss is also small
+   */
+  if (IS_GB)
+    {
+      if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
+         AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
+         AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
+       {
+         if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
+              AOP_SIZE (IC_RIGHT (ic)) == 2) &&
+             (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
+              AOP_SIZE (IC_RIGHT (ic)) <= 2))
+           {
+             if (getPairId (AOP (IC_RIGHT (ic))) == PAIR_BC)
+               {
+                 /* Swap left and right */
+                 operand *t = IC_RIGHT (ic);
+                 IC_RIGHT (ic) = IC_LEFT (ic);
+                 IC_LEFT (ic) = t;
                }
-            }
-        }
-    } else {
-        // left & result in different registers
-        if(AOP_TYPE(result) == AOP_CRY){
-           assert(0);
-        } else {
-           for(;(size--);offset++) {
-               // normal case
-               // result = left & right
-               if(AOP_TYPE(right) == AOP_LIT){
-                   if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
-                       aopPut(AOP(result),
-                              aopGet(AOP(left),offset,FALSE),
-                              offset);
-                       continue;
-                   } else if(bytelit == 0){
-                       aopPut(AOP(result),zero,offset);
-                       continue;
-                   }
+             if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
+               {
+                 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
+                 emit2 ("add hl,bc");
                }
-               // 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));
-               else {
-                   MOVA(aopGet(AOP(right),offset,FALSE));
-                   emitcode("and","a,%s",
-                            aopGet(AOP(left),offset,FALSE));
+             else
+               {
+                 fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
+                 fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
+                 emit2 ("add hl,de");
                }
-               aopPut(AOP(result),"a",offset);
+             commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
+             goto release;
+           }
+         else if (size == 4)
+           {
+             emitDebug ("; WARNING: This add is probably broken.\n");
            }
        }
+    }
 
+  while (size--)
+    {
+      if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
+       {
+         _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
+         if (offset == 0)
+           emit2 ("add a,%s",
+                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+         else
+           emit2 ("adc a,%s",
+                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+       }
+      else
+       {
+         _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
+         if (offset == 0)
+           emit2 ("add a,%s",
+                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+         else
+           emit2 ("adc a,%s",
+                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+       }
+      aopPut (AOP (IC_RESULT (ic)), "a", offset++);
     }
 
-release :
-    freeAsmop(left,NULL,ic);
-    freeAsmop(right,NULL,ic);
-    freeAsmop(result,NULL,ic);
+release:
+  freeAsmop (IC_LEFT (ic), NULL, ic);
+  freeAsmop (IC_RIGHT (ic), NULL, ic);
+  freeAsmop (IC_RESULT (ic), NULL, ic);
+
 }
 
 /*-----------------------------------------------------------------*/
-/* genOr  - code for or                                            */
+/* genMinusDec :- does subtraction with deccrement if possible     */
 /*-----------------------------------------------------------------*/
-static void genOr (iCode *ic, iCode *ifx)
+static bool
+genMinusDec (iCode * ic)
 {
-    operand *left, *right, *result;
-    int size, offset=0;
-    unsigned long lit = 0L;
+  unsigned int icount;
+  unsigned int size = getDataSize (IC_RESULT (ic));
 
-    aopOp((left = IC_LEFT(ic)),ic,FALSE);
-    aopOp((right= IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,TRUE);
+  /* will try to generate an increment */
+  /* if the right side is not a literal we cannot */
+  if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
+    return FALSE;
 
-#if 1
-    emitcode("","; Type res[%d] = l[%d]&r[%d]",
-             AOP_TYPE(result),
-             AOP_TYPE(left), AOP_TYPE(right));
-    emitcode("","; Size res[%d] = l[%d]&r[%d]",
-             AOP_SIZE(result),
-             AOP_SIZE(left), AOP_SIZE(right));
-#endif
+  /* if the literal value of the right hand side
+     is greater than 4 then it is not worth it */
+  if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
+    return FALSE;
 
-    /* if left is a literal & right is not then exchange them */
-    if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
-       AOP_NEEDSACC(left)) {
-        operand *tmp = right ;
-        right = left;
-        left = tmp;
-    }
-
-    /* if result = right then exchange them */
-    if(sameRegs(AOP(result),AOP(right))){
-        operand *tmp = right ;
-        right = left;
-        left = tmp;
-    }
-
-    /* if right is bit then exchange them */
-    if (AOP_TYPE(right) == AOP_CRY &&
-        AOP_TYPE(left) != AOP_CRY){
-        operand *tmp = right ;
-        right = left;
-        left = tmp;
-    }
-    if(AOP_TYPE(right) == AOP_LIT)
-        lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
-
-    size = AOP_SIZE(result);
-
-    if (AOP_TYPE(left) == AOP_CRY){
-       assert(0);
-        goto release ;
-    }
-
-    if((AOP_TYPE(right) == AOP_LIT) &&
-       (AOP_TYPE(result) == AOP_CRY) &&
-       (AOP_TYPE(left) != AOP_CRY)){
-       assert(0);
-        goto release ;
-    }
-
-    /* if left is same as result */
-    if(sameRegs(AOP(result),AOP(left))){
-        for(;size--; offset++) {
-            if(AOP_TYPE(right) == AOP_LIT){
-                if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
-                    continue;
-                else 
-                   emitcode("or","%s,%s; 5",
-                            aopGet(AOP(left),offset,FALSE),
-                            aopGet(AOP(right),offset,FALSE));
-            } else {
-               if (AOP_TYPE(left) == AOP_ACC) 
-                   emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
-               else {              
-                   MOVA(aopGet(AOP(right),offset,FALSE));
-                   emitcode("or","a,%s ; 7",
-                            aopGet(AOP(left),offset,FALSE));
-                   aopPut(AOP(result),"a ; 8",0);
-               }
-            }
-        }
-    } else {
-        // left & result in different registers
-        if(AOP_TYPE(result) == AOP_CRY){
-           assert(0);
-        } else for(;(size--);offset++){
-            // normal case
-            // result = left & right
-            if(AOP_TYPE(right) == AOP_LIT){
-                if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
-                    aopPut(AOP(result),
-                           aopGet(AOP(left),offset,FALSE),
-                           offset);
-                    continue;
-                }
-            }
-            // faster than result <- left, anl result,right
-            // and better if result is SFR
-           if (AOP_TYPE(left) == AOP_ACC) 
-               emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
-           else {
-               MOVA(aopGet(AOP(right),offset,FALSE));
-               emitcode("or","a,%s",
-                        aopGet(AOP(left),offset,FALSE));
-           }
-           aopPut(AOP(result),"a",offset);                     
-           /* PENDING: something weird is going on here.  Add exception. */
-           if (AOP_TYPE(result) == AOP_ACC)
-               break;
-        }
+  size = getDataSize (IC_RESULT (ic));
+
+  /* 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--)
+       emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
+      return TRUE;
+    }
+
+  /* If result is a pair */
+  if (isPair (AOP (IC_RESULT (ic))))
+    {
+      movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
+      movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
+      while (icount--)
+       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 (PAIR_HL, AOP (IC_RESULT (ic)));
+
+      while (icount--) {
+        emit2 ("dec hl");
+      }
+      aopPut (AOP (IC_RESULT (ic)), "l", LSB);
+      aopPut (AOP (IC_RESULT (ic)), "h", MSB16);
+
+      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)
+    return FALSE;
+
+  /* we can if the aops of the left & result match or if they are in
+     registers and the registers are the same */
+  if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
+    {
+      while (icount--)
+       emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
+      return TRUE;
     }
 
-release :
-    freeAsmop(left,NULL,ic);
-    freeAsmop(right,NULL,ic);
-    freeAsmop(result,NULL,ic);
+  return FALSE;
 }
 
 /*-----------------------------------------------------------------*/
-/* genXor - code for xclusive or                                   */
+/* genMinus - generates code for subtraction                       */
 /*-----------------------------------------------------------------*/
-static void genXor (iCode *ic, iCode *ifx)
+static void
+genMinus (iCode * ic)
 {
-    operand *left, *right, *result;
-    int size, offset=0;
-    unsigned long lit = 0L;
+  int size, offset = 0;
+  unsigned long lit = 0L;
 
-    aopOp((left = IC_LEFT(ic)),ic,FALSE);
-    aopOp((right= IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,TRUE);
-
-    /* if left is a literal & right is not then exchange them */
-    if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
-       AOP_NEEDSACC(left)) {
-        operand *tmp = right ;
-        right = left;
-        left = tmp;
-    }
+  aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
+  aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
+  aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
 
-    /* if result = right then exchange them */
-    if(sameRegs(AOP(result),AOP(right))){
-        operand *tmp = right ;
-        right = left;
-        left = tmp;
+  /* special cases :- */
+  /* if both left & right are in bit space */
+  if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
+      AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
+    {
+      wassert (0);
+      goto release;
     }
 
-    /* if right is bit then exchange them */
-    if (AOP_TYPE(right) == AOP_CRY &&
-        AOP_TYPE(left) != AOP_CRY){
-        operand *tmp = right ;
-        right = left;
-        left = tmp;
-    }
-    if(AOP_TYPE(right) == AOP_LIT)
-        lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
+  /* if I can do an decrement instead of subtract then GOOD for ME */
+  if (genMinusDec (ic) == TRUE)
+    goto release;
 
-    size = AOP_SIZE(result);
+  size = getDataSize (IC_RESULT (ic));
 
-    if (AOP_TYPE(left) == AOP_CRY){
-       assert(0);
-        goto release ;
+  if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
+    {
     }
-
-    if((AOP_TYPE(right) == AOP_LIT) &&
-       (AOP_TYPE(result) == AOP_CRY) &&
-       (AOP_TYPE(left) != AOP_CRY)){
-       assert(0);
-        goto release ;
+  else
+    {
+      lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+      lit = -(long) lit;
     }
 
-    /* if left is same as result */
-    if(sameRegs(AOP(result),AOP(left))){
-        for(;size--; offset++) {
-            if(AOP_TYPE(right) == AOP_LIT){
-                if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
-                    continue;
-                else {
-                   MOVA(aopGet(AOP(right),offset,FALSE));
-                   emitcode("xor","a,%s",
-                            aopGet(AOP(left),offset,FALSE));
-                   aopPut(AOP(result),"a",0);
-               }
-            } else {
-               if (AOP_TYPE(left) == AOP_ACC) 
-                   emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
-               else {              
-                   MOVA(aopGet(AOP(right),offset,FALSE));
-                   emitcode("xor","a,%s",
-                            aopGet(AOP(left),offset,FALSE));
-                   aopPut(AOP(result),"a",0);
+  /* Same logic as genPlus */
+  if (IS_GB)
+    {
+      if (AOP_TYPE (IC_LEFT (ic)) == AOP_STK ||
+         AOP_TYPE (IC_RIGHT (ic)) == AOP_STK ||
+         AOP_TYPE (IC_RESULT (ic)) == AOP_STK)
+       {
+         if ((AOP_SIZE (IC_LEFT (ic)) == 2 ||
+              AOP_SIZE (IC_RIGHT (ic)) == 2) &&
+             (AOP_SIZE (IC_LEFT (ic)) <= 2 &&
+              AOP_SIZE (IC_RIGHT (ic)) <= 2))
+           {
+             PAIR_ID left = getPairId (AOP (IC_LEFT (ic)));
+             PAIR_ID right = getPairId (AOP (IC_RIGHT (ic)));
+
+             if (left == PAIR_INVALID && right == PAIR_INVALID)
+               {
+                 left = PAIR_DE;
+                 right = PAIR_HL;
                }
-            }
-        }
-    } else {
-        // left & result in different registers
-        if(AOP_TYPE(result) == AOP_CRY){
-           assert(0);
-        } else for(;(size--);offset++){
-            // normal case
-            // result = left & right
-            if(AOP_TYPE(right) == AOP_LIT){
-                if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
-                    aopPut(AOP(result),
-                           aopGet(AOP(left),offset,FALSE),
-                           offset);
-                    continue;
-                }
-            }
-            // faster than result <- left, anl result,right
-            // and better if result is SFR
-           if (AOP_TYPE(left) == AOP_ACC) 
-               emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
-           else {
-               MOVA(aopGet(AOP(right),offset,FALSE));
-               emitcode("xor","a,%s",
-                        aopGet(AOP(left),offset,FALSE));
-               aopPut(AOP(result),"a",0);
-           }
-           aopPut(AOP(result),"a",offset);                     
-        }
+             else if (right == PAIR_INVALID)
+               right = PAIR_DE;
+             else if (left == PAIR_INVALID)
+               left = PAIR_DE;
+
+             fetchPair (left, AOP (IC_LEFT (ic)));
+             /* Order is important.  Right may be HL */
+             fetchPair (right, AOP (IC_RIGHT (ic)));
+
+             emit2 ("ld a,%s", _pairs[left].l);
+             emit2 ("sub a,%s", _pairs[right].l);
+             emit2 ("ld e,a");
+             emit2 ("ld a,%s", _pairs[left].h);
+             emit2 ("sbc a,%s", _pairs[right].h);
+
+             aopPut (AOP (IC_RESULT (ic)), "a", 1);
+             aopPut (AOP (IC_RESULT (ic)), "e", 0);
+             goto release;
+           }
+         else if (size == 4)
+           {
+             emitDebug ("; WARNING: This sub is probably broken.\n");
+           }
+       }
+    }
+
+  /* if literal, add a,#-lit, else normal subb */
+  while (size--)
+    {
+      _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
+      if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
+       {
+         if (!offset)
+           emit2 ("sub a,%s",
+                     aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+         else
+           emit2 ("sbc a,%s",
+                     aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+       }
+      else
+       {
+         /* first add without previous c */
+         if (!offset)
+           emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
+         else
+           emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
+       }
+      aopPut (AOP (IC_RESULT (ic)), "a", offset++);
     }
 
-release :
-    freeAsmop(left,NULL,ic);
-    freeAsmop(right,NULL,ic);
-    freeAsmop(result,NULL,ic);
+  if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
+      AOP_SIZE (IC_LEFT (ic)) == 3 &&
+      !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
+    wassert (0);
+
+release:
+  freeAsmop (IC_LEFT (ic), NULL, ic);
+  freeAsmop (IC_RIGHT (ic), NULL, ic);
+  freeAsmop (IC_RESULT (ic), NULL, ic);
 }
 
 /*-----------------------------------------------------------------*/
-/* genInline - write the inline code out                           */
+/* genMult - generates code for multiplication                     */
 /*-----------------------------------------------------------------*/
-static void genInline (iCode *ic)
+static void
+genMult (iCode * ic)
 {
-    char buffer[MAX_INLINEASM];
-    char *bp = buffer;
-    char *bp1= buffer;
-    
-    inLine += (!options.asmpeep);
-    strcpy(buffer,IC_INLINE(ic));
-
-    /* emit each line as a code */
-    while (*bp) {
-        if (*bp == '\n') {
-            *bp++ = '\0';
-            emitcode(bp1,"");
-            bp1 = bp;
-        } else {
-            if (*bp == ':') {
-                bp++;
-                *bp = '\0';
-                bp++;
-                emitcode(bp1,"");
-                bp1 = bp;
-            } else
-                bp++;
-        }
-    }
-    if (bp1 != bp)
-        emitcode(bp1,"");
-    /*     emitcode("",buffer); */
-    inLine -= (!options.asmpeep);
+  /* Shouldn't occur - all done through function calls */
+  wassert (0);
 }
 
 /*-----------------------------------------------------------------*/
-/* genRRC - rotate right with carry                                */
+/* genDiv - generates code for division                            */
 /*-----------------------------------------------------------------*/
-static void genRRC (iCode *ic)
+static void
+genDiv (iCode * ic)
 {
-    assert(0);
+  /* Shouldn't occur - all done through function calls */
+  wassert (0);
 }
 
 /*-----------------------------------------------------------------*/
-/* genRLC - generate code for rotate left with carry               */
+/* genMod - generates code for division                            */
 /*-----------------------------------------------------------------*/
-static void genRLC (iCode *ic)
-{    
-    assert(0);
+static void
+genMod (iCode * ic)
+{
+  /* Shouldn't occur - all done through function calls */
+  wassert (0);
 }
 
 /*-----------------------------------------------------------------*/
-/* shiftR2Left2Result - shift right two bytes from left to result  */
+/* genIfxJump :- will create a jump depending on the ifx           */
 /*-----------------------------------------------------------------*/
-static void shiftR2Left2Result (operand *left, int offl,
-                                operand *result, int offr,
-                                int shCount, int sign)
+static void
+genIfxJump (iCode * ic, char *jval)
 {
-    if(sameRegs(AOP(result), AOP(left)) &&
-       ((offl + MSB16) == offr)){
-       assert(0);
-    } else {
-       movLeft2Result(left, offl, result, offr, 0);
-       movLeft2Result(left, offl+1, result, offr+1, 0);
-    }
+  symbol *jlbl;
+  const char *inst;
 
-    if (sign) {
-       assert(0);
+  /* if true label then we jump if condition
+     supplied is true */
+  if (IC_TRUE (ic))
+    {
+      jlbl = IC_TRUE (ic);
+      if (!strcmp (jval, "a"))
+       {
+         inst = "nz";
+       }
+      else if (!strcmp (jval, "c"))
+       {
+         inst = "c";
+       }
+      else if (!strcmp (jval, "nc"))
+       {
+         inst = "nc";
+       }
+      else
+       {
+         /* The buffer contains the bit on A that we should test */
+         inst = "nz";
+       }
     }
-    else {
-       /*      if (AOP(result)->type == AOP_REG) {*/
-           int size = 2;
-           int offset = 0;
-           symbol *tlbl , *tlbl1;
-           char *l;
+  else
+    {
+      /* false label is present */
+      jlbl = IC_FALSE (ic);
+      if (!strcmp (jval, "a"))
+       {
+         inst = "z";
+       }
+      else if (!strcmp (jval, "c"))
+       {
+         inst = "nc";
+       }
+      else if (!strcmp (jval, "nc"))
+       {
+         inst = "c";
+       }
+      else
+       {
+         /* The buffer contains the bit on A that we should test */
+         inst = "z";
+       }
+    }
+  /* Z80 can do a conditional long jump */
+  if (!strcmp (jval, "a"))
+    {
+      emit2 ("or a,a");
+    }
+  else if (!strcmp (jval, "c"))
+    {
+    }
+  else if (!strcmp (jval, "nc"))
+    {
+    }
+  else
+    {
+      emit2 ("bit %s,a", jval);
+    }
+  emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
 
-           /* Left is already in result - so now do the shift */
-           if (shCount>1) {
-               emitcode("ld","a,#%u+1", shCount);
-               tlbl = newiTempLabel(NULL);
-               tlbl1 = newiTempLabel(NULL);
-               emitcode("jp", LABEL_STR ,tlbl1->key+100); 
-               emitcode("", LABEL_STR ":",tlbl->key+100);    
-           }
+  /* mark the icode as generated */
+  ic->generated = 1;
+}
 
-           emitcode("or", "a,a");
-           offset = size;
-           while (size--) {
-               l = aopGet(AOP(result), --offset, FALSE);
-               emitcode("rr","%s", l);         
-           }
-           if (shCount>1) {
-               emitcode("", LABEL_STR ":",tlbl1->key+100);
-               emitcode("dec", "a");
-               emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
-           }
-    }
+static const char *
+_getPairIdName (PAIR_ID id)
+{
+  return _pairs[id].name;
 }
 
-/*-----------------------------------------------------------------*/
-/* shiftL2Left2Result - shift left two bytes from left to result   */
-/*-----------------------------------------------------------------*/
-static void shiftL2Left2Result (operand *left, int offl,
-                                operand *result, int offr, int shCount)
+/** Generic compare for > or <
+ */
+static void
+genCmp (operand * left, operand * right,
+       operand * result, iCode * ifx, int sign)
 {
-    if(sameRegs(AOP(result), AOP(left)) &&
-       ((offl + MSB16) == offr)){
-       assert(0);
-    } else {
-       /* Copy left into result */
-       movLeft2Result(left, offl, result, offr, 0);
-       movLeft2Result(left, offl+1, result, offr+1, 0);
+  int size, offset = 0;
+  unsigned long lit = 0L;
+  bool swap_sense = FALSE;
+
+  /* if left & right are bit variables */
+  if (AOP_TYPE (left) == AOP_CRY &&
+      AOP_TYPE (right) == AOP_CRY)
+    {
+      /* Cant happen on the Z80 */
+      wassert (0);
     }
-    /* PENDING: for now just see if it'll work. */
-    /*if (AOP(result)->type == AOP_REG) { */
+  else
     {
-       int size = 2;
-       int offset = 0;
-       symbol *tlbl , *tlbl1;
-       char *l;
-
-       /* Left is already in result - so now do the shift */
-       if (shCount>1) {
-           emitcode("ld","a,#%u+1", shCount);
-           tlbl = newiTempLabel(NULL);
-           tlbl1 = newiTempLabel(NULL);
-           emitcode("jp", LABEL_STR ,tlbl1->key+100); 
-           emitcode("", LABEL_STR ":",tlbl->key+100);    
-       }
-
-       emitcode("or", "a,a");
-       while (size--) {
-           l = aopGet(AOP(result),offset++,FALSE);
-           emitcode("rl","%s", l);         
+      /* subtract right from left if at the
+         end the carry flag is set then we know that
+         left is greater than right */
+      size = max (AOP_SIZE (left), AOP_SIZE (right));
+
+      /* if unsigned char cmp with lit, just compare */
+      if ((size == 1) &&
+         (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
+       {
+         emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
+         if (sign)
+           {
+             emit2 ("xor a,!immedbyte", 0x80);
+             emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
+           }
+         else
+           emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
        }
-       if (shCount>1) {
-           emitcode("", LABEL_STR ":",tlbl1->key+100);
-           emitcode("dec", "a");
-           emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
+      else
+       {
+         /* Special cases:
+            On the GB:
+            If the left or the right is a lit:
+            Load -lit into HL, add to right via, check sense.
+          */
+         if (IS_GB && size == 2 && (AOP_TYPE (right) == AOP_LIT || AOP_TYPE (left) == AOP_LIT))
+           {
+             PAIR_ID id = PAIR_DE;
+             asmop *lit = AOP (right);
+             asmop *op = AOP (left);
+             swap_sense = TRUE;
+
+             if (AOP_TYPE (left) == AOP_LIT)
+               {
+                 swap_sense = FALSE;
+                 lit = AOP (left);
+                 op = AOP (right);
+               }
+             if (sign)
+               {
+                 emit2 ("ld e,%s", aopGet (op, 0, 0));
+                 emit2 ("ld a,%s", aopGet (op, 1, 0));
+                 emit2 ("xor a,!immedbyte", 0x80);
+                 emit2 ("ld d,a");
+               }
+             else
+               {
+                 id = getPairId (op);
+                 if (id == PAIR_INVALID)
+                   {
+                     fetchPair (PAIR_DE, op);
+                     id = PAIR_DE;
+                   }
+               }
+             spillPair (PAIR_HL);
+             emit2 ("ld hl,%s", fetchLitSpecial (lit, TRUE, sign));
+             emit2 ("add hl,%s", _getPairIdName (id));
+             goto release;
+           }
+         if (AOP_TYPE (right) == AOP_LIT)
+           {
+             lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+             /* optimize if(x < 0) or if(x >= 0) */
+             if (lit == 0L)
+               {
+                 if (!sign)
+                   {
+                     /* No sign so it's always false */
+                     _clearCarry();
+                   }
+                 else
+                   {
+                     /* Just load in the top most bit */
+                     _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
+                     if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
+                       {
+                         genIfxJump (ifx, "7");
+                         return;
+                       }
+                     else
+                       emit2 ("rlc a");
+                   }
+                 goto release;
+               }
+           }
+         if (sign)
+           {
+             /* First setup h and l contaning the top most bytes XORed */
+             bool fDidXor = FALSE;
+             if (AOP_TYPE (left) == AOP_LIT)
+               {
+                 unsigned long lit = (unsigned long)
+                 floatFromVal (AOP (left)->aopu.aop_lit);
+                 emit2 ("ld %s,!immedbyte", _fTmp[0],
+                        0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
+               }
+             else
+               {
+                 emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE));
+                 emit2 ("xor a,!immedbyte", 0x80);
+                 emit2 ("ld %s,a", _fTmp[0]);
+                 fDidXor = TRUE;
+               }
+             if (AOP_TYPE (right) == AOP_LIT)
+               {
+                 unsigned long lit = (unsigned long)
+                 floatFromVal (AOP (right)->aopu.aop_lit);
+                 emit2 ("ld %s,!immedbyte", _fTmp[1],
+                        0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
+               }
+             else
+               {
+                 emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE));
+                 emit2 ("xor a,!immedbyte", 0x80);
+                 emit2 ("ld %s,a", _fTmp[1]);
+                 fDidXor = TRUE;
+               }
+             if (!fDidXor)
+               _clearCarry();
+           }
+         else
+           {
+             _clearCarry();
+           }
+         while (size--)
+           {
+             /* Do a long subtract */
+             if (!sign || size)
+               {
+                 _moveA (aopGet (AOP (left), offset, FALSE));
+               }
+             if (sign && size == 0)
+               {
+                 emit2 ("ld a,%s", _fTmp[0]);
+                 emit2 ("sbc a,%s", _fTmp[1]);
+               }
+             else
+               {
+                 /* Subtract through, propagating the carry */
+                 emit2 ("sbc a,%s", aopGet (AOP (right), offset++, FALSE));
+               }
+           }
        }
     }
-}
 
-/*-----------------------------------------------------------------*/
-/* AccRol - rotate left accumulator by known count                 */
-/*-----------------------------------------------------------------*/
-static void AccRol (int shCount)
-{
-    shCount &= 0x0007;              // shCount : 0..7
-    switch(shCount){
-        case 0 :
-            break;
-        case 1 :
-            emitcode("rl","a");
-            break;
-        case 2 :
-            emitcode("rl","a");
-            emitcode("rl","a");
-            break;
-        case 3 :
-            emitcode("rl","a");
-            emitcode("rl","a");
-            emitcode("rl","a");
-            break;
-        case 4 :
-            emitcode("rl","a");
-            emitcode("rl","a");
-            emitcode("rl","a");
-            emitcode("rl","a");
-            break;
-        case 5 :
-            emitcode("rr","a");
-            emitcode("rr","a");
-            emitcode("rr","a");
-            break;
-        case 6 :
-            emitcode("rr","a");
-            emitcode("rr","a");
-            break;
-        case 7 :
-            emitcode("rr","a");
-            break;
+release:
+  if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
+    {
+      outBitCLong (result, swap_sense);
+    }
+  else
+    {
+      /* if the result is used in the next
+         ifx conditional branch then generate
+         code a little differently */
+      if (ifx)
+       genIfxJump (ifx, swap_sense ? "nc" : "c");
+      else
+       outBitCLong (result, swap_sense);
+      /* leave the result in acc */
     }
 }
 
 /*-----------------------------------------------------------------*/
-/* AccLsh - left shift accumulator by known count                  */
+/* genCmpGt :- greater than comparison                             */
 /*-----------------------------------------------------------------*/
-static void AccLsh (int shCount)
-{
-    if(shCount != 0){
-        if(shCount == 1)
-            emitcode("add","a,a");
-        else 
-           if(shCount == 2) {
-            emitcode("add","a,a");
-            emitcode("add","a,a");
-        } else {
-            /* rotate left accumulator */
-            AccRol(shCount);
-            /* and kill the lower order bits */
-            emitcode("and","a,#0x%02x", SLMask[shCount]);
-        }
-    }
+static void
+genCmpGt (iCode * ic, iCode * ifx)
+{
+  operand *left, *right, *result;
+  sym_link *letype, *retype;
+  int sign;
+
+  left = IC_LEFT (ic);
+  right = IC_RIGHT (ic);
+  result = IC_RESULT (ic);
+
+  letype = getSpec (operandType (left));
+  retype = getSpec (operandType (right));
+  sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
+  /* assign the amsops */
+  aopOp (left, ic, FALSE, FALSE);
+  aopOp (right, ic, FALSE, FALSE);
+  aopOp (result, ic, TRUE, FALSE);
+
+  genCmp (right, left, result, ifx, sign);
+
+  freeAsmop (left, NULL, ic);
+  freeAsmop (right, NULL, ic);
+  freeAsmop (result, NULL, ic);
 }
 
 /*-----------------------------------------------------------------*/
-/* shiftL1Left2Result - shift left one byte from left to result    */
+/* genCmpLt - less than comparisons                                */
 /*-----------------------------------------------------------------*/
-static void shiftL1Left2Result (operand *left, int offl,
-                                operand *result, int offr, int shCount)
+static void
+genCmpLt (iCode * ic, iCode * ifx)
 {
-    char *l;
-    l = aopGet(AOP(left),offl,FALSE);
-    MOVA(l);
-    /* shift left accumulator */
-    AccLsh(shCount);
-    aopPut(AOP(result),"a",offr);
-}
+  operand *left, *right, *result;
+  sym_link *letype, *retype;
+  int sign;
+
+  left = IC_LEFT (ic);
+  right = IC_RIGHT (ic);
+  result = IC_RESULT (ic);
 
+  letype = getSpec (operandType (left));
+  retype = getSpec (operandType (right));
+  sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
+
+  /* assign the amsops */
+  aopOp (left, ic, FALSE, FALSE);
+  aopOp (right, ic, FALSE, FALSE);
+  aopOp (result, ic, TRUE, FALSE);
+
+  genCmp (left, right, result, ifx, sign);
+
+  freeAsmop (left, NULL, ic);
+  freeAsmop (right, NULL, ic);
+  freeAsmop (result, NULL, ic);
+}
 
 /*-----------------------------------------------------------------*/
-/* genlshTwo - left shift two bytes by known amount != 0           */
+/* gencjneshort - compare and jump if not equal                    */
 /*-----------------------------------------------------------------*/
-static void genlshTwo (operand *result,operand *left, int shCount)
+static void
+gencjneshort (operand * left, operand * right, symbol * lbl)
 {
-    int size = AOP_SIZE(result);
+  int size = max (AOP_SIZE (left), AOP_SIZE (right));
+  int offset = 0;
+  unsigned long lit = 0L;
 
-    assert(size==2);
+  /* Swap the left and right if it makes the computation easier */
+  if (AOP_TYPE (left) == AOP_LIT)
+    {
+      operand *t = right;
+      right = left;
+      left = t;
+    }
 
-    /* if shCount >= 8 */
-    if (shCount >= 8) {
-        shCount -= 8 ;
+  if (AOP_TYPE (right) == AOP_LIT)
+    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
 
-        if (size > 1){
-            if (shCount) {
-                movLeft2Result(left, LSB, result, MSB16, 0);
-               aopPut(AOP(result),zero, 0);   
-               shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
+  /* if the right side is a literal then anything goes */
+  if (AOP_TYPE (right) == AOP_LIT &&
+      AOP_TYPE (left) != AOP_DIR)
+    {
+      if (lit == 0)
+       {
+         emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
+         if (size > 1)
+           {
+             size--;
+             offset++;
+             while (size--)
+               {
+                 emit2 ("or a,%s", aopGet (AOP (left), offset, FALSE));
+               }
            }
-            else {
-                movLeft2Result(left, LSB, result, MSB16, 0);
-               aopPut(AOP(result),zero, 0);   
+         else
+           {
+             emit2 ("or a,a");
            }
-        }
-        aopPut(AOP(result),zero,LSB);   
+         emit2 ("jp nz,!tlabel", lbl->key + 100);
+       }
+      else
+       {
+         while (size--)
+           {
+             emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
+             if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
+               emit2 ("or a,a");
+             else
+               emit2 ("cp a,%s", aopGet (AOP (right), offset, FALSE));
+             emit2 ("jp nz,!tlabel", lbl->key + 100);
+             offset++;
+           }
+       }
     }
-    /*  1 <= shCount <= 7 */
-    else {  
-        if(size == 1) {
-           assert(0);
+  /* if the right side is in a register or in direct space or
+     if the left is a pointer register & right is not */
+  else if (AOP_TYPE (right) == AOP_REG ||
+          AOP_TYPE (right) == AOP_DIR ||
+          (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
+    {
+      while (size--)
+       {
+         _moveA (aopGet (AOP (left), offset, FALSE));
+         if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
+             ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
+           /* PENDING */
+           emit2 ("jp nz,!tlabel", lbl->key + 100);
+         else
+           {
+             emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
+             emit2 ("jp nz,!tlabel", lbl->key + 100);
+           }
+         offset++;
        }
-        else {
-            shiftL2Left2Result(left, LSB, result, LSB, shCount);
+    }
+  else
+    {
+      /* right is a pointer reg need both a & b */
+      /* PENDING: is this required? */
+      while (size--)
+       {
+         _moveA (aopGet (AOP (right), offset, FALSE));
+         emit2 ("cp %s", aopGet (AOP (left), offset, FALSE));
+         emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
+         offset++;
        }
     }
 }
 
 /*-----------------------------------------------------------------*/
-/* genlshOne - left shift a one byte quantity by known count       */
+/* gencjne - compare and jump if not equal                         */
 /*-----------------------------------------------------------------*/
-static void genlshOne (operand *result, operand *left, int shCount)
-{       
-    shiftL1Left2Result(left, LSB, result, LSB, shCount);
+static void
+gencjne (operand * left, operand * right, symbol * lbl)
+{
+  symbol *tlbl = newiTempLabel (NULL);
+
+  gencjneshort (left, right, lbl);
+
+  /* PENDING: ?? */
+  emit2 ("ld a,!one");
+  emit2 ("!shortjp !tlabel", tlbl->key + 100);
+  emitLabel (lbl->key + 100);
+  emit2 ("xor a,a");
+  emitLabel (tlbl->key + 100);
 }
 
 /*-----------------------------------------------------------------*/
-/* genLeftShiftLiteral - left shifting by known count              */
+/* genCmpEq - generates code for equal to                          */
 /*-----------------------------------------------------------------*/
-static void genLeftShiftLiteral (operand *left,
-                                 operand *right,
-                                 operand *result,
-                                 iCode *ic)
-{    
-    int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
-    int size;
-
-    freeAsmop(right,NULL,ic);
+static void
+genCmpEq (iCode * ic, iCode * ifx)
+{
+  operand *left, *right, *result;
 
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,FALSE);
+  aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
+  aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
+  aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
 
-    size = getSize(operandType(result));
+  emitDebug ("; genCmpEq: left %u, right %u, result %u\n", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
 
-#if VIEW_SIZE
-    emitcode("; shift left ","result %d, left %d",size,
-             AOP_SIZE(left));
-#endif
+  /* Swap operands if it makes the operation easier. ie if:
+     1.  Left is a literal.
+   */
+  if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
+    {
+      operand *t = IC_RIGHT (ic);
+      IC_RIGHT (ic) = IC_LEFT (ic);
+      IC_LEFT (ic) = t;
+    }
 
-    /* I suppose that the left size >= result size */
-    if (shCount == 0) {
-       assert(0);
+  if (ifx && !AOP_SIZE (result))
+    {
+      symbol *tlbl;
+      /* if they are both bit variables */
+      if (AOP_TYPE (left) == AOP_CRY &&
+         ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
+       {
+         wassert (0);
+       }
+      else
+       {
+         tlbl = newiTempLabel (NULL);
+         gencjneshort (left, right, tlbl);
+         if (IC_TRUE (ifx))
+           {
+             emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
+             emitLabel (tlbl->key + 100);
+           }
+         else
+           {
+             /* PENDING: do this better */
+             symbol *lbl = newiTempLabel (NULL);
+             emit2 ("!shortjp !tlabel", lbl->key + 100);
+             emitLabel (tlbl->key + 100);
+             emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
+             emitLabel (lbl->key + 100);
+           }
+       }
+      /* mark the icode as generated */
+      ifx->generated = 1;
+      goto release;
     }
 
-    else if(shCount >= (size * 8))
-        while(size--)
-            aopPut(AOP(result),zero,size);
-    else{
-        switch (size) {
-       case 1:
-           genlshOne (result,left,shCount);
-           break;
-       case 2:
-           genlshTwo (result,left,shCount);
-           break;
-       case 4:
-           assert(0);
-           break;
-       default:
-           assert(0);
-        }
+  /* if they are both bit variables */
+  if (AOP_TYPE (left) == AOP_CRY &&
+      ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
+    {
+      wassert (0);
+    }
+  else
+    {
+      gencjne (left, right, newiTempLabel (NULL));
+      if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
+       {
+         wassert (0);
+       }
+      if (ifx)
+       {
+         genIfxJump (ifx, "a");
+         goto release;
+       }
+      /* if the result is used in an arithmetic operation
+         then put the result in place */
+      if (AOP_TYPE (result) != AOP_CRY)
+       {
+         outAcc (result);
+       }
+      /* leave the result in acc */
     }
-    freeAsmop(left,NULL,ic);
-    freeAsmop(result,NULL,ic);
+
+release:
+  freeAsmop (left, NULL, ic);
+  freeAsmop (right, NULL, ic);
+  freeAsmop (result, NULL, ic);
 }
 
 /*-----------------------------------------------------------------*/
-/* genLeftShift - generates code for left shifting                 */
+/* ifxForOp - returns the icode containing the ifx for operand     */
 /*-----------------------------------------------------------------*/
-static void genLeftShift (iCode *ic)
+static iCode *
+ifxForOp (operand * op, iCode * ic)
 {
-    int size, offset;
-    char *l;
-    symbol *tlbl , *tlbl1;
-    operand *left,*right, *result;
-
-    right = IC_RIGHT(ic);
-    left  = IC_LEFT(ic);
-    result = IC_RESULT(ic);
+  /* if true symbol then needs to be assigned */
+  if (IS_TRUE_SYMOP (op))
+    return NULL;
 
-    aopOp(right,ic,FALSE);
+  /* if this has register type condition and
+     the next instruction is ifx with the same operand
+     and live to of the operand is upto the ifx only then */
+  if (ic->next &&
+      ic->next->op == IFX &&
+      IC_COND (ic->next)->key == op->key &&
+      OP_SYMBOL (op)->liveTo <= ic->next->seq)
+    return ic->next;
 
-    /* if the shift count is known then do it 
-    as efficiently as possible */
-    if (AOP_TYPE(right) == AOP_LIT) {
-        genLeftShiftLiteral (left,right,result,ic);
-        return ;
-    }
+  return NULL;
+}
 
-    /* shift count is unknown then we have to form a loop get the loop
-       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");
-    freeAsmop (right,NULL,ic);
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,FALSE);
-
-    /* now move the left to the result if they are not the
-       same */
-#if 1
-    if (!sameRegs(AOP(left),AOP(result))) {
-
-        size = AOP_SIZE(result);
-        offset = 0;
-        while (size--) {
-            l = aopGet(AOP(left),offset,FALSE);
-           aopPut(AOP(result),l,offset);
-            offset++;
-        }
-    }
-#else
-    size = AOP_SIZE(result);
-    offset = 0;
-    while (size--) {
-       l = aopGet(AOP(left),offset,FALSE);
-       aopPut(AOP(result),l,offset);
-       offset++;
+/*-----------------------------------------------------------------*/
+/* genAndOp - for && operation                                     */
+/*-----------------------------------------------------------------*/
+static void
+genAndOp (iCode * ic)
+{
+  operand *left, *right, *result;
+  symbol *tlbl;
+
+  /* note here that && operations that are in an if statement are
+     taken away by backPatchLabels only those used in arthmetic
+     operations remain */
+  aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
+  aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
+  aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
+
+  /* if both are bit variables */
+  if (AOP_TYPE (left) == AOP_CRY &&
+      AOP_TYPE (right) == AOP_CRY)
+    {
+      wassert (0);
     }
-#endif
-
-
-    tlbl = newiTempLabel(NULL);
-    size = AOP_SIZE(result);
-    offset = 0 ;   
-    tlbl1 = newiTempLabel(NULL);
-
-    emitcode("jp", LABEL_STR ,tlbl1->key+100); 
-    emitcode("", LABEL_STR ":",tlbl->key+100);    
-    l = aopGet(AOP(result),offset,FALSE);
-    emitcode("or", "a,a");
-    while (size--) {
-        l = aopGet(AOP(result),offset++,FALSE);
-        emitcode("rl","%s", l);         
+  else
+    {
+      tlbl = newiTempLabel (NULL);
+      _toBoolean (left);
+      emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
+      _toBoolean (right);
+      emitLabel (tlbl->key + 100);
+      outBitAcc (result);
     }
-    emitcode("", LABEL_STR ":",tlbl1->key+100);
-    emitcode("dec", "a");
-    emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
 
-    freeAsmop(left,NULL,ic);
-    freeAsmop(result,NULL,ic);
+  freeAsmop (left, NULL, ic);
+  freeAsmop (right, NULL, ic);
+  freeAsmop (result, NULL, ic);
 }
 
-/* genlshTwo - left shift two bytes by known amount != 0           */
 /*-----------------------------------------------------------------*/
-static void genrshOne (operand *result,operand *left, int shCount)
+/* genOrOp - for || operation                                      */
+/*-----------------------------------------------------------------*/
+static void
+genOrOp (iCode * ic)
 {
-    /* Errk */
-    int size = AOP_SIZE(result);
-    char *l;
-
-    assert(size==1);
-    assert(shCount<8);
-
-    l = aopGet(AOP(left),0,FALSE);
-    if (AOP(result)->type == AOP_REG) {
-       aopPut(AOP(result), l, 0);
-       l = aopGet(AOP(result), 0, FALSE);
-       while (shCount--) 
-           emitcode("srl", "%s", l);
+  operand *left, *right, *result;
+  symbol *tlbl;
+
+  /* note here that || operations that are in an
+     if statement are taken away by backPatchLabels
+     only those used in arthmetic operations remain */
+  aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
+  aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
+  aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
+
+  /* if both are bit variables */
+  if (AOP_TYPE (left) == AOP_CRY &&
+      AOP_TYPE (right) == AOP_CRY)
+    {
+      wassert (0);
     }
-    else {
-       MOVA(l);
-       while (shCount--) {
-           emitcode("srl", "a");
-       }
-       aopPut(AOP(result),"a",0);
+  else
+    {
+      tlbl = newiTempLabel (NULL);
+      _toBoolean (left);
+      emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+      _toBoolean (right);
+      emitLabel (tlbl->key + 100);
+      outBitAcc (result);
     }
+
+  freeAsmop (left, NULL, ic);
+  freeAsmop (right, NULL, ic);
+  freeAsmop (result, NULL, ic);
 }
 
 /*-----------------------------------------------------------------*/
-/* AccRsh - right shift accumulator by known count                 */
+/* isLiteralBit - test if lit == 2^n                               */
 /*-----------------------------------------------------------------*/
-static void AccRsh (int shCount)
-{
-    if(shCount != 0){
-        if(shCount == 1){
-            CLRC;
-            emitcode("rr","a");
-        } else {
-            /* rotate right accumulator */
-            AccRol(8 - shCount);
-            /* and kill the higher order bits */
-            emitcode("and","a,#0x%02x", SRMask[shCount]);
-        }
-    }
+int
+isLiteralBit (unsigned long lit)
+{
+  unsigned long pw[32] =
+  {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
+   0x100L, 0x200L, 0x400L, 0x800L,
+   0x1000L, 0x2000L, 0x4000L, 0x8000L,
+   0x10000L, 0x20000L, 0x40000L, 0x80000L,
+   0x100000L, 0x200000L, 0x400000L, 0x800000L,
+   0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
+   0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
+  int idx;
+
+  for (idx = 0; idx < 32; idx++)
+    if (lit == pw[idx])
+      return idx + 1;
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
-/* shiftR1Left2Result - shift right one byte from left to result   */
+/* jmpTrueOrFalse -                                                */
 /*-----------------------------------------------------------------*/
-static void shiftR1Left2Result (operand *left, int offl,
-                                operand *result, int offr,
-                                int shCount, int sign)
+static void
+jmpTrueOrFalse (iCode * ic, symbol * tlbl)
 {
-    MOVA(aopGet(AOP(left),offl,FALSE));
-    if (sign) {
-       assert(0);
+  // ugly but optimized by peephole
+  if (IC_TRUE (ic))
+    {
+      symbol *nlbl = newiTempLabel (NULL);
+      emit2 ("jp !tlabel", nlbl->key + 100);
+      emitLabel (tlbl->key + 100);
+      emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
+      emitLabel (nlbl->key + 100);
     }
-    else {
-        AccRsh(shCount);
+  else
+    {
+      emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
+      emitLabel (tlbl->key + 100);
     }
-    aopPut(AOP(result),"a",offr);
+  ic->generated = 1;
 }
 
 /*-----------------------------------------------------------------*/
-/* genrshTwo - right shift two bytes by known amount != 0          */
+/* genAnd  - code for and                                          */
 /*-----------------------------------------------------------------*/
-static void genrshTwo (operand *result,operand *left,
-                       int shCount, int sign)
+static void
+genAnd (iCode * ic, iCode * ifx)
 {
-    /* if shCount >= 8 */
-    if (shCount >= 8) {
-        shCount -= 8 ;
-        if (shCount) {
-           assert(0);
-            shiftR1Left2Result(left, MSB16, result, LSB,
-                               shCount, sign);
-       }
-        else {
-            movLeft2Result(left, MSB16, result, LSB, sign);
-           aopPut(AOP(result),zero,1);
-       }
+  operand *left, *right, *result;
+  int size, offset = 0;
+  unsigned long lit = 0L;
+  int bytelit = 0;
+
+  aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
+  aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
+  aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
+
+#ifdef DEBUG_TYPE
+  emitDebug ("; Type res[%d] = l[%d]&r[%d]",
+           AOP_TYPE (result),
+           AOP_TYPE (left), AOP_TYPE (right));
+  emitDebug ("; Size res[%d] = l[%d]&r[%d]",
+           AOP_SIZE (result),
+           AOP_SIZE (left), AOP_SIZE (right));
+#endif
+
+  /* if left is a literal & right is not then exchange them */
+  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
+      AOP_NEEDSACC (left))
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
     }
-    /*  1 <= shCount <= 7 */
-    else {
-        shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
+
+  /* if result = right then exchange them */
+  if (sameRegs (AOP (result), AOP (right)))
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
     }
-}
 
-/*-----------------------------------------------------------------*/
-/* genRightShiftLiteral - left shifting by known count              */
-/*-----------------------------------------------------------------*/
-static void genRightShiftLiteral (operand *left,
-                                 operand *right,
-                                 operand *result,
-                                 iCode *ic)
-{    
-    int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
-    int size;
+  /* if right is bit then exchange them */
+  if (AOP_TYPE (right) == AOP_CRY &&
+      AOP_TYPE (left) != AOP_CRY)
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
+    }
+  if (AOP_TYPE (right) == AOP_LIT)
+    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
 
-    freeAsmop(right,NULL,ic);
+  size = AOP_SIZE (result);
 
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,FALSE);
+  if (AOP_TYPE (left) == AOP_CRY)
+    {
+      wassert (0);
+      goto release;
+    }
 
-    size = getSize(operandType(result));
+  // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
+  // bit = val & 0xZZ     - size = 1, ifx = FALSE -
+  if ((AOP_TYPE (right) == AOP_LIT) &&
+      (AOP_TYPE (result) == AOP_CRY) &&
+      (AOP_TYPE (left) != AOP_CRY))
+    {
+      int posbit = isLiteralBit (lit);
+      /* left &  2^n */
+      if (posbit)
+       {
+         posbit--;
+         _moveA (aopGet (AOP (left), posbit >> 3, FALSE));
+         // bit = left & 2^n
+         if (size)
+           {
+             wassert (0);
+             emit2 ("mov c,acc.%d", posbit & 0x07);
+           }
+         // if(left &  2^n)
+         else
+           {
+             if (ifx)
+               {
+                 sprintf (buffer, "%d", posbit & 0x07);
+                 genIfxJump (ifx, buffer);
+               }
+             else
+               {
+                 wassert (0);
+               }
+             goto release;
+           }
+       }
+      else
+       {
+         symbol *tlbl = newiTempLabel (NULL);
+         int sizel = AOP_SIZE (left);
+         if (size)
+           {
+             wassert (0);
+             emit2 ("setb c");
+           }
+         while (sizel--)
+           {
+             if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
+               {
+                 _moveA (aopGet (AOP (left), offset, FALSE));
+                 // byte ==  2^n ?
+                 if ((posbit = isLiteralBit (bytelit)) != 0)
+                   {
+                     wassert (0);
+                     emit2 ("jb acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
+                   }
+                 else
+                   {
+                     if (bytelit != 0x0FFL)
+                       emit2 ("and a,%s",
+                                 aopGet (AOP (right), offset, FALSE));
+                     else
+                       /* For the flags */
+                       emit2 ("or a,a");
+                     emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+                   }
+               }
+             offset++;
+           }
+         // bit = left & literal
+         if (size)
+           {
+             emit2 ("clr c");
+             emit2 ("!tlabeldef", tlbl->key + 100);
+           }
+         // if(left & literal)
+         else
+           {
+             if (ifx)
+               jmpTrueOrFalse (ifx, tlbl);
+             goto release;
+           }
+       }
+      outBitC (result);
+      goto release;
+    }
 
-    emitcode("; shift right ","result %d, left %d",size,
-             AOP_SIZE(left));
+  /* if left is same as result */
+  if (sameRegs (AOP (result), AOP (left)))
+    {
+      for (; size--; offset++)
+       {
+         if (AOP_TYPE (right) == AOP_LIT)
+           {
+             if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
+               continue;
+             else
+               {
+                 if (bytelit == 0)
+                   aopPut (AOP (result), "!zero", offset);
+                 else
+                   {
+                     _moveA (aopGet (AOP (left), offset, FALSE));
+                     emit2 ("and a,%s",
+                               aopGet (AOP (right), offset, FALSE));
+                     aopPut (AOP (left), "a", offset);
+                   }
+               }
 
-    /* I suppose that the left size >= result size */
-    if (shCount == 0) {
-       assert(0);
+           }
+         else
+           {
+             if (AOP_TYPE (left) == AOP_ACC)
+               {
+                 wassert (0);
+               }
+             else
+               {
+                 _moveA (aopGet (AOP (left), offset, FALSE));
+                 emit2 ("and a,%s",
+                           aopGet (AOP (right), offset, FALSE));
+                 aopPut (AOP (left), "a", offset);
+               }
+           }
+       }
     }
+  else
+    {
+      // left & result in different registers
+      if (AOP_TYPE (result) == AOP_CRY)
+       {
+         wassert (0);
+       }
+      else
+       {
+         for (; (size--); offset++)
+           {
+             // normal case
+             // result = left & right
+             if (AOP_TYPE (right) == AOP_LIT)
+               {
+                 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
+                   {
+                     aopPut (AOP (result),
+                             aopGet (AOP (left), offset, FALSE),
+                             offset);
+                     continue;
+                   }
+                 else if (bytelit == 0)
+                   {
+                     aopPut (AOP (result), "!zero", offset);
+                     continue;
+                   }
+               }
+             // faster than result <- left, anl result,right
+             // and better if result is SFR
+             if (AOP_TYPE (left) == AOP_ACC)
+               emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
+             else
+               {
+                 _moveA (aopGet (AOP (left), offset, FALSE));
+                 emit2 ("and a,%s",
+                           aopGet (AOP (right), offset, FALSE));
+               }
+             aopPut (AOP (result), "a", offset);
+           }
+       }
 
-    else if(shCount >= (size * 8))
-        while(size--)
-            aopPut(AOP(result),zero,size);
-    else{
-        switch (size) {
-       case 1:
-           genrshOne(result, left, shCount);
-           break;
-       case 2:
-           /* PENDING: sign support */
-           genrshTwo(result, left, shCount, FALSE);
-           break;
-       case 4:
-           assert(0);
-           break;
-       default:
-           assert(0);
-        }
     }
-    freeAsmop(left,NULL,ic);
-    freeAsmop(result,NULL,ic);
+
+release:
+  freeAsmop (left, NULL, ic);
+  freeAsmop (right, NULL, ic);
+  freeAsmop (result, NULL, ic);
 }
 
 /*-----------------------------------------------------------------*/
-/* genRightShift - generate code for right shifting                */
+/* genOr  - code for or                                            */
 /*-----------------------------------------------------------------*/
-static void genRightShift (iCode *ic)
+static void
+genOr (iCode * ic, iCode * ifx)
 {
-    operand *left,*right, *result;
+  operand *left, *right, *result;
+  int size, offset = 0;
+  unsigned long lit = 0L;
 
-    right = IC_RIGHT(ic);
-    left  = IC_LEFT(ic);
-    result = IC_RESULT(ic);
+  aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
+  aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
+  aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
 
-    aopOp(right,ic,FALSE);
+#if 1
+  emitDebug ("; Type res[%d] = l[%d]&r[%d]",
+           AOP_TYPE (result),
+           AOP_TYPE (left), AOP_TYPE (right));
+  emitDebug ("; Size res[%d] = l[%d]&r[%d]",
+           AOP_SIZE (result),
+           AOP_SIZE (left), AOP_SIZE (right));
+#endif
 
-    /* if the shift count is known then do it 
-    as efficiently as possible */
-    if (AOP_TYPE(right) == AOP_LIT) {
-        genRightShiftLiteral (left,right,result,ic);
-        return ;
+  /* if left is a literal & right is not then exchange them */
+  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
+      AOP_NEEDSACC (left))
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
     }
-    else {
-       assert(0);
+
+  /* if result = right then exchange them */
+  if (sameRegs (AOP (result), AOP (right)))
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
+    }
+
+  /* if right is bit then exchange them */
+  if (AOP_TYPE (right) == AOP_CRY &&
+      AOP_TYPE (left) != AOP_CRY)
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
+    }
+  if (AOP_TYPE (right) == AOP_LIT)
+    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+
+  size = AOP_SIZE (result);
+
+  if (AOP_TYPE (left) == AOP_CRY)
+    {
+      wassert (0);
+      goto release;
+    }
+
+  if ((AOP_TYPE (right) == AOP_LIT) &&
+      (AOP_TYPE (result) == AOP_CRY) &&
+      (AOP_TYPE (left) != AOP_CRY))
+    {
+      wassert (0);
+      goto release;
+    }
+
+  /* if left is same as result */
+  if (sameRegs (AOP (result), AOP (left)))
+    {
+      for (; size--; offset++)
+       {
+         if (AOP_TYPE (right) == AOP_LIT)
+           {
+             if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
+               continue;
+             else
+               {
+                 _moveA (aopGet (AOP (left), offset, FALSE));
+                 emit2 ("or a,%s",
+                           aopGet (AOP (right), offset, FALSE));
+                 aopPut (AOP (result), "a", offset);
+               }
+           }
+         else
+           {
+             if (AOP_TYPE (left) == AOP_ACC)
+               emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
+             else
+               {
+                 _moveA (aopGet (AOP (left), offset, FALSE));
+                 emit2 ("or a,%s",
+                           aopGet (AOP (right), offset, FALSE));
+                 aopPut (AOP (result), "a", offset);
+               }
+           }
+       }
+    }
+  else
+    {
+      // left & result in different registers
+      if (AOP_TYPE (result) == AOP_CRY)
+       {
+         wassert (0);
+       }
+      else
+       for (; (size--); offset++)
+         {
+           // normal case
+           // result = left & right
+           if (AOP_TYPE (right) == AOP_LIT)
+             {
+               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
+                 {
+                   aopPut (AOP (result),
+                           aopGet (AOP (left), offset, FALSE),
+                           offset);
+                   continue;
+                 }
+             }
+           // faster than result <- left, anl result,right
+           // and better if result is SFR
+           if (AOP_TYPE (left) == AOP_ACC)
+             emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
+           else
+             {
+               _moveA (aopGet (AOP (left), offset, FALSE));
+               emit2 ("or a,%s",
+                         aopGet (AOP (right), offset, FALSE));
+             }
+           aopPut (AOP (result), "a", offset);
+           /* PENDING: something weird is going on here.  Add exception. */
+           if (AOP_TYPE (result) == AOP_ACC)
+             break;
+         }
     }
+
+release:
+  freeAsmop (left, NULL, ic);
+  freeAsmop (right, NULL, ic);
+  freeAsmop (result, NULL, ic);
 }
 
 /*-----------------------------------------------------------------*/
-/* genGenPointerGet - gget value from generic pointer space        */
+/* genXor - code for xclusive or                                   */
 /*-----------------------------------------------------------------*/
-static void genGenPointerGet (operand *left,
-                              operand *result, iCode *ic)
+static void
+genXor (iCode * ic, iCode * ifx)
 {
-    int size, offset ;
-    link *retype = getSpec(operandType(result));
+  operand *left, *right, *result;
+  int size, offset = 0;
+  unsigned long lit = 0L;
 
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,FALSE);
+  aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
+  aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
+  aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
 
-    if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
-       /* Just do it */
-       emitcode("ld", "a,(%s)", getPairName(AOP(left)));
-       aopPut(AOP(result),"a", 0);
-       freeAsmop(left,NULL,ic);
-       goto release;
+  /* if left is a literal & right is not then exchange them */
+  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
+      AOP_NEEDSACC (left))
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
     }
 
-    /* For now we always load into IY */
-    /* if this is remateriazable */
-    if (AOP_TYPE(left) == AOP_IMMD)
-       emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
-    else { /* we need to get it byte by byte */
-       fetchHL(AOP(left));
+  /* if result = right then exchange them */
+  if (sameRegs (AOP (result), AOP (right)))
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
+    }
+
+  /* if right is bit then exchange them */
+  if (AOP_TYPE (right) == AOP_CRY &&
+      AOP_TYPE (left) != AOP_CRY)
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
     }
-    /* so iy now contains the address */
-    freeAsmop(left,NULL,ic);
+  if (AOP_TYPE (right) == AOP_LIT)
+    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
 
-    /* if bit then unpack */
-    if (IS_BITVAR(retype)) {
-       assert(0);
+  size = AOP_SIZE (result);
+
+  if (AOP_TYPE (left) == AOP_CRY)
+    {
+      wassert (0);
+      goto release;
     }
-    else {
-        size = AOP_SIZE(result);
-        offset = 0 ;
 
-        while (size--) {
-           /* PENDING: make this better */
-           if (AOP(result)->type == AOP_REG) {
-               aopPut(AOP(result),"(hl)",offset++);
-           }
-           else {
-               emitcode("ld", "a,(hl)", offset);
-               aopPut(AOP(result),"a",offset++);
+  if ((AOP_TYPE (right) == AOP_LIT) &&
+      (AOP_TYPE (result) == AOP_CRY) &&
+      (AOP_TYPE (left) != AOP_CRY))
+    {
+      wassert (0);
+      goto release;
+    }
+
+  /* if left is same as result */
+  if (sameRegs (AOP (result), AOP (left)))
+    {
+      for (; size--; offset++)
+       {
+         if (AOP_TYPE (right) == AOP_LIT)
+           {
+             if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
+               continue;
+             else
+               {
+                 _moveA (aopGet (AOP (right), offset, FALSE));
+                 emit2 ("xor a,%s",
+                           aopGet (AOP (left), offset, FALSE));
+                 aopPut (AOP (result), "a", offset);
+               }
            }
-           if (size) {
-               emitcode("inc", "hl");
+         else
+           {
+             if (AOP_TYPE (left) == AOP_ACC)
+                {
+                  emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
+                }
+             else
+               {
+                 _moveA (aopGet (AOP (right), offset, FALSE));
+                 emit2 ("xor a,%s",
+                           aopGet (AOP (left), offset, FALSE));
+                 aopPut (AOP (result), "a", 0);
+               }
            }
-        }
+       }
+    }
+  else
+    {
+      // left & result in different registers
+      if (AOP_TYPE (result) == AOP_CRY)
+       {
+         wassert (0);
+       }
+      else
+       for (; (size--); offset++)
+         {
+           // normal case
+           // result = left & right
+           if (AOP_TYPE (right) == AOP_LIT)
+             {
+               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
+                 {
+                   aopPut (AOP (result),
+                           aopGet (AOP (left), offset, FALSE),
+                           offset);
+                   continue;
+                 }
+             }
+           // faster than result <- left, anl result,right
+           // and better if result is SFR
+           if (AOP_TYPE (left) == AOP_ACC) 
+              {
+                emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
+              }
+           else
+             {
+               _moveA (aopGet (AOP (right), offset, FALSE));
+               emit2 ("xor a,%s",
+                         aopGet (AOP (left), offset, FALSE));
+             }
+           aopPut (AOP (result), "a", offset);
+         }
     }
 
- release:
-    freeAsmop(result,NULL,ic);
+release:
+  freeAsmop (left, NULL, ic);
+  freeAsmop (right, NULL, ic);
+  freeAsmop (result, NULL, ic);
 }
 
 /*-----------------------------------------------------------------*/
-/* genPointerGet - generate code for pointer get                   */
+/* genInline - write the inline code out                           */
 /*-----------------------------------------------------------------*/
-static void genPointerGet (iCode *ic)
+static void
+genInline (iCode * ic)
 {
-    operand *left, *result ;
-    link *type, *etype;
+  char *buffer, *bp, *bp1;
+
+  _G.lines.isInline += (!options.asmpeep);
+
+  buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
+  strcpy (buffer, IC_INLINE (ic));
 
-    left = IC_LEFT(ic);
-    result = IC_RESULT(ic) ;
+  /* emit each line as a code */
+  while (*bp)
+    {
+      if (*bp == '\n')
+       {
+         *bp++ = '\0';
+         emit2 (bp1);
+         bp1 = bp;
+       }
+      else
+       {
+         if (*bp == ':')
+           {
+             bp++;
+             *bp = '\0';
+             bp++;
+             emit2 (bp1);
+             bp1 = bp;
+           }
+         else
+           bp++;
+       }
+    }
+  if (bp1 != bp)
+    emit2 (bp1);
+  _G.lines.isInline -= (!options.asmpeep);
 
-    /* depending on the type of pointer we need to
-    move it to the correct pointer register */
-    type = operandType(left);
-    etype = getSpec(type);
+}
 
-    genGenPointerGet (left,result,ic);
+/*-----------------------------------------------------------------*/
+/* genRRC - rotate right with carry                                */
+/*-----------------------------------------------------------------*/
+static void
+genRRC (iCode * ic)
+{
+  wassert (0);
 }
 
-bool isRegOrLit(asmop *aop)
+/*-----------------------------------------------------------------*/
+/* genRLC - generate code for rotate left with carry               */
+/*-----------------------------------------------------------------*/
+static void
+genRLC (iCode * ic)
 {
-    if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
-       return TRUE;
-    return FALSE;
+  wassert (0);
 }
 
 /*-----------------------------------------------------------------*/
-/* genGenPointerSet - stores the value into a pointer location        */
+/* genGetHbit - generates code get highest order bit               */
 /*-----------------------------------------------------------------*/
-static void genGenPointerSet (operand *right,
-                              operand *result, iCode *ic)
-{    
-    int size, offset ;
-    link *retype = getSpec(operandType(right));
-
-    aopOp(result,ic,FALSE);
-    aopOp(right,ic,FALSE);
-
-    /* Handle the exceptions first */
-    if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
-       /* Just do it */
-       char *l = aopGet(AOP(right), 0, FALSE);
-       MOVA(l);
-       emitcode("ld", "(%s),a", getPairName(AOP(result)));
-       freeAsmop(result,NULL,ic);
-       goto release;
+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);
     }
-       
-    /* if the operand is already in dptr 
-       then we do nothing else we move the value to dptr */
-    if (AOP_TYPE(result) != AOP_STR) {
-        /* if this is remateriazable */
-        if (AOP_TYPE(result) == AOP_IMMD) {
-           emitcode("", "; Error 2");
-           emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
-        }
-        else { /* we need to get it byte by byte */
-           /* PENDING: do this better */
-           fetchHL(AOP(result));
-        }
+  else
+    {
+      emit2 ("rlc a");
+      /* PENDING: For re-target. */
+      emit2 ("and a,#1");
+      outAcc (result);
     }
-    /* so hl know contains the address */
-    freeAsmop(result,NULL,ic);
 
-    /* if bit then unpack */
-    if (IS_BITVAR(retype)) {
-       assert(0);
-    }
-    else {
-        size = AOP_SIZE(right);
-        offset = 0 ;
 
-        while (size--) {
-            char *l = aopGet(AOP(right),offset,FALSE);
+  freeAsmop (left, NULL, ic);
+  freeAsmop (result, NULL, ic);
+}
 
-           if (isRegOrLit(AOP(right))) {
-               emitcode("ld", "(hl),%s", l);
-           }
-           else {
-               MOVA(l);
-               emitcode("ld", "(hl),a", offset);
-           }
-           if (size) {
-               emitcode("inc", "hl");
-           }
-           offset++;
+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++;
     }
-    release:
-    freeAsmop(right,NULL,ic);
 }
 
 /*-----------------------------------------------------------------*/
-/* genPointerSet - stores the value into a pointer location        */
+/* shiftR2Left2Result - shift right two bytes from left to result  */
 /*-----------------------------------------------------------------*/
-static void genPointerSet (iCode *ic)
-{    
-    operand *right, *result ;
-    link *type, *etype;
+static void
+shiftR2Left2Result (operand * left, int offl,
+                   operand * result, int offr,
+                   int shCount, int is_signed)
+{
+  int size = 2;
+  symbol *tlbl, *tlbl1;
 
-    right = IC_RIGHT(ic);
-    result = IC_RESULT(ic) ;
+  movLeft2Result (left, offl, result, offr, 0);
+  movLeft2Result (left, offl + 1, result, offr + 1, 0);
 
-    /* depending on the type of pointer we need to
-    move it to the correct pointer register */
-    type = operandType(result);
-    etype = getSpec(type);
-    
-    genGenPointerSet (right,result,ic);
+  /*  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)
+    {
+      while (shCount--)
+        {
+          emitRsh2 (AOP (result), size, is_signed);
+        }
+    }
+  else
+    {
+      emit2 ("ld a,!immedbyte+1", shCount);
+      emit2 ("!shortjp !tlabel", tlbl1->key + 100);
+      emitLabel (tlbl->key + 100);
+
+      emitRsh2 (AOP (result), size, is_signed);
+
+      emitLabel (tlbl1->key + 100);
+      emit2 ("dec a");
+      emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* genIfx - generate code for Ifx statement                        */
+/* shiftL2Left2Result - shift left two bytes from left to result   */
 /*-----------------------------------------------------------------*/
-static void genIfx (iCode *ic, iCode *popIc)
+static void
+shiftL2Left2Result (operand * left, int offl,
+                   operand * result, int offr, int shCount)
 {
-    operand *cond = IC_COND(ic);
-    int isbit =0;
+  if (sameRegs (AOP (result), AOP (left)) &&
+      ((offl + MSB16) == offr))
+    {
+      wassert (0);
+    }
+  else
+    {
+      /* Copy left into result */
+      movLeft2Result (left, offl, result, offr, 0);
+      movLeft2Result (left, offl + 1, result, offr + 1, 0);
+    }
+  /* PENDING: for now just see if it'll work. */
+  /*if (AOP(result)->type == AOP_REG) { */
+  {
+    int size = 2;
+    int offset = 0;
+    symbol *tlbl, *tlbl1;
+    const char *l;
 
-    aopOp(cond,ic,FALSE);
+    tlbl = newiTempLabel (NULL);
+    tlbl1 = newiTempLabel (NULL);
 
-    /* get the value into acc */
-    if (AOP_TYPE(cond) != AOP_CRY)
-        toBoolean(cond);
-    else
-        isbit = 1;
-    /* the result is now in the accumulator */
-    freeAsmop(cond,NULL,ic);
+    /* 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);
+      }
 
-    /* if there was something to be popped then do it */
-    if (popIc)
-        genIpop(popIc);
+    emit2 ("or a,a");
+    while (size--)
+      {
+       l = aopGet (AOP (result), offset, FALSE);
 
-    /* if the condition is  a bit variable */
-    if (isbit && IS_ITEMP(cond) && 
-       SPIL_LOC(cond))
-       genIfxJump(ic,SPIL_LOC(cond)->rname);
-    else
-       if (isbit && !IS_ITEMP(cond))
-           genIfxJump(ic,OP_SYMBOL(cond)->rname);
-       else
-           genIfxJump(ic,"a");
+       emit2 ("rl %s", l);
 
-    ic->generated = 1;
+        offset++;
+      }
+    if (shCount > 1)
+      {
+       emitLabel (tlbl1->key + 100);
+       emit2 ("dec a");
+       emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+      }
+  }
 }
 
 /*-----------------------------------------------------------------*/
-/* genAddrOf - generates code for address of                       */
+/* AccRol - rotate left accumulator by known count                 */
 /*-----------------------------------------------------------------*/
-static void genAddrOf (iCode *ic)
+static void
+AccRol (int shCount)
 {
-    symbol *sym = OP_SYMBOL(IC_LEFT(ic));
-
-    aopOp(IC_RESULT(ic),ic,FALSE);
+  shCount &= 0x0007;           // shCount : 0..7
 
-    /* if the operand is on the stack then we 
-    need to get the stack offset of this
-    variable */
-    if (sym->onStack) {
-        /* if it has an offset  then we need to compute it */
-       if (IS_GB) {
-           emitcode("lda", "hl,%d(sp)", sym->stack);
-           emitcode("ld", "d,h");
-           emitcode("ld", "e,l");
-           aopPut(AOP(IC_RESULT(ic)), "e", 0);
-           aopPut(AOP(IC_RESULT(ic)), "d", 1);
-           goto end;
-       }
-       else {
-           emitcode("push", "de");
-           emitcode("push", "ix");
-           emitcode("pop", "hl");
-           emitcode("ld", "de,#%d", sym->stack);
-           emitcode("add", "hl,de");
-           emitcode("pop", "de");
-       }
-    }
-    else {
-       emitcode("ld", "hl,#%s", sym->rname);
+  switch (shCount)
+    {
+    case 0:
+      break;
+    case 1:
+      emit2 ("rl a");
+      break;
+    case 2:
+      emit2 ("rl a");
+      emit2 ("rl a");
+      break;
+    case 3:
+      emit2 ("rl a");
+      emit2 ("rl a");
+      emit2 ("rl a");
+      break;
+    case 4:
+      emit2 ("rl a");
+      emit2 ("rl a");
+      emit2 ("rl a");
+      emit2 ("rl a");
+      break;
+    case 5:
+      emit2 ("rr a");
+      emit2 ("rr a");
+      emit2 ("rr a");
+      break;
+    case 6:
+      emit2 ("rr a");
+      emit2 ("rr a");
+      break;
+    case 7:
+      emit2 ("rr a");
+      break;
     }
-    aopPut(AOP(IC_RESULT(ic)), "l", 0);
-    aopPut(AOP(IC_RESULT(ic)), "h", 1);
-end:
-    freeAsmop(IC_RESULT(ic),NULL,ic);
 }
 
 /*-----------------------------------------------------------------*/
-/* genAssign - generate code for assignment                        */
+/* AccLsh - left shift accumulator by known count                  */
 /*-----------------------------------------------------------------*/
-static void genAssign (iCode *ic)
+static void
+AccLsh (int shCount)
 {
-    operand *result, *right;
-    int size, offset ;
-    unsigned long lit = 0L;
-
-    result = IC_RESULT(ic);
-    right  = IC_RIGHT(ic) ;
-
-#if 1
-    /* Dont bother assigning if they are the same */
-    if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
-       emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
-        return;
-    }
-#endif
+  static const unsigned char SLMask[] =
+    {
+      0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00
+    };
 
-    aopOp(right,ic,FALSE);
-    aopOp(result,ic,TRUE);
-
-    /* if they are the same registers */
-    if (sameRegs(AOP(right),AOP(result))) {
-       emitcode("", "; (registers are the same)");
-        goto release;
-    }
-
-    /* if the result is a bit */
-    if (AOP_TYPE(result) == AOP_CRY) {
-       assert(0);
-    }
-
-    /* general case */
-    size = AOP_SIZE(result);
-    offset = 0;
-
-    if(AOP_TYPE(right) == AOP_LIT)
-       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
-    if((size > 1) &&
-       (AOP_TYPE(result) != AOP_REG) &&
-       (AOP_TYPE(right) == AOP_LIT) &&
-       !IS_FLOAT(operandType(right)) &&
-       (lit < 256L)) {
-       bool fXored = FALSE;
-       offset = 0;
-       /* Work from the top down.
-          Done this way so that we can use the cached copy of 0
-          in A for a fast clear */
-       while (size--) {
-           if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
-               if (!fXored && size>1) {
-                   emitcode("xor", "a,a");
-                   fXored = TRUE;
-               }
-               if (fXored) {
-                   aopPut(AOP(result),"a",offset);
-               }
-               else {
-                   aopPut(AOP(result), "#0", offset);
-               }
-           }
-           else
-               aopPut(AOP(result),
-                      aopGet(AOP(right),offset,FALSE),
-                      offset);
-           offset++;
+  if (shCount != 0)
+    {
+      if (shCount == 1)
+       {
+         emit2 ("add a,a");
+       }
+      else if (shCount == 2)
+       {
+         emit2 ("add a,a");
+         emit2 ("add a,a");
        }
-    } else {
-       while (size--) {
-           aopPut(AOP(result),
-                  aopGet(AOP(right),offset,FALSE),
-                  offset);
-           offset++;
+      else
+       {
+         /* rotate left accumulator */
+         AccRol (shCount);
+         /* and kill the lower order bits */
+         emit2 ("and a,!immedbyte", SLMask[shCount]);
        }
     }
-    
-release:
-    freeAsmop(right,NULL,ic);
-    freeAsmop(result,NULL,ic);
-}   
+}
 
 /*-----------------------------------------------------------------*/
-/* genJumpTab - genrates code for jump table                       */
+/* shiftL1Left2Result - shift left one byte from left to result    */
 /*-----------------------------------------------------------------*/
-static void genJumpTab (iCode *ic)
-{
-    symbol *jtab;
-    char *l;
-
-    aopOp(IC_JTCOND(ic),ic,FALSE);
-    /* get the condition into accumulator */
-    l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
-    MOVA(l);
-    if (!IS_GB)
-       emitcode("push", "de");
-    emitcode("ld", "e,%s", l);
-    emitcode("ld", "d,#0");
-    jtab = newiTempLabel(NULL);
-    emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
-    emitcode("add", "hl,de");
-    emitcode("add", "hl,de");
-    freeAsmop(IC_JTCOND(ic),NULL,ic);
-    if (!IS_GB)
-       emitcode("pop", "de");
-    emitcode("jp", "(hl)");
-    emitcode("","%05d$:",jtab->key+100);
-    /* now generate the jump labels */
-    for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
-         jtab = setNextItem(IC_JTLABELS(ic)))
-        emitcode("jp", LABEL_STR, jtab->key+100);
+static void
+shiftL1Left2Result (operand * left, int offl,
+                   operand * result, int offr, int shCount)
+{
+  const char *l;
+  l = aopGet (AOP (left), offl, FALSE);
+  _moveA (l);
+  /* shift left accumulator */
+  AccLsh (shCount);
+  aopPut (AOP (result), "a", offr);
 }
 
+
 /*-----------------------------------------------------------------*/
-/* genCast - gen code for casting                                  */
+/* genlshTwo - left shift two bytes by known amount != 0           */
 /*-----------------------------------------------------------------*/
-static void genCast (iCode *ic)
+static void
+genlshTwo (operand * result, operand * left, int shCount)
 {
-    operand *result = IC_RESULT(ic);
-    link *ctype = operandType(IC_LEFT(ic));
-    operand *right = IC_RIGHT(ic);
-    int size, offset ;
-
-    /* if they are equivalent then do nothing */
-    if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
-        return ;
+  int size = AOP_SIZE (result);
 
-    aopOp(right,ic,FALSE) ;
-    aopOp(result,ic,FALSE);
+  wassert (size == 2);
 
-    /* if the result is a bit */
-    if (AOP_TYPE(result) == AOP_CRY) {
-       assert(0);
+  /* if shCount >= 8 */
+  if (shCount >= 8)
+    {
+      shCount -= 8;
+      if (size > 1)
+       {
+         if (shCount)
+           {
+             movLeft2Result (left, LSB, result, MSB16, 0);
+             aopPut (AOP (result), "!zero", 0);
+             shiftL1Left2Result (left, MSB16, result, MSB16, shCount);
+           }
+         else
+           {
+             movLeft2Result (left, LSB, result, MSB16, 0);
+             aopPut (AOP (result), "!zero", 0);
+           }
+       }
+      else
+       {
+         aopPut (AOP (result), "!zero", LSB);
+       }
     }
-
-    /* if they are the same size : or less */
-    if (AOP_SIZE(result) <= AOP_SIZE(right)) {
-
-        /* if they are in the same place */
-        if (sameRegs(AOP(right),AOP(result)))
-            goto release;
-
-        /* if they in different places then copy */
-        size = AOP_SIZE(result);
-        offset = 0 ;
-        while (size--) {
-            aopPut(AOP(result),
-                   aopGet(AOP(right),offset,FALSE),
-                   offset);
-            offset++;
+  /*  1 <= shCount <= 7 */
+  else
+    {
+      if (size == 1)
+       {
+         wassert (0);
+       }
+      else
+       {
+         shiftL2Left2Result (left, LSB, result, LSB, shCount);
+       }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genlshOne - left shift a one byte quantity by known count       */
+/*-----------------------------------------------------------------*/
+static void
+genlshOne (operand * result, operand * left, int shCount)
+{
+  shiftL1Left2Result (left, LSB, result, LSB, shCount);
+}
+
+/*-----------------------------------------------------------------*/
+/* genLeftShiftLiteral - left shifting by known count              */
+/*-----------------------------------------------------------------*/
+static void
+genLeftShiftLiteral (operand * left,
+                    operand * right,
+                    operand * result,
+                    iCode * ic)
+{
+  int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+  int size;
+
+  freeAsmop (right, NULL, ic);
+
+  aopOp (left, ic, FALSE, FALSE);
+  aopOp (result, ic, FALSE, FALSE);
+
+  size = getSize (operandType (result));
+
+#if VIEW_SIZE
+  emitDebug ("; shift left  result %d, left %d", size,
+           AOP_SIZE (left));
+#endif
+
+  /* I suppose that the left size >= result size */
+  if (shCount == 0)
+    {
+      wassert (0);
+    }
+
+  else if (shCount >= (size * 8)) 
+    {
+      while (size--)
+        {
+          aopPut (AOP (result), "!zero", size);
+        }
+    }
+  else
+    {
+      switch (size)
+       {
+       case 1:
+         genlshOne (result, left, shCount);
+         break;
+       case 2:
+         genlshTwo (result, left, shCount);
+         break;
+       case 4:
+         wassertl (0, "Shifting of longs is currently unsupported");
+         break;
+       default:
+         wassert (0);
+       }
+    }
+  freeAsmop (left, NULL, ic);
+  freeAsmop (result, NULL, ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genLeftShift - generates code for left shifting                 */
+/*-----------------------------------------------------------------*/
+static void
+genLeftShift (iCode * ic)
+{
+  int size, offset;
+  const char *l;
+  symbol *tlbl, *tlbl1;
+  operand *left, *right, *result;
+
+  right = IC_RIGHT (ic);
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+
+  aopOp (right, ic, FALSE, FALSE);
+
+  /* if the shift count is known then do it
+     as efficiently as possible */
+  if (AOP_TYPE (right) == AOP_LIT)
+    {
+      genLeftShiftLiteral (left, right, result, ic);
+      return;
+    }
+
+  /* shift count is unknown then we have to form a loop get the loop
+     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 ) */
+  emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
+  emit2 ("inc a");
+  freeAsmop (right, NULL, ic);
+  aopOp (left, ic, FALSE, FALSE);
+  aopOp (result, ic, FALSE, FALSE);
+
+  /* now move the left to the result if they are not the
+     same */
+#if 1
+  if (!sameRegs (AOP (left), AOP (result)))
+    {
+
+      size = AOP_SIZE (result);
+      offset = 0;
+      while (size--)
+       {
+         l = aopGet (AOP (left), offset, FALSE);
+         aopPut (AOP (result), l, offset);
+         offset++;
+       }
+    }
+#else
+  size = AOP_SIZE (result);
+  offset = 0;
+  while (size--)
+    {
+      l = aopGet (AOP (left), offset, FALSE);
+      aopPut (AOP (result), l, offset);
+      offset++;
+    }
+#endif
+
+
+  tlbl = newiTempLabel (NULL);
+  size = AOP_SIZE (result);
+  offset = 0;
+  tlbl1 = newiTempLabel (NULL);
+
+  emit2 ("!shortjp !tlabel", tlbl1->key + 100);
+  emitLabel (tlbl->key + 100);
+  l = aopGet (AOP (result), offset, FALSE);
+
+  emit2 ("or a,a");
+
+  while (size--)
+    {
+      l = aopGet (AOP (result), offset++, FALSE);
+      emit2 ("rl %s", l);
+    }
+  emitLabel (tlbl1->key + 100);
+  emit2 ("dec a");
+  emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+
+  freeAsmop (left, NULL, ic);
+  freeAsmop (result, NULL, ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genrshOne - left shift two bytes by known amount != 0           */
+/*-----------------------------------------------------------------*/
+static void
+genrshOne (operand * result, operand * left, int shCount, int is_signed)
+{
+  /* Errk */
+  int size = AOP_SIZE (result);
+  const char *l;
+
+  wassert (size == 1);
+  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--)
+        {
+          emit2 ("%s %s", is_signed ? "sra" : "srl", l);
+        }
+    }
+  else
+    {
+      _moveA (l);
+      while (shCount--)
+       {
+         emit2 ("%s a", is_signed ? "sra" : "srl");
+       }
+      aopPut (AOP (result), "a", 0);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccRsh - right shift accumulator by known count                 */
+/*-----------------------------------------------------------------*/
+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 */
+      AccRol (8 - shCount);
+      /* and kill the higher order bits */
+      emit2 ("and a,!immedbyte", SRMask[shCount]);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftR1Left2Result - shift right one byte from left to result   */
+/*-----------------------------------------------------------------*/
+static void
+shiftR1Left2Result (operand * left, int offl,
+                   operand * result, int offr,
+                   int shCount, int sign)
+{
+  _moveA (aopGet (AOP (left), offl, FALSE));
+  if (sign)
+    {
+      wassert (0);
+    }
+  else
+    {
+      AccRsh (shCount);
+    }
+  aopPut (AOP (result), "a", offr);
+}
+
+/*-----------------------------------------------------------------*/
+/* genrshTwo - right shift two bytes by known amount != 0          */
+/*-----------------------------------------------------------------*/
+static void
+genrshTwo (operand * result, operand * left,
+          int shCount, int sign)
+{
+  /* if shCount >= 8 */
+  if (shCount >= 8)
+    {
+      shCount -= 8;
+      if (shCount)
+       {
+         shiftR1Left2Result (left, MSB16, result, LSB,
+                             shCount, sign);
+       }
+      else
+       {
+         movLeft2Result (left, MSB16, result, LSB, sign);
+       }
+      aopPut (AOP (result), "!zero", 1);
+    }
+  /*  1 <= shCount <= 7 */
+  else
+    {
+      shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genRightShiftLiteral - left shifting by known count              */
+/*-----------------------------------------------------------------*/
+static void
+genRightShiftLiteral (operand * left,
+                     operand * right,
+                     operand * result,
+                     iCode * ic,
+                      int sign)
+{
+  int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+  int size;
+
+  freeAsmop (right, NULL, ic);
+
+  aopOp (left, ic, FALSE, FALSE);
+  aopOp (result, ic, FALSE, FALSE);
+
+  size = getSize (operandType (result));
+
+  emitDebug ("; shift right  result %d, left %d", size,
+           AOP_SIZE (left));
+
+  /* I suppose that the left size >= result size */
+  if (shCount == 0)
+    {
+      wassert (0);
+    }
+
+  else if (shCount >= (size * 8))
+    while (size--)
+      aopPut (AOP (result), "!zero", size);
+  else
+    {
+      switch (size)
+       {
+       case 1:
+         genrshOne (result, left, shCount, sign);
+         break;
+       case 2:
+         /* PENDING: sign support */
+         genrshTwo (result, left, shCount, sign);
+         break;
+       case 4:
+         wassertl (0, "Asked to shift right a long which should be a function call");
+         break;
+       default:
+         wassertl (0, "Entered default case in right shift delegate");
+       }
+    }
+  freeAsmop (left, NULL, ic);
+  freeAsmop (result, NULL, ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRightShift - generate code for right shifting                */
+/*-----------------------------------------------------------------*/
+static void
+genRightShift (iCode * ic)
+{
+  operand *right, *left, *result;
+  sym_link *retype;
+  int size, offset, first = 1;
+  const char *l;
+  bool is_signed;
+
+  symbol *tlbl, *tlbl1;
+
+  /* if signed then we do it the hard way preserve the
+     sign bit moving it inwards */
+  retype = getSpec (operandType (IC_RESULT (ic)));
+
+  is_signed = !SPEC_USIGN (retype);
+
+  /* signed & unsigned types are treated the same : i.e. the
+     signed is NOT propagated inwards : quoting from the
+     ANSI - standard : "for E1 >> E2, is equivalent to division
+     by 2**E2 if unsigned or if it has a non-negative value,
+     otherwise the result is implementation defined ", MY definition
+     is that the sign does not get propagated */
+
+  right = IC_RIGHT (ic);
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+
+  aopOp (right, ic, FALSE, FALSE);
+
+  /* if the shift count is known then do it
+     as efficiently as possible */
+  if (AOP_TYPE (right) == AOP_LIT)
+    {
+      genRightShiftLiteral (left, right, result, ic, is_signed);
+      return;
+    }
+
+  aopOp (left, ic, FALSE, FALSE);
+  aopOp (result, ic, FALSE, FALSE);
+
+  /* now move the left to the result if they are not the
+     same */
+  if (!sameRegs (AOP (left), AOP (result)) &&
+      AOP_SIZE (result) > 1)
+    {
+
+      size = AOP_SIZE (result);
+      offset = 0;
+      while (size--)
+       {
+         l = aopGet (AOP (left), offset, FALSE);
+         aopPut (AOP (result), l, offset);
+         offset++;
+       }
+    }
+
+  emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
+  emit2 ("inc a");
+  freeAsmop (right, NULL, ic);
+
+  tlbl = newiTempLabel (NULL);
+  tlbl1 = newiTempLabel (NULL);
+  size = AOP_SIZE (result);
+  offset = size - 1;
+
+  emit2 ("!shortjp !tlabel", tlbl1->key + 100);
+  emitLabel (tlbl->key + 100);
+  while (size--)
+    {
+      l = aopGet (AOP (result), offset--, FALSE);
+      if (first)
+       {
+          emit2 ("%s %s", is_signed ? "sra" : "srl", l);
+         first = 0;
+       }
+      else
+        {
+          emit2 ("rr %s", l);
         }
-        goto release;
+    }
+  emitLabel (tlbl1->key + 100);
+  emit2 ("dec a");
+  emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+
+  freeAsmop (left, NULL, ic);
+  freeAsmop (result, NULL, ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genGenPointerGet -  get value from generic pointer space        */
+/*-----------------------------------------------------------------*/
+static void
+genGenPointerGet (operand * left,
+                 operand * result, iCode * ic)
+{
+  int size, offset;
+  sym_link *retype = getSpec (operandType (result));
+  int pair = PAIR_HL;
+
+  if (IS_GB)
+    pair = PAIR_DE;
+
+  aopOp (left, ic, FALSE, FALSE);
+  aopOp (result, ic, FALSE, FALSE);
+
+  if (isPair (AOP (left)) && AOP_SIZE (result) == 1)
+    {
+      /* Just do it */
+      if (isPtrPair (AOP (left)))
+       {
+         tsprintf (buffer, "!*pair", getPairName (AOP (left)));
+         aopPut (AOP (result), buffer, 0);
+       }
+      else
+       {
+         emit2 ("ld a,!*pair", getPairName (AOP (left)));
+         aopPut (AOP (result), "a", 0);
+       }
+      freeAsmop (left, NULL, ic);
+      goto release;
+    }
+
+  /* For now we always load into IY */
+  /* if this is remateriazable */
+  fetchPair (pair, AOP (left));
+
+  /* so iy now contains the address */
+  freeAsmop (left, NULL, ic);
+
+  /* if bit then unpack */
+  if (IS_BITVAR (retype))
+    {
+      wassert (0);
+    }
+  else
+    {
+      size = AOP_SIZE (result);
+      offset = 0;
+
+      while (size--)
+       {
+         /* PENDING: make this better */
+         if (!IS_GB && AOP (result)->type == AOP_REG)
+           {
+             aopPut (AOP (result), "!*hl", offset++);
+           }
+         else
+           {
+             emit2 ("ld a,!*pair", _pairs[pair].name);
+             aopPut (AOP (result), "a", offset++);
+           }
+         if (size)
+           {
+             emit2 ("inc %s", _pairs[pair].name);
+             _G.pairs[pair].offset++;
+           }
+       }
+    }
+
+release:
+  freeAsmop (result, NULL, ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genPointerGet - generate code for pointer get                   */
+/*-----------------------------------------------------------------*/
+static void
+genPointerGet (iCode * ic)
+{
+  operand *left, *result;
+  sym_link *type, *etype;
+
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+
+  /* depending on the type of pointer we need to
+     move it to the correct pointer register */
+  type = operandType (left);
+  etype = getSpec (type);
+
+  genGenPointerGet (left, result, ic);
+}
+
+bool
+isRegOrLit (asmop * aop)
+{
+  if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
+    return TRUE;
+  return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* genGenPointerSet - stores the value into a pointer location        */
+/*-----------------------------------------------------------------*/
+static void
+genGenPointerSet (operand * right,
+                 operand * result, iCode * ic)
+{
+  int size, offset;
+  sym_link *retype = getSpec (operandType (right));
+  PAIR_ID pairId = PAIR_HL;
+
+  aopOp (result, ic, FALSE, FALSE);
+  aopOp (right, ic, FALSE, FALSE);
+
+  if (IS_GB)
+    pairId = PAIR_DE;
+
+  /* Handle the exceptions first */
+  if (isPair (AOP (result)) && (AOP_SIZE (right) == 1))
+    {
+      /* Just do it */
+      const char *l = aopGet (AOP (right), 0, FALSE);
+      const char *pair = getPairName (AOP (result));
+      if (canAssignToPtr (l) && isPtr (pair))
+       {
+         emit2 ("ld !*pair,%s", pair, l);
+       }
+      else
+       {
+         _moveA (l);
+         emit2 ("ld !*pair,a", pair);
+       }
+      goto release;
+    }
+
+  /* if the operand is already in dptr
+     then we do nothing else we move the value to dptr */
+  if (AOP_TYPE (result) != AOP_STR)
+    {
+      fetchPair (pairId, AOP (result));
+    }
+  /* so hl know contains the address */
+  freeAsmop (result, NULL, ic);
+
+  /* if bit then unpack */
+  if (IS_BITVAR (retype))
+    {
+      wassert (0);
+    }
+  else
+    {
+      size = AOP_SIZE (right);
+      offset = 0;
+
+      while (size--)
+       {
+         const char *l = aopGet (AOP (right), offset, FALSE);
+         if (isRegOrLit (AOP (right)) && !IS_GB)
+           {
+             emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
+           }
+         else
+           {
+             _moveA (l);
+             emit2 ("ld !*pair,a", _pairs[pairId].name);
+           }
+         if (size)
+           {
+             emit2 ("inc %s", _pairs[pairId].name);
+             _G.pairs[pairId].offset++;
+           }
+         offset++;
+       }
+    }
+release:
+  freeAsmop (right, NULL, ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genPointerSet - stores the value into a pointer location        */
+/*-----------------------------------------------------------------*/
+static void
+genPointerSet (iCode * ic)
+{
+  operand *right, *result;
+  sym_link *type, *etype;
+
+  right = IC_RIGHT (ic);
+  result = IC_RESULT (ic);
+
+  /* depending on the type of pointer we need to
+     move it to the correct pointer register */
+  type = operandType (result);
+  etype = getSpec (type);
+
+  genGenPointerSet (right, result, ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genIfx - generate code for Ifx statement                        */
+/*-----------------------------------------------------------------*/
+static void
+genIfx (iCode * ic, iCode * popIc)
+{
+  operand *cond = IC_COND (ic);
+  int isbit = 0;
+
+  aopOp (cond, ic, FALSE, TRUE);
+
+  /* get the value into acc */
+  if (AOP_TYPE (cond) != AOP_CRY)
+    _toBoolean (cond);
+  else
+    isbit = 1;
+  /* the result is now in the accumulator */
+  freeAsmop (cond, NULL, ic);
+
+  /* if there was something to be popped then do it */
+  if (popIc)
+    genIpop (popIc);
+
+  /* if the condition is  a bit variable */
+  if (isbit && IS_ITEMP (cond) &&
+      SPIL_LOC (cond))
+    genIfxJump (ic, SPIL_LOC (cond)->rname);
+  else if (isbit && !IS_ITEMP (cond))
+    genIfxJump (ic, OP_SYMBOL (cond)->rname);
+  else
+    genIfxJump (ic, "a");
+
+  ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* genAddrOf - generates code for address of                       */
+/*-----------------------------------------------------------------*/
+static void
+genAddrOf (iCode * ic)
+{
+  symbol *sym = OP_SYMBOL (IC_LEFT (ic));
+
+  aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
+
+  /* if the operand is on the stack then we
+     need to get the stack offset of this
+     variable */
+  if (IS_GB)
+    {
+      if (sym->onStack)
+       {
+         spillCached ();
+         if (sym->stack <= 0)
+           {
+             emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
+           }
+         else
+           {
+             emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
+           }
+         emit2 ("ld d,h");
+         emit2 ("ld e,l");
+       }
+      else
+       {
+         emit2 ("ld de,!hashedstr", sym->rname);
+       }
+      aopPut (AOP (IC_RESULT (ic)), "e", 0);
+      aopPut (AOP (IC_RESULT (ic)), "d", 1);
+    }
+  else
+    {
+      spillCached ();
+      if (sym->onStack)
+       {
+         /* if it has an offset  then we need to compute it */
+         if (sym->stack > 0)
+           emit2 ("ld hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
+         else
+           emit2 ("ld hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
+         emit2 ("add hl,sp");
+       }
+      else
+       {
+         emit2 ("ld hl,#%s", sym->rname);
+       }
+      aopPut (AOP (IC_RESULT (ic)), "l", 0);
+      aopPut (AOP (IC_RESULT (ic)), "h", 1);
+    }
+  freeAsmop (IC_RESULT (ic), NULL, ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genAssign - generate code for assignment                        */
+/*-----------------------------------------------------------------*/
+static void
+genAssign (iCode * ic)
+{
+  operand *result, *right;
+  int size, offset;
+  unsigned long lit = 0L;
+
+  result = IC_RESULT (ic);
+  right = IC_RIGHT (ic);
+
+#if 1
+  /* Dont bother assigning if they are the same */
+  if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
+    {
+      emitDebug ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
+      return;
+    }
+#endif
+
+  aopOp (right, ic, FALSE, FALSE);
+  aopOp (result, ic, TRUE, FALSE);
+
+  /* if they are the same registers */
+  if (sameRegs (AOP (right), AOP (result)))
+    {
+      emitDebug ("; (registers are the same)");
+      goto release;
+    }
+
+  /* if the result is a bit */
+  if (AOP_TYPE (result) == AOP_CRY)
+    {
+      wassert (0);
+    }
+
+  /* general case */
+  size = AOP_SIZE (result);
+  offset = 0;
+
+  if (AOP_TYPE (right) == AOP_LIT)
+    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+  if (isPair (AOP (result)))
+    {
+      fetchPair (getPairId (AOP (result)), AOP (right));
+    }
+  else if ((size > 1) &&
+          (AOP_TYPE (result) != AOP_REG) &&
+          (AOP_TYPE (right) == AOP_LIT) &&
+          !IS_FLOAT (operandType (right)) &&
+          (lit < 256L))
+    {
+      bool fXored = FALSE;
+      offset = 0;
+      /* Work from the top down.
+         Done this way so that we can use the cached copy of 0
+         in A for a fast clear */
+      while (size--)
+       {
+         if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
+           {
+             if (!fXored && size > 1)
+               {
+                 emit2 ("xor a,a");
+                 fXored = TRUE;
+               }
+             if (fXored)
+               {
+                 aopPut (AOP (result), "a", offset);
+               }
+             else
+               {
+                 aopPut (AOP (result), "!zero", offset);
+               }
+           }
+         else
+           aopPut (AOP (result),
+                   aopGet (AOP (right), offset, FALSE),
+                   offset);
+         offset++;
+       }
+    }
+  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));
+      emit2 ("ld e,%s", aopGet (AOP (right), 1, FALSE));
+      aopPut (AOP (result), "a", 0);
+      aopPut (AOP (result), "e", 1);
+    }
+  else
+    {
+      while (size--)
+       {
+         /* PENDING: do this check better */
+         if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
+           {
+             _moveA (aopGet (AOP (right), offset, FALSE));
+             aopPut (AOP (result), "a", offset);
+           }
+         else
+           aopPut (AOP (result),
+                   aopGet (AOP (right), offset, FALSE),
+                   offset);
+         offset++;
+       }
+    }
+
+release:
+  freeAsmop (right, NULL, ic);
+  freeAsmop (result, NULL, ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genJumpTab - genrates code for jump table                       */
+/*-----------------------------------------------------------------*/
+static void
+genJumpTab (iCode * ic)
+{
+  symbol *jtab;
+  const char *l;
+
+  aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
+  /* get the condition into accumulator */
+  l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
+  if (!IS_GB)
+    emit2 ("push de");
+  emit2 ("ld e,%s", l);
+  emit2 ("ld d,!zero");
+  jtab = newiTempLabel (NULL);
+  spillCached ();
+  emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
+  emit2 ("add hl,de");
+  emit2 ("add hl,de");
+  emit2 ("add hl,de");
+  freeAsmop (IC_JTCOND (ic), NULL, ic);
+  if (!IS_GB)
+    emit2 ("pop de");
+  emit2 ("jp !*hl");
+  emitLabel (jtab->key + 100);
+  /* now generate the jump labels */
+  for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
+       jtab = setNextItem (IC_JTLABELS (ic)))
+    emit2 ("jp !tlabel", jtab->key + 100);
+}
+
+/*-----------------------------------------------------------------*/
+/* genCast - gen code for casting                                  */
+/*-----------------------------------------------------------------*/
+static void
+genCast (iCode * ic)
+{
+  operand *result = IC_RESULT (ic);
+  sym_link *ctype = operandType (IC_LEFT (ic));
+  operand *right = IC_RIGHT (ic);
+  int size, offset;
+
+  /* if they are equivalent then do nothing */
+  if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
+    return;
+
+  aopOp (right, ic, FALSE, FALSE);
+  aopOp (result, ic, FALSE, FALSE);
+
+  /* if the result is a bit */
+  if (AOP_TYPE (result) == AOP_CRY)
+    {
+      wassert (0);
     }
 
-    /* PENDING: should be OK. */
+  /* if they are the same size : or less */
+  if (AOP_SIZE (result) <= AOP_SIZE (right))
+    {
+
+      /* if they are in the same place */
+      if (sameRegs (AOP (right), AOP (result)))
+       goto release;
+
+      /* if they in different places then copy */
+      size = AOP_SIZE (result);
+      offset = 0;
+      while (size--)
+       {
+         aopPut (AOP (result),
+                 aopGet (AOP (right), offset, FALSE),
+                 offset);
+         offset++;
+       }
+      goto release;
+    }
+
+  /* PENDING: should be OK. */
 #if 0
-    /* if the result is of type pointer */
-    if (IS_PTR(ctype)) {
-       assert(0);
+  /* if the result is of type pointer */
+  if (IS_PTR (ctype))
+    {
+      wassert (0);
     }
 #endif
-    
-    /* so we now know that the size of destination is greater
-    than the size of the source */
-    /* we move to result for the size of source */
-    size = AOP_SIZE(right);
-    offset = 0 ;
-    while (size--) {
-        aopPut(AOP(result),
-               aopGet(AOP(right),offset,FALSE),
-               offset);
-        offset++;
+
+  /* so we now know that the size of destination is greater
+     than the size of the source */
+  /* we move to result for the size of source */
+  size = AOP_SIZE (right);
+  offset = 0;
+  while (size--)
+    {
+      aopPut (AOP (result),
+             aopGet (AOP (right), offset, FALSE),
+             offset);
+      offset++;
     }
 
-    /* now depending on the sign of the destination */
-    size = AOP_SIZE(result) - AOP_SIZE(right);
-    /* Unsigned or not an integral type - right fill with zeros */
-    if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
-        while (size--)
-            aopPut(AOP(result),zero,offset++);
-    } else {
-        /* we need to extend the sign :{ */
-        char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
-                         FALSE);
-        MOVA(l);
-       emitcode("", "; genCast: sign extend untested.");
-        emitcode("rla", "");
-        emitcode("sbc", "a,a");
-        while (size--)
-            aopPut(AOP(result),"a",offset++);   
+  /* now depending on the sign of the destination */
+  size = AOP_SIZE (result) - AOP_SIZE (right);
+  /* Unsigned or not an integral type - right fill with zeros */
+  if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
+    {
+      while (size--)
+       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);
+      emitDebug ("; genCast: sign extend untested.");
+      emit2 ("rla ");
+      emit2 ("sbc a,a");
+      while (size--)
+       aopPut (AOP (result), "a", offset++);
     }
 
 release:
-    freeAsmop(right, NULL, ic);
-    freeAsmop(result, NULL, ic);
+  freeAsmop (right, NULL, ic);
+  freeAsmop (result, NULL, ic);
 }
 
 /*-----------------------------------------------------------------*/
 /* genReceive - generate code for a receive iCode                  */
 /*-----------------------------------------------------------------*/
-static void genReceive (iCode *ic)
-{    
-    if (isOperandInFarSpace(IC_RESULT(ic)) && 
-       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
-         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
-       assert(0);
-    } else {
-       accInUse++;
-       aopOp(IC_RESULT(ic),ic,FALSE);  
-       accInUse--;
-       assignResultValue(IC_RESULT(ic));       
+static void
+genReceive (iCode * ic)
+{
+  if (isOperandInFarSpace (IC_RESULT (ic)) &&
+      (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
+       IS_TRUE_SYMOP (IC_RESULT (ic))))
+    {
+      wassert (0);
+    }
+  else
+    {
+        // PENDING: HACK
+        int size;
+        int i;
+
+        aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
+        size = AOP_SIZE(IC_RESULT(ic));
+
+        for (i = 0; i < size; i++) {
+            aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
+       }
     }
 
-    freeAsmop(IC_RESULT(ic),NULL,ic);
+  freeAsmop (IC_RESULT (ic), NULL, ic);
 }
 
-/*-----------------------------------------------------------------*/
-/* genZ80Code - generate code for Z80 based controllers            */
-/*-----------------------------------------------------------------*/
-void genZ80Code (iCode *lic)
+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)
 {
-    iCode *ic;
-    int cln = 0;
+  char line[256];
+
+  if (self->pos > 0)
+    {
+      int i;
+      sprintf(line, ".db 0x%02X", self->buffer[0]);
 
-    /* HACK */
-    if (IS_GB) {
-       _fReturn = _gbz80_return;
-       _fTmp = _gbz80_return;
+      for (i = 1; i < self->pos; i++)
+        {
+          sprintf(line + strlen(line), ", 0x%02X", self->buffer[i]);
+        }
+      emit2(line);
     }
-    else {
-       _fReturn = _z80_return;
-       _fTmp = _z80_return;
+  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;
+}
 
-    lineHead = lineCurr = NULL;
+/* 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.
+*/
 
-    /* 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;
+/** 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");
     }
-    /* stack pointer name */
-    spname = "sp";
     
-    for (ic = lic ; ic ; ic = ic->next ) {
-       
-       if ( cln != ic->lineno ) {
-           if ( options.debug ) {
-               debugLine = 1;
-               emitcode("","C$%s$%d$%d$%d ==.",
-                        ic->filename,ic->lineno,
-                        ic->level,ic->block);
-               debugLine = 0;
-           }
-           emitcode(";","%s %d",ic->filename,ic->lineno);
-           cln = ic->lineno ;
-       }
-       /* if the result is marked as
-          spilt and rematerializable or code for
-          this has already been generated then
-          do nothing */
-       if (resultRemat(ic) || ic->generated ) 
-           continue ;
+  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);
+                }
+            }
+       }
        
-       /* depending on the operation */
-       switch (ic->op) {
-       case '!' :
-           emitcode("", "; genNot");
-           genNot(ic);
-           break;
-           
-       case '~' :
-           emitcode("", "; genCpl");
-           genCpl(ic);
-           break;
-           
+      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            */
+/*-----------------------------------------------------------------*/
+void
+genZ80Code (iCode * lic)
+{
+  iCode *ic;
+  int cln = 0;
+
+  /* HACK */
+  if (IS_GB)
+    {
+      _fReturn = _gbz80_return;
+      _fTmp = _gbz80_return;
+    }
+  else
+    {
+      _fReturn = _z80_return;
+      _fTmp = _z80_return;
+    }
+
+  _G.lines.head = _G.lines.current = NULL;
+
+  for (ic = lic; ic; ic = ic->next)
+    {
+
+      if (cln != ic->lineno)
+       {
+         emit2 ("; %s %d", ic->filename, ic->lineno);
+         cln = ic->lineno;
+       }
+      /* if the result is marked as
+         spilt and rematerializable or code for
+         this has already been generated then
+         do nothing */
+      if (resultRemat (ic) || ic->generated)
+       continue;
+
+      /* depending on the operation */
+      switch (ic->op)
+       {
+       case '!':
+         emitDebug ("; genNot");
+         genNot (ic);
+         break;
+
+       case '~':
+         emitDebug ("; genCpl");
+         genCpl (ic);
+         break;
+
        case UNARYMINUS:
-           emitcode("", "; genUminus");
-           genUminus (ic);
-           break;
-           
+         emitDebug ("; genUminus");
+         genUminus (ic);
+         break;
+
        case IPUSH:
-           emitcode("", "; genIpush");
-           genIpush (ic);
-           break;
-           
+         emitDebug ("; genIpush");
+         genIpush (ic);
+         break;
+
        case IPOP:
-           /* IPOP happens only when trying to restore a 
-              spilt live range, if there is an ifx statement
-              following this pop then the if statement might
-              be using some of the registers being popped which
-              would destory the contents of the register so
-              we need to check for this condition and handle it */
-           if (ic->next            && 
-               ic->next->op == IFX &&
-               regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
-               emitcode("", "; genIfx");
-               genIfx (ic->next,ic);
-           }
-           else {
-               emitcode("", "; genIpop");
-               genIpop (ic);
-           }
-           break; 
-           
+         /* IPOP happens only when trying to restore a
+            spilt live range, if there is an ifx statement
+            following this pop then the if statement might
+            be using some of the registers being popped which
+            would destory the contents of the register so
+            we need to check for this condition and handle it */
+         if (ic->next &&
+             ic->next->op == IFX &&
+             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
+           {
+              emitDebug ("; genIfx");
+             genIfx (ic->next, ic);
+           }
+         else
+           {
+             emitDebug ("; genIpop");
+             genIpop (ic);
+           }
+         break;
+
        case CALL:
-           emitcode("", "; genCall");
-           genCall (ic);
-           break;
-           
+         emitDebug ("; genCall");
+         genCall (ic);
+         break;
+
        case PCALL:
-           emitcode("", "; genPcall");
-           genPcall (ic);
-           break;
-           
+         emitDebug ("; genPcall");
+         genPcall (ic);
+         break;
+
        case FUNCTION:
-           emitcode("", "; genFunction");
-           genFunction (ic);
-           break;
-           
+         emitDebug ("; genFunction");
+         genFunction (ic);
+         break;
+
        case ENDFUNCTION:
-           emitcode("", "; genEndFunction");
-           genEndFunction (ic);
-           break;
-           
+         emitDebug ("; genEndFunction");
+         genEndFunction (ic);
+         break;
+
        case RETURN:
-           emitcode("", "; genRet");
-           genRet (ic);
-           break;
-           
+         emitDebug ("; genRet");
+         genRet (ic);
+         break;
+
        case LABEL:
-           emitcode("", "; genLabel");
-           genLabel (ic);
-           break;
-           
+         emitDebug ("; genLabel");
+         genLabel (ic);
+         break;
+
        case GOTO:
-           emitcode("", "; genGoto");
-           genGoto (ic);
-           break;
-           
-       case '+' :
-           emitcode("", "; genPlus");
-           genPlus (ic) ;
-           break;
-           
-       case '-' :
-           emitcode("", "; genMinus");
-           genMinus (ic);
-           break;
-           
-       case '*' :
-           emitcode("", "; genMult");
-           genMult (ic);
-           break;
-           
-       case '/' :
-           emitcode("", "; genDiv");
-           genDiv (ic) ;
-           break;
-           
-       case '%' :
-           emitcode("", "; genMod");
-           genMod (ic);
-           break;
-           
-       case '>' :
-           emitcode("", "; genCmpGt");
-           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
-           break;
-           
-       case '<' :
-           emitcode("", "; genCmpLt");
-           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
-           break;
-           
+         emitDebug ("; genGoto");
+         genGoto (ic);
+         break;
+
+       case '+':
+         emitDebug ("; genPlus");
+         genPlus (ic);
+         break;
+
+       case '-':
+         emitDebug ("; genMinus");
+         genMinus (ic);
+         break;
+
+       case '*':
+         emitDebug ("; genMult");
+         genMult (ic);
+         break;
+
+       case '/':
+         emitDebug ("; genDiv");
+         genDiv (ic);
+         break;
+
+       case '%':
+         emitDebug ("; genMod");
+         genMod (ic);
+         break;
+
+       case '>':
+         emitDebug ("; genCmpGt");
+         genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
+         break;
+
+       case '<':
+         emitDebug ("; genCmpLt");
+         genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
+         break;
+
        case LE_OP:
        case GE_OP:
        case NE_OP:
-           
-           /* note these two are xlated by algebraic equivalence
-              during parsing SDCC.y */
-           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-                  "got '>=' or '<=' shouldn't have come here");
-           break;      
-           
+
+         /* note these two are xlated by algebraic equivalence
+            during parsing SDCC.y */
+         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                 "got '>=' or '<=' shouldn't have come here");
+         break;
+
        case EQ_OP:
-           emitcode("", "; genCmpEq");
-           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
-           break;          
-           
+         emitDebug ("; genCmpEq");
+         genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
+         break;
+
        case AND_OP:
-           emitcode("", "; genAndOp");
-           genAndOp (ic);
-           break;
-           
+         emitDebug ("; genAndOp");
+         genAndOp (ic);
+         break;
+
        case OR_OP:
-           emitcode("", "; genOrOp");
-           genOrOp (ic);
-           break;
-           
-       case '^' :
-           emitcode("", "; genXor");
-           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
-           break;
-           
-       case '|' :
-           emitcode("", "; genOr");
-           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
-           break;
-           
+         emitDebug ("; genOrOp");
+         genOrOp (ic);
+         break;
+
+       case '^':
+         emitDebug ("; genXor");
+         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
+         break;
+
+       case '|':
+         emitDebug ("; genOr");
+         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
+         break;
+
        case BITWISEAND:
-           emitcode("", "; genAnd");
-            genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
-           break;
-           
+         emitDebug ("; genAnd");
+         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
+         break;
+
        case INLINEASM:
-           emitcode("", "; genInline");
-           genInline (ic);
-           break;
-           
+         emitDebug ("; genInline");
+         genInline (ic);
+         break;
+
        case RRC:
-           emitcode("", "; genRRC");
-           genRRC (ic);
-           break;
-           
+         emitDebug ("; genRRC");
+         genRRC (ic);
+         break;
+
        case RLC:
-           emitcode("", "; genRLC");
-           genRLC (ic);
-           break;
-           
+         emitDebug ("; genRLC");
+         genRLC (ic);
+         break;
+
        case GETHBIT:
-           emitcode("", "; genHBIT");
-           assert(0);
-           
+         emitDebug ("; genGetHBIT");
+         genGetHbit (ic);
+          break;
+
        case LEFT_OP:
-           emitcode("", "; genLeftShift");
-           genLeftShift (ic);
-           break;
-           
+         emitDebug ("; genLeftShift");
+         genLeftShift (ic);
+         break;
+
        case RIGHT_OP:
-           emitcode("", "; genRightShift");
-           genRightShift (ic);
-           break;
-           
+         emitDebug ("; genRightShift");
+         genRightShift (ic);
+         break;
+
        case GET_VALUE_AT_ADDRESS:
-           emitcode("", "; genPointerGet");
-           genPointerGet(ic);
-           break;
-           
-       case '=' :
+         emitDebug ("; genPointerGet");
+         genPointerGet (ic);
+         break;
+
+       case '=':
 
-           if (POINTER_SET(ic)) {
-               emitcode("", "; genAssign (pointer)");
-               genPointerSet(ic);
+         if (POINTER_SET (ic))
+           {
+             emitDebug ("; genAssign (pointer)");
+             genPointerSet (ic);
            }
-           else {
-               emitcode("", "; genAssign");
-               genAssign(ic);
+         else
+           {
+             emitDebug ("; genAssign");
+             genAssign (ic);
            }
-           break;
-           
+         break;
+
        case IFX:
-           emitcode("", "; genIfx");
-           genIfx (ic,NULL);
-           break;
-           
+          emitDebug ("; genIfx");
+         genIfx (ic, NULL);
+         break;
+
        case ADDRESS_OF:
-           emitcode("", "; genAddrOf");
-           genAddrOf (ic);
-           break;
-           
+         emitDebug ("; genAddrOf");
+         genAddrOf (ic);
+         break;
+
        case JUMPTABLE:
-           emitcode("", "; genJumpTab");
-           genJumpTab (ic);
-           break;
-           
+         emitDebug ("; genJumpTab");
+         genJumpTab (ic);
+         break;
+
        case CAST:
-           emitcode("", "; genCast");
-           genCast (ic);
-           break;
-           
+         emitDebug ("; genCast");
+         genCast (ic);
+         break;
+
        case RECEIVE:
-           emitcode("", "; genReceive");
-           genReceive(ic);
-           break;
-           
+         emitDebug ("; genReceive");
+         genReceive (ic);
+         break;
+
        case SEND:
-           emitcode("", "; addSet");
-           addSet(&sendSet,ic);
-           break;
+         emitDebug ("; addSet");
+         addSet (&_G.sendSet, ic);
+         break;
 
-       default :
-           ic = ic;
-           /*      piCode(ic,stdout); */
+       case ARRAYINIT:
+           genArrayInit(ic);
+           break;
            
-        }
+       default:
+         ic = ic;
+         /*      piCode(ic,stdout); */
+
+       }
     }
-    
 
-    /* now we are ready to call the 
-       peep hole optimizer */
-    if (!options.nopeep)
-       peepHole (&lineHead);
 
-    /* now do the actual printing */
-    printLine (lineHead,codeOutFile);
-    return;
+  /* now we are ready to call the
+     peep hole optimizer */
+  if (!options.nopeep)
+    peepHole (&_G.lines.head);
+
+  /* This is unfortunate */
+  /* now do the actual printing */
+  {
+    FILE *fp = codeOutFile;
+    if (isInHome () && codeOutFile == code->oFile)
+      codeOutFile = home->oFile;
+    printLine (_G.lines.head, codeOutFile);
+    if (_G.flushStatics)
+      {
+       flushStatics ();
+       _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;
+}
+
+*/