* device/lib/Makefile.in (Z80SOURCES): enabled float support
[fw/sdcc] / src / mcs51 / gen.c
index ec9099cbb473a3a73421d285bd7bbce7499d4544..53b528eeff26b71aeff9d60aed34e687a9803a05 100644 (file)
 /*-------------------------------------------------------------------------
-  SDCCgen51.c - source file for code generation for 8051
-  
+  gen.c - source file for code generation for 8051
+
   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
-  
+
   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!
-  
+
   Notes:
-  000123 mlh   Moved aopLiteral to SDCCglue.c to help the split
-               Made everything static
+  000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
+      Made everything static
 -------------------------------------------------------------------------*/
 
+//#define D(x)
+#define D(x) x
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 #include "SDCCglobl.h"
-
-#ifdef HAVE_SYS_ISA_DEFS_H
-#include <sys/isa_defs.h>
-#else
-#ifdef HAVE_ENDIAN_H
-#include <endian.h>
-#else
-#ifndef __BORLANDC__
-#warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
-#warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
-#endif
-#endif
-#endif
+#include "newalloc.h"
 
 #include "common.h"
 #include "SDCCpeeph.h"
 #include "ralloc.h"
 #include "gen.h"
 
-char *aopLiteral (value *val, int offset);
+char *aopLiteral (value * val, int offset);
+char *aopLiteralLong (value * val, int offset, int size);
+extern int allocInfo;
 
-/* this is the down and dirty file with all kinds of 
+/* 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 *one = "#0x01";
+static char *spname;
 
-char *fReturn8051[] = {"dpl","dph","b","a" };
-char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
-unsigned fReturnSize = 4; /* shared with ralloc.c */
+char *fReturn8051[] =
+{"dpl", "dph", "b", "a"};
+unsigned fReturnSizeMCS51 = 4;  /* shared with ralloc.c */
 char **fReturn = fReturn8051;
-static char *accUse[] = {"a","b"};
+static char *accUse[] =
+{"a", "b"};
+
+static unsigned short rbank = -1;
+
+#define REG_WITH_INDEX   mcs51_regWithIdx
+
+#define AOP(op) op->aop
+#define AOP_TYPE(op) AOP(op)->type
+#define AOP_SIZE(op) AOP(op)->size
+#define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
+                        AOP_TYPE(x) == AOP_R0))
+
+#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
+                         AOP_TYPE(x) == AOP_DPTR || \
+                         AOP(x)->paged))
+
+#define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
+                       (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
+                        x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
 
-static short rbank = -1;
+#define SYM_BP(sym)   (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
 
-static struct {
+#define R0INB   _G.bu.bs.r0InB
+#define R1INB   _G.bu.bs.r1InB
+#define OPINB   _G.bu.bs.OpInB
+#define BINUSE  _G.bu.BInUse
+
+static struct
+  {
     short r0Pushed;
     short r1Pushed;
+    union
+      {
+        struct
+          {
+            short r0InB : 2;//2 so we can see it overflow
+            short r1InB : 2;//2 so we can see it overflow
+            short OpInB : 2;//2 so we can see it overflow
+          } bs;
+        short BInUse;
+      } bu;
     short accInUse;
     short inLine;
     short debugLine;
     short nRegsSaved;
     set *sendSet;
-} _G;
+    iCode *current_iCode;
+    symbol *currentFunc;
+  }
+_G;
+
+static char *rb1regs[] = {
+    "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
+    "b0",  "b1",  "b2",  "b3",  "b4",  "b5",  "b6",  "b7"
+};
 
-extern int mcs51_ptrRegReq ;
-extern int mcs51_nRegs;
 extern FILE *codeOutFile;
-static void saverbank (int, iCode *,bool);
+static void saveRBank (int, iCode *, bool);
+
 #define RESULTONSTACK(x) \
                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
                          IC_RESULT(x)->aop->type == AOP_STK )
 
-#define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
-#define CLRC    emitcode("clr","c");
+#define MOVA(x)  mova(x)  /* use function to avoid multiple eval */
+#define MOVB(x)  movb(x)
+
+#define CLRC     emitcode("clr","c")
+#define SETC     emitcode("setb","c")
 
 static lineNode *lineHead = NULL;
 static lineNode *lineCurr = NULL;
 
-static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
-0xE0, 0xC0, 0x80, 0x00};
-static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
-0x07, 0x03, 0x01, 0x00};
+static unsigned char SLMask[] =
+{0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
+ 0xE0, 0xC0, 0x80, 0x00};
+static unsigned char SRMask[] =
+{0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
+ 0x07, 0x03, 0x01, 0x00};
 
 #define LSB     0
 #define MSB16   1
@@ -108,943 +148,1557 @@ static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
 /*-----------------------------------------------------------------*/
 /* emitcode - writes the code into a file : for now it is simple    */
 /*-----------------------------------------------------------------*/
-static void emitcode (char *inst,char *fmt, ...)
+static void
+emitcode (char *inst, const char *fmt,...)
+{
+  va_list ap;
+  char lb[INITIAL_INLINEASM];
+  char *lbp = lb;
+
+  va_start (ap, fmt);
+
+  if (inst && *inst)
+    {
+      if (fmt && *fmt)
+        {
+          SNPRINTF (lb, sizeof(lb), "%s\t", inst);
+        }
+      else
+        {
+          SNPRINTF (lb, sizeof(lb), "%s", inst);
+        }
+
+      tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
+    }
+  else
+    {
+      tvsprintf (lb, sizeof(lb), fmt, ap);
+    }
+
+  while (isspace ((unsigned char)*lbp))
+    {
+      lbp++;
+    }
+
+  if (lbp && *lbp)
+    {
+      lineCurr = (lineCurr ?
+                  connectLine (lineCurr, newLineNode (lb)) :
+                  (lineHead = newLineNode (lb)));
+    }
+
+  lineCurr->isInline = _G.inLine;
+  lineCurr->isDebug = _G.debugLine;
+  lineCurr->ic = _G.current_iCode;
+  lineCurr->isComment = (*lbp==';');
+  va_end (ap);
+}
+
+static void
+emitLabel (symbol *tlbl)
+{
+  emitcode ("", "%05d$:", tlbl->key + 100);
+}
+
+/*-----------------------------------------------------------------*/
+/* mcs51_emitDebuggerSymbol - associate the current code location  */
+/*   with a debugger symbol                                        */
+/*-----------------------------------------------------------------*/
+void
+mcs51_emitDebuggerSymbol (char * debugSym)
+{
+  _G.debugLine = 1;
+  emitcode ("", "%s ==.", debugSym);
+  _G.debugLine = 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* mova - moves specified value into accumulator                   */
+/*-----------------------------------------------------------------*/
+static void
+mova (const char *x)
+{
+  /* do some early peephole optimization */
+  if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
+    return;
+
+  emitcode("mov", "a,%s", x);
+}
+
+/*-----------------------------------------------------------------*/
+/* movb - moves specified value into register b                    */
+/*-----------------------------------------------------------------*/
+static void
+movb (const char *x)
 {
-    va_list ap;
-    char lb[MAX_INLINEASM];  
-    char *lbp = lb;
+  /* do some early peephole optimization */
+  if (!strncmp(x, "b", 2))
+    return;
 
-    va_start(ap,fmt);   
+  emitcode("mov","b,%s", x);
+}
 
-    if (inst && *inst) {
-       if (fmt && *fmt)
-           sprintf(lb,"%s\t",inst);
-       else
-           sprintf(lb,"%s",inst);
-        vsprintf(lb+(strlen(lb)),fmt,ap);
-    }  else
-        vsprintf(lb,fmt,ap);
+/*-----------------------------------------------------------------*/
+/* movc - moves specified value into the carry                     */
+/*-----------------------------------------------------------------*/
+static void
+movc (const char *s)
+{
+  if (s == zero)
+    CLRC;
+  else if (s == one)
+    SETC;
+  else if (strcmp (s, "c"))
+    {/* it's not in carry already */
+      MOVA (s);
+      /* set C, if a >= 1 */
+      emitcode ("add", "a,#0xff");
+    }
+}
 
-    while (isspace(*lbp)) lbp++;
+/*-----------------------------------------------------------------*/
+/* pushB - saves register B if necessary                           */
+/*-----------------------------------------------------------------*/
+static bool
+pushB (void)
+{
+  bool pushedB = FALSE;
 
-    if (lbp && *lbp) 
-        lineCurr = (lineCurr ?
-                    connectLine(lineCurr,newLineNode(lb)) :
-                    (lineHead = newLineNode(lb)));
-    lineCurr->isInline = _G.inLine;
-    lineCurr->isDebug  = _G.debugLine;
-    va_end(ap);
+  if (BINUSE)
+    {
+      emitcode ("push", "b");
+//    printf("B was in use !\n");
+      pushedB = TRUE;
+    }
+  else
+    {
+      OPINB++;
+    }
+  return pushedB;
 }
 
 /*-----------------------------------------------------------------*/
-/* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
+/* popB - restores value of register B if necessary                */
 /*-----------------------------------------------------------------*/
-static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
+static void
+popB (bool pushedB)
 {
-    bool r0iu = FALSE , r1iu = FALSE;
-    bool r0ou = FALSE , r1ou = FALSE;
+  if (pushedB)
+    {
+      emitcode ("pop", "b");
+    }
+  else
+    {
+      OPINB--;
+    }
+}
 
-    /* the logic: if r0 & r1 used in the instruction
-    then we are in trouble otherwise */
+/*-----------------------------------------------------------------*/
+/* pushReg - saves register                                        */
+/*-----------------------------------------------------------------*/
+static bool
+pushReg (int index, bool bits_pushed)
+{
+  regs * reg = REG_WITH_INDEX (index);
+  if (reg->type == REG_BIT)
+    {
+      if (!bits_pushed)
+        emitcode ("push", "%s", reg->base);
+      return TRUE;
+    }
+  else
+    emitcode ("push", "%s", reg->dname);
+  return bits_pushed;
+}
 
-    /* first check if r0 & r1 are used by this
-    instruction, in which case we are in trouble */
-    if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
-        (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
+/*-----------------------------------------------------------------*/
+/* popReg - restores register                                      */
+/*-----------------------------------------------------------------*/
+static bool
+popReg (int index, bool bits_popped)
+{
+  regs * reg = REG_WITH_INDEX (index);
+  if (reg->type == REG_BIT)
     {
-        goto endOfWorld;      
+      if (!bits_popped)
+        emitcode ("pop", "%s", reg->base);
+      return TRUE;
+    }
+  else
+    emitcode ("pop", "%s", reg->dname);
+  return bits_popped;
+}
+
+/*-----------------------------------------------------------------*/
+/* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
+/*-----------------------------------------------------------------*/
+static regs *
+getFreePtr (iCode * ic, asmop ** aopp, bool result)
+{
+  bool r0iu, r1iu;
+  bool r0ou, r1ou;
+
+  /* the logic: if r0 & r1 used in the instruction
+     then we are in trouble otherwise */
+
+  /* first check if r0 & r1 are used by this
+     instruction, in which case we are in trouble */
+  r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
+  r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
+  if (r0iu && r1iu) {
+      goto endOfWorld;
     }
 
-    r0ou = bitVectBitValue(ic->rMask,R0_IDX);
-    r1ou = bitVectBitValue(ic->rMask,R1_IDX);
+  r0ou = bitVectBitValue (ic->rMask, R0_IDX);
+  r1ou = bitVectBitValue (ic->rMask, R1_IDX);
+
+  /* if no usage of r0 then return it */
+  if (!r0iu && !r0ou)
+    {
+      ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
+      (*aopp)->type = AOP_R0;
 
-    /* if no usage of r0 then return it */
-    if (!r0iu && !r0ou) {
-        ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
-        (*aopp)->type = AOP_R0;
-        
-        return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
+      return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
     }
 
-    /* if no usage of r1 then return it */
-    if (!r1iu && !r1ou) {
-        ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
-        (*aopp)->type = AOP_R1;
+  /* if no usage of r1 then return it */
+  if (!r1iu && !r1ou)
+    {
+      ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
+      (*aopp)->type = AOP_R1;
 
-        return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R1_IDX);
-    }    
+      return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
+    }
 
-    /* now we know they both have usage */
-    /* if r0 not used in this instruction */
-    if (!r0iu) {
-        /* push it if not already pushed */
-        if (!_G.r0Pushed) {
-            emitcode ("push","%s",
-                      mcs51_regWithIdx(R0_IDX)->dname);
-            _G.r0Pushed++ ;
+  /* now we know they both have usage */
+  /* if r0 not used in this instruction */
+  if (!r0iu)
+    {
+      /* push it if not already pushed */
+      if (ic->op == IPUSH)
+        {
+          MOVB (REG_WITH_INDEX (R0_IDX)->dname);
+          R0INB++;
+        }
+      else if (!_G.r0Pushed)
+        {
+          emitcode ("push", "%s",
+                    REG_WITH_INDEX (R0_IDX)->dname);
+          _G.r0Pushed++;
         }
-        
-        ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
-        (*aopp)->type = AOP_R0;
 
-        return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
+      ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
+      (*aopp)->type = AOP_R0;
+
+      return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
     }
 
-    /* if r1 not used then */
+  /* if r1 not used then */
 
-    if (!r1iu) {
-        /* push it if not already pushed */
-        if (!_G.r1Pushed) {
-            emitcode ("push","%s",
-                      mcs51_regWithIdx(R1_IDX)->dname);
-            _G.r1Pushed++ ;
+  if (!r1iu)
+    {
+      /* push it if not already pushed */
+      if (ic->op == IPUSH)
+        {
+          MOVB (REG_WITH_INDEX (R1_IDX)->dname);
+          R1INB++;
+        }
+      else if (!_G.r1Pushed)
+        {
+          emitcode ("push", "%s",
+                    REG_WITH_INDEX (R1_IDX)->dname);
+          _G.r1Pushed++;
         }
-        
-        ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
-        (*aopp)->type = AOP_R1;
-        return mcs51_regWithIdx(R1_IDX);
+
+      ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
+      (*aopp)->type = AOP_R1;
+      return REG_WITH_INDEX (R1_IDX);
+    }
+
+endOfWorld:
+  /* I said end of world, but not quite end of world yet */
+  /* if this is a result then we can push it on the stack */
+  if (result)
+    {
+      (*aopp)->type = AOP_STK;
+      return NULL;
+    }
+  /* in the case that result AND left AND right needs a pointer reg
+     we can safely use the result's */
+  if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
+    {
+      (*aopp)->type = AOP_R0;
+      return REG_WITH_INDEX (R0_IDX);
+    }
+  if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
+    {
+      (*aopp)->type = AOP_R1;
+      return REG_WITH_INDEX (R1_IDX);
+    }
+
+  /* now this is REALLY the end of the world */
+  werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+          "getFreePtr should never reach here");
+  exit (1);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* getTempRegs - initialize an array of pointers to GPR registers */
+/*               that are not in use. Returns 1 if the requested   */
+/*               number of registers were available, 0 otherwise.  */
+/*-----------------------------------------------------------------*/
+int
+getTempRegs(regs **tempRegs, int size, iCode *ic)
+{
+  bitVect * freeRegs;
+  int i;
+  int offset;
+
+  if (!ic)
+    ic = _G.current_iCode;
+  if (!ic)
+    return 0;
+  if (!_G.currentFunc)
+    return 0;
+
+  freeRegs = newBitVect(8);
+  bitVectSetBit (freeRegs, R2_IDX);
+  bitVectSetBit (freeRegs, R3_IDX);
+  bitVectSetBit (freeRegs, R4_IDX);
+  bitVectSetBit (freeRegs, R5_IDX);
+  bitVectSetBit (freeRegs, R6_IDX);
+  bitVectSetBit (freeRegs, R7_IDX);
+
+  if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
+    {
+      bitVect * newfreeRegs;
+      newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
+      freeBitVect(freeRegs);
+      freeRegs = newfreeRegs;
     }
+  freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
 
-endOfWorld :
-    /* I said end of world but not quite end of world yet */
-    /* if this is a result then we can push it on the stack*/
-    if (result) {
-        (*aopp)->type = AOP_STK;    
-        return NULL;
+  offset = 0;
+  for (i=0; i<freeRegs->size; i++)
+    {
+      if (bitVectBitValue(freeRegs,i))
+        tempRegs[offset++] = REG_WITH_INDEX(i);
+      if (offset>=size)
+        {
+          freeBitVect(freeRegs);
+          return 1;
+        }
     }
 
-    piCode(ic,stdout);
-    /* other wise this is true end of the world */
-    werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-           "getFreePtr should never reach here");
-    exit(0);
+  freeBitVect(freeRegs);
+  return 0;
 }
 
+
 /*-----------------------------------------------------------------*/
 /* 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;
+  aop->allocated = 1;
+  return aop;
 }
 
 /*-----------------------------------------------------------------*/
 /* pointerCode - returns the code for a pointer type               */
 /*-----------------------------------------------------------------*/
-static int pointerCode (link *etype)
+static int
+pointerCode (sym_link * etype)
 {
-    int p_type;
 
-    return PTR_TYPE(SPEC_OCLS(etype));
+  return PTR_TYPE (SPEC_OCLS (etype));
 
-/*     if (SPEC_OCLS(etype)->codesp ) { */
-/*     p_type = CPOINTER ;      */
-/*     } */
-/*     else */
-/*     if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
-/*         p_type = FPOINTER ; */
-/*     else */
-/*         if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
-/*             p_type = PPOINTER; */
-/*         else */
-/*             if (SPEC_OCLS(etype) == idata ) */
-/*                 p_type = IPOINTER; */
-/*             else */
-/*                 p_type = POINTER ; */
-/*     return p_type; */
 }
 
 /*-----------------------------------------------------------------*/
-/* aopForSym - for a true symbol                                   */
+/* leftRightUseAcc - returns size of accumulator use by operands   */
 /*-----------------------------------------------------------------*/
-static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
-{
-    asmop *aop;
-    memmap *space= SPEC_OCLS(sym->etype);
-
-    /* if already has one */
-    if (sym->aop)
-        return sym->aop;
-
-    /* assign depending on the storage class */
-    /* if it is on the stack or indirectly addressable */
-    /* space we need to assign either r0 or r1 to it   */    
-    if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
-        sym->aop = aop = newAsmop(0);
-        aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
-        aop->size = getSize(sym->type);
-
-        /* now assign the address of the variable to 
-        the pointer register */
-        if (aop->type != AOP_STK) {
-
-            if (sym->onStack) {
-                    if ( _G.accInUse )
-                        emitcode("push","acc");
-
-                    emitcode("mov","a,_bp");
-                    emitcode("add","a,#0x%02x",
-                             ((sym->stack < 0) ?
-                             ((char)(sym->stack - _G.nRegsSaved )) :
-                             ((char)sym->stack)) & 0xff);
-                    emitcode("mov","%s,a",
-                             aop->aopu.aop_ptr->name);
-
-                    if ( _G.accInUse )
-                        emitcode("pop","acc");
-            } else
-                emitcode("mov","%s,#%s",
-                         aop->aopu.aop_ptr->name,
-                         sym->rname);
-            aop->paged = space->paged;
-        } else
-            aop->aopu.aop_stk = sym->stack;
-        return aop;
-    }
-    
-    if (sym->onStack && options.stack10bit)
-    {
-        /* It's on the 10 bit stack, which is located in
-         * far data space.
-         */
-         
-         if (result)
-         {
-             fprintf(stderr, 
-                    "*** Internal error: 10 bit stack var used as result.\n");
-             emitcode(";", "look at me!");
-         }
-         
-        
-        if ( _G.accInUse )
-               emitcode("push","acc");
-
-        emitcode("mov","a,_bp");
-        emitcode("add","a,#0x%02x",
-                 ((sym->stack < 0) ?
-                   ((char)(sym->stack - _G.nRegsSaved )) :
-                   ((char)sym->stack)) & 0xff);
-        
-        if (/* result */ 1)
-        {
-            emitcode (";", "#switchDPTR(2)");
-        }
-       emitcode ("mov","dpx,#0x40");
-       emitcode ("mov","dph,#0x00");
-       emitcode ("mov", "dpl, a");
-       if (/* result */ 1)
-       {
-           emitcode (";", "#switchDPTR(1)");
-       }
-       
-        if ( _G.accInUse )
-            emitcode("pop","acc");
-            
-        if (/* !result */ 0)
-        {
-           sym->aop = aop = newAsmop(AOP_DPTR);
-       }
-       else
-       {
-           sym->aop = aop = newAsmop(AOP_DPTR2);
-       }
-       aop->size = getSize(sym->type); 
-       return aop;
-    }
-
-    /* if in bit space */
-    if (IN_BITSPACE(space)) {
-        sym->aop = aop = newAsmop (AOP_CRY);
-        aop->aopu.aop_dir = sym->rname ;
-        aop->size = getSize(sym->type);
-        return aop;
-    }
-    /* 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);
-        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 = FPTRSIZE; 
-        return aop;
-    }
-
-    /* only remaining is far space */
-    /* in which case DPTR gets the address */
-    sym->aop = aop = newAsmop(AOP_DPTR);
-    emitcode ("mov","dptr,#%s", sym->rname);
-    aop->size = getSize(sym->type);
-
-    /* if it is in code space */
-    if (IN_CODESPACE(space))
-        aop->code = 1;
-
-    return aop;     
+static int
+leftRightUseAcc(iCode *ic)
+{
+  operand *op;
+  int size;
+  int accuseSize = 0;
+  int accuse = 0;
+
+  if (!ic)
+    {
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+              "null iCode pointer");
+      return 0;
+    }
+
+  if (ic->op == IFX)
+    {
+      op = IC_COND (ic);
+      if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
+        {
+          accuse = 1;
+          size = getSize (OP_SYMBOL (op)->type);
+          if (size>accuseSize)
+            accuseSize = size;
+        }
+    }
+  else if (ic->op == JUMPTABLE)
+    {
+      op = IC_JTCOND (ic);
+      if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
+        {
+          accuse = 1;
+          size = getSize (OP_SYMBOL (op)->type);
+          if (size>accuseSize)
+            accuseSize = size;
+        }
+    }
+  else
+    {
+      op = IC_LEFT (ic);
+      if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
+        {
+          accuse = 1;
+          size = getSize (OP_SYMBOL (op)->type);
+          if (size>accuseSize)
+            accuseSize = size;
+        }
+      op = IC_RIGHT (ic);
+      if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
+        {
+          accuse = 1;
+          size = getSize (OP_SYMBOL (op)->type);
+          if (size>accuseSize)
+            accuseSize = size;
+        }
+    }
+
+  if (accuseSize)
+    return accuseSize;
+  else
+    return accuse;
 }
 
 /*-----------------------------------------------------------------*/
-/* aopForRemat - rematerialzes an object                           */
+/* aopForSym - for a true symbol                                   */
 /*-----------------------------------------------------------------*/
-static asmop *aopForRemat (symbol *sym)
+static asmop *
+aopForSym (iCode * ic, symbol * sym, bool result)
 {
-    char *s = buffer;   
-    iCode *ic = sym->rematiCode;
-    asmop *aop = newAsmop(AOP_IMMD);
+  asmop *aop;
+  memmap *space;
+  bool accuse = leftRightUseAcc (ic) || _G.accInUse;
 
-    while (1) {
+  wassertl (ic != NULL, "Got a null iCode");
+  wassertl (sym != NULL, "Got a null symbol");
 
-        /* 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 ;
+  space = SPEC_OCLS (sym->etype);
+
+  /* if already has one */
+  if (sym->aop)
+    {
+      sym->aop->allocated++;
+      return sym->aop;
+    }
+
+  /* assign depending on the storage class */
+  /* if it is on the stack or indirectly addressable */
+  /* space we need to assign either r0 or r1 to it   */
+  if (sym->onStack || sym->iaccess)
+    {
+      sym->aop = aop = newAsmop (0);
+      aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
+      aop->size = getSize (sym->type);
+
+      /* now assign the address of the variable to
+         the pointer register */
+      if (aop->type != AOP_STK)
+        {
+          if (sym->onStack)
+            {
+              signed char offset = ((sym->stack < 0) ?
+                         ((signed char) (sym->stack - _G.nRegsSaved)) :
+                         ((signed char) sym->stack)) & 0xff;
+
+              if ((abs(offset) <= 3) ||
+                  (accuse && (abs(offset) <= 7)))
+                {
+                  emitcode ("mov", "%s,%s",
+                            aop->aopu.aop_ptr->name, SYM_BP (sym));
+                  while (offset < 0)
+                    {
+                      emitcode ("dec", aop->aopu.aop_ptr->name);
+                      offset++;
+                    }
+                  while (offset > 0)
+                    {
+                      emitcode ("inc", aop->aopu.aop_ptr->name);
+                      offset--;
+                    }
+                }
+              else
+                {
+                  if (accuse)
+                    emitcode ("push", "acc");
+                  emitcode ("mov", "a,%s", SYM_BP (sym));
+                  emitcode ("add", "a,#0x%02x", offset);
+                  emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
+                  if (accuse)
+                    emitcode ("pop", "acc");
+                }
+            }
+          else
+            {
+              emitcode ("mov", "%s,#%s",
+                        aop->aopu.aop_ptr->name,
+                        sym->rname);
+            }
+          aop->paged = space->paged;
         }
+      else
+        aop->aopu.aop_stk = sym->stack;
+      return aop;
+    }
 
-        /* we reached the end */
-        sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
-        break;
+  /* if in bit space */
+  if (IN_BITSPACE (space))
+    {
+      sym->aop = aop = newAsmop (AOP_CRY);
+      aop->aopu.aop_dir = sym->rname;
+      aop->size = getSize (sym->type);
+      return aop;
+    }
+  /* if it is in direct space */
+  if (IN_DIRSPACE (space))
+    {
+      //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
+      //printTypeChainRaw(sym->type, NULL);
+      //printf("space = %s\n", space ? space->sname : "NULL");
+      sym->aop = aop = newAsmop (AOP_DIR);
+      aop->aopu.aop_dir = sym->rname;
+      aop->size = getSize (sym->type);
+      return aop;
+    }
+
+  /* special case for a function */
+  if (IS_FUNC (sym->type))
+    {
+      sym->aop = aop = newAsmop (AOP_IMMD);
+      aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
+      aop->size = getSize (sym->type);
+      return aop;
+    }
+
+  /* only remaining is far space */
+  /* in which case DPTR gets the address */
+  sym->aop = aop = newAsmop (AOP_DPTR);
+  emitcode ("mov", "dptr,#%s", sym->rname);
+  aop->size = getSize (sym->type);
+
+  /* if it is in code space */
+  if (IN_CODESPACE (space))
+    aop->code = 1;
+
+  return aop;
+}
+
+/*-----------------------------------------------------------------*/
+/* aopForRemat - rematerialzes an object                           */
+/*-----------------------------------------------------------------*/
+static asmop *
+aopForRemat (symbol * sym)
+{
+  iCode *ic = sym->rematiCode;
+  asmop *aop = newAsmop (AOP_IMMD);
+  int ptr_type = 0;
+  int val = 0;
+
+  for (;;)
+    {
+      if (ic->op == '+')
+        val += (int) operandLitValue (IC_RIGHT (ic));
+      else if (ic->op == '-')
+        val -= (int) operandLitValue (IC_RIGHT (ic));
+      else if (IS_CAST_ICODE(ic)) {
+              sym_link *from_type = operandType(IC_RIGHT(ic));
+              aop->aopu.aop_immd.from_cast_remat = 1;
+              ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
+              ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
+              continue;
+      } else break;
+
+      ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+    }
+
+  if (val)
+    {
+      SNPRINTF (buffer, sizeof(buffer),
+                "(%s %c 0x%04x)",
+                OP_SYMBOL (IC_LEFT (ic))->rname,
+                val >= 0 ? '+' : '-',
+                abs (val) & 0xffff);
+    }
+  else
+    {
+      strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
+    }
+
+  aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
+  /* set immd2 field if required */
+  if (aop->aopu.aop_immd.from_cast_remat)
+    {
+      SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
+      aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
     }
 
-    ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
-    strcpy(aop->aopu.aop_immd,buffer);    
-    return aop;        
+  return aop;
 }
 
 /*-----------------------------------------------------------------*/
 /* regsInCommon - two operands have some registers in common       */
 /*-----------------------------------------------------------------*/
-static bool regsInCommon (operand *op1, operand *op2)
+static 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                                        */
 /*-----------------------------------------------------------------*/
-static bool operandsEqu ( operand *op1, operand *op2)
+static 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're 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 TRUE ;
+  /* if they are the same */
+  if (sym1 == sym2)
+    return TRUE;
 
-    if (strcmp(sym1->rname,sym2->rname) == 0)
-        return TRUE;
+  /* if they have the same rname */
+  if (sym1->rname[0] && sym2->rname[0] &&
+      strcmp (sym1->rname, sym2->rname) == 0 &&
+      !(IS_PARM (op2) && IS_ITEMP (op1)))
+    return TRUE;
 
+  /* if left is a tmp & right is not */
+  if (IS_ITEMP (op1) &&
+      !IS_ITEMP (op2) &&
+      sym1->isspilt &&
+      (sym1->usl.spillLoc == sym2))
+    return TRUE;
 
-    /* if left is a tmp & right is not */
-    if (IS_ITEMP(op1)  && 
-        !IS_ITEMP(op2) &&
-        sym1->isspilt  &&
-        (sym1->usl.spillLoc == sym2))
-        return TRUE;
+  if (IS_ITEMP (op2) &&
+      !IS_ITEMP (op1) &&
+      sym2->isspilt &&
+      sym1->level > 0 &&
+      (sym2->usl.spillLoc == sym1))
+    return TRUE;
+
+  return FALSE;
+}
 
-    if (IS_ITEMP(op2)  && 
-        !IS_ITEMP(op1) &&
-        sym2->isspilt  &&
-       sym1->level > 0 &&
-        (sym2->usl.spillLoc == sym1))
-        return TRUE ;
+/*-----------------------------------------------------------------*/
+/* sameByte - two asmops have the same address at given offsets    */
+/*-----------------------------------------------------------------*/
+static bool
+sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
+{
+  if (aop1 == aop2 && off1 == off2)
+    return TRUE;
+
+  if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
+    return FALSE;
 
-    return FALSE ;
+  if (aop1->type != aop2->type)
+    return FALSE;
+
+  if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
+    return FALSE;
+
+  return TRUE;
 }
 
 /*-----------------------------------------------------------------*/
 /* sameRegs - two asmops have the same registers                   */
 /*-----------------------------------------------------------------*/
-static bool sameRegs (asmop *aop1, asmop *aop2 )
+static bool
+sameRegs (asmop * aop1, asmop * aop2)
 {
-    int i;
+  int i;
 
-    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 && aop1->type != AOP_CRY)
+    return FALSE;
 
-    if (aop1->size != aop2->size )
-        return FALSE ;
+  if (aop1->type != aop2->type)
+    return FALSE;
 
-    for (i = 0 ; i < aop1->size ; i++ )
-        if (aop1->aopu.aop_reg[i] !=
-            aop2->aopu.aop_reg[i] )
-            return FALSE ;
+  if (aop1->size != aop2->size)
+    return FALSE;
 
-    return TRUE ;
+  for (i = 0; i < aop1->size; i++)
+    if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
+      return FALSE;
+
+  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)
 {
-    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 the underlying symbol has a aop */
-    if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
-        op->aop = OP_SYMBOL(op)->aop;
-        return;
+  /* if already has a asmop then continue */
+  if (op->aop)
+    {
+      op->aop->allocated++;
+      return;
     }
 
-    /* if this is a true symbol */
-    if (IS_TRUE_SYMOP(op)) {    
-        op->aop = aopForSym(ic,OP_SYMBOL(op),result);
-        return ;
+  /* if the underlying symbol has a aop */
+  if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
+    {
+      op->aop = OP_SYMBOL (op)->aop;
+      op->aop->allocated++;
+      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 */
+  /* if this is a true symbol */
+  if (IS_TRUE_SYMOP (op))
+    {
+      op->aop = aopForSym (ic, OP_SYMBOL (op), result);
+      return;
+    }
 
-    sym = OP_SYMBOL(op);
+  /* this is a temporary : this has
+     only five choices :
+     a) register
+     b) spillocation
+     c) rematerialize
+     d) conditional
+     e) can be a return use only */
 
+  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) {
+  /* 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;
+      /* 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 < fReturnSize ; i++ )
-                aop->aopu.aop_str[i] = fReturn[i];
-            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;
         }
 
-        /* else spill location  */
-        sym->aop = op->aop = aop = 
-                                  aopForSym(ic,sym->usl.spillLoc,result);
-        aop->size = getSize(sym->type);
-        return;
+      if (sym->ruonly)
+        {
+          unsigned i;
+
+          aop = op->aop = sym->aop = newAsmop (AOP_STR);
+          aop->size = getSize (sym->type);
+          for (i = 0; i < fReturnSizeMCS51; i++)
+            aop->aopu.aop_str[i] = fReturn[i];
+          return;
+        }
+
+      if (sym->usl.spillLoc)
+        {
+          asmop *oldAsmOp = NULL;
+
+          if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
+            {
+              /* force a new aop if sizes differ */
+              oldAsmOp = sym->usl.spillLoc->aop;
+              sym->usl.spillLoc->aop = NULL;
+            }
+          sym->aop = op->aop = aop =
+                     aopForSym (ic, sym->usl.spillLoc, result);
+          if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
+            {
+              /* Don't reuse the new aop, go with the last one */
+              sym->usl.spillLoc->aop = oldAsmOp;
+            }
+          aop->size = getSize (sym->type);
+          return;
+        }
+
+      /* else must be a dummy iTemp */
+      sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
+      aop->size = getSize (sym->type);
+      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];
+  /* if the type is a bit register */
+  if (sym->regType == REG_BIT)
+    {
+      sym->aop = op->aop = aop = newAsmop (AOP_CRY);
+      aop->size = sym->nRegs;//1???
+      aop->aopu.aop_reg[0] = sym->regs[0];
+      aop->aopu.aop_dir = sym->regs[0]->name;
+      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];
 }
 
 /*-----------------------------------------------------------------*/
 /* freeAsmop - free up the asmop given to an operand               */
 /*----------------------------------------------------------------*/
-static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
-{   
-    asmop *aop ;
-
-    if (!op)
-        aop = aaop;
-    else 
-        aop = op->aop;
-
-    if (!aop)
-        return ;
-
-    if (aop->freed)
-        goto dealloc; 
-
-    aop->freed = 1;
-
-    /* depending on the asmop type only three cases need work AOP_RO
-       , AOP_R1 && AOP_STK */
-    switch (aop->type) {
-        case AOP_R0 :
-            if (_G.r0Pushed ) {
-                if (pop) {
-                    emitcode ("pop","ar0");     
-                    _G.r0Pushed--;
-                }
-            }
-            bitVectUnSetBit(ic->rUsed,R0_IDX);
-            break;
+static void
+freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
+{
+  asmop *aop;
 
-        case AOP_R1 :
-            if (_G.r1Pushed ) {
-                if (pop) {
-                    emitcode ("pop","ar1");
-                    _G.r1Pushed--;
-                }
-            }
-            bitVectUnSetBit(ic->rUsed,R1_IDX);          
-            break;
+  if (!op)
+    aop = aaop;
+  else
+    aop = op->aop;
 
-        case AOP_STK :
-        {
-            int sz = aop->size;    
-            int stk = aop->aopu.aop_stk + aop->size;
-            bitVectUnSetBit(ic->rUsed,R0_IDX);
-            bitVectUnSetBit(ic->rUsed,R1_IDX);          
+  if (!aop)
+    return;
 
-            getFreePtr(ic,&aop,FALSE);
-            
-            if (options.stack10bit)
+  aop->allocated--;
+
+  if (aop->allocated)
+    goto dealloc;
+
+  /* depending on the asmop type only three cases need work
+     AOP_R0, AOP_R1 & AOP_STK */
+  switch (aop->type)
+    {
+    case AOP_R0:
+      if (R0INB)
+        {
+          emitcode ("mov", "r0,b");
+          R0INB--;
+        }
+      else if (_G.r0Pushed)
+        {
+          if (pop)
             {
-                /* I'm not sure what to do here yet... */
-                /* #STUB */
-               fprintf(stderr, 
-                       "*** Warning: probably generating bad code for "
-                       "10 bit stack mode.\n");
-            }
-            
-            if (stk) {
-                emitcode ("mov","a,_bp");
-                emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
-                emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
-            } else {
-                emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
+              emitcode ("pop", "ar0");
+              _G.r0Pushed--;
             }
+        }
+      bitVectUnSetBit (ic->rUsed, R0_IDX);
+      break;
 
-            while (sz--) {
-                emitcode("pop","acc");
-                emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
-                if (!sz) break;
-                emitcode("dec","%s",aop->aopu.aop_ptr->name);
-            }
-            op->aop = aop;
-            freeAsmop(op,NULL,ic,TRUE);
-            if (_G.r0Pushed) {
-                emitcode("pop","ar0");
-                _G.r0Pushed--;
+    case AOP_R1:
+      if (R1INB)
+        {
+          emitcode ("mov", "r1,b");
+          R1INB--;
+        }
+      else if (_G.r1Pushed)
+        {
+          if (pop)
+            {
+              emitcode ("pop", "ar1");
+              _G.r1Pushed--;
             }
-
-            if (_G.r1Pushed) {
-                emitcode("pop","ar1");
-                _G.r1Pushed--;
-            }       
         }
+      bitVectUnSetBit (ic->rUsed, R1_IDX);
+      break;
+
+    case AOP_STK:
+      {
+        int sz = aop->size;
+        int stk = aop->aopu.aop_stk + aop->size - 1;
+        bitVectUnSetBit (ic->rUsed, R0_IDX);
+        bitVectUnSetBit (ic->rUsed, R1_IDX);
+
+        getFreePtr (ic, &aop, FALSE);
+
+        if (stk)
+          {
+            emitcode ("mov", "a,_bp");
+            emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
+            emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
+          }
+        else
+          {
+            emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
+          }
+
+        while (sz--)
+          {
+            emitcode ("pop", "acc");
+            emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
+            if (!sz)
+              break;
+            emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
+          }
+        op->aop = aop;
+        freeAsmop (op, NULL, ic, TRUE);
+        if (_G.r1Pushed)
+          {
+            emitcode ("pop", "ar1");
+            _G.r1Pushed--;
+          }
+        if (_G.r0Pushed)
+          {
+            emitcode ("pop", "ar0");
+            _G.r0Pushed--;
+          }
+      }
+      break;
     }
 
 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;
+        }
+    }
+}
+
+/*------------------------------------------------------------------*/
+/* freeForBranchAsmop - partial free up of Asmop for a branch; just */
+/*                      pop r0 or r1 off stack if pushed            */
+/*------------------------------------------------------------------*/
+static void
+freeForBranchAsmop (operand * op)
+{
+  asmop *aop;
+
+  if (!op)
+    return;
+
+  aop = op->aop;
+
+  if (!aop)
+    return;
+
+  if (!aop->allocated)
+    return;
+
+  switch (aop->type)
+    {
+    case AOP_R0:
+      if (R0INB)
+        {
+          emitcode ("mov", "r0,b");
+        }
+      else if (_G.r0Pushed)
+        {
+          emitcode ("pop", "ar0");
         }
+      break;
+
+    case AOP_R1:
+      if (R1INB)
+        {
+          emitcode ("mov", "r1,b");
+        }
+      else if (_G.r1Pushed)
+        {
+          emitcode ("pop", "ar1");
+        }
+      break;
+
+    case AOP_STK:
+      {
+        int sz = aop->size;
+        int stk = aop->aopu.aop_stk + aop->size - 1;
+
+        emitcode ("mov", "b,r0");
+        if (stk)
+          {
+            emitcode ("mov", "a,_bp");
+            emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
+            emitcode ("mov", "r0,a");
+          }
+        else
+          {
+            emitcode ("mov", "r0,_bp");
+          }
+
+        while (sz--)
+          {
+            emitcode ("pop", "acc");
+            emitcode ("mov", "@r0,a");
+            if (!sz)
+              break;
+            emitcode ("dec", "r0");
+          }
+        emitcode ("mov", "r0,b");
+      }
     }
+
 }
 
 /*-----------------------------------------------------------------*/
-/* aopGet - for fetching value of the aop                          */
+/* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
+/*                 clobber the accumulator                         */
 /*-----------------------------------------------------------------*/
-static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
+static bool
+aopGetUsesAcc (operand * oper, int offset)
+{
+  asmop * aop = AOP (oper);
+
+  if (offset > (aop->size - 1))
+    return FALSE;
+
+  switch (aop->type)
+    {
+
+    case AOP_R0:
+    case AOP_R1:
+      if (aop->paged)
+        return TRUE;
+      return FALSE;
+    case AOP_DPTR:
+      return TRUE;
+    case AOP_IMMD:
+      return FALSE;
+    case AOP_DIR:
+      return FALSE;
+    case AOP_REG:
+      wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
+      return FALSE;
+    case AOP_CRY:
+      return TRUE;
+    case AOP_ACC:
+      if (offset)
+        return FALSE;
+      return TRUE;
+    case AOP_LIT:
+      return FALSE;
+    case AOP_STR:
+      if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
+        return TRUE;
+      return FALSE;
+    case AOP_DUMMY:
+      return FALSE;
+    default:
+      /* Error case --- will have been caught already */
+      wassert(0);
+      return FALSE;
+    }
+}
+
+/*-------------------------------------------------------------------*/
+/* aopGet - for fetching value of the aop                            */
+/*-------------------------------------------------------------------*/
+static char *
+aopGet (operand * oper, int offset, bool bit16, bool dname)
 {
-    char *s = buffer ;
-    char *rs;
+  asmop * aop = AOP (oper);
 
-    /* offset is greater than
-    size then zero */
-    if (offset > (aop->size - 1) &&
-        aop->type != AOP_LIT)
-        return zero;
+  /* 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_DUMMY:
+      return zero;
 
-    /* depending on type */
-    switch (aop->type) {
-       
     case AOP_R0:
     case AOP_R1:
-       /* if we need to increment it */       
-       while (offset > aop->coff) {        
-           emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
-           aop->coff++;
-       }
-       
-       while (offset < aop->coff) {
-           emitcode("dec","%s",aop->aopu.aop_ptr->name);
-           aop->coff--;
-       }
-       
-       aop->coff = offset ;
-       if (aop->paged) {
-           emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
-           return (dname ? "acc" : "a");
-       }       
-       sprintf(s,"@%s",aop->aopu.aop_ptr->name);
-       ALLOC_ATOMIC(rs,strlen(s)+1);
-       strcpy(rs,s);   
-       return rs;
-       
+      /* if we need to increment it */
+      while (offset > aop->coff)
+        {
+          emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
+          aop->coff++;
+        }
+
+      while (offset < aop->coff)
+        {
+          emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
+          aop->coff--;
+        }
+
+      aop->coff = offset;
+      if (aop->paged)
+        {
+          emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
+          return (dname ? "acc" : "a");
+        }
+      SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
+      return Safe_strdup(buffer);
+
     case AOP_DPTR:
-    case AOP_DPTR2:
-    
-       if (aop->type == AOP_DPTR2)
-       {
-           emitcode (";", "#switchDPTR(2)");
-       }
-    
-       while (offset > aop->coff) {
-           emitcode ("inc","dptr");
-           aop->coff++;
-       }
-       
-       while (offset < aop->coff) {        
-           emitcode("lcall","__decdptr");
-           aop->coff--;
-       }
-       
-       aop->coff = offset;
-       if (aop->code) {
-           emitcode("clr","a");
-           emitcode("movc","a,@a+dptr");
-        }
-       else
-           emitcode("movx","a,@dptr");
-           
-       if (aop->type == AOP_DPTR2)
-       {
-           emitcode (";", "#switchDPTR(1)");
-       }           
-           
-       return (dname ? "acc" : "a");
-       
-       
+      if (aop->code && aop->coff==0 && offset>=1) {
+        emitcode ("mov", "a,#0x%02x", offset);
+        emitcode ("movc", "a,@a+dptr");
+        return (dname ? "acc" : "a");
+      }
+
+      while (offset > aop->coff)
+        {
+          emitcode ("inc", "dptr");
+          aop->coff++;
+        }
+
+      while (offset < aop->coff)
+        {
+          emitcode ("lcall", "__decdptr");
+          aop->coff--;
+        }
+
+      aop->coff = offset;
+      if (aop->code)
+        {
+          emitcode ("clr", "a");
+          emitcode ("movc", "a,@a+dptr");
+        }
+      else
+        {
+          emitcode ("movx", "a,@dptr");
+        }
+      return (dname ? "acc" : "a");
+
     case AOP_IMMD:
-       if (bit16) 
-           sprintf (s,"#(%s)",aop->aopu.aop_immd);
-       else
-           if (offset) 
-               sprintf(s,"#(%s >> %d)",
-                       aop->aopu.aop_immd,
-                       offset*8);
-           else
-               sprintf(s,"#%s",
-                       aop->aopu.aop_immd);
-       ALLOC_ATOMIC(rs,strlen(s)+1);
-       strcpy(rs,s);   
-       return rs;
-       
+      if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
+        {
+          SNPRINTF(buffer, sizeof(buffer),
+                   "%s",aop->aopu.aop_immd.aop_immd2);
+        }
+      else if (bit16)
+        {
+          SNPRINTF(buffer, sizeof(buffer),
+                   "#%s", aop->aopu.aop_immd.aop_immd1);
+        }
+      else if (offset)
+        {
+          SNPRINTF (buffer, sizeof(buffer),
+                    "#(%s >> %d)",
+                    aop->aopu.aop_immd.aop_immd1,
+                    offset * 8);
+        }
+      else
+        {
+          SNPRINTF (buffer, sizeof(buffer),
+                    "#%s",
+                    aop->aopu.aop_immd.aop_immd1);
+        }
+      return Safe_strdup(buffer);
+
     case AOP_DIR:
-       if (offset)
-           sprintf(s,"(%s + %d)",
-                   aop->aopu.aop_dir,
-                   offset);
-       else
-           sprintf(s,"%s",aop->aopu.aop_dir);
-       ALLOC_ATOMIC(rs,strlen(s)+1);
-       strcpy(rs,s);   
-       return rs;
-       
+      if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
+        {
+          SNPRINTF (buffer, sizeof(buffer),
+                    "(%s >> %d)",
+                    aop->aopu.aop_dir, offset * 8);
+        }
+      else if (offset)
+        {
+          SNPRINTF (buffer, sizeof(buffer),
+                    "(%s + %d)",
+                    aop->aopu.aop_dir,
+                    offset);
+        }
+      else
+        {
+          SNPRINTF (buffer, sizeof(buffer),
+                    "%s",
+                    aop->aopu.aop_dir);
+        }
+
+      return Safe_strdup(buffer);
+
     case AOP_REG:
-       if (dname) 
-           return aop->aopu.aop_reg[offset]->dname;
-       else
-           return aop->aopu.aop_reg[offset]->name;
-       
+      if (dname)
+        return aop->aopu.aop_reg[offset]->dname;
+      else
+        return aop->aopu.aop_reg[offset]->name;
+
     case AOP_CRY:
-       emitcode("clr","a");
-       emitcode("mov","c,%s",aop->aopu.aop_dir);
-       emitcode("rlc","a") ;
-       return (dname ? "acc" : "a");
-       
+      emitcode ("clr", "a");
+      emitcode ("mov", "c,%s", aop->aopu.aop_dir);
+      emitcode ("rlc", "a");
+      return (dname ? "acc" : "a");
+
     case AOP_ACC:
-       if (!offset && dname)
-           return "acc";
-       return aop->aopu.aop_str[offset];
+      if (!offset && dname)
+        return "acc";
+      return aop->aopu.aop_str[offset];
 
     case AOP_LIT:
-       return aopLiteral (aop->aopu.aop_lit,offset);
-       
+      return aopLiteral (aop->aopu.aop_lit, offset);
+
     case AOP_STR:
-       aop->coff = offset ;
-       if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
-           dname)
-           return "acc";
-       
-       return aop->aopu.aop_str[offset];
-       
+      aop->coff = offset;
+      if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
+          dname)
+        return "acc";
+
+      return aop->aopu.aop_str[offset];
+
     }
 
-    werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-           "aopget got unsupported aop->type");
-    exit(0);
+  werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+          "aopget got unsupported aop->type");
+  exit (1);
+}
+
+/*-----------------------------------------------------------------*/
+/* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
+/*                 clobber the accumulator                         */
+/*-----------------------------------------------------------------*/
+static bool
+aopPutUsesAcc (operand * oper, const char *s, int offset)
+{
+  asmop * aop = AOP (oper);
+
+  if (offset > (aop->size - 1))
+    return FALSE;
+
+  switch (aop->type)
+    {
+    case AOP_DUMMY:
+      return TRUE;
+    case AOP_DIR:
+      return FALSE;
+    case AOP_REG:
+      wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
+      return FALSE;
+    case AOP_DPTR:
+      return TRUE;
+    case AOP_R0:
+    case AOP_R1:
+      return ((aop->paged) || (*s == '@'));
+    case AOP_STK:
+      return (*s == '@');
+    case AOP_CRY:
+      return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
+    case AOP_STR:
+      return FALSE;
+    case AOP_IMMD:
+      return FALSE;
+    case AOP_ACC:
+      return FALSE;
+    default:
+      /* Error case --- will have been caught already */
+      wassert(0);
+      return FALSE;
+    }
 }
+
 /*-----------------------------------------------------------------*/
-/* aopPut - puts a string for a aop                                */
+/* aopPut - puts a string for a aop and indicates if acc is in use */
 /*-----------------------------------------------------------------*/
-static void aopPut (asmop *aop, char *s, int offset)
+static bool
+aopPut (operand * result, const char *s, int offset)
 {
-    char *d = buffer ;
-    symbol *lbl ;
+  bool bvolatile = isOperandVolatile (result, FALSE);
+  bool accuse = FALSE;
+  asmop * aop = AOP (result);
 
-    if (aop->size && offset > ( aop->size - 1)) {
-        werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-               "aopPut got offset > aop->size");
-        exit(0);
+  if (aop->size && offset > (aop->size - 1))
+    {
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+              "aopPut got offset > aop->size");
+      exit (1);
     }
 
-    /* will assign value to value */
-    /* depending on where it is ofcourse */
-    switch (aop->type) {
+  /* will assign value to value */
+  /* depending on where it is ofcourse */
+  switch (aop->type)
+    {
+    case AOP_DUMMY:
+      MOVA (s);         /* read s in case it was volatile */
+      accuse = TRUE;
+      break;
+
     case AOP_DIR:
-       if (offset)
-           sprintf(d,"(%s + %d)",
-                   aop->aopu.aop_dir,offset);
-       else
-           sprintf(d,"%s",aop->aopu.aop_dir);
-       
-       if (strcmp(d,s))
-           emitcode("mov","%s,%s",d,s);
-       
-       break;
-       
+      if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
+        {
+          SNPRINTF (buffer, sizeof(buffer),
+                    "(%s >> %d)",
+                    aop->aopu.aop_dir, offset * 8);
+        }
+      else if (offset)
+        {
+          SNPRINTF (buffer, sizeof(buffer),
+                    "(%s + %d)",
+                    aop->aopu.aop_dir, offset);
+        }
+      else
+        {
+          SNPRINTF (buffer, sizeof(buffer),
+                    "%s",
+                    aop->aopu.aop_dir);
+        }
+
+      if (strcmp (buffer, s) || bvolatile)
+        {
+          emitcode ("mov", "%s,%s", buffer, s);
+        }
+      if (!strcmp (buffer, "acc"))
+        {
+          accuse = TRUE;
+        }
+      break;
+
     case AOP_REG:
-       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
-           strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
-           if (*s == '@'           ||
-               strcmp(s,"r0") == 0 ||
-               strcmp(s,"r1") == 0 ||
-               strcmp(s,"r2") == 0 ||
-               strcmp(s,"r3") == 0 ||
-               strcmp(s,"r4") == 0 ||
-               strcmp(s,"r5") == 0 ||
-               strcmp(s,"r6") == 0 || 
-               strcmp(s,"r7") == 0 )
-               emitcode("mov","%s,%s",
-                        aop->aopu.aop_reg[offset]->dname,s);
-           else
-               emitcode("mov","%s,%s",
-                        aop->aopu.aop_reg[offset]->name,s);
-       }
-       break;
-       
+      if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
+          strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
+        {
+          if (*s == '@' ||
+              strcmp (s, "r0") == 0 ||
+              strcmp (s, "r1") == 0 ||
+              strcmp (s, "r2") == 0 ||
+              strcmp (s, "r3") == 0 ||
+              strcmp (s, "r4") == 0 ||
+              strcmp (s, "r5") == 0 ||
+              strcmp (s, "r6") == 0 ||
+              strcmp (s, "r7") == 0)
+            {
+              emitcode ("mov", "%s,%s",
+                        aop->aopu.aop_reg[offset]->dname, s);
+            }
+          else
+            {
+              emitcode ("mov", "%s,%s",
+                        aop->aopu.aop_reg[offset]->name, s);
+            }
+        }
+      break;
+
     case AOP_DPTR:
-    case AOP_DPTR2:
-    
-        if (aop->type == AOP_DPTR2)
-       {
-           emitcode (";", "#switchDPTR(2)");
-       }
-    
-       if (aop->code) {
-           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-                  "aopPut writting to code space");
-           exit(0);
-       }
-       
-       while (offset > aop->coff) {
-           aop->coff++;
-           emitcode ("inc","dptr");
-       }
-       
-       while (offset < aop->coff) {
-           aop->coff-- ;
-           emitcode("lcall","__decdptr");
-       }
-       
-       aop->coff = offset;
-       
-       /* if not in accumulater */
-       MOVA(s);        
-       
-       emitcode ("movx","@dptr,a");
-       
-    if (aop->type == AOP_DPTR2)
-       {
-           emitcode (";", "#switchDPTR(1)");
-       }       
-       break;
-       
+      if (aop->code)
+        {
+          werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                  "aopPut writing to code space");
+          exit (1);
+        }
+
+      while (offset > aop->coff)
+        {
+          aop->coff++;
+          emitcode ("inc", "dptr");
+        }
+
+      while (offset < aop->coff)
+        {
+          aop->coff--;
+          emitcode ("lcall", "__decdptr");
+        }
+
+      aop->coff = offset;
+
+      /* if not in accumulator */
+      MOVA (s);
+
+      emitcode ("movx", "@dptr,a");
+      break;
+
     case AOP_R0:
     case AOP_R1:
-       while (offset > aop->coff) {
-           aop->coff++;
-           emitcode("inc","%s",aop->aopu.aop_ptr->name);
-       }
-       while (offset < aop->coff) {
-           aop->coff-- ;
-           emitcode ("dec","%s",aop->aopu.aop_ptr->name);
-       }
-       aop->coff = offset;
-       
-       if (aop->paged) {
-           MOVA(s);           
-           emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
-           
-       } else
-           if (*s == '@') {
-               MOVA(s);
-               emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
-           } else
-               if (strcmp(s,"r0") == 0 ||
-                   strcmp(s,"r1") == 0 ||
-                   strcmp(s,"r2") == 0 ||
-                   strcmp(s,"r3") == 0 ||
-                   strcmp(s,"r4") == 0 ||
-                   strcmp(s,"r5") == 0 ||
-                   strcmp(s,"r6") == 0 || 
-                   strcmp(s,"r7") == 0 ) {
-                   char buffer[10];
-                   sprintf(buffer,"a%s",s);
-                   emitcode("mov","@%s,%s",
-                            aop->aopu.aop_ptr->name,buffer);
-               } else
-                   emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
-       
-       break;
-       
+      while (offset > aop->coff)
+        {
+          aop->coff++;
+          emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
+        }
+      while (offset < aop->coff)
+        {
+          aop->coff--;
+          emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
+        }
+      aop->coff = offset;
+
+      if (aop->paged)
+        {
+          MOVA (s);
+          emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
+        }
+      else if (*s == '@')
+        {
+          MOVA (s);
+          emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
+        }
+      else if (strcmp (s, "r0") == 0 ||
+               strcmp (s, "r1") == 0 ||
+               strcmp (s, "r2") == 0 ||
+               strcmp (s, "r3") == 0 ||
+               strcmp (s, "r4") == 0 ||
+               strcmp (s, "r5") == 0 ||
+               strcmp (s, "r6") == 0 ||
+               strcmp (s, "r7") == 0)
+        {
+          char buffer[10];
+          SNPRINTF (buffer, sizeof(buffer), "a%s", s);
+          emitcode ("mov", "@%s,%s",
+                    aop->aopu.aop_ptr->name, buffer);
+        }
+      else
+        {
+          emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
+        }
+      break;
+
     case AOP_STK:
-       if (strcmp(s,"a") == 0)
-           emitcode("push","acc");
-       else
-           emitcode("push","%s",s);
-       
-       break;
-       
+      if (strcmp (s, "a") == 0)
+        emitcode ("push", "acc");
+      else
+        if (*s=='@') {
+          MOVA(s);
+          emitcode ("push", "acc");
+        } else {
+          emitcode ("push", s);
+        }
+
+      break;
+
     case AOP_CRY:
-       /* if bit variable */
-       if (!aop->aopu.aop_dir) {
-           emitcode("clr","a");
-           emitcode("rlc","a");
-       } else {
-           if (s == zero) 
-               emitcode("clr","%s",aop->aopu.aop_dir);
-           else
-               if (s == one)
-                   emitcode("setb","%s",aop->aopu.aop_dir);
-               else
-                   if (!strcmp(s,"c"))
-                       emitcode("mov","%s,c",aop->aopu.aop_dir);
-                   else {
-                       lbl = newiTempLabel(NULL);
-                       
-                       if (strcmp(s,"a")) {
-                           MOVA(s);
-                       }
-                       emitcode("clr","c");
-                       emitcode("jz","%05d$",lbl->key+100);
-                       emitcode("cpl","c");
-                       emitcode("","%05d$:",lbl->key+100);
-                       emitcode("mov","%s,c",aop->aopu.aop_dir);
-                   }
-       }
-       break;
-       
+      /* if not bit variable */
+      if (!aop->aopu.aop_dir)
+        {
+          /* inefficient: move carry into A and use jz/jnz */
+          emitcode ("clr", "a");
+          emitcode ("rlc", "a");
+          accuse = TRUE;
+        }
+      else
+        {
+          if (s == zero)
+            emitcode ("clr", "%s", aop->aopu.aop_dir);
+          else if (s == one)
+            emitcode ("setb", "%s", aop->aopu.aop_dir);
+          else if (!strcmp (s, "c"))
+            emitcode ("mov", "%s,c", aop->aopu.aop_dir);
+          else if (strcmp (s, aop->aopu.aop_dir))
+            {
+              MOVA (s);
+              /* set C, if a >= 1 */
+              emitcode ("add", "a,#0xff");
+              emitcode ("mov", "%s,c", aop->aopu.aop_dir);
+            }
+        }
+      break;
+
     case AOP_STR:
-       aop->coff = offset;
-       if (strcmp(aop->aopu.aop_str[offset],s))
-           emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
-       break;
-       
+      aop->coff = offset;
+      if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
+        emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
+      break;
+
     case AOP_ACC:
-       aop->coff = offset;
-       if (!offset && (strcmp(s,"acc") == 0))
-           break;
-       
-       if (strcmp(aop->aopu.aop_str[offset],s))
-           emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
-       break;
+      accuse = TRUE;
+      aop->coff = offset;
+      if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
+        break;
 
-    default :
-       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-              "aopPut got unsupported aop->type");
-       exit(0);    
-    }    
+      if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
+        emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
+      break;
+
+    default:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+              "aopPut got unsupported aop->type");
+      exit (1);
+    }
 
+    return accuse;
 }
 
 
@@ -1052,23 +1706,25 @@ static void aopPut (asmop *aop, char *s, int offset)
 /*-----------------------------------------------------------------*/
 /* pointToEnd :- points to the last byte of the operand            */
 /*-----------------------------------------------------------------*/
-static void pointToEnd (asmop *aop)
+static void
+pointToEnd (asmop * aop)
 {
-    int count ;
-    if (!aop)
-        return ;
+  int count;
+  if (!aop)
+    return;
 
-    aop->coff = count = (aop->size - 1);
-    switch (aop->type) {
-        case AOP_R0 :
-        case AOP_R1 :
-            while (count--)
-                emitcode("inc","%s",aop->aopu.aop_ptr->name);
-            break;
-        case AOP_DPTR :
-            while (count--)
-                emitcode("inc","dptr");
-            break;
+  aop->coff = count = (aop->size - 1);
+  switch (aop->type)
+    {
+    case AOP_R0:
+    case AOP_R1:
+      while (count--)
+        emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
+      break;
+    case AOP_DPTR:
+      while (count--)
+        emitcode ("inc", "dptr");
+      break;
     }
 
 }
@@ -1077,141 +1733,84 @@ static void pointToEnd (asmop *aop)
 /*-----------------------------------------------------------------*/
 /* reAdjustPreg - points a register back to where it should        */
 /*-----------------------------------------------------------------*/
-static void reAdjustPreg (asmop *aop)
+static void
+reAdjustPreg (asmop * aop)
 {
-    int size ;
-
-    aop->coff = 0;
-    if ((size = aop->size) <= 1)
-        return ;
-    size-- ;
-    switch (aop->type) {
-        case AOP_R0 :
-        case AOP_R1 :
-            while (size--)
-                emitcode("dec","%s",aop->aopu.aop_ptr->name);
-            break;          
-        case AOP_DPTR :
-        case AOP_DPTR2:
-            if (aop->type == AOP_DPTR2)
-           {
-               emitcode (";", "#switchDPTR(2)");
-           } 
-            while (size--)
-                emitcode("lcall","__decdptr");
-                
-           if (aop->type == AOP_DPTR2)
-           {
-               emitcode (";", "#switchDPTR(1)");
-           }                
-            break;  
-
-    }   
+  if ((aop->coff==0) || (aop->size <= 1))
+    return;
 
+  switch (aop->type)
+    {
+    case AOP_R0:
+    case AOP_R1:
+      while (aop->coff--)
+        emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
+      break;
+    case AOP_DPTR:
+      while (aop->coff--)
+        {
+          emitcode ("lcall", "__decdptr");
+        }
+      break;
+    }
+  aop->coff = 0;
 }
 
-#define AOP(op) op->aop
-#define AOP_TYPE(op) AOP(op)->type
-#define AOP_SIZE(op) AOP(op)->size
-#define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
-                       AOP_TYPE(x) == AOP_R0))
-
-#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
-                        AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
-                         AOP(x)->paged)) 
-
-#define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
-                      (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
-                      x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
-
 /*-----------------------------------------------------------------*/
-/* genNotFloat - generates not for float operations              */
+/* opIsGptr: returns non-zero if the passed operand is       */
+/* a generic pointer type.             */
 /*-----------------------------------------------------------------*/
-static void genNotFloat (operand *op, operand *res)
+static int
+opIsGptr (operand * op)
 {
-    int size, offset;
-    char *l;
-    symbol *tlbl ;
-
-    /* we will put 127 in the first byte of 
-    the result */
-    aopPut(AOP(res),"#127",0);
-    size = AOP_SIZE(op) - 1;
-    offset = 1;
-
-    l = aopGet(op->aop,offset++,FALSE,FALSE);
-    MOVA(l);    
-
-    while(size--) {
-        emitcode("orl","a,%s",
-                 aopGet(op->aop,
-                        offset++,FALSE,FALSE));
-    }
-    tlbl = newiTempLabel(NULL);
+  sym_link *type = operandType (op);
 
-    tlbl = newiTempLabel(NULL);
-    aopPut(res->aop,one,1);
-    emitcode("jz","%05d$",(tlbl->key+100));
-    aopPut(res->aop,zero,1);
-    emitcode("","%05d$:",(tlbl->key+100));
-
-    size = res->aop->size - 2;
-    offset = 2;    
-    /* put zeros in the rest */
-    while (size--) 
-        aopPut(res->aop,zero,offset++);
-}
-
-/*-----------------------------------------------------------------*/
-/* opIsGptr: returns non-zero if the passed operand is            */   
-/* a generic pointer type.                                        */
-/*-----------------------------------------------------------------*/ 
-static int opIsGptr(operand *op)
-{
-    link *type = operandType(op);
-    
-    if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
+  if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
     {
-        return 1;
+      return 1;
     }
-    return 0;        
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* getDataSize - get the operand data size                         */
 /*-----------------------------------------------------------------*/
-static int getDataSize(operand *op)
+static int
+getDataSize (operand * op)
 {
-    int size;
-    size = AOP_SIZE(op);
-    if (size == GPTRSIZE)
+  int size;
+  size = AOP_SIZE (op);
+  if (size == GPTRSIZE)
     {
-        link *type = operandType(op);
-        if (IS_GENPTR(type))
+      sym_link *type = operandType (op);
+      if (IS_GENPTR (type))
         {
-            /* generic pointer; arithmetic operations
-             * should ignore the high byte (pointer type).
-             */
-            size--;
+          /* generic pointer; arithmetic operations
+           * should ignore the high byte (pointer type).
+           */
+          size--;
         }
     }
-    return size;
+  return size;
 }
 
 /*-----------------------------------------------------------------*/
 /* outAcc - output Acc                                             */
 /*-----------------------------------------------------------------*/
-static void outAcc(operand *result)
+static 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++);
+  int size, offset;
+  size = getDataSize (result);
+  if (size)
+    {
+      aopPut (result, "a", 0);
+      size--;
+      offset = 1;
+      /* unsigned or positive */
+      while (size--)
+        {
+          aopPut (result, zero, offset++);
         }
     }
 }
@@ -1219,6455 +1818,10048 @@ static void outAcc(operand *result)
 /*-----------------------------------------------------------------*/
 /* outBitC - output a bit C                                        */
 /*-----------------------------------------------------------------*/
-static void outBitC(operand *result)
+static void
+outBitC (operand * result)
 {
-    /* if the result is bit */
-    if (AOP_TYPE(result) == AOP_CRY) 
-        aopPut(AOP(result),"c",0);
-    else {
-        emitcode("clr","a");
-        emitcode("rlc","a");
-        outAcc(result);
+  /* if the result is bit */
+  if (AOP_TYPE (result) == AOP_CRY)
+    {
+      aopPut (result, "c", 0);
+    }
+  else
+    {
+      emitcode ("clr", "a");
+      emitcode ("rlc", "a");
+      outAcc (result);
     }
 }
 
 /*-----------------------------------------------------------------*/
 /* toBoolean - emit code for orl a,operator(sizeop)                */
 /*-----------------------------------------------------------------*/
-static void toBoolean(operand *oper)
+static void
+toBoolean (operand * oper)
 {
-    int size = AOP_SIZE(oper) - 1;
-    int offset = 1;
-    MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
-    while (size--) 
-        emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
-}
+  int size = AOP_SIZE (oper) - 1;
+  int offset = 1;
+  bool AccUsed = FALSE;
+  bool pushedB;
 
+  while (!AccUsed && size--)
+    {
+      AccUsed |= aopGetUsesAcc(oper, offset++);
+    }
 
-/*-----------------------------------------------------------------*/
+  size = AOP_SIZE (oper) - 1;
+  offset = 1;
+  MOVA (aopGet (oper, 0, FALSE, FALSE));
+  if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
+    {
+      pushedB = pushB ();
+      emitcode("mov", "b,a");
+      while (--size)
+        {
+          MOVA (aopGet (oper, offset++, FALSE, FALSE));
+          emitcode ("orl", "b,a");
+        }
+      MOVA (aopGet (oper, offset++, FALSE, FALSE));
+      emitcode ("orl", "a,b");
+      popB (pushedB);
+    }
+  else
+    {
+      while (size--)
+        {
+          emitcode ("orl", "a,%s",
+                    aopGet (oper, offset++, FALSE, FALSE));
+        }
+    }
+}
+
+
+/*-------------------------------------------------------------------*/
+/* xch_a_aopGet - for exchanging acc with value of the aop           */
+/*-------------------------------------------------------------------*/
+static char *
+xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
+{
+  char * l;
+
+  if (aopGetUsesAcc (oper, offset))
+    {
+      emitcode("mov", "b,a");
+      MOVA (aopGet (oper, offset, bit16, dname));
+      emitcode("xch", "a,b");
+      aopPut (oper, "a", offset);
+      emitcode("xch", "a,b");
+      l = "b";
+    }
+  else
+    {
+      l = aopGet (oper, offset, bit16, dname);
+      emitcode("xch", "a,%s", l);
+    }
+  return l;
+}
+
+
+/*-----------------------------------------------------------------*/
 /* genNot - generate code for ! operation                          */
 /*-----------------------------------------------------------------*/
-static void genNot (iCode *ic)
+static void
+genNot (iCode * ic)
 {
-    symbol *tlbl;
-    link *optype = operandType(IC_LEFT(ic));
+  symbol *tlbl;
 
-    /* assign asmOps to operand & result */
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
+  D (emitcode (";", "genNot"));
 
-    /* if in bit space then a special case */
-    if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
-        emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
-        emitcode("cpl","c"); 
-        outBitC(IC_RESULT(ic));
-        goto release;
-    }
+  /* assign asmOps to operand & result */
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  aopOp (IC_RESULT (ic), ic, TRUE);
 
-    /* if type float then do float */
-    if (IS_FLOAT(optype)) {
-        genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
-        goto release;
+  /* if in bit space then a special case */
+  if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
+    {
+      /* if left==result then cpl bit */
+      if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
+        {
+          emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
+        }
+      else
+        {
+          emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
+          emitcode ("cpl", "c");
+          outBitC (IC_RESULT (ic));
+        }
+      goto release;
     }
 
-    toBoolean(IC_LEFT(ic));
+  toBoolean (IC_LEFT (ic));
 
-    tlbl = newiTempLabel(NULL);
-    emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
-    emitcode("","%05d$:",tlbl->key+100);
-    outBitC(IC_RESULT(ic));
+  /* set C, if a == 0 */
+  tlbl = newiTempLabel (NULL);
+  emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
+  emitLabel (tlbl);
+  outBitC (IC_RESULT (ic));
 
-release:    
-    /* release the aops */
-    freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
-    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+release:
+  /* release the aops */
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+  freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
 }
 
 
 /*-----------------------------------------------------------------*/
 /* genCpl - generate code for complement                           */
 /*-----------------------------------------------------------------*/
-static void genCpl (iCode *ic)
+static void
+genCpl (iCode * ic)
 {
-    int offset = 0;
-    int size ;
+  int offset = 0;
+  int size;
+  symbol *tlbl;
+  sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
+
+  D(emitcode (";", "genCpl"));
 
+  /* assign asmOps to operand & result */
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  aopOp (IC_RESULT (ic), ic, TRUE);
 
-    /* assign asmOps to operand & result */
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
+  /* special case if in bit space */
+  if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
+    {
+      char *l;
 
-    /* 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 ) { 
+      if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
+          (SPEC_USIGN (letype) && IS_CHAR (letype)))
+        {
+          /* promotion rules are responsible for this strange result:
+             bit -> int -> ~int -> bit
+             uchar -> int -> ~int -> bit
+          */
+          emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
+          goto release;
+        }
 
-        emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
-        emitcode("cpl","c"); 
-        emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
-        goto release; 
-    } 
+      tlbl=newiTempLabel(NULL);
+      l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
+      if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
+          AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
+          IS_AOP_PREG (IC_LEFT (ic)))
+        {
+          emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
+        }
+      else
+        {
+          MOVA (l);
+          emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
+        }
+      emitLabel (tlbl);
+      outBitC (IC_RESULT(ic));
+      goto release;
+    }
 
-    size = AOP_SIZE(IC_RESULT(ic));
-    while (size--) {
-        char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
-        MOVA(l);       
-        emitcode("cpl","a");
-        aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+  size = AOP_SIZE (IC_RESULT (ic));
+  while (size--)
+    {
+      char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
+      MOVA (l);
+      emitcode ("cpl", "a");
+      aopPut (IC_RESULT (ic), "a", offset++);
     }
 
 
 release:
-    /* release the aops */
-    freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
-    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+  /* release the aops */
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+  freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
 }
 
 /*-----------------------------------------------------------------*/
 /* genUminusFloat - unary minus for floating points                */
 /*-----------------------------------------------------------------*/
-static void genUminusFloat(operand *op,operand *result)
+static void
+genUminusFloat (operand * op, operand * result)
 {
-    int size ,offset =0 ;
-    char *l;
-    /* for this we just need to flip the 
-    first it then copy the rest in place */
-    size = AOP_SIZE(op) - 1;
-    l = aopGet(AOP(op),3,FALSE,FALSE);
+  int size, offset = 0;
+  char *l;
+
+  D (emitcode (";", "genUminusFloat"));
 
-    MOVA(l);    
+  /* for this we just copy and then flip the bit */
 
-    emitcode("cpl","acc.7");
-    aopPut(AOP(result),"a",3);    
+  size = AOP_SIZE (op) - 1;
 
-    while(size--) {
-        aopPut(AOP(result),
-               aopGet(AOP(op),offset,FALSE,FALSE),
-               offset);
-        offset++;
-    }          
+  while (size--)
+    {
+      aopPut (result,
+              aopGet (op, offset, FALSE, FALSE),
+              offset);
+      offset++;
+    }
+
+  l = aopGet (op, offset, FALSE, FALSE);
+  MOVA (l);
+
+  emitcode ("cpl", "acc.7");
+  aopPut (result, "a", offset);
 }
 
 /*-----------------------------------------------------------------*/
 /* genUminus - unary minus code generation                         */
 /*-----------------------------------------------------------------*/
-static void genUminus (iCode *ic)
+static void
+genUminus (iCode * ic)
 {
-    int offset ,size ;
-    link *optype, *rtype;
+  int offset, size;
+  sym_link *optype;
 
+  D (emitcode (";", "genUminus"));
 
-    /* assign asmops */
-    aopOp(IC_LEFT(ic),ic,FALSE);
-    aopOp(IC_RESULT(ic),ic,TRUE);
+  /* assign asmops */
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  aopOp (IC_RESULT (ic), ic, TRUE);
 
-    /* if both in bit space then special
-    case */
-    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
-        AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
+  /* if both in bit space then special
+     case */
+  if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
+      AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
+    {
 
-        emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
-        emitcode("cpl","c"); 
-        emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
-        goto release; 
-    } 
+      emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
+      emitcode ("cpl", "c");
+      emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
+      goto release;
+    }
 
-    optype = operandType(IC_LEFT(ic));
-    rtype = operandType(IC_RESULT(ic));
+  optype = operandType (IC_LEFT (ic));
 
-    /* if float then do float stuff */
-    if (IS_FLOAT(optype)) {
-        genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
-        goto release;
+  /* if float then do float stuff */
+  if (IS_FLOAT (optype))
+    {
+      genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
+      goto release;
     }
 
-    /* otherwise subtract from zero */
-    size = AOP_SIZE(IC_LEFT(ic));
-    offset = 0 ;
-    CLRC ;
-    while(size--) {
-        char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
-        if (!strcmp(l,"a")) {
-            emitcode("cpl","a");
-            emitcode("inc","a");
-        } else {
-            emitcode("clr","a");
-            emitcode("subb","a,%s",l);
-        }       
-        aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+  /* otherwise subtract from zero */
+  size = AOP_SIZE (IC_LEFT (ic));
+  offset = 0;
+  while (size--)
+    {
+      char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
+      if (!strcmp (l, "a"))
+        {
+          if (offset == 0)
+            SETC;
+          emitcode ("cpl", "a");
+          emitcode ("addc", "a,#0");
+        }
+      else
+        {
+          if (offset == 0)
+            CLRC;
+          emitcode ("clr", "a");
+          emitcode ("subb", "a,%s", l);
+        }
+      aopPut (IC_RESULT (ic), "a", offset++);
     }
 
-    /* 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("subb","a,acc");
-        while (size--) 
-            aopPut(AOP(IC_RESULT(ic)),"a",offset++);
-    }       
+  /* 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 ("subb", "a,acc");
+      while (size--)
+        aopPut (IC_RESULT (ic), "a", offset++);
+    }
 
 release:
-    /* release the aops */
-    freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
-    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
+  /* release the aops */
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+  freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
 }
 
 /*-----------------------------------------------------------------*/
 /* saveRegisters - will look for a call and save the registers     */
 /*-----------------------------------------------------------------*/
-static void saveRegisters(iCode *lic) 
+static void
+saveRegisters (iCode * lic)
 {
-    int i;
-    iCode *ic;
-    bitVect *rsave;
-    link *detype;
+  int i;
+  iCode *ic;
+  bitVect *rsave;
 
-    /* look for call */
-    for (ic = lic ; ic ; ic = ic->next) 
-        if (ic->op == CALL || ic->op == PCALL)
-            break;
+  /* look for call */
+  for (ic = lic; ic; ic = ic->next)
+    if (ic->op == CALL || ic->op == PCALL)
+      break;
+
+  if (!ic)
+    {
+      fprintf (stderr, "found parameter push with no function call\n");
+      return;
+    }
+
+  /* if the registers have been saved already or don't need to be then
+     do nothing */
+  if (ic->regsSaved)
+    return;
+  if (IS_SYMOP(IC_LEFT(ic)) &&
+      (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
+       IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
+    return;
 
-    if (!ic) {
-        fprintf(stderr,"found parameter push with no function call\n");
-        return ;
-    }
-
-    /* if the registers have been saved already then
-    do nothing */
-    if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
-        return ;
-
-    /* find the registers in use at this time 
-    and push them away to safety */
-    rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
-                          ic->rUsed);
-
-    ic->regsSaved = 1;
-    if (options.useXstack) {
-       if (bitVectBitValue(rsave,R0_IDX))
-           emitcode("mov","b,r0");
-       emitcode("mov","r0,%s",spname);
-       for (i = 0 ; i < mcs51_nRegs ; i++) {
-           if (bitVectBitValue(rsave,i)) {
-               if (i == R0_IDX)
-                   emitcode("mov","a,b");
-               else
-                   emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
-               emitcode("movx","@r0,a");
-               emitcode("inc","r0");
-           }
-       }
-       emitcode("mov","%s,r0",spname);
-       if (bitVectBitValue(rsave,R0_IDX))
-           emitcode("mov","r0,b");         
-    } else
-       for (i = 0 ; i < mcs51_nRegs ; i++) {
-           if (bitVectBitValue(rsave,i))
-               emitcode("push","%s",mcs51_regWithIdx(i)->dname);
-       }
-
-    detype = getSpec(operandType(IC_LEFT(ic)));
-    if (detype        && 
-        (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
-       IS_ISR(currFunc->etype) &&
-        !ic->bankSaved) 
-
-        saverbank(SPEC_BANK(detype),ic,TRUE);
+  /* save the registers in use at this time but skip the
+     ones for the result */
+  rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
+                         mcs51_rUmaskForOp (IC_RESULT(ic)));
 
+  ic->regsSaved = 1;
+  if (options.useXstack)
+    {
+      bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
+      int nBits = bitVectnBitsOn (rsavebits);
+      int count = bitVectnBitsOn (rsave);
+
+      if (nBits != 0)
+        {
+          count = count - nBits + 1;
+          /* remove all but the first bits as they are pushed all at once */
+          rsave = bitVectCplAnd (rsave, rsavebits);
+          rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
+        }
+
+      if (count == 1)
+        {
+          regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
+          if (reg->type == REG_BIT)
+            {
+              emitcode ("mov", "a,%s", reg->base);
+            }
+          else
+            {
+              emitcode ("mov", "a,%s", reg->name);
+            }
+          emitcode ("mov", "r0,%s", spname);
+          emitcode ("inc", "%s", spname);// allocate before use
+          emitcode ("movx", "@r0,a");
+          if (bitVectBitValue (rsave, R0_IDX))
+            emitcode ("mov", "r0,a");
+        }
+      else if (count != 0)
+        {
+          if (bitVectBitValue (rsave, R0_IDX))
+            {
+              emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
+            }
+          emitcode ("mov", "r0,%s", spname);
+          MOVA ("r0");
+          emitcode ("add", "a,#%d", count);
+          emitcode ("mov", "%s,a", spname);
+          for (i = 0; i < mcs51_nRegs; i++)
+            {
+              if (bitVectBitValue (rsave, i))
+                {
+                  regs * reg = REG_WITH_INDEX (i);
+                  if (i == R0_IDX)
+                    {
+                      emitcode ("pop", "acc");
+                      emitcode ("push", "acc");
+                    }
+                  else if (reg->type == REG_BIT)
+                    {
+                      emitcode ("mov", "a,%s", reg->base);
+                    }
+                  else
+                    {
+                      emitcode ("mov", "a,%s", reg->name);
+                    }
+                  emitcode ("movx", "@r0,a");
+                  if (--count)
+                    {
+                      emitcode ("inc", "r0");
+                    }
+                }
+            }
+          if (bitVectBitValue (rsave, R0_IDX))
+            {
+              emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
+            }
+        }
+    }
+  else
+    {
+      bool bits_pushed = FALSE;
+      for (i = 0; i < mcs51_nRegs; i++)
+        {
+          if (bitVectBitValue (rsave, i))
+            {
+              bits_pushed = pushReg (i, bits_pushed);
+            }
+        }
+    }
 }
+
 /*-----------------------------------------------------------------*/
 /* unsaveRegisters - pop the pushed registers                      */
 /*-----------------------------------------------------------------*/
-static void unsaveRegisters (iCode *ic)
+static void
+unsaveRegisters (iCode * ic)
 {
-    int i;
-    bitVect *rsave;
-    /* find the registers in use at this time 
-    and push them away to safety */
-    rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
-                          ic->rUsed);
-    
-    if (options.useXstack) {
-       emitcode("mov","r0,%s",spname); 
-       for (i =  mcs51_nRegs ; i >= 0 ; i--) {
-           if (bitVectBitValue(rsave,i)) {
-               emitcode("dec","r0");
-               emitcode("movx","a,@r0");
-               if (i == R0_IDX)
-                   emitcode("mov","b,a");
-               else
-                   emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
-           }       
+  int i;
+  bitVect *rsave;
 
-       }
-       emitcode("mov","%s,r0",spname);
-       if (bitVectBitValue(rsave,R0_IDX))
-           emitcode("mov","r0,b");
-    } else
-       for (i =  mcs51_nRegs ; i >= 0 ; i--) {
-           if (bitVectBitValue(rsave,i))
-               emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
-       }
+  /* restore the registers in use at this time but skip the
+     ones for the result */
+  rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
+                         mcs51_rUmaskForOp (IC_RESULT(ic)));
 
-}  
+  if (options.useXstack)
+    {
+      bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
+      int nBits = bitVectnBitsOn (rsavebits);
+      int count = bitVectnBitsOn (rsave);
+
+      if (nBits != 0)
+        {
+          count = count - nBits + 1;
+          /* remove all but the first bits as they are popped all at once */
+          rsave = bitVectCplAnd (rsave, rsavebits);
+          rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
+        }
+
+      if (count == 1)
+        {
+          regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
+          emitcode ("mov", "r0,%s", spname);
+          emitcode ("dec", "r0");
+          emitcode ("movx", "a,@r0");
+          if (reg->type == REG_BIT)
+            {
+              emitcode ("mov", "%s,a", reg->base);
+            }
+          else
+            {
+              emitcode ("mov", "%s,a", reg->name);
+            }
+          emitcode ("dec", "%s", spname);
+        }
+      else if (count != 0)
+        {
+          emitcode ("mov", "r0,%s", spname);
+          for (i = mcs51_nRegs; i >= 0; i--)
+            {
+              if (bitVectBitValue (rsave, i))
+                {
+                  regs * reg = REG_WITH_INDEX (i);
+                  emitcode ("dec", "r0");
+                  emitcode ("movx", "a,@r0");
+                  if (i == R0_IDX)
+                    {
+                      emitcode ("push", "acc");
+                    }
+                  else if (reg->type == REG_BIT)
+                    {
+                      emitcode ("mov", "%s,a", reg->base);
+                    }
+                  else
+                    {
+                      emitcode ("mov", "%s,a", reg->name);
+                    }
+                }
+            }
+          emitcode ("mov", "%s,r0", spname);
+          if (bitVectBitValue (rsave, R0_IDX))
+            {
+              emitcode ("pop", "ar0");
+            }
+        }
+    }
+  else
+    {
+      bool bits_popped = FALSE;
+      for (i = mcs51_nRegs; i >= 0; i--)
+        {
+          if (bitVectBitValue (rsave, i))
+            {
+              bits_popped = popReg (i, bits_popped);
+            }
+        }
+    }
+}
 
 
 /*-----------------------------------------------------------------*/
-/* pushSide -                                                     */
+/* pushSide -                                                      */
 /*-----------------------------------------------------------------*/
-static void pushSide(operand * oper, int size)
+static void
+pushSide (operand * oper, int size)
 {
-       int offset = 0;
-       while (size--) {
-               char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
-               if (AOP_TYPE(oper) != AOP_REG &&
-                   AOP_TYPE(oper) != AOP_DIR &&
-                   strcmp(l,"a") ) {
-                       emitcode("mov","a,%s",l);
-                       emitcode("push","acc");
-               } else
-                       emitcode("push","%s",l);
-       }
+  int offset = 0;
+  while (size--)
+    {
+      char *l = aopGet (oper, offset++, FALSE, TRUE);
+      if (AOP_TYPE (oper) != AOP_REG &&
+          AOP_TYPE (oper) != AOP_DIR &&
+          strcmp (l, "a"))
+        {
+          MOVA (l);
+          emitcode ("push", "acc");
+        }
+      else
+        {
+          emitcode ("push", "%s", l);
+        }
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* assignResultValue -                                            */
+/* assignResultValue - also indicates if acc is in use afterwards  */
 /*-----------------------------------------------------------------*/
-static void assignResultValue(operand * oper)
+static bool
+assignResultValue (operand * oper, operand * func)
 {
-       int offset = 0;
-       int size = AOP_SIZE(oper);
-       while (size--) {
-               aopPut(AOP(oper),fReturn[offset],offset);
-               offset++;
-       }
+  int offset = 0;
+  int size = AOP_SIZE (oper);
+  bool accuse = FALSE;
+  bool pushedA = FALSE;
+
+  if (func && IS_BIT (OP_SYM_ETYPE (func)))
+    {
+      outBitC (oper);
+      return FALSE;
+    }
+
+  if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
+    {
+      emitcode ("push", "acc");
+      pushedA = TRUE;
+    }
+  while (size--)
+    {
+      if ((offset == 3) && pushedA)
+        emitcode ("pop", "acc");
+      accuse |= aopPut (oper, fReturn[offset], offset);
+      offset++;
+    }
+  return accuse;
 }
 
 
 /*-----------------------------------------------------------------*/
 /* genXpush - pushes onto the external stack                       */
 /*-----------------------------------------------------------------*/
-static void genXpush (iCode *ic)
+static void
+genXpush (iCode * ic)
 {
-    asmop *aop = newAsmop(0);
-    regs *r ;
-    int size,offset = 0;
-
-    aopOp(IC_LEFT(ic),ic,FALSE);
-    r = getFreePtr(ic,&aop,FALSE);
+  asmop *aop = newAsmop (0);
+  regs *r;
+  int size, offset = 0;
 
-    
-    emitcode("mov","%s,_spx",r->name);
+  D (emitcode (";", "genXpush"));
 
-    size = AOP_SIZE(IC_LEFT(ic));
-    while(size--) {
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  r = getFreePtr (ic, &aop, FALSE);
 
-       char *l = aopGet(AOP(IC_LEFT(ic)),
-                        offset++,FALSE,FALSE); 
-       MOVA(l);            
-       emitcode("movx","@%s,a",r->name);       
-       emitcode("inc","%s",r->name);
+  size = AOP_SIZE (IC_LEFT (ic));
 
+  if (size == 1)
+    {
+      MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
+      emitcode ("mov", "%s,%s", r->name, spname);
+      emitcode ("inc", "%s", spname); // allocate space first
+      emitcode ("movx", "@%s,a", r->name);
     }
+  else
+    {
+      // allocate space first
+      emitcode ("mov", "%s,%s", r->name, spname);
+      MOVA (r->name);
+      emitcode ("add", "a,#%d", size);
+      emitcode ("mov", "%s,a", spname);
 
-       
-    emitcode("mov","_spx,%s",r->name);
+      while (size--)
+        {
+          MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
+          emitcode ("movx", "@%s,a", r->name);
+          emitcode ("inc", "%s", r->name);
+        }
+    }
 
-    freeAsmop(NULL,aop,ic,TRUE);
-    freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
+  freeAsmop (NULL, aop, ic, TRUE);
+  freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genIpush - genrate code for pushing this gets a little complex  */
+/* genIpush - generate code for pushing this gets a little complex */
 /*-----------------------------------------------------------------*/
-static void genIpush (iCode *ic)
+static void
+genIpush (iCode * ic)
 {
-    int size, offset = 0 ;
-    char *l;
+  int size, offset = 0;
+  char *l;
+  char *prev = "";
 
+  D (emitcode (";", "genIpush"));
 
-    /* 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) {
+  /* 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 ;
+      /* and the item is spilt then do nothing */
+      if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
+        return;
 
-        aopOp(IC_LEFT(ic),ic,FALSE);
-        size = AOP_SIZE(IC_LEFT(ic));
-        /* push it on the stack */
-        while(size--) {
-            l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
-            if (*l == '#') {
-                MOVA(l);
-                l = "acc";
+      aopOp (IC_LEFT (ic), ic, FALSE);
+      size = AOP_SIZE (IC_LEFT (ic));
+      /* push it on the stack */
+      while (size--)
+        {
+          l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
+          if (*l == '#')
+            {
+              MOVA (l);
+              l = "acc";
             }
-            emitcode("push","%s",l);
+          emitcode ("push", "%s", l);
         }
-        return ;        
+      return;
     }
 
-    /* this is a paramter push: in this case we call
-    the routine to find the call and save those
-    registers that need to be saved */   
-    saveRegisters(ic);
+  /* this is a parameter push: in this case we call
+     the routine to find the call and save those
+     registers that need to be saved */
+  saveRegisters (ic);
 
-    /* if use external stack then call the external
-    stack pushing routine */
-    if (options.useXstack) {
-        genXpush(ic);
-        return ;
+  /* if use external stack then call the external
+     stack pushing routine */
+  if (options.useXstack)
+    {
+      genXpush (ic);
+      return;
     }
 
-    /* then do the push */
-    aopOp(IC_LEFT(ic),ic,FALSE);
+  /* then do the push */
+  aopOp (IC_LEFT (ic), ic, FALSE);
 
+  // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
+  size = AOP_SIZE (IC_LEFT (ic));
 
-       // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
-    size = AOP_SIZE(IC_LEFT(ic));
-
-    while (size--) {
-        l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
-        if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
-            AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
-            strcmp(l,"a") ) {
-            emitcode("mov","a,%s",l);
-            emitcode("push","acc");
-        } else
-            emitcode("push","%s",l);
-    }       
+  while (size--)
+    {
+      l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
+      if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
+          AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
+        {
+          if (strcmp (l, prev) || *l == '@')
+            MOVA (l);
+          emitcode ("push", "acc");
+        }
+      else
+        {
+          emitcode ("push", "%s", l);
+        }
+      prev = l;
+    }
 
-    freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
+  freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
 /* genIpop - recover the registers: can happen only for spilling   */
 /*-----------------------------------------------------------------*/
-static void genIpop (iCode *ic)
+static void
+genIpop (iCode * ic)
 {
-    int size,offset ;
+  int size, offset;
 
+  D (emitcode (";", "genIpop"));
 
-    /* if the temp was not pushed then */
-    if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
-        return ;
+  /* if the temp was not pushed then */
+  if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
+    return;
 
-    aopOp(IC_LEFT(ic),ic,FALSE);
-    size = AOP_SIZE(IC_LEFT(ic));
-    offset = (size-1);
-    while (size--) 
-        emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
-                                   FALSE,TRUE));
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  size = AOP_SIZE (IC_LEFT (ic));
+  offset = (size - 1);
+  while (size--)
+    {
+      emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
+                                     FALSE, TRUE));
+    }
 
-    freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
+  freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* unsaverbank - restores the resgister bank from stack            */
+/* saveRBank - saves an entire register bank on the stack          */
 /*-----------------------------------------------------------------*/
-static void unsaverbank (int bank,iCode *ic,bool popPsw)
+static void
+saveRBank (int bank, iCode * ic, bool pushPsw)
 {
-    int i;
-    asmop *aop ;
-    regs *r = NULL;
+  int i;
+  int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
+  asmop *aop = NULL;
+  regs *r = NULL;
 
-    if (popPsw) {
-       if (options.useXstack) {
-           aop = newAsmop(0);
-           r = getFreePtr(ic,&aop,FALSE);
-           
-           
-           emitcode("mov","%s,_spx",r->name);
-           emitcode("movx","a,@%s",r->name);
-           emitcode("mov","psw,a");
-           emitcode("dec","%s",r->name);
-           
-       }else
-           emitcode ("pop","psw");
+  if (options.useXstack)
+    {
+      if (!ic)
+        {
+          /* Assume r0 is available for use. */
+          r = REG_WITH_INDEX (R0_IDX);;
+        }
+      else
+        {
+          aop = newAsmop (0);
+          r = getFreePtr (ic, &aop, FALSE);
+        }
+      // allocate space first
+      emitcode ("mov", "%s,%s", r->name, spname);
+      MOVA (r->name);
+      emitcode ("add", "a,#%d", count);
+      emitcode ("mov", "%s,a", spname);
     }
 
-    for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
-        if (options.useXstack) {       
-            emitcode("movx","a,@%s",r->name);
-            emitcode("mov","(%s+%d),a",
-                     regs8051[i].base,8*bank+regs8051[i].offset);
-            emitcode("dec","%s",r->name);
+  for (i = 0; i < 8; i++)
+    {
+      if (options.useXstack)
+        {
+          emitcode ("mov", "a,(%s+%d)",
+                    regs8051[i].base, 8 * bank + regs8051[i].offset);
+          emitcode ("movx", "@%s,a", r->name);
+          if (--count)
+            emitcode ("inc", "%s", r->name);
+        }
+      else
+        emitcode ("push", "(%s+%d)",
+                  regs8051[i].base, 8 * bank + regs8051[i].offset);
+    }
 
-        } else 
-            emitcode("pop","(%s+%d)",
-                     regs8051[i].base,8*bank+regs8051[i].offset);
+  if (mcs51_nRegs > 8)
+    {
+      if (options.useXstack)
+        {
+          emitcode ("mov", "a,bits");
+          emitcode ("movx", "@%s,a", r->name);
+          if (--count)
+            emitcode ("inc", "%s", r->name);
+        }
+      else
+        {
+          emitcode ("push", "bits");
+        }
+      BitBankUsed = 1;
     }
 
-    if (options.useXstack) {
+  if (pushPsw)
+    {
+      if (options.useXstack)
+        {
+          emitcode ("mov", "a,psw");
+          emitcode ("movx", "@%s,a", r->name);
+        }
+      else
+        {
+          emitcode ("push", "psw");
+        }
+
+      emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
+    }
 
-       emitcode("mov","_spx,%s",r->name);
-       freeAsmop(NULL,aop,ic,TRUE);
+  if (aop)
+    {
+      freeAsmop (NULL, aop, ic, TRUE);
+    }
 
-    } 
+  if (ic)
+  {
+    ic->bankSaved = 1;
+  }
 }
 
 /*-----------------------------------------------------------------*/
-/* saverbank - saves an entire register bank on the stack          */
+/* unsaveRBank - restores the register bank from stack             */
 /*-----------------------------------------------------------------*/
-static void saverbank (int bank, iCode *ic, bool pushPsw)
+static void
+unsaveRBank (int bank, iCode * ic, bool popPsw)
 {
-    int i;
-    asmop *aop ;
-    regs *r = NULL;
+  int i;
+  asmop *aop = NULL;
+  regs *r = NULL;
 
-    if (options.useXstack) {
+  if (options.useXstack)
+    {
+      if (!ic)
+        {
+          /* Assume r0 is available for use. */
+          r = REG_WITH_INDEX (R0_IDX);;
+        }
+      else
+        {
+          aop = newAsmop (0);
+          r = getFreePtr (ic, &aop, FALSE);
+        }
+      emitcode ("mov", "%s,%s", r->name, spname);
+    }
 
-       aop = newAsmop(0);
-       r = getFreePtr(ic,&aop,FALSE);  
-       emitcode("mov","%s,_spx",r->name);
+  if (popPsw)
+    {
+      if (options.useXstack)
+        {
+          emitcode ("dec", "%s", r->name);
+          emitcode ("movx", "a,@%s", r->name);
+          emitcode ("mov", "psw,a");
+        }
+      else
+        {
+          emitcode ("pop", "psw");
+        }
+    }
 
+  if (mcs51_nRegs > 8)
+    {
+      if (options.useXstack)
+        {
+          emitcode ("dec", "%s", r->name);
+          emitcode ("movx", "a,@%s", r->name);
+          emitcode ("mov", "bits,a");
+        }
+      else
+        {
+          emitcode ("pop", "bits");
+        }
     }
 
-    for (i = 0 ; i < mcs51_nRegs ;i++) {
-        if (options.useXstack) {
-            emitcode("inc","%s",r->name);
-            emitcode("mov","a,(%s+%d)",
-                     regs8051[i].base,8*bank+regs8051[i].offset);
-            emitcode("movx","@%s,a",r->name);           
-        } else 
-            emitcode("push","(%s+%d)",
-                     regs8051[i].base,8*bank+regs8051[i].offset);
+  for (i = 7; i >= 0; i--)
+    {
+      if (options.useXstack)
+        {
+          emitcode ("dec", "%s", r->name);
+          emitcode ("movx", "a,@%s", r->name);
+          emitcode ("mov", "(%s+%d),a",
+                    regs8051[i].base, 8 * bank + regs8051[i].offset);
+        }
+      else
+        {
+          emitcode ("pop", "(%s+%d)",
+                  regs8051[i].base, 8 * bank + regs8051[i].offset);
+        }
     }
-    
-    if (pushPsw) {
-       if (options.useXstack) {
-           emitcode("mov","a,psw");
-           emitcode("movx","@%s,a",r->name);   
-           emitcode("inc","%s",r->name);
-           emitcode("mov","_spx,%s",r->name);       
-           freeAsmop (NULL,aop,ic,TRUE);
-           
-       } else
-           emitcode("push","psw");
-       
-       emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
+
+  if (options.useXstack)
+    {
+      emitcode ("mov", "%s,%s", spname, r->name);
     }
-    ic->bankSaved = 1;
 
+  if (aop)
+    {
+      freeAsmop (NULL, aop, ic, TRUE);
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* genCall - generates a call statement                            */
+/* genSend - gen code for SEND                                     */
 /*-----------------------------------------------------------------*/
-static void genCall (iCode *ic)
-{
-    link *detype;   
-
-    /* if caller saves & we have not saved then */
-    if (!ic->regsSaved)
-        saveRegisters(ic);
-
-    /* if we are calling a function that is not using
-    the same register bank then we need to save the
-    destination registers on the stack */
-    detype = getSpec(operandType(IC_LEFT(ic)));
-    if (detype        && 
-        (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
-       IS_ISR(currFunc->etype) &&
-        !ic->bankSaved) 
-
-        saverbank(SPEC_BANK(detype),ic,TRUE);
-
-    /* if send set is not empty the assign */
-    if (_G.sendSet) {
-       iCode *sic ;
-
-       for (sic = setFirstItem(_G.sendSet) ; sic ; 
-            sic = setNextItem(_G.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,FALSE);
-               if (strcmp(l,fReturn[offset]))
-                   emitcode("mov","%s,%s",
-                            fReturn[offset],
-                            l);
-               offset++;
-           }
-           freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
-       }
-       _G.sendSet = NULL;
-    }
-    /* make the call */
-    emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
-                           OP_SYMBOL(IC_LEFT(ic))->rname :
-                           OP_SYMBOL(IC_LEFT(ic))->name));
-
-    /* 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)) ) {
-
-        _G.accInUse++;
-        aopOp(IC_RESULT(ic),ic,FALSE);
-        _G.accInUse--;
-
-       assignResultValue(IC_RESULT(ic));
-               
-        freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
-    }
-
-    /* adjust the stack for parameters if 
-    required */
-    if (IC_LEFT(ic)->parmBytes) {
-        int i;
-        if (IC_LEFT(ic)->parmBytes > 3) {
-            emitcode("mov","a,%s",spname);
-            emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
-            emitcode("mov","%s,a",spname);
-        } else 
-            for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
-                emitcode("dec","%s",spname);
+static void genSend(set *sendSet)
+{
+  iCode *sic;
+  int bit_count = 0;
+
+  /* first we do all bit parameters */
+  for (sic = setFirstItem (sendSet); sic;
+       sic = setNextItem (sendSet))
+    {
+      if (sic->argreg > 12)
+        {
+          int bit = sic->argreg-13;
+
+          aopOp (IC_LEFT (sic), sic, FALSE);
+
+          /* if left is a literal then
+             we know what the value is */
+          if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
+            {
+              if (((int) operandLitValue (IC_LEFT (sic))))
+                  emitcode ("setb", "b[%d]", bit);
+              else
+                  emitcode ("clr", "b[%d]", bit);
+            }
+          else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
+            {
+              char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
+                if (strcmp (l, "c"))
+                    emitcode ("mov", "c,%s", l);
+                emitcode ("mov", "b[%d],c", bit);
+            }
+          else
+            {
+              /* we need to or */
+              toBoolean (IC_LEFT (sic));
+              /* set C, if a >= 1 */
+              emitcode ("add", "a,#0xff");
+              emitcode ("mov", "b[%d],c", bit);
+            }
+          bit_count++;
+          BitBankUsed = 1;
 
+          freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
+        }
     }
 
-    /* if register bank was saved then pop them */
-    if (ic->bankSaved)
-        unsaverbank(SPEC_BANK(detype),ic,TRUE);
+  if (bit_count)
+    {
+      saveRegisters (setFirstItem (sendSet));
+      emitcode ("mov", "bits,b");
+    }
 
-    /* if we hade saved some registers then unsave them */
-    if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
-        unsaveRegisters (ic);
+  /* then we do all other parameters */
+  for (sic = setFirstItem (sendSet); sic;
+       sic = setNextItem (sendSet))
+    {
+      if (sic->argreg <= 12)
+        {
+          int size, offset = 0;
+          aopOp (IC_LEFT (sic), sic, FALSE);
+          size = AOP_SIZE (IC_LEFT (sic));
 
+          if (sic->argreg == 1)
+            {
+              while (size--)
+                {
+                  char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
+                  if (strcmp (l, fReturn[offset]))
+                    {
+                      emitcode ("mov", "%s,%s", fReturn[offset], l);
+                    }
+                  offset++;
+                }
+            }
+          else
+            {
+              while (size--)
+                {
+                  emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
+                            aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
+                  offset++;
+                }
+            }
+          freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
+        }
+    }
+}
 
+/*-----------------------------------------------------------------*/
+/* selectRegBank - emit code to select the register bank           */
+/*-----------------------------------------------------------------*/
+static void
+selectRegBank (short bank, bool keepFlags)
+{
+  /* if f.e. result is in carry */
+  if (keepFlags)
+    {
+      emitcode ("anl", "psw,#0xE7");
+      if (bank)
+        emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
+    }
+  else
+    {
+      emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* genPcall - generates a call by pointer statement                */
+/* genCall - generates a call statement                            */
 /*-----------------------------------------------------------------*/
-static void genPcall (iCode *ic)
+static void
+genCall (iCode * ic)
 {
-    link *detype;
-    symbol *rlbl = newiTempLabel(NULL);
+  sym_link *dtype;
+  sym_link *etype;
+//  bool restoreBank = FALSE;
+  bool swapBanks = FALSE;
+  bool accuse = FALSE;
+  bool accPushed = FALSE;
+  bool resultInF0 = FALSE;
+  bool assignResultGenerated = FALSE;
 
+  D (emitcode (";", "genCall"));
 
-    /* if caller saves & we have not saved then */
-    if (!ic->regsSaved)
-        saveRegisters(ic);
+  dtype = operandType (IC_LEFT (ic));
+  etype = getSpec(dtype);
+  /* if send set is not empty then assign */
+  if (_G.sendSet)
+    {
+        if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
+            genSend(reverseSet(_G.sendSet));
+        } else {
+            genSend(_G.sendSet);
+        }
+      _G.sendSet = NULL;
+    }
 
-    /* if we are calling a function that is not using
-    the same register bank then we need to save the
-    destination registers on the stack */
-    detype = getSpec(operandType(IC_LEFT(ic)));
-    if (detype        && 
-       IS_ISR(currFunc->etype) &&
-        (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
-        saverbank(SPEC_BANK(detype),ic,TRUE);
+  /* if we are calling a not _naked function that is not using
+     the same register bank then we need to save the
+     destination registers on the stack */
+  if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
+      (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
+       !IFFUNC_ISISR (dtype))
+    {
+      swapBanks = TRUE;
+    }
 
+  /* if caller saves & we have not saved then */
+  if (!ic->regsSaved)
+      saveRegisters (ic);
 
-    /* push the return address on to the stack */
-    emitcode("mov","a,#%05d$",(rlbl->key+100));
-    emitcode("push","acc");    
-    emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
-    emitcode("push","acc");
-    
-    if (options.model == MODEL_FLAT24)
+  if (swapBanks)
     {
-       emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
-       emitcode("push","acc");    
+        emitcode ("mov", "psw,#0x%02x",
+           ((FUNC_REGBANK(dtype)) << 3) & 0xff);
     }
 
-    /* now push the calling address */
-    aopOp(IC_LEFT(ic),ic,FALSE);
-
-    pushSide(IC_LEFT(ic), FPTRSIZE);
-
-    freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
-
-    /* if send set is not empty the assign */
-    if (_G.sendSet) {
-       iCode *sic ;
-
-       for (sic = setFirstItem(_G.sendSet) ; sic ; 
-            sic = setNextItem(_G.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,FALSE);
-               if (strcmp(l,fReturn[offset]))
-                   emitcode("mov","%s,%s",
-                            fReturn[offset],
-                            l);
-               offset++;
-           }
-           freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
-       }
-       _G.sendSet = NULL;
+  /* make the call */
+  if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
+    {
+      if (IFFUNC_CALLEESAVES(dtype))
+        {
+          werror (E_BANKED_WITH_CALLEESAVES);
+        }
+      else
+        {
+          char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
+                     OP_SYMBOL (IC_LEFT (ic))->rname :
+                     OP_SYMBOL (IC_LEFT (ic))->name);
+
+          emitcode ("mov", "r0,#%s", l);
+          emitcode ("mov", "r1,#(%s >> 8)", l);
+          emitcode ("mov", "r2,#(%s >> 16)", l);
+          emitcode ("lcall", "__sdcc_banked_call");
+        }
     }
-
-    emitcode("ret","");
-    emitcode("","%05d$:",(rlbl->key+100));
-
-
-    /* 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)) ) {
-
-        _G.accInUse++;
-        aopOp(IC_RESULT(ic),ic,FALSE);
-        _G.accInUse--;
-       
-       assignResultValue(IC_RESULT(ic));
-
-        freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+  else
+    {
+      emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
+                                OP_SYMBOL (IC_LEFT (ic))->rname :
+                                OP_SYMBOL (IC_LEFT (ic))->name));
     }
 
-    /* adjust the stack for parameters if 
-    required */
-    if (IC_LEFT(ic)->parmBytes) {
-        int i;
-        if (IC_LEFT(ic)->parmBytes > 3) {
-            emitcode("mov","a,%s",spname);
-            emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
-            emitcode("mov","%s,a",spname);
-        } else 
-            for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
-                emitcode("dec","%s",spname);
-
+  if (swapBanks)
+    {
+      selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
     }
 
-    /* if register bank was saved then unsave them */
-    if (detype        && 
-        (SPEC_BANK(currFunc->etype) != 
-         SPEC_BANK(detype)))
-        unsaverbank(SPEC_BANK(detype),ic,TRUE);
-
-    /* if we hade saved some registers then
-    unsave them */
-    if (ic->regsSaved)
-        unsaveRegisters (ic);
+  /* if we need assign a result value */
+  if ((IS_ITEMP (IC_RESULT (ic)) &&
+       !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
+       (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
+        OP_SYMBOL (IC_RESULT (ic))->accuse ||
+        OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
+      IS_TRUE_SYMOP (IC_RESULT (ic)))
+    {
 
-}
+      _G.accInUse++;
+      aopOp (IC_RESULT (ic), ic, FALSE);
+      _G.accInUse--;
 
-/*-----------------------------------------------------------------*/
-/* resultRemat - result  is rematerializable                       */
-/*-----------------------------------------------------------------*/
-static int resultRemat (iCode *ic)
-{
-    if (SKIP_IC(ic) || ic->op == IFX)
-        return 0;
+      accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
+      assignResultGenerated = TRUE;
 
-    if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
-        symbol *sym = OP_SYMBOL(IC_RESULT(ic));
-        if (sym->remat && !POINTER_SET(ic)) 
-            return 1;
+      freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
     }
 
-    return 0;
-}
-
-#ifdef __BORLANDC__
-#define STRCASECMP stricmp
-#else
-#define STRCASECMP strcasecmp
-#endif
+  /* adjust the stack for parameters if required */
+  if (ic->parmBytes)
+    {
+      int i;
+      if (ic->parmBytes > 3)
+        {
+          if (accuse)
+            {
+              emitcode ("push", "acc");
+              accPushed = TRUE;
+            }
+          if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
+              IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
+              !assignResultGenerated)
+            {
+              emitcode ("mov", "F0,c");
+              resultInF0 = TRUE;
+            }
 
-/*-----------------------------------------------------------------*/
-/* inExcludeList - return 1 if the string is in exclude Reg list   */
-/*-----------------------------------------------------------------*/
-static bool inExcludeList(char *s)
-{
-    int i =0;
-    
-    if (options.excludeRegs[i] &&
-    STRCASECMP(options.excludeRegs[i],"none") == 0)
-       return FALSE ;
+          emitcode ("mov", "a,%s", spname);
+          emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
+          emitcode ("mov", "%s,a", spname);
 
-    for ( i = 0 ; options.excludeRegs[i]; i++) {
-       if (options.excludeRegs[i] &&
-        STRCASECMP(s,options.excludeRegs[i]) == 0)
-           return TRUE;
+          /* unsaveRegisters from xstack needs acc, but */
+          /* unsaveRegisters from stack needs this popped */
+          if (accPushed && !options.useXstack)
+            {
+              emitcode ("pop", "acc");
+              accPushed = FALSE;
+            }
+        }
+      else
+        for (i = 0; i < ic->parmBytes; i++)
+          emitcode ("dec", "%s", spname);
     }
-    return FALSE ;
-}
-
-/*-----------------------------------------------------------------*/
-/* genFunction - generated code for function entry                 */
-/*-----------------------------------------------------------------*/
-static void genFunction (iCode *ic)
-{
-    symbol *sym;
-    link *fetype;
-
-    _G.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)));
-
-    /* if critical function then turn interrupts off */
-    if (SPEC_CRTCL(fetype))
-        emitcode("clr","ea");
-
-    /* here we need to generate the equates for the
-       register bank if required */
-    if (SPEC_BANK(fetype) != rbank) {
-        int i ;
-
-        rbank = SPEC_BANK(fetype);
-        for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
-            if (strcmp(regs8051[i].base,"0") == 0)
-                emitcode("","%s = 0x%02x",
-                         regs8051[i].dname,
-                         8*rbank+regs8051[i].offset);
-            else
-                emitcode ("","%s = %s + 0x%02x",
-                          regs8051[i].dname,
-                          regs8051[i].base,
-                          8*rbank+regs8051[i].offset);
-        }
-    }
-
-    /* if this is an interrupt service routine then
-    save acc, b, dpl, dph  */
-    if (IS_ISR(sym->etype)) {
-        
-       if (!inExcludeList("acc"))          
-           emitcode ("push","acc");    
-       if (!inExcludeList("b"))
-           emitcode ("push","b");
-       if (!inExcludeList("dpl"))
-           emitcode ("push","dpl");
-       if (!inExcludeList("dph"))
-           emitcode ("push","dph");
-       if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
-           emitcode ("push", "dpx");   
-       /* if this isr has no bank i.e. is going to
-          run with bank 0 , then we need to save more
-          registers :-) */
-       if (!SPEC_BANK(sym->etype)) {
-
-           /* if this function does not call any other
-              function then we can be economical and
-              save only those registers that are used */
-           if (! sym->hasFcall) {
-               int i;
-
-               /* if any registers used */
-               if (sym->regsUsed) {
-                   /* save the registers used */
-                   for ( i = 0 ; i < sym->regsUsed->size ; i++) {
-                       if (bitVectBitValue(sym->regsUsed,i) ||
-                          (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
-                           emitcode("push","%s",mcs51_regWithIdx(i)->dname);                       
-                   }
-               }
-               
-           } else {
-               /* this function has  a function call cannot
-                  determines register usage so we will have the
-                  entire bank */
-               saverbank(0,ic,FALSE);
-           }       
-       }
-    } else {
-       /* if callee-save to be used for this function
-          then save the registers being used in this function */
-       if (sym->calleeSave) {
-           int i;
-           
-           /* if any registers used */
-           if (sym->regsUsed) {
-               /* save the registers used */
-               for ( i = 0 ; i < sym->regsUsed->size ; i++) {
-                   if (bitVectBitValue(sym->regsUsed,i) ||
-                      (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
-                       emitcode("push","%s",mcs51_regWithIdx(i)->dname);
-                       _G.nRegsSaved++;
-                   }
-               }
-           }
-       }
-    }
-
-    /* set the register bank to the desired value */
-    if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
-        emitcode("push","psw");
-        emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);   
-    }
-
-    if (IS_RENT(sym->etype) || options.stackAuto) {
-
-       if (options.useXstack) {
-           emitcode("mov","r0,%s",spname);
-           emitcode("mov","a,_bp");
-           emitcode("movx","@r0,a");
-           emitcode("inc","%s",spname);
-       }
-       else
-       {
-           /* set up the stack */
-           emitcode ("push","_bp");     /* save the callers stack  */
-       }
-       emitcode ("mov","_bp,%s",spname);
-    }
-
-    /* adjust the stack for the function */
-    if (sym->stack) {
-
-       int i = sym->stack;
-       if (i > 256 ) 
-           werror(W_STACK_OVERFLOW,sym->name);
-
-       if (i > 3 && sym->recvSize < 4) {              
-
-           emitcode ("mov","a,sp");
-           emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
-           emitcode ("mov","sp,a");
-          
-       }
-       else
-           while(i--)
-               emitcode("inc","sp");
-    }
-
-     if (sym->xstack) {
-
-       emitcode ("mov","a,_spx");
-       emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
-       emitcode ("mov","_spx,a");
-    }    
-
-}
 
-/*-----------------------------------------------------------------*/
-/* genEndFunction - generates epilogue for functions               */
-/*-----------------------------------------------------------------*/
-static void genEndFunction (iCode *ic)
-{
-    symbol *sym = OP_SYMBOL(IC_LEFT(ic));
-
-    if (IS_RENT(sym->etype) || options.stackAuto)
-    {
-        emitcode ("mov","%s,_bp",spname);
-    }
-
-    /* if use external stack but some variables were
-    added to the local stack then decrement the
-    local stack */
-    if (options.useXstack && sym->stack) {      
-        emitcode("mov","a,sp");
-        emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
-        emitcode("mov","sp,a");
-    }
-
-
-    if ((IS_RENT(sym->etype) || options.stackAuto)) {
-       if (options.useXstack) {
-           emitcode("mov","r0,%s",spname);
-           emitcode("movx","a,@r0");
-           emitcode("mov","_bp,a");
-           emitcode("dec","%s",spname);
-       }
-       else
-       {
-           emitcode ("pop","_bp");
-       }
-    }
-
-    /* restore the register bank  */    
-    if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
-        emitcode ("pop","psw");
-
-    if (IS_ISR(sym->etype)) {
-
-       /* now we need to restore the registers */
-       /* if this isr has no bank i.e. is going to
-          run with bank 0 , then we need to save more
-          registers :-) */
-       if (!SPEC_BANK(sym->etype)) {
-           
-           /* if this function does not call any other
-              function then we can be economical and
-              save only those registers that are used */
-           if (! sym->hasFcall) {
-               int i;
-               
-               /* if any registers used */
-               if (sym->regsUsed) {
-                   /* save the registers used */
-                   for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
-                       if (bitVectBitValue(sym->regsUsed,i) ||
-                          (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
-                           emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
-                   }
-               }
-               
-           } else {
-               /* this function has  a function call cannot
-                  determines register usage so we will have the
-                  entire bank */
-               unsaverbank(0,ic,FALSE);
-           }       
-       }
-
-       if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
-           emitcode ("pop", "dpx");
-       if (!inExcludeList("dph"))
-           emitcode ("pop","dph");
-       if (!inExcludeList("dpl"))
-           emitcode ("pop","dpl");
-       if (!inExcludeList("b"))
-           emitcode ("pop","b");
-       if (!inExcludeList("acc"))
-           emitcode ("pop","acc");
-
-        if (SPEC_CRTCL(sym->etype))
-            emitcode("setb","ea");
-
-       /* if debug then send end of function */
-/*     if (options.debug && currFunc) { */
-       if (currFunc) {
-           _G.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);
-           _G.debugLine = 0;
-       }
-       
-        emitcode ("reti","");
-    }
-    else {
-        if (SPEC_CRTCL(sym->etype))
-            emitcode("setb","ea");
-       
-       if (sym->calleeSave) {
-           int i;
-           
-           /* if any registers used */
-           if (sym->regsUsed) {
-               /* save the registers used */
-               for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
-                   if (bitVectBitValue(sym->regsUsed,i) ||
-                      (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
-                       emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
-               }
-           }
-           
-       }
-
-       /* if debug then send end of function */
-/*     if (options.debug && currFunc) { */
-       if (currFunc) {
-           _G.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);
-           _G.debugLine = 0;
-       }
-
-        emitcode ("ret","");
+  /* if we had saved some registers then unsave them */
+  if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
+    {
+      if (accuse && !accPushed && options.useXstack)
+        {
+          /* xstack needs acc, but doesn't touch normal stack */
+          emitcode ("push", "acc");
+          accPushed = TRUE;
+        }
+      unsaveRegisters (ic);
     }
 
-}
+//  /* if register bank was saved then pop them */
+//  if (restoreBank)
+//    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
 
-/*-----------------------------------------------------------------*/
-/* genRet - generate code for return statement                     */
-/*-----------------------------------------------------------------*/
-static void genRet (iCode *ic)
-{
-    int size,offset = 0 , pushed = 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));
-    
-    while (size--) {
-           char *l ;
-           if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
-                   /* #NOCHANGE */
-                   l = aopGet(AOP(IC_LEFT(ic)),offset++,
-                          FALSE,TRUE);
-                   emitcode("push","%s",l);
-                   pushed++;
-           } else {
-                   l = aopGet(AOP(IC_LEFT(ic)),offset,
-                              FALSE,FALSE);
-                   if (strcmp(fReturn[offset],l))
-                           emitcode("mov","%s,%s",fReturn[offset++],l);
-           }
-    }    
-
-    if (pushed) {
-       while(pushed) {
-           pushed--;
-           if (strcmp(fReturn[pushed],"a"))
-               emitcode("pop",fReturn[pushed]);
-           else
-               emitcode("pop","acc");
-       }
-    }
-    freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
-    
- 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("ljmp","%05d$",(returnLabel->key+100));
-    
-}
+  if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
+    {
+      if (resultInF0)
+          emitcode ("mov", "c,F0");
 
-/*-----------------------------------------------------------------*/
-/* genLabel - generates a label                                    */
-/*-----------------------------------------------------------------*/
-static void genLabel (iCode *ic)
-{
-    /* special case never generate */
-    if (IC_LABEL(ic) == entryLabel)
-        return ;
+      aopOp (IC_RESULT (ic), ic, FALSE);
+      assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
+      freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+    }
 
-    emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
+  if (accPushed)
+    emitcode ("pop", "acc");
 }
 
 /*-----------------------------------------------------------------*/
-/* genGoto - generates a ljmp                                      */
+/* genPcall - generates a call by pointer statement                */
 /*-----------------------------------------------------------------*/
-static void genGoto (iCode *ic)
-{
-    emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
-}
+static void
+genPcall (iCode * ic)
+{
+  sym_link *dtype;
+  sym_link *etype;
+  symbol *rlbl = newiTempLabel (NULL);
+//  bool restoreBank=FALSE;
+  bool swapBanks = FALSE;
+  bool resultInF0 = FALSE;
+
+  D (emitcode (";", "genPcall"));
+
+  dtype = operandType (IC_LEFT (ic))->next;
+  etype = getSpec(dtype);
+  /* if caller saves & we have not saved then */
+  if (!ic->regsSaved)
+    saveRegisters (ic);
+
+  /* if we are calling a not _naked function that is not using
+     the same register bank then we need to save the
+     destination registers on the stack */
+  if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
+      (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
+      !IFFUNC_ISISR (dtype))
+    {
+//    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
+//    restoreBank=TRUE;
+      swapBanks = TRUE;
+      // need caution message to user here
+    }
 
-/*-----------------------------------------------------------------*/
-/* findLabelBackwards: walks back through the iCode chain looking  */
-/* for the given label. Returns number of iCode instructions      */
-/* between that label and given ic.                               */
-/* Returns zero if label not found.                               */
-/*-----------------------------------------------------------------*/
-static int findLabelBackwards(iCode *ic, int key)
-{
-    int count = 0;
-    
-    while (ic->prev)
+  if (IS_LITERAL(etype))
     {
-        ic = ic->prev;
-        count++;
-        
-        if (ic->op == LABEL && IC_LABEL(ic)->key == key)
+      /* if send set is not empty then assign */
+      if (_G.sendSet)
         {
-            /* printf("findLabelBackwards = %d\n", count); */
-            return count;
+          genSend(reverseSet(_G.sendSet));
+          _G.sendSet = NULL;
         }
-    }
-    
-    /* printf("findLabelBackwards: not found.\n"); */
-    
-    return 0;
-}
 
-/*-----------------------------------------------------------------*/
-/* genPlusIncr :- does addition with increment if possible         */
-/*-----------------------------------------------------------------*/
-static bool genPlusIncr (iCode *ic)
-{
-    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 ;
-    
-    /* if the literal value of the right hand side
-       is greater than 4 then it is not worth it */
-    if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
-        return FALSE ;
-    
-    /* if increment 16 bits in register */
-    if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
-        (size > 1) &&
-        (icount == 1)) {
-        symbol *tlbl;
-        int emitTlbl;
-        int labelRange;
-
-       /* If the next instruction is a goto and the goto target
-        * is < 10 instructions previous to this, we can generate
-        * jumps straight to that target.
-        */
-        if (ic->next && ic->next->op == GOTO
-            && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
-            && labelRange <= 10 )
-        {
-           emitcode(";", "tail increment optimized");
-           tlbl = IC_LABEL(ic->next);
-           emitTlbl = 0;
-        }
-        else
+      if (swapBanks)
         {
-            tlbl = newiTempLabel(NULL);
-            emitTlbl = 1;
-        }
-       emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
-       if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
-          IS_AOP_PREG(IC_RESULT(ic)))
-           emitcode("cjne","%s,#0x00,%05d$"
-                    ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
-                    ,tlbl->key+100);
-       else {
-           emitcode("clr","a");
-           emitcode("cjne","a,%s,%05d$"
-                    ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
-                    ,tlbl->key+100);
-       }
-    
-       emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
-       if (size > 2)
-       {
-           if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
-              IS_AOP_PREG(IC_RESULT(ic)))
-               emitcode("cjne","%s,#0x00,%05d$"
-                        ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
-                        ,tlbl->key+100);
-           else
-               emitcode("cjne","a,%s,%05d$"
-                        ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
-                        ,tlbl->key+100);
-           
-           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
-       }
-       if (size > 3)
-       {
-           if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
-              IS_AOP_PREG(IC_RESULT(ic)))
-               emitcode("cjne","%s,#0x00,%05d$"
-                        ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
-                        ,tlbl->key+100);
-           else{
-               emitcode("cjne","a,%s,%05d$"
-                        ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
-                        ,tlbl->key+100);
-           }
-           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
-       }
-       
-       if (emitTlbl)
-       {
-           emitcode("","%05d$:",tlbl->key+100);
-       }
-        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))) ) {
-       
-        if (icount > 3) {
-            MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));       
-            emitcode("add","a,#0x%02x",((char) icount) & 0xff);
-            aopPut(AOP(IC_RESULT(ic)),"a",0);
-        } else {
-           
-            while (icount--) 
-                emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+          emitcode ("mov", "psw,#0x%02x",
+           ((FUNC_REGBANK(dtype)) << 3) & 0xff);
         }
-       
-        return TRUE ;
-    }
-    
-    return FALSE ;
-}
-
-/*-----------------------------------------------------------------*/
-/* outBitAcc - output a bit in acc                                 */
-/*-----------------------------------------------------------------*/
-static void outBitAcc(operand *result)
-{
-    symbol *tlbl = newiTempLabel(NULL);
-    /* if the result is a bit */
-    if (AOP_TYPE(result) == AOP_CRY){
-        aopPut(AOP(result),"a",0);
-    }
-    else {
-        emitcode("jz","%05d$",tlbl->key+100);
-        emitcode("mov","a,%s",one);
-        emitcode("","%05d$:",tlbl->key+100);
-        outAcc(result);
-    }
-}
 
-/*-----------------------------------------------------------------*/
-/* genPlusBits - generates code for addition of two bits           */
-/*-----------------------------------------------------------------*/
-static void genPlusBits (iCode *ic)
-{
-    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
-        symbol *lbl = newiTempLabel(NULL);
-        emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
-        emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
-        emitcode("cpl","c");
-        emitcode("","%05d$:",(lbl->key+100));
-        outBitC(IC_RESULT(ic));
-    }
-    else{
-        emitcode("clr","a");
-        emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
-        emitcode("rlc","a");
-        emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
-        emitcode("addc","a,#0x00");
-        outAcc(IC_RESULT(ic));
-    }
-}
+      if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
+        {
+          if (IFFUNC_CALLEESAVES(dtype))
+            {
+              werror (E_BANKED_WITH_CALLEESAVES);
+            }
+          else
+            {
+              char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
 
-#if 0
-/* This is the original version of this code.
- *
- * This is being kept around for reference, 
- * because I am not entirely sure I got it right...
- */
-static void adjustArithmeticResult(iCode *ic)
-{
-    if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
-       AOP_SIZE(IC_LEFT(ic)) == 3   &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
-       aopPut(AOP(IC_RESULT(ic)),
-              aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
-              2);
-
-    if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
-       AOP_SIZE(IC_RIGHT(ic)) == 3   &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
-       aopPut(AOP(IC_RESULT(ic)),
-              aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
-              2);
-    
-    if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
-       AOP_SIZE(IC_LEFT(ic)) < 3    &&
-       AOP_SIZE(IC_RIGHT(ic)) < 3   &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
-       char buffer[5];
-       sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
-       aopPut(AOP(IC_RESULT(ic)),buffer,2);
+              emitcode ("mov", "r0,#%s", l);
+              emitcode ("mov", "r1,#(%s >> 8)", l);
+              emitcode ("mov", "r2,#(%s >> 16)", l);
+              emitcode ("lcall", "__sdcc_banked_call");
+            }
+        }
+      else
+        {
+          emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
+        }
     }
-}
-#else
-/* This is the pure and virtuous version of this code.
- * I'm pretty certain it's right, but not enough to toss the old 
- * code just yet...
- */
-static void adjustArithmeticResult(iCode *ic)
-{
-    if (opIsGptr(IC_RESULT(ic)) &&
-       opIsGptr(IC_LEFT(ic))   &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
+  else
     {
-       aopPut(AOP(IC_RESULT(ic)),
-              aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
-              GPTRSIZE - 1);
-    }
+      if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
+        {
+          if (IFFUNC_CALLEESAVES(dtype))
+            {
+              werror (E_BANKED_WITH_CALLEESAVES);
+            }
+          else
+            {
+              aopOp (IC_LEFT (ic), ic, FALSE);
 
-    if (opIsGptr(IC_RESULT(ic)) &&
-        opIsGptr(IC_RIGHT(ic))   &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
-    {
-       aopPut(AOP(IC_RESULT(ic)),
-              aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
-              GPTRSIZE - 1);
-    }
+              if (!swapBanks)
+                {
+                  emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
+                  emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
+                  emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
+                }
+              else
+                {
+                  int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
+                  emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
+                  emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
+                  emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
+                }
 
-    if (opIsGptr(IC_RESULT(ic))           &&
-        AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
-        AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
-        !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
-        !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
-        char buffer[5];
-        sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
-        aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
-     }
-}
-#endif
+              freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
 
-/*-----------------------------------------------------------------*/
-/* genPlus - generates code for addition                           */
-/*-----------------------------------------------------------------*/
-static void genPlus (iCode *ic)
-{
-    int size, offset = 0;
+              /* if send set is not empty then assign */
+              if (_G.sendSet)
+                {
+                  genSend(reverseSet(_G.sendSet));
+                  _G.sendSet = NULL;
+                }
 
-    /* special cases :- */
+              if (swapBanks)
+                {
+                  emitcode ("mov", "psw,#0x%02x",
+                   ((FUNC_REGBANK(dtype)) << 3) & 0xff);
+                }
 
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RIGHT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
+              /* make the call */
+              emitcode ("lcall", "__sdcc_banked_call");
+            }
+        }
+      else
+        {
+          /* push the return address on to the stack */
+          emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
+          emitcode ("push", "acc");
+          emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
+          emitcode ("push", "acc");
 
-    /* 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;
-    }
+          /* now push the calling address */
+          aopOp (IC_LEFT (ic), ic, FALSE);
 
-    /* if both left & right are in bit
-    space */
-    if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
-        AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
-        genPlusBits (ic);
-        goto release ;
-    }
+          pushSide (IC_LEFT (ic), FPTRSIZE);
 
-    /* if left in bit space & right literal */
-    if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
-        AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
-        emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
-        /* if result in bit space */
-        if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
-            if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
-                emitcode("cpl","c");
-            outBitC(IC_RESULT(ic));
-        } else {
-            size = getDataSize(IC_RESULT(ic));
-            while (size--) {
-                MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
-                emitcode("addc","a,#00");
-                aopPut(AOP(IC_RESULT(ic)),"a",offset++);
-            }
-        }
-        goto release ;
-    }
-
-    /* if I can do an increment instead
-    of add then GOOD for ME */
-    if (genPlusIncr (ic) == TRUE)
-        goto release;   
-
-    size = getDataSize(IC_RESULT(ic));
-
-    while(size--){
-       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
-           MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
-           if(offset == 0)
-               emitcode("add","a,%s",
-                        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
-           else
-               emitcode("addc","a,%s",
-                        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
-       } else {
-           MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
-           if(offset == 0)
-               emitcode("add","a,%s",
-                        aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
-           else
-               emitcode("addc","a,%s",
-                        aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
-       }
-        aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
-    }
-
-    adjustArithmeticResult(ic);
+          freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
 
-release:
-    freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
-}
-
-/*-----------------------------------------------------------------*/
-/* genMinusDec :- does subtraction with deccrement if possible     */
-/*-----------------------------------------------------------------*/
-static bool genMinusDec (iCode *ic)
-{
-    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 ;
-
-    /* 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)) > 4)
-        return FALSE ;
-
-    /* if decrement 16 bits in register */
-    if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
-        (size > 1) &&
-        (icount == 1)) {
-            symbol *tlbl;
-            int emitTlbl;
-            int labelRange;
-
-           /* If the next instruction is a goto and the goto target
-            * is <= 10 instructions previous to this, we can generate
-            * jumps straight to that target.
-            */
-            if (ic->next && ic->next->op == GOTO
-                && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
-                && labelRange <= 10 )
-            {        
-               emitcode(";", "tail decrement optimized");
-               tlbl = IC_LABEL(ic->next);
-               emitTlbl = 0;
+          /* if send set is not empty the assign */
+          if (_G.sendSet)
+            {
+              genSend(reverseSet(_G.sendSet));
+              _G.sendSet = NULL;
             }
-            else
+
+          if (swapBanks)
             {
-                tlbl = newiTempLabel(NULL);
-                emitTlbl = 1;
-            }
-        
-               emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
-               if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
-                  IS_AOP_PREG(IC_RESULT(ic)))
-                       emitcode("cjne","%s,#0xff,%05d$"
-                                        ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
-                                        ,tlbl->key+100);
-               else{
-                       emitcode("mov","a,#0xff");
-                       emitcode("cjne","a,%s,%05d$"
-                                        ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
-                                        ,tlbl->key+100);
-               }
-               emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
-               if (size > 2)
-               {
-                       if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
-                          IS_AOP_PREG(IC_RESULT(ic)))
-                               emitcode("cjne","%s,#0xff,%05d$"
-                                                ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
-                                                ,tlbl->key+100);
-                       else{
-                               emitcode("cjne","a,%s,%05d$"
-                                                ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
-                                                ,tlbl->key+100);
-                       }
-                       emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
-               }
-               if (size > 3)
-               {
-                       if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
-                          IS_AOP_PREG(IC_RESULT(ic)))
-                               emitcode("cjne","%s,#0xff,%05d$"
-                                                ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
-                                                ,tlbl->key+100);
-                       else{
-                               emitcode("cjne","a,%s,%05d$"
-                                                ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
-                                                ,tlbl->key+100);
-                       }
-                       emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
-               }
-               if (emitTlbl)
-               {
-                   emitcode("","%05d$:",tlbl->key+100);
-               }
-        return TRUE;
+              emitcode ("mov", "psw,#0x%02x",
+               ((FUNC_REGBANK(dtype)) << 3) & 0xff);
+            }
+
+          /* make the call */
+          emitcode ("ret", "");
+          emitLabel (rlbl);
+        }
+    }
+  if (swapBanks)
+    {
+      selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
     }
 
-    /* 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 we need assign a result value */
+  if ((IS_ITEMP (IC_RESULT (ic)) &&
+       !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
+       (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
+        OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
+      IS_TRUE_SYMOP (IC_RESULT (ic)))
+    {
 
-    /* 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)))) {
+      _G.accInUse++;
+      aopOp (IC_RESULT (ic), ic, FALSE);
+      _G.accInUse--;
 
-        while (icount--) 
-            emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+      assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
 
-        return TRUE ;
+      freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
     }
 
-    return FALSE ;
-}
+  /* adjust the stack for parameters if required */
+  if (ic->parmBytes)
+    {
+      int i;
+      if (ic->parmBytes > 3)
+        {
+          if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
+              IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
+            {
+              emitcode ("mov", "F0,c");
+              resultInF0 = TRUE;
+            }
 
-/*-----------------------------------------------------------------*/
-/* addSign - complete with sign                                    */
-/*-----------------------------------------------------------------*/
-static void addSign(operand *result, int offset, int sign)
-{
-    int size = (getDataSize(result) - offset);
-    if(size > 0){
-        if(sign){
-            emitcode("rlc","a");
-            emitcode("subb","a,acc");
-            while(size--)
-                aopPut(AOP(result),"a",offset++); 
-        } else
-            while(size--)
-                aopPut(AOP(result),zero,offset++);
+          emitcode ("mov", "a,%s", spname);
+          emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
+          emitcode ("mov", "%s,a", spname);
+        }
+      else
+        for (i = 0; i < ic->parmBytes; i++)
+          emitcode ("dec", "%s", spname);
     }
-}
 
-/*-----------------------------------------------------------------*/
-/* genMinusBits - generates code for subtraction  of two bits      */
-/*-----------------------------------------------------------------*/
-static void genMinusBits (iCode *ic)
-{
-    symbol *lbl = newiTempLabel(NULL);
-    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
-        emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
-        emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
-        emitcode("cpl","c");
-        emitcode("","%05d$:",(lbl->key+100));
-        outBitC(IC_RESULT(ic));
-    }
-    else{
-        emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
-        emitcode("subb","a,acc");
-        emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
-        emitcode("inc","a");
-        emitcode("","%05d$:",(lbl->key+100));
-        aopPut(AOP(IC_RESULT(ic)),"a",0);
-        addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
+//  /* if register bank was saved then unsave them */
+//  if (restoreBank)
+//    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
+
+  /* if we had saved some registers then unsave them */
+  if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
+    unsaveRegisters (ic);
+
+  if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
+    {
+      if (resultInF0)
+          emitcode ("mov", "c,F0");
+
+      aopOp (IC_RESULT (ic), ic, FALSE);
+      assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
+      freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
     }
 }
 
 /*-----------------------------------------------------------------*/
-/* genMinus - generates code for subtraction                       */
+/* resultRemat - result  is rematerializable                       */
 /*-----------------------------------------------------------------*/
-static void genMinus (iCode *ic)
+static int
+resultRemat (iCode * ic)
 {
-    int size, offset = 0;
-    unsigned long lit = 0L;
-
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RIGHT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
-
-    /* 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) {
-        genMinusBits (ic);
-        goto release ;
-    }
-
-    /* if I can do an decrement instead
-    of subtract then GOOD for ME */
-    if (genMinusDec (ic) == TRUE)
-        goto release;   
-
-    size = getDataSize(IC_RESULT(ic));   
-
-    if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
-        CLRC;
-    }
-    else{
-        lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
-        lit = - (long)lit;
-    }
+  if (SKIP_IC (ic) || ic->op == IFX)
+    return 0;
 
-    /* if literal, add a,#-lit, else normal subb */
-    while (size--) {
-        MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));    
-        if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)  
-            emitcode("subb","a,%s",
-                     aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
-        else{
-            /* first add without previous c */
-            if(!offset)
-                emitcode("add","a,#0x%02x",
-                         (unsigned int)(lit & 0x0FFL));
-            else
-                emitcode("addc","a,#0x%02x",
-                         (unsigned int)((lit >> (offset*8)) & 0x0FFL));
-        }
-        aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
+  if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
+    {
+      symbol *sym = OP_SYMBOL (IC_RESULT (ic));
+      if (sym->remat && !POINTER_SET (ic))
+        return 1;
     }
 
-    adjustArithmeticResult(ic);
-        
-release:
-    freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+  return 0;
 }
 
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+#define STRCASECMP stricmp
+#else
+#define STRCASECMP strcasecmp
+#endif
 
 /*-----------------------------------------------------------------*/
-/* genMultbits :- multiplication of bits                           */
+/* inExcludeList - return 1 if the string is in exclude Reg list   */
 /*-----------------------------------------------------------------*/
-static void genMultbits (operand *left, 
-                         operand *right, 
-                         operand *result)
+static int
+regsCmp(void *p1, void *p2)
 {
-    emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-    emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
-    outBitC(result);
+  return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
 }
 
-
-/*-----------------------------------------------------------------*/
-/* genMultOneByte : 8 bit multiplication & division                */
-/*-----------------------------------------------------------------*/
-static void genMultOneByte (operand *left,
-                            operand *right,
-                            operand *result)
+static bool
+inExcludeList (char *s)
 {
-    link *opetype = operandType(result);
-    char *l ;
-    symbol *lbl ;
-    int size,offset;
-
-    /* (if two literals, the value is computed before) */
-    /* if one literal, literal on the right */
-    if (AOP_TYPE(left) == AOP_LIT){
-        operand *t = right;
-        right = left;
-        left = t;
-    }
+  const char *p = setFirstItem(options.excludeRegsSet);
 
-    size = AOP_SIZE(result);
-    /* signed or unsigned */
-    emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
-    l = aopGet(AOP(left),0,FALSE,FALSE);
-    MOVA(l);       
-    emitcode("mul","ab");
-    /* if result size = 1, mul signed = mul unsigned */
-    aopPut(AOP(result),"a",0);
-    if (size > 1){
-        if (SPEC_USIGN(opetype)){
-            aopPut(AOP(result),"b",1);
-            if (size > 2)
-                /* for filling the MSBs */
-                emitcode("clr","a");
-        }
-        else{
-            emitcode("mov","a,b");
+  if (p == NULL || STRCASECMP(p, "none") == 0)
+    return FALSE;
 
-            /* adjust the MSB if left or right neg */
 
-            /* if one literal */
-            if (AOP_TYPE(right) == AOP_LIT){
-                /* AND literal negative */
-                if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
-                    /* adjust MSB (c==0 after mul) */
-                    emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
-                }
-            }
-            else{
-                lbl = newiTempLabel(NULL);
-                emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
-                emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
-                emitcode("","%05d$:",(lbl->key+100));
-                emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
-                lbl = newiTempLabel(NULL);      
-                emitcode("jc","%05d$",(lbl->key+100));          
-                emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
-                emitcode("","%05d$:",(lbl->key+100));
-            }
-
-            lbl = newiTempLabel(NULL);
-            emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
-            emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
-            emitcode("","%05d$:",(lbl->key+100));
-            emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
-            lbl = newiTempLabel(NULL);      
-            emitcode("jc","%05d$",(lbl->key+100));          
-            emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
-            emitcode("","%05d$:",(lbl->key+100));
-
-            aopPut(AOP(result),"a",1);
-            if(size > 2){
-                /* get the sign */
-                emitcode("rlc","a");
-                emitcode("subb","a,acc");
-            }
-        }
-        size -= 2;   
-        offset = 2;
-        if (size > 0)
-            while (size--)
-                aopPut(AOP(result),"a",offset++);
-    }
+  return isinSetWith(options.excludeRegsSet, s, regsCmp);
 }
 
 /*-----------------------------------------------------------------*/
-/* genMult - generates code for multiplication                     */
+/* genFunction - generated code for function entry                 */
 /*-----------------------------------------------------------------*/
-static void genMult (iCode *ic)
-{
-    operand *left = IC_LEFT(ic);
-    operand *right = IC_RIGHT(ic);
-    operand *result= IC_RESULT(ic);   
-
-    /* assign the amsops */
-    aopOp (left,ic,FALSE);
-    aopOp (right,ic,FALSE);
-    aopOp (result,ic,TRUE);
-
-    /* special cases first */
-    /* both are bits */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right)== AOP_CRY) {
-        genMultbits(left,right,result);
-        goto release ;
-    }
+static void
+genFunction (iCode * ic)
+{
+  symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
+  sym_link *ftype;
+  bool     switchedPSW = FALSE;
+  int      calleesaves_saved_register = -1;
+  int      stackAdjust = sym->stack;
+  int      accIsFree = sym->recvSize < 4;
+  iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
+  bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
+
+  _G.nRegsSaved = 0;
+  /* create the function header */
+  emitcode (";", "-----------------------------------------");
+  emitcode (";", " function %s", sym->name);
+  emitcode (";", "-----------------------------------------");
+
+  emitcode ("", "%s:", sym->rname);
+  ftype = operandType (IC_LEFT (ic));
+  _G.currentFunc = sym;
+
+  if (IFFUNC_ISNAKED(ftype))
+  {
+      emitcode(";", "naked function: no prologue.");
+      return;
+  }
+
+  /* here we need to generate the equates for the
+     register bank if required */
+  if (FUNC_REGBANK (ftype) != rbank)
+    {
+      int i;
 
-    /* if both are of size == 1 */
-    if (AOP_SIZE(left) == 1 &&
-        AOP_SIZE(right) == 1 ) {
-        genMultOneByte(left,right,result);
-        goto release ;
+      rbank = FUNC_REGBANK (ftype);
+      for (i = 0; i < mcs51_nRegs; i++)
+        {
+          if (regs8051[i].type != REG_BIT)
+            {
+              if (strcmp (regs8051[i].base, "0") == 0)
+                emitcode ("", "%s = 0x%02x",
+                          regs8051[i].dname,
+                          8 * rbank + regs8051[i].offset);
+              else
+                emitcode ("", "%s = %s + 0x%02x",
+                          regs8051[i].dname,
+                          regs8051[i].base,
+                          8 * rbank + regs8051[i].offset);
+            }
+        }
     }
 
-    /* should have been converted to function call */       
-    assert(1) ;
+  /* if this is an interrupt service routine then
+     save acc, b, dpl, dph  */
+  if (IFFUNC_ISISR (sym->type))
+    {
+      if (!inExcludeList ("acc"))
+        emitcode ("push", "acc");
+      if (!inExcludeList ("b"))
+        emitcode ("push", "b");
+      if (!inExcludeList ("dpl"))
+        emitcode ("push", "dpl");
+      if (!inExcludeList ("dph"))
+        emitcode ("push", "dph");
+      /* if this isr has no bank i.e. is going to
+         run with bank 0 , then we need to save more
+         registers :-) */
+      if (!FUNC_REGBANK (sym->type))
+        {
+          int i;
 
-release :
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE); 
-}
+          /* if this function does not call any other
+             function then we can be economical and
+             save only those registers that are used */
+          if (!IFFUNC_HASFCALL(sym->type))
+            {
+              /* if any registers used */
+              if (sym->regsUsed)
+                {
+                  bool bits_pushed = FALSE;
+                  /* save the registers used */
+                  for (i = 0; i < sym->regsUsed->size; i++)
+                    {
+                      if (bitVectBitValue (sym->regsUsed, i))
+                        bits_pushed = pushReg (i, bits_pushed);
+                    }
+                }
+            }
+          else
+            {
+              /* this function has a function call. We cannot
+                 determine register usage so we will have to push the
+                 entire bank */
+                saveRBank (0, ic, FALSE);
+                if (options.parms_in_bank1) {
+                    for (i=0; i < 8 ; i++ ) {
+                        emitcode ("push","%s",rb1regs[i]);
+                    }
+                }
+            }
+        }
+        else
+        {
+            /* This ISR uses a non-zero bank.
+             *
+             * We assume that the bank is available for our
+             * exclusive use.
+             *
+             * However, if this ISR calls a function which uses some
+             * other bank, we must save that bank entirely.
+             */
+            unsigned long banksToSave = 0;
 
-/*-----------------------------------------------------------------*/
-/* genDivbits :- division of bits                                  */
-/*-----------------------------------------------------------------*/
-static void genDivbits (operand *left, 
-                        operand *right, 
-                        operand *result)
-{
+            if (IFFUNC_HASFCALL(sym->type))
+            {
 
-    char *l;
+#define MAX_REGISTER_BANKS 4
 
-    /* the result must be bit */    
-    emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
-    l = aopGet(AOP(left),0,FALSE,FALSE);
+                iCode *i;
+                int ix;
 
-    MOVA(l);    
+                for (i = ic; i; i = i->next)
+                {
+                    if (i->op == ENDFUNCTION)
+                    {
+                        /* we got to the end OK. */
+                        break;
+                    }
 
-    emitcode("div","ab");
-    emitcode("rrc","a");
-    aopPut(AOP(result),"c",0);
-}
-
-/*-----------------------------------------------------------------*/
-/* genDivOneByte : 8 bit division                                  */
-/*-----------------------------------------------------------------*/
-static void genDivOneByte (operand *left,
-                           operand *right,
-                           operand *result)
-{
-    link *opetype = operandType(result);
-    char *l ;
-    symbol *lbl ;
-    int size,offset;
-
-    size = AOP_SIZE(result) - 1;
-    offset = 1;
-    /* signed or unsigned */
-    if (SPEC_USIGN(opetype)) {
-        /* unsigned is easy */
-        emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
-        l = aopGet(AOP(left),0,FALSE,FALSE);
-        MOVA(l);        
-        emitcode("div","ab");
-        aopPut(AOP(result),"a",0);
-        while (size--)
-            aopPut(AOP(result),zero,offset++);
-        return ;
-    }
-
-    /* signed is a little bit more difficult */
-
-    /* save the signs of the operands */
-    l = aopGet(AOP(left),0,FALSE,FALSE);    
-    MOVA(l);    
-    emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
-    emitcode("push","acc"); /* save it on the stack */
-
-    /* now sign adjust for both left & right */
-    l =  aopGet(AOP(right),0,FALSE,FALSE);    
-    MOVA(l);       
-    lbl = newiTempLabel(NULL);
-    emitcode("jnb","acc.7,%05d$",(lbl->key+100));   
-    emitcode("cpl","a");   
-    emitcode("inc","a");
-    emitcode("","%05d$:",(lbl->key+100));
-    emitcode("mov","b,a");
-
-    /* sign adjust left side */
-    l =  aopGet(AOP(left),0,FALSE,FALSE);    
-    MOVA(l);
-
-    lbl = newiTempLabel(NULL);
-    emitcode("jnb","acc.7,%05d$",(lbl->key+100));
-    emitcode("cpl","a");
-    emitcode("inc","a");
-    emitcode("","%05d$:",(lbl->key+100));
-
-    /* now the division */
-    emitcode("div","ab");
-    /* we are interested in the lower order
-    only */
-    emitcode("mov","b,a");
-    lbl = newiTempLabel(NULL);
-    emitcode("pop","acc");   
-    /* if there was an over flow we don't 
-    adjust the sign of the result */
-    emitcode("jb","ov,%05d$",(lbl->key+100));
-    emitcode("jnb","acc.7,%05d$",(lbl->key+100));
-    CLRC;
-    emitcode("clr","a");
-    emitcode("subb","a,b");
-    emitcode("mov","b,a");
-    emitcode("","%05d$:",(lbl->key+100));
+                    if (i->op == CALL)
+                    {
+                        sym_link *dtype;
+
+                        dtype = operandType (IC_LEFT(i));
+                        if (dtype
+                         && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
+                        {
+                             /* Mark this bank for saving. */
+                             if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
+                             {
+                                 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
+                             }
+                             else
+                             {
+                                 banksToSave |= (1 << FUNC_REGBANK(dtype));
+                             }
+
+                             /* And note that we don't need to do it in
+                              * genCall.
+                              */
+                             i->bankSaved = 1;
+                        }
+                    }
+                    if (i->op == PCALL)
+                    {
+                        /* This is a mess; we have no idea what
+                         * register bank the called function might
+                         * use.
+                         *
+                         * The only thing I can think of to do is
+                         * throw a warning and hope.
+                         */
+                        werror(W_FUNCPTR_IN_USING_ISR);
+                    }
+                }
 
-    /* now we are done */
-    aopPut(AOP(result),"b",0);
-    if(size > 0){
-        emitcode("mov","c,b.7");
-        emitcode("subb","a,acc");   
-    }
-    while (size--)
-        aopPut(AOP(result),"a",offset++);
+                if (banksToSave && options.useXstack)
+                {
+                    /* Since we aren't passing it an ic,
+                     * saveRBank will assume r0 is available to abuse.
+                     *
+                     * So switch to our (trashable) bank now, so
+                     * the caller's R0 isn't trashed.
+                     */
+                    emitcode ("push", "psw");
+                    emitcode ("mov", "psw,#0x%02x",
+                              (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
+                    switchedPSW = TRUE;
+                }
 
-}
+                for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
+                {
+                     if (banksToSave & (1 << ix))
+                     {
+                         saveRBank(ix, NULL, FALSE);
+                     }
+                }
+            }
+            // TODO: this needs a closer look
+            SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
+        }
 
-/*-----------------------------------------------------------------*/
-/* genDiv - generates code for division                            */
-/*-----------------------------------------------------------------*/
-static void genDiv (iCode *ic)
-{
-    operand *left = IC_LEFT(ic);
-    operand *right = IC_RIGHT(ic);
-    operand *result= IC_RESULT(ic);   
+      /* Set the register bank to the desired value if nothing else */
+      /* has done so yet. */
+      if (!switchedPSW)
+        {
+          emitcode ("push", "psw");
+          emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
+        }
+    }
+  else
+    {
+      /* This is a non-ISR function. The caller has already switched register */
+      /* banks, if necessary, so just handle the callee-saves option. */
 
-    /* assign the amsops */
-    aopOp (left,ic,FALSE);
-    aopOp (right,ic,FALSE);
-    aopOp (result,ic,TRUE);
+      /* if callee-save to be used for this function
+         then save the registers being used in this function */
+      if (IFFUNC_CALLEESAVES(sym->type))
+        {
+          int i;
 
-    /* special cases first */
-    /* both are bits */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right)== AOP_CRY) {
-        genDivbits(left,right,result);
-        goto release ;
+          /* if any registers used */
+          if (sym->regsUsed)
+            {
+              bool bits_pushed = FALSE;
+              /* save the registers used */
+              for (i = 0; i < sym->regsUsed->size; i++)
+                {
+                  if (bitVectBitValue (sym->regsUsed, i))
+                    {
+                      /* remember one saved register for later usage */
+                      if (calleesaves_saved_register < 0)
+                        calleesaves_saved_register = i;
+                      bits_pushed = pushReg (i, bits_pushed);
+                      _G.nRegsSaved++;
+                    }
+                }
+            }
+        }
     }
 
-    /* if both are of size == 1 */
-    if (AOP_SIZE(left) == 1 &&
-        AOP_SIZE(right) == 1 ) {
-        genDivOneByte(left,right,result);
-        goto release ;
+  if (fReentrant)
+    {
+      if (options.useXstack)
+        {
+          if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
+            {
+              emitcode ("mov", "r0,%s", spname);
+              emitcode ("inc", "%s", spname);
+              emitcode ("xch", "a,_bpx");
+              emitcode ("movx", "@r0,a");
+              emitcode ("inc", "r0");
+              emitcode ("mov", "a,r0");
+              emitcode ("xch", "a,_bpx");
+            }
+          if (sym->stack)
+            {
+              emitcode ("push", "_bp");     /* save the callers stack  */
+              emitcode ("mov", "_bp,sp");
+            }
+        }
+      else
+        {
+          if (sym->stack || FUNC_HASSTACKPARM(sym->type))
+            {
+              /* set up the stack */
+              emitcode ("push", "_bp");     /* save the callers stack  */
+              emitcode ("mov", "_bp,sp");
+            }
+        }
     }
 
-    /* should have been converted to function call */
-    assert(1);
-release :
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE); 
-}
-
-/*-----------------------------------------------------------------*/
-/* genModbits :- modulus of bits                                   */
-/*-----------------------------------------------------------------*/
-static void genModbits (operand *left, 
-                        operand *right, 
-                        operand *result)
-{
+  /* For some cases it is worthwhile to perform a RECEIVE iCode */
+  /* before setting up the stack frame completely. */
+  if (ric && ric->argreg == 1 && IC_RESULT (ric))
+    {
+      symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
 
-    char *l;
+      if (rsym->isitmp)
+        {
+          if (rsym && rsym->regType == REG_CND)
+            rsym = NULL;
+          if (rsym && (rsym->accuse || rsym->ruonly))
+            rsym = NULL;
+          if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
+            rsym = rsym->usl.spillLoc;
+        }
 
-    /* the result must be bit */    
-    emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
-    l = aopGet(AOP(left),0,FALSE,FALSE);
+      /* If the RECEIVE operand immediately spills to the first entry on the */
+      /* stack, we can push it directly (since sp = _bp + 1 at this point) */
+      /* rather than the usual @r0/r1 machinations. */
+      if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
+        {
+          int ofs;
 
-    MOVA(l);       
+          _G.current_iCode = ric;
+          D(emitcode (";     genReceive",""));
+          for (ofs=0; ofs < sym->recvSize; ofs++)
+            {
+              if (!strcmp (fReturn[ofs], "a"))
+                emitcode ("push", "acc");
+              else
+                emitcode ("push", fReturn[ofs]);
+            }
+          stackAdjust -= sym->recvSize;
+          if (stackAdjust<0)
+            {
+              assert (stackAdjust>=0);
+              stackAdjust = 0;
+            }
+          _G.current_iCode = ic;
+          ric->generated = 1;
+          accIsFree = 1;
+        }
+      /* If the RECEIVE operand is 4 registers, we can do the moves now */
+      /* to free up the accumulator. */
+      else if (rsym && rsym->nRegs && sym->recvSize == 4)
+        {
+          int ofs;
 
-    emitcode("div","ab");
-    emitcode("mov","a,b");
-    emitcode("rrc","a");
-    aopPut(AOP(result),"c",0);
-}
+          _G.current_iCode = ric;
+          D(emitcode (";     genReceive",""));
+          for (ofs=0; ofs < sym->recvSize; ofs++)
+            {
+              emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
+            }
+          _G.current_iCode = ic;
+          ric->generated = 1;
+          accIsFree = 1;
+        }
+    }
 
-/*-----------------------------------------------------------------*/
-/* genModOneByte : 8 bit modulus                                   */
-/*-----------------------------------------------------------------*/
-static void genModOneByte (operand *left,
-                           operand *right,
-                           operand *result)
-{
-    link *opetype = operandType(result);
-    char *l ;
-    symbol *lbl ;
-
-    /* signed or unsigned */
-    if (SPEC_USIGN(opetype)) {
-        /* unsigned is easy */
-        emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
-        l = aopGet(AOP(left),0,FALSE,FALSE);
-        MOVA(l);    
-        emitcode("div","ab");
-        aopPut(AOP(result),"b",0);
-        return ;
-    }
-
-    /* signed is a little bit more difficult */
-
-    /* save the signs of the operands */
-    l = aopGet(AOP(left),0,FALSE,FALSE);    
-    MOVA(l);
-
-    emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
-    emitcode("push","acc"); /* save it on the stack */
-
-    /* now sign adjust for both left & right */
-    l =  aopGet(AOP(right),0,FALSE,FALSE);    
-    MOVA(l);
-
-    lbl = newiTempLabel(NULL);
-    emitcode("jnb","acc.7,%05d$",(lbl->key+100));  
-    emitcode("cpl","a");   
-    emitcode("inc","a");
-    emitcode("","%05d$:",(lbl->key+100));
-    emitcode("mov","b,a"); 
-
-    /* sign adjust left side */
-    l =  aopGet(AOP(left),0,FALSE,FALSE);    
-    MOVA(l);
-
-    lbl = newiTempLabel(NULL);
-    emitcode("jnb","acc.7,%05d$",(lbl->key+100));
-    emitcode("cpl","a");   
-    emitcode("inc","a");
-    emitcode("","%05d$:",(lbl->key+100));
-
-    /* now the multiplication */
-    emitcode("div","ab");
-    /* we are interested in the lower order
-    only */
-    lbl = newiTempLabel(NULL);
-    emitcode("pop","acc");   
-    /* if there was an over flow we don't 
-    adjust the sign of the result */
-    emitcode("jb","ov,%05d$",(lbl->key+100));
-    emitcode("jnb","acc.7,%05d$",(lbl->key+100));
-    CLRC ;
-    emitcode("clr","a");
-    emitcode("subb","a,b");
-    emitcode("mov","b,a");
-    emitcode("","%05d$:",(lbl->key+100));
-
-    /* now we are done */
-    aopPut(AOP(result),"b",0);
+  /* adjust the stack for the function */
+  if (stackAdjust)
+    {
+      int i = stackAdjust;
+      if (i > 256)
+        werror (W_STACK_OVERFLOW, sym->name);
 
-}
+      if (i > 3 && accIsFree)
+        {
+          emitcode ("mov", "a,sp");
+          emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
+          emitcode ("mov", "sp,a");
+        }
+      else if (i > 5)
+        {
+          /* The accumulator is not free, so we will need another register */
+          /* to clobber. No need to worry about a possible conflict with */
+          /* the above early RECEIVE optimizations since they would have */
+          /* freed the accumulator if they were generated. */
 
-/*-----------------------------------------------------------------*/
-/* genMod - generates code for division                            */
-/*-----------------------------------------------------------------*/
-static void genMod (iCode *ic)
-{
-    operand *left = IC_LEFT(ic);
-    operand *right = IC_RIGHT(ic);
-    operand *result= IC_RESULT(ic);  
+          if (IFFUNC_CALLEESAVES(sym->type))
+            {
+              /* if it's a callee-saves function we need a saved register */
+              if (calleesaves_saved_register >= 0)
+                {
+                  emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
+                  emitcode ("mov", "a,sp");
+                  emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
+                  emitcode ("mov", "sp,a");
+                  emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
+                }
+              else
+                /* do it the hard way */
+                while (i--)
+                  emitcode ("inc", "sp");
+            }
+          else
+            {
+              /* not callee-saves, we can clobber r0 */
+              emitcode ("mov", "r0,a");
+              emitcode ("mov", "a,sp");
+              emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
+              emitcode ("mov", "sp,a");
+              emitcode ("mov", "a,r0");
+            }
+        }
+      else
+        while (i--)
+          emitcode ("inc", "sp");
+    }
 
-    /* assign the amsops */
-    aopOp (left,ic,FALSE);
-    aopOp (right,ic,FALSE);
-    aopOp (result,ic,TRUE);
+  if (sym->xstack)
+    {
+      char i = ((char) sym->xstack & 0xff);
 
-    /* special cases first */
-    /* both are bits */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right)== AOP_CRY) {
-        genModbits(left,right,result);
-        goto release ;
+      if (i > 3 && accIsFree)
+        {
+          emitcode ("mov", "a,_spx");
+          emitcode ("add", "a,#0x%02x", i);
+          emitcode ("mov", "_spx,a");
+        }
+      else if (i > 5)
+        {
+          emitcode ("push", "acc");
+          emitcode ("mov", "a,_spx");
+          emitcode ("add", "a,#0x%02x", i);
+          emitcode ("mov", "_spx,a");
+          emitcode ("pop", "acc");
+        }
+      else
+        {
+          while (i--)
+            emitcode ("inc", "_spx");
+        }
     }
 
-    /* if both are of size == 1 */
-    if (AOP_SIZE(left) == 1 &&
-        AOP_SIZE(right) == 1 ) {
-        genModOneByte(left,right,result);
-        goto release ;
+  /* if critical function then turn interrupts off */
+  if (IFFUNC_ISCRITICAL (ftype))
+    {
+      symbol *tlbl = newiTempLabel (NULL);
+      emitcode ("setb", "c");
+      emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
+      emitcode ("clr", "c");
+      emitLabel (tlbl);
+      emitcode ("push", "psw"); /* save old ea via c in psw */
     }
-
-    /* should have been converted to function call */
-    assert(1);
-
-release :
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE); 
 }
 
 /*-----------------------------------------------------------------*/
-/* genIfxJump :- will create a jump depending on the ifx           */
+/* genEndFunction - generates epilogue for functions               */
 /*-----------------------------------------------------------------*/
-static void genIfxJump (iCode *ic, char *jval)
-{
-    symbol *jlbl ;
-    symbol *tlbl = newiTempLabel(NULL);
-    char *inst;
+static void
+genEndFunction (iCode * ic)
+{
+  symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
+  lineNode *lnp = lineCurr;
+  bitVect  *regsUsed;
+  bitVect  *regsUsedPrologue;
+  bitVect  *regsUnneeded;
+  int      idx;
+
+  _G.currentFunc = NULL;
+  if (IFFUNC_ISNAKED(sym->type))
+  {
+      emitcode(";", "naked function: no epilogue.");
+      if (options.debug && currFunc)
+        debugFile->writeEndFunction (currFunc, ic, 0);
+      return;
+  }
+
+  if (IFFUNC_ISCRITICAL (sym->type))
+    {
+      if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
+        {
+          emitcode ("rlc", "a");   /* save c in a */
+          emitcode ("pop", "psw"); /* restore ea via c in psw */
+          emitcode ("mov", "ea,c");
+          emitcode ("rrc", "a");   /* restore c from a */
+        }
+      else
+        {
+          emitcode ("pop", "psw"); /* restore ea via c in psw */
+          emitcode ("mov", "ea,c");
+        }
+    }
 
-    /* if true label then we jump if condition
-    supplied is true */
-    if ( IC_TRUE(ic) ) {
-        jlbl = IC_TRUE(ic);
-        inst = ((strcmp(jval,"a") == 0 ? "jz" :
-                 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
+  if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
+    {
+      if (options.useXstack)
+        {
+          if (sym->stack)
+            {
+              emitcode ("mov", "sp,_bp");
+              emitcode ("pop", "_bp");
+            }
+          if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
+            {
+              emitcode ("xch", "a,_bpx");
+              emitcode ("mov", "r0,a");
+              emitcode ("dec", "r0");
+              emitcode ("movx", "a,@r0");
+              emitcode ("xch", "a,_bpx");
+              emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
+            }
+        }
+      else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
+        {
+          if (sym->stack)
+            emitcode ("mov", "sp,_bp");
+          emitcode ("pop", "_bp");
+        }
     }
-    else {
-        /* false label is present */
-        jlbl = IC_FALSE(ic) ;
-        inst = ((strcmp(jval,"a") == 0 ? "jnz" :
-                 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));              
+
+  /* restore the register bank  */
+  if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
+  {
+    if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
+     || !options.useXstack)
+    {
+        /* Special case of ISR using non-zero bank with useXstack
+         * is handled below.
+         */
+        emitcode ("pop", "psw");
     }
-    if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0) 
-        emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
-    else
-        emitcode(inst,"%05d$",tlbl->key+100);
-    emitcode("ljmp","%05d$",jlbl->key+100);
-    emitcode("","%05d$:",tlbl->key+100);                
+  }
 
-    /* mark the icode as generated */
-    ic->generated = 1;
-}
+  if (IFFUNC_ISISR (sym->type))
+    {
 
-/*-----------------------------------------------------------------*/
-/* genCmp :- greater or less than comparison                       */
-/*-----------------------------------------------------------------*/
-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 ) {
-        emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
-        emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
-    } 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, do cjne left,#right,zz */
-        if((size == 1) && !sign &&
-           (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
-            symbol *lbl  = newiTempLabel(NULL);
-            emitcode("cjne","%s,%s,%05d$",
-                     aopGet(AOP(left),offset,FALSE,FALSE),
-                     aopGet(AOP(right),offset,FALSE,FALSE),
-                     lbl->key+100);
-            emitcode("","%05d$:",lbl->key+100);
-        } 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){
-                        CLRC;
-                    }
-                    else{
-                        MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
-                        if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
-                            genIfxJump (ifx,"acc.7");
-                            return;
-                        }
-                        else    
-                            emitcode("rlc","a");
+      /* now we need to restore the registers */
+      /* if this isr has no bank i.e. is going to
+         run with bank 0 , then we need to save more
+         registers :-) */
+      if (!FUNC_REGBANK (sym->type))
+        {
+          int i;
+          /* if this function does not call any other
+             function then we can be economical and
+             save only those registers that are used */
+          if (!IFFUNC_HASFCALL(sym->type))
+            {
+              /* if any registers used */
+              if (sym->regsUsed)
+                {
+                  bool bits_popped = FALSE;
+                  /* save the registers used */
+                  for (i = sym->regsUsed->size; i >= 0; i--)
+                    {
+                      if (bitVectBitValue (sym->regsUsed, i))
+                        bits_popped = popReg (i, bits_popped);
                     }
-                    goto release;
                 }
             }
-            CLRC;
-            while (size--) {
-                MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
-                if (sign && size == 0) {
-                    emitcode("xrl","a,#0x80");
-                    if (AOP_TYPE(right) == AOP_LIT){
-                        unsigned long lit = (unsigned long)
-                           floatFromVal(AOP(right)->aopu.aop_lit);
-                        emitcode("subb","a,#0x%02x",
-                                0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));                       
-                    } else {
-                        emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
-                        emitcode("xrl","b,#0x80");
-                        emitcode("subb","a,b");
-                    }
-                } else      
-                    emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
+          else
+            {
+              if (options.parms_in_bank1) {
+                  for (i = 7 ; i >= 0 ; i-- ) {
+                      emitcode ("pop","%s",rb1regs[i]);
+                  }
+              }
+              /* this function has  a function call cannot
+                 determines register usage so we will have to pop the
+                 entire bank */
+              unsaveRBank (0, ic, FALSE);
             }
         }
-    }
-
-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 */
-    }
-}
+        {
+            /* This ISR uses a non-zero bank.
+             *
+             * Restore any register banks saved by genFunction
+             * in reverse order.
+             */
+            unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
+            int ix;
 
-/*-----------------------------------------------------------------*/
-/* genCmpGt :- greater than comparison                             */
-/*-----------------------------------------------------------------*/
-static void genCmpGt (iCode *ic, iCode *ifx)
-{
-    operand *left, *right, *result;
-    link *letype , *retype;
-    int sign ;
+            for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
+            {
+                if (savedBanks & (1 << ix))
+                {
+                    unsaveRBank(ix, NULL, FALSE);
+                }
+            }
 
-    left = IC_LEFT(ic);
-    right= IC_RIGHT(ic);
-    result = IC_RESULT(ic);
+            if (options.useXstack)
+            {
+                /* Restore bank AFTER calling unsaveRBank,
+                 * since it can trash r0.
+                 */
+                emitcode ("pop", "psw");
+            }
+        }
 
-    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 (!inExcludeList ("dph"))
+        emitcode ("pop", "dph");
+      if (!inExcludeList ("dpl"))
+        emitcode ("pop", "dpl");
+      if (!inExcludeList ("b"))
+        emitcode ("pop", "b");
+      if (!inExcludeList ("acc"))
+        emitcode ("pop", "acc");
+
+      /* if debug then send end of function */
+      if (options.debug && currFunc)
+        {
+          debugFile->writeEndFunction (currFunc, ic, 1);
+        }
 
-    genCmp(right, left, result, ifx, sign);
+      emitcode ("reti", "");
+    }
+  else
+    {
+      if (IFFUNC_CALLEESAVES(sym->type))
+        {
+          int i;
 
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE); 
-}
+          /* if any registers used */
+          if (sym->regsUsed)
+            {
+              /* save the registers used */
+              for (i = sym->regsUsed->size; i >= 0; i--)
+                {
+                  if (bitVectBitValue (sym->regsUsed, i) ||
+                      (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
+                    emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
+                }
+            }
+          else if (mcs51_ptrRegReq)
+            {
+              emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
+              emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
+            }
 
-/*-----------------------------------------------------------------*/
-/* genCmpLt - less than comparisons                                */
-/*-----------------------------------------------------------------*/
-static void genCmpLt (iCode *ic, iCode *ifx)
-{
-    operand *left, *right, *result;
-    link *letype , *retype;
-    int sign ;
+        }
 
-    left = IC_LEFT(ic);
-    right= IC_RIGHT(ic);
-    result = IC_RESULT(ic);
+      /* if debug then send end of function */
+      if (options.debug && currFunc)
+        {
+          debugFile->writeEndFunction (currFunc, ic, 1);
+        }
 
-    letype = getSpec(operandType(left));
-    retype =getSpec(operandType(right));
-    sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
+      if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
+        {
+          emitcode ("ljmp", "__sdcc_banked_ret");
+        }
+      else
+        {
+          emitcode ("ret", "");
+        }
+    }
 
-    /* assign the amsops */
-    aopOp (left,ic,FALSE);
-    aopOp (right,ic,FALSE);
-    aopOp (result,ic,TRUE);
+  if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
+    return;
 
-    genCmp(left, right, result, ifx, sign);
+  /* If this was an interrupt handler using bank 0 that called another */
+  /* function, then all registers must be saved; nothing to optimized. */
+  if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
+      && !FUNC_REGBANK(sym->type))
+    return;
 
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE); 
-}
+  /* There are no push/pops to optimize if not callee-saves or ISR */
+  if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
+    return;
 
-/*-----------------------------------------------------------------*/
-/* 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;
-
-    /* if the left side is a literal or 
-    if the right is in a pointer register and left 
-    is not */
-    if ((AOP_TYPE(left) == AOP_LIT) || 
-        (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
-        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("cjne","%s,%s,%05d$",
-                     aopGet(AOP(left),offset,FALSE,FALSE),
-                     aopGet(AOP(right),offset,FALSE,FALSE),
-                     lbl->key+100);
-            offset++;
-        }
-    }
+  /* If there were stack parameters, we cannot optimize without also    */
+  /* fixing all of the stack offsets; this is too dificult to consider. */
+  if (FUNC_HASSTACKPARM(sym->type))
+    return;
 
-    /* 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) ||
-             (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
-        while (size--) {
-            MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
-            if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
-               ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
-                emitcode("jnz","%05d$",lbl->key+100);
-            else
-                emitcode("cjne","a,%s,%05d$",
-                         aopGet(AOP(right),offset,FALSE,TRUE),
-                         lbl->key+100);
-            offset++;
-        }
-    } else {
-        /* right is a pointer reg need both a & b */
-        while(size--) {
-            char *l = aopGet(AOP(left),offset,FALSE,FALSE);
-            if(strcmp(l,"b"))
-                emitcode("mov","b,%s",l);
-            MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
-            emitcode("cjne","a,b,%05d$",lbl->key+100);    
-            offset++;
-        }
-    }
-}
+  /* Compute the registers actually used */
+  regsUsed = newBitVect (mcs51_nRegs);
+  regsUsedPrologue = newBitVect (mcs51_nRegs);
+  while (lnp)
+    {
+      if (lnp->ic && lnp->ic->op == FUNCTION)
+        regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
+      else
+        regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
 
-/*-----------------------------------------------------------------*/
-/* gencjne - compare and jump if not equal                         */
-/*-----------------------------------------------------------------*/
-static void gencjne(operand *left, operand *right, symbol *lbl)
-{
-    symbol *tlbl  = newiTempLabel(NULL);
+      if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
+          && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
+        break;
+      if (!lnp->prev)
+        break;
+      lnp = lnp->prev;
+    }
 
-    gencjneshort(left, right, lbl);
+  if (bitVectBitValue (regsUsedPrologue, CND_IDX)
+      && !bitVectBitValue (regsUsed, CND_IDX))
+    {
+      regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
+      if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
+          && !sym->stack && !FUNC_ISCRITICAL (sym->type))
+        bitVectUnSetBit (regsUsed, CND_IDX);
+    }
+  else
+    regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
 
-    emitcode("mov","a,%s",one);
-    emitcode("sjmp","%05d$",tlbl->key+100);
-    emitcode("","%05d$:",lbl->key+100);
-    emitcode("clr","a");
-    emitcode("","%05d$:",tlbl->key+100);
-}
+  /* If this was an interrupt handler that called another function */
+  /* function, then assume A, B, DPH, & DPL may be modified by it. */
+  if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
+    {
+      regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
+      regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
+      regsUsed = bitVectSetBit (regsUsed, B_IDX);
+      regsUsed = bitVectSetBit (regsUsed, A_IDX);
+      regsUsed = bitVectSetBit (regsUsed, CND_IDX);
+    }
 
-/*-----------------------------------------------------------------*/
-/* genCmpEq - generates code for equal to                          */
-/*-----------------------------------------------------------------*/
-static void genCmpEq (iCode *ic, iCode *ifx)
-{
-    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);
-
-    /* if literal, literal on the right or 
-    if the right is in a pointer register and left 
-    is not */
-    if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
-        (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
-        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))) {
-            if(AOP_TYPE(right) == AOP_LIT){
-                unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
-                if(lit == 0L){
-                    emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-                    emitcode("cpl","c");
-                } else if(lit == 1L) {
-                    emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-                } else {
-                    emitcode("clr","c");
+  /* Remove the unneeded push/pops */
+  regsUnneeded = newBitVect (mcs51_nRegs);
+  while (lnp)
+    {
+      if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
+        {
+          if (!strncmp(lnp->line, "push", 4))
+            {
+              idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
+              if (idx>=0 && !bitVectBitValue (regsUsed, idx))
+                {
+                  connectLine (lnp->prev, lnp->next);
+                  regsUnneeded = bitVectSetBit (regsUnneeded, idx);
                 }
-                /* AOP_TYPE(right) == AOP_CRY */
-            } else {
-                symbol *lbl = newiTempLabel(NULL);
-                emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-                emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
-                emitcode("cpl","c");
-                emitcode("","%05d$:",(lbl->key+100));
-            }
-            /* if true label then we jump if condition
-            supplied is true */
-            tlbl = newiTempLabel(NULL);
-            if ( IC_TRUE(ifx) ) {
-                emitcode("jnc","%05d$",tlbl->key+100);
-                emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
-            } else {
-                emitcode("jc","%05d$",tlbl->key+100);
-                emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
             }
-            emitcode("","%05d$:",tlbl->key+100);                
-        } else {
-            tlbl = newiTempLabel(NULL);
-            gencjneshort(left, right, tlbl);
-            if ( IC_TRUE(ifx) ) {
-                emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
-                emitcode("","%05d$:",tlbl->key+100);                
-            } else {
-                symbol *lbl = newiTempLabel(NULL);
-                emitcode("sjmp","%05d$",lbl->key+100);
-                emitcode("","%05d$:",tlbl->key+100);                
-                emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
-                emitcode("","%05d$:",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))) {
-        if(AOP_TYPE(right) == AOP_LIT){
-            unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
-            if(lit == 0L){
-                emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-                emitcode("cpl","c");
-            } else if(lit == 1L) {
-                emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-            } else {
-                emitcode("clr","c");
+          if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
+            {
+              idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
+              if (idx>=0 && !bitVectBitValue (regsUsed, idx))
+                {
+                  connectLine (lnp->prev, lnp->next);
+                  regsUnneeded = bitVectSetBit (regsUnneeded, idx);
+                }
             }
-            /* AOP_TYPE(right) == AOP_CRY */
-        } else {
-            symbol *lbl = newiTempLabel(NULL);
-            emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-            emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
-            emitcode("cpl","c");
-            emitcode("","%05d$:",(lbl->key+100));
-        }
-        /* c = 1 if egal */
-        if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
-            outBitC(result);
-            goto release ;
-        }
-        if (ifx) {
-            genIfxJump (ifx,"c");
-            goto release ;
-        }
-        /* if the result is used in an arithmetic operation
-        then put the result in place */
-        outBitC(result);
-    } else {
-        gencjne(left,right,newiTempLabel(NULL));    
-        if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
-            aopPut(AOP(result),"a",0);
-            goto release ;
-        }
-        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 */
+        }
+      lnp = lnp->next;
     }
 
-release:
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE);
+  for (idx = 0; idx < regsUnneeded->size; idx++)
+    if (bitVectBitValue (regsUnneeded, idx))
+      emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
+
+  freeBitVect (regsUnneeded);
+  freeBitVect (regsUsed);
+  freeBitVect (regsUsedPrologue);
 }
 
 /*-----------------------------------------------------------------*/
-/* ifxForOp - returns the icode containing the ifx for operand     */
+/* genRet - generate code for return statement                     */
 /*-----------------------------------------------------------------*/
-static iCode *ifxForOp ( operand *op, iCode *ic )
+static void
+genRet (iCode * ic)
 {
-    /* if true symbol then needs to be assigned */
-    if (IS_TRUE_SYMOP(op))
-        return NULL ;
+  int size, offset = 0, pushed = 0;
 
-    /* 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;
+  D (emitcode (";", "genRet"));
 
-    return NULL;
-}
-/*-----------------------------------------------------------------*/
-/* genAndOp - for && operation                                     */
-/*-----------------------------------------------------------------*/
-static void genAndOp (iCode *ic)
-{
-    operand *left,*right, *result;
-    symbol *tlbl;
+  /* if we have no return value then
+     just generate the "ret" */
+  if (!IC_LEFT (ic))
+    goto jumpret;
 
-    /* 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);
+  /* 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 both are bit variables */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right) == AOP_CRY ) {
-        emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-        emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
-        outBitC(result);
-    } else {
-        tlbl = newiTempLabel(NULL);
-        toBoolean(left);    
-        emitcode("jz","%05d$",tlbl->key+100);
-        toBoolean(right);
-        emitcode("","%05d$:",tlbl->key+100);
-        outBitAcc(result);
+  if (IS_BIT(_G.currentFunc->etype))
+    {
+      movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
+      size = 0;
     }
 
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE);
-}
-
-
-/*-----------------------------------------------------------------*/
-/* genOrOp - for || operation                                      */
-/*-----------------------------------------------------------------*/
-static void genOrOp (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);
-    aopOp((right=IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,FALSE);
+  while (size--)
+    {
+      char *l;
+      if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
+        {
+          /* #NOCHANGE */
+          l = aopGet (IC_LEFT (ic), offset++,
+                      FALSE, TRUE);
+          emitcode ("push", "%s", l);
+          pushed++;
+        }
+      else
+        {
+          l = aopGet (IC_LEFT (ic), offset,
+                      FALSE, FALSE);
+          if (strcmp (fReturn[offset], l))
+            emitcode ("mov", "%s,%s", fReturn[offset++], l);
+        }
+    }
 
-    /* if both are bit variables */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right) == AOP_CRY ) {
-        emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-        emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
-        outBitC(result);
-    } else {
-        tlbl = newiTempLabel(NULL);
-        toBoolean(left);
-        emitcode("jnz","%05d$",tlbl->key+100);
-        toBoolean(right);
-        emitcode("","%05d$:",tlbl->key+100);
-        outBitAcc(result);
+  while (pushed)
+    {
+      pushed--;
+      if (strcmp (fReturn[pushed], "a"))
+        emitcode ("pop", fReturn[pushed]);
+      else
+        emitcode ("pop", "acc");
     }
+  freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
 
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE);            
-}
+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 ("ljmp", "%05d$", (returnLabel->key + 100));
 
-/*-----------------------------------------------------------------*/
-/* isLiteralBit - test if lit == 2^n                               */
-/*-----------------------------------------------------------------*/
-static 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;
 }
 
 /*-----------------------------------------------------------------*/
-/* continueIfTrue -                                                */
+/* genLabel - generates a label                                    */
 /*-----------------------------------------------------------------*/
-static void continueIfTrue (iCode *ic)
+static void
+genLabel (iCode * ic)
 {
-    if(IC_TRUE(ic))
-        emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
-    ic->generated = 1;
+  /* special case never generate */
+  if (IC_LABEL (ic) == entryLabel)
+    return;
+
+  emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
 }
 
 /*-----------------------------------------------------------------*/
-/* jmpIfTrue -                                                     */
+/* genGoto - generates a ljmp                                      */
 /*-----------------------------------------------------------------*/
-static void jumpIfTrue (iCode *ic)
+static void
+genGoto (iCode * ic)
 {
-    if(!IC_TRUE(ic))
-        emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
-    ic->generated = 1;
+  emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
 }
 
 /*-----------------------------------------------------------------*/
-/* jmpTrueOrFalse -                                                */
+/* findLabelBackwards: walks back through the iCode chain looking  */
+/* for the given label. Returns number of iCode instructions     */
+/* between that label and given ic.          */
+/* Returns zero if label not found.          */
 /*-----------------------------------------------------------------*/
-static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
+static int
+findLabelBackwards (iCode * ic, int key)
 {
-    // ugly but optimized by peephole
-    if(IC_TRUE(ic)){
-        symbol *nlbl = newiTempLabel(NULL);
-        emitcode("sjmp","%05d$",nlbl->key+100);                 
-        emitcode("","%05d$:",tlbl->key+100);
-        emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
-        emitcode("","%05d$:",nlbl->key+100);
-    }
-    else{
-        emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
-        emitcode("","%05d$:",tlbl->key+100);
-    }
-    ic->generated = 1;
+  int count = 0;
+
+  while (ic->prev)
+    {
+      ic = ic->prev;
+      count++;
+
+      /* If we have any pushes or pops, we cannot predict the distance.
+         I don't like this at all, this should be dealt with in the
+         back-end */
+      if (ic->op == IPUSH || ic->op == IPOP) {
+        return 0;
+      }
+
+      if (ic->op == LABEL && IC_LABEL (ic)->key == key)
+        {
+          return count;
+        }
+    }
+
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
-/* genAnd  - code for and                                          */
+/* genPlusIncr :- does addition with increment if possible         */
 /*-----------------------------------------------------------------*/
-static void genAnd (iCode *ic, iCode *ifx)
+static bool
+genPlusIncr (iCode * ic)
 {
-    operand *left, *right, *result;
-    int size, offset=0;  
-    unsigned long lit = 0L;
-    int bytelit = 0;
-    char buffer[10];
+  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;
 
-#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
+  icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
 
-    /* if left is a literal & right is not then exchange them */
-    if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
-       AOP_NEEDSACC(left)) {
-        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(bit & yy)
-    // result = bit & yy;
-    if (AOP_TYPE(left) == AOP_CRY){
-        // c = bit & literal;
-        if(AOP_TYPE(right) == AOP_LIT){
-            if(lit & 1) {
-                if(size && sameRegs(AOP(result),AOP(left)))
-                    // no change
-                    goto release;
-                emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-            } else {
-                // bit(result) = 0;
-                if(size && (AOP_TYPE(result) == AOP_CRY)){
-                    emitcode("clr","%s",AOP(result)->aopu.aop_dir);
-                    goto release;
-                }
-                if((AOP_TYPE(result) == AOP_CRY) && ifx){
-                    jumpIfTrue(ifx);
-                    goto release;
-                }
-                emitcode("clr","c");
-            }
-        } else {
-            if (AOP_TYPE(right) == AOP_CRY){
-                // c = bit & bit;
-                emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
-                emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
-            } else {
-                // c = bit & val;
-                MOVA(aopGet(AOP(right),0,FALSE,FALSE));
-                // c = lsb
-                emitcode("rrc","a");
-                emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
-            }
-        }
-        // bit = c
-        // val = c
-        if(size)
-            outBitC(result);
-        // if(bit & ...)
-        else if((AOP_TYPE(result) == AOP_CRY) && ifx)
-            genIfxJump(ifx, "c");           
-        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,FALSE));
-            // bit = left & 2^n
-            if(size)
-                emitcode("mov","c,acc.%d",posbit&0x07);
-            // if(left &  2^n)
-            else{
-                if(ifx){
-                    sprintf(buffer,"acc.%d",posbit&0x07);
-                    genIfxJump(ifx, buffer);
-                }
-                goto release;
-            }
-        } else {
-            symbol *tlbl = newiTempLabel(NULL);
-            int sizel = AOP_SIZE(left);
-            if(size)
-                emitcode("setb","c");
-            while(sizel--){
-                if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
-                    MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
-                    // byte ==  2^n ?
-                    if((posbit = isLiteralBit(bytelit)) != 0)
-                        emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
-                    else{
-                        if(bytelit != 0x0FFL)
-                            emitcode("anl","a,%s",
-                                     aopGet(AOP(right),offset,FALSE,TRUE));
-                        emitcode("jnz","%05d$",tlbl->key+100);
-                    }
-                }
-                offset++;
-            }
-            // bit = left & literal
-            if(size){
-                emitcode("clr","c");
-                emitcode("","%05d$:",tlbl->key+100);
+  D(emitcode (";     genPlusIncr",""));
+
+  /* if increment >=16 bits in register or direct space */
+  if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
+      sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
+      !isOperandVolatile (IC_RESULT (ic), FALSE) &&
+      (size > 1) &&
+      (icount == 1))
+    {
+      symbol *tlbl;
+      int emitTlbl;
+      int labelRange;
+
+      /* If the next instruction is a goto and the goto target
+       * is < 10 instructions previous to this, we can generate
+       * jumps straight to that target.
+       */
+      if (ic->next && ic->next->op == GOTO
+          && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
+          && labelRange <= 10)
+        {
+          D (emitcode (";", "tail increment optimized (range %d)", labelRange));
+          tlbl = IC_LABEL (ic->next);
+          emitTlbl = 0;
+        }
+      else
+        {
+          tlbl = newiTempLabel (NULL);
+          emitTlbl = 1;
+        }
+      emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
+      if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
+          IS_AOP_PREG (IC_RESULT (ic)))
+        emitcode ("cjne", "%s,#0x00,%05d$",
+                  aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
+                  tlbl->key + 100);
+      else
+        {
+          emitcode ("clr", "a");
+          emitcode ("cjne", "a,%s,%05d$",
+                    aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
+                    tlbl->key + 100);
+        }
+
+      emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
+      if (size > 2)
+        {
+          if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
+              IS_AOP_PREG (IC_RESULT (ic)))
+            emitcode ("cjne", "%s,#0x00,%05d$",
+                      aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
+                      tlbl->key + 100);
+          else
+            emitcode ("cjne", "a,%s,%05d$",
+                      aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
+                      tlbl->key + 100);
+
+          emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
+        }
+      if (size > 3)
+        {
+          if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
+              IS_AOP_PREG (IC_RESULT (ic)))
+            emitcode ("cjne", "%s,#0x00,%05d$",
+                      aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
+                      tlbl->key + 100);
+          else
+            {
+              emitcode ("cjne", "a,%s,%05d$",
+                        aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
+                        tlbl->key + 100);
             }
-            // if(left & literal)
-            else{
-                if(ifx)
-                    jmpTrueOrFalse(ifx, tlbl);
-                goto release ;
+          emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
+        }
+
+      if (emitTlbl)
+        {
+          emitLabel (tlbl);
+        }
+      return TRUE;
+    }
+
+  /* if result is dptr */
+  if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
+      (AOP_SIZE (IC_RESULT (ic)) == 2) &&
+      !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
+      !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
+    {
+      if (aopGetUsesAcc (IC_LEFT (ic), 0))
+        return FALSE;
+
+      if (icount > 9)
+        return FALSE;
+
+      if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
+        return FALSE;
+
+      aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
+      aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
+      while (icount--)
+        emitcode ("inc", "dptr");
+
+      return TRUE;
+    }
+
+  /* if the literal value of the right hand side
+     is greater than 4 then it is not worth it */
+  if (icount > 4)
+    return 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;
+
+  /* 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))))
+    {
+      if (icount > 3)
+        {
+          MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
+          emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
+          aopPut (IC_RESULT (ic), "a", 0);
+        }
+      else
+        {
+          while (icount--)
+            {
+              emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
             }
         }
-        outBitC(result);
-        goto release ;
+
+      return TRUE;
     }
 
-    /* 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 
-                       if (IS_AOP_PREG(result)) {
-                           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
-                           emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
-                           aopPut(AOP(result),"a",offset);
-                       } else
-                           emitcode("anl","%s,%s",
-                                    aopGet(AOP(left),offset,FALSE,TRUE),
-                                    aopGet(AOP(right),offset,FALSE,FALSE));
-            } else {
-               if (AOP_TYPE(left) == AOP_ACC)
-                   emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
-               else {
-                   MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
-                   if (IS_AOP_PREG(result)) {
-                       emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
-                       aopPut(AOP(result),"a",offset);
-
-                   } else
-                       emitcode("anl","%s,a",
-                                aopGet(AOP(left),offset,FALSE,TRUE));
-               }
-            }
-        }
-    } else {
-        // left & result in different registers
-        if(AOP_TYPE(result) == AOP_CRY){
-            // result = bit
-            // if(size), result in bit
-            // if(!size && ifx), conditional oper: if(left & right)
-            symbol *tlbl = newiTempLabel(NULL);
-            int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
-            if(size)
-                emitcode("setb","c");
-            while(sizer--){
-                MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
-                emitcode("anl","a,%s",
-                         aopGet(AOP(left),offset,FALSE,FALSE));
-                emitcode("jnz","%05d$",tlbl->key+100);
-                offset++;
-            }
-            if(size){
-                CLRC;
-                emitcode("","%05d$:",tlbl->key+100);
-                outBitC(result);
-            } else if(ifx)
-                jmpTrueOrFalse(ifx, tlbl);
-        } 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,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) 
-                   emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
-               else {
-                   MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
-                   emitcode("anl","a,%s",
-                            aopGet(AOP(left),offset,FALSE,FALSE));
-               }
-               aopPut(AOP(result),"a",offset);
-           }
-       }
-    }
-
-release :
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE);     
+  return FALSE;
 }
 
 /*-----------------------------------------------------------------*/
-/* genOr  - code for or                                            */
+/* outBitAcc - output a bit in acc                                 */
+/*-----------------------------------------------------------------*/
+static void
+outBitAcc (operand * result)
+{
+  symbol *tlbl = newiTempLabel (NULL);
+  /* if the result is a bit */
+  if (AOP_TYPE (result) == AOP_CRY)
+    {
+      aopPut (result, "a", 0);
+    }
+  else
+    {
+      emitcode ("jz", "%05d$", tlbl->key + 100);
+      emitcode ("mov", "a,%s", one);
+      emitLabel (tlbl);
+      outAcc (result);
+    }
+}
+
 /*-----------------------------------------------------------------*/
-static void genOr (iCode *ic, iCode *ifx)
+/* genPlusBits - generates code for addition of two bits           */
+/*-----------------------------------------------------------------*/
+static void
+genPlusBits (iCode * ic)
 {
-    operand *left, *right, *result;
-    int size, offset=0;
-    unsigned long lit = 0L;
+  D (emitcode (";", "genPlusBits"));
 
-    aopOp((left = IC_LEFT(ic)),ic,FALSE);
-    aopOp((right= IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,TRUE);
+  if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
+    {
+      symbol *lbl = newiTempLabel (NULL);
+      emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
+      emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
+      emitcode ("cpl", "c");
+      emitLabel (lbl);
+      outBitC (IC_RESULT (ic));
+    }
+  else
+    {
+      emitcode ("clr", "a");
+      emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
+      emitcode ("rlc", "a");
+      emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
+      emitcode ("addc", "a,%s", zero);
+      outAcc (IC_RESULT (ic));
+    }
+}
 
-#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));
+#if 0
+/* This is the original version of this code.
+
+ * This is being kept around for reference,
+ * because I am not entirely sure I got it right...
+ */
+static void
+adjustArithmeticResult (iCode * ic)
+{
+  if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
+      AOP_SIZE (IC_LEFT (ic)) == 3 &&
+      !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
+    aopPut (IC_RESULT (ic),
+            aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
+            2);
+
+  if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
+      AOP_SIZE (IC_RIGHT (ic)) == 3 &&
+      !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
+    aopPut (IC_RESULT (ic),
+            aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
+            2);
+
+  if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
+      AOP_SIZE (IC_LEFT (ic)) < 3 &&
+      AOP_SIZE (IC_RIGHT (ic)) < 3 &&
+      !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
+      !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
+    {
+      char buffer[5];
+      sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
+      aopPut (IC_RESULT (ic), buffer, 2);
+    }
+}
+#else
+/* This is the pure and virtuous version of this code.
+ * I'm pretty certain it's right, but not enough to toss the old
+ * code just yet...
+ */
+static void
+adjustArithmeticResult (iCode * ic)
+{
+  if (opIsGptr (IC_RESULT (ic)) &&
+      opIsGptr (IC_LEFT (ic)) &&
+      !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
+    {
+      aopPut (IC_RESULT (ic),
+              aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
+              GPTRSIZE - 1);
+    }
+
+  if (opIsGptr (IC_RESULT (ic)) &&
+      opIsGptr (IC_RIGHT (ic)) &&
+      !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
+    {
+      aopPut (IC_RESULT (ic),
+              aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
+              GPTRSIZE - 1);
+    }
+
+  if (opIsGptr (IC_RESULT (ic)) &&
+      AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
+      AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
+      !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
+      !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
+    {
+      char buffer[5];
+      SNPRINTF (buffer, sizeof(buffer),
+                "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
+      aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
+    }
+}
 #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;
-    }
-
-    /* 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(bit | yy)
-    // xx = bit | yy;
-    if (AOP_TYPE(left) == AOP_CRY){
-        if(AOP_TYPE(right) == AOP_LIT){
-            // c = bit & literal;
-            if(lit){
-                // lit != 0 => result = 1
-                if(AOP_TYPE(result) == AOP_CRY){
-                    if(size)
-                        emitcode("setb","%s",AOP(result)->aopu.aop_dir);
-                    else if(ifx)
-                        continueIfTrue(ifx);
-                    goto release;
-                }
-                emitcode("setb","c");
-            } else {
-                // lit == 0 => result = left
-                if(size && sameRegs(AOP(result),AOP(left)))
-                    goto release;
-                emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-            }
-        } else {
-            if (AOP_TYPE(right) == AOP_CRY){
-                // c = bit | bit;
-                emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
-                emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
-            }
-            else{
-                // c = bit | val;
-                symbol *tlbl = newiTempLabel(NULL);
-                if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
-                    emitcode("setb","c");
-                emitcode("jb","%s,%05d$",
-                         AOP(left)->aopu.aop_dir,tlbl->key+100);
-                toBoolean(right);
-                emitcode("jnz","%05d$",tlbl->key+100);
-                if((AOP_TYPE(result) == AOP_CRY) && ifx){
-                    jmpTrueOrFalse(ifx, tlbl);
-                    goto release;
-                } else {
-                    CLRC;
-                    emitcode("","%05d$:",tlbl->key+100);
-                }
-            }
+/*-----------------------------------------------------------------*/
+/* genPlus - generates code for addition                           */
+/*-----------------------------------------------------------------*/
+static void
+genPlus (iCode * ic)
+{
+  int size, offset = 0;
+  int skip_bytes = 0;
+  char *add = "add";
+  bool swappedLR = FALSE;
+  operand *leftOp, *rightOp;
+  operand * op;
+
+  D (emitcode (";", "genPlus"));
+
+  /* special cases :- */
+
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  aopOp (IC_RIGHT (ic), ic, FALSE);
+  aopOp (IC_RESULT (ic), ic, TRUE);
+
+  /* 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;
+      swappedLR = TRUE;
+    }
+
+  /* if both left & right are in bit
+     space */
+  if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
+      AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
+    {
+      genPlusBits (ic);
+      goto release;
+    }
+
+  /* if left in bit space & right literal */
+  if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
+      AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
+    {
+      emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
+      /* if result in bit space */
+      if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
+        {
+          if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
+            emitcode ("cpl", "c");
+          outBitC (IC_RESULT (ic));
         }
-        // bit = c
-        // val = c
-        if(size)
-            outBitC(result);
-        // if(bit | ...)
-        else if((AOP_TYPE(result) == AOP_CRY) && ifx)
-            genIfxJump(ifx, "c");           
-        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)){
-        if(lit){
-            // result = 1
-            if(size)
-                emitcode("setb","%s",AOP(result)->aopu.aop_dir);
-            else 
-                continueIfTrue(ifx);
-            goto release;
-        } else {
-            // lit = 0, result = boolean(left)
-            if(size)
-                emitcode("setb","c");
-            toBoolean(right);
-            if(size){
-                symbol *tlbl = newiTempLabel(NULL);
-                emitcode("jnz","%05d$",tlbl->key+100);
-                CLRC;
-                emitcode("","%05d$:",tlbl->key+100);
-            } else {
-                genIfxJump (ifx,"a");
-                goto release;
+      else
+        {
+          size = getDataSize (IC_RESULT (ic));
+          while (size--)
+            {
+              MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
+              emitcode ("addc", "a,%s", zero);
+              aopPut (IC_RESULT (ic), "a", offset++);
             }
         }
-        outBitC(result);
-        goto release ;
+      goto release;
+    }
+
+  /* if I can do an increment instead
+     of add then GOOD for ME */
+  if (genPlusIncr (ic) == TRUE)
+    goto release;
+
+  size = getDataSize (IC_RESULT (ic));
+  leftOp = IC_LEFT(ic);
+  rightOp = IC_RIGHT(ic);
+  op = IC_LEFT(ic);
+
+  /* if this is an add for an array access
+     at a 256 byte boundary */
+  if ( 2 == size
+       && AOP_TYPE (op) == AOP_IMMD
+       && IS_SYMOP (op)
+       && IS_SPEC (OP_SYM_ETYPE (op))
+       && SPEC_ABSA (OP_SYM_ETYPE (op))
+       && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
+     )
+    {
+      D(emitcode (";     genPlus aligned array",""));
+      aopPut (IC_RESULT (ic),
+              aopGet (rightOp, 0, FALSE, FALSE),
+              0);
+
+      if( 1 == getDataSize (IC_RIGHT (ic)) )
+        {
+          aopPut (IC_RESULT (ic),
+                  aopGet (leftOp, 1, FALSE, FALSE),
+                  1);
+        }
+      else
+        {
+          MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
+          emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
+          aopPut (IC_RESULT (ic), "a", 1);
+        }
+      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 
-                   if (IS_AOP_PREG(left)) {
-                       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
-                       emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
-                       aopPut(AOP(result),"a",offset);
-                   } else
-                       emitcode("orl","%s,%s",
-                                aopGet(AOP(left),offset,FALSE,TRUE),
-                                aopGet(AOP(right),offset,FALSE,FALSE));
-            } else {
-               if (AOP_TYPE(left) == AOP_ACC) 
-                   emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
-               else {              
-                   MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
-                   if (IS_AOP_PREG(left)) {
-                       emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
-                       aopPut(AOP(result),"a",offset);
-                   } else
-                       emitcode("orl","%s,a",
-                                aopGet(AOP(left),offset,FALSE,TRUE));
-               }
-            }
-        }
-    } else {
-        // left & result in different registers
-        if(AOP_TYPE(result) == AOP_CRY){
-            // result = bit
-            // if(size), result in bit
-            // if(!size && ifx), conditional oper: if(left | right)
-            symbol *tlbl = newiTempLabel(NULL);
-            int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
-            if(size)
-                emitcode("setb","c");
-            while(sizer--){
-                MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
-                emitcode("orl","a,%s",
-                         aopGet(AOP(left),offset,FALSE,FALSE));
-                emitcode("jnz","%05d$",tlbl->key+100);
-                offset++;
-            }
-            if(size){
-                CLRC;
-                emitcode("","%05d$:",tlbl->key+100);
-                outBitC(result);
-            } else if(ifx)
-                jmpTrueOrFalse(ifx, tlbl);
-        } 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,FALSE),
-                           offset);
-                    continue;
-                }
+  /* if the lower bytes of a literal are zero skip the addition */
+  if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
+    {
+       while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
+              (skip_bytes+1 < size))
+         {
+           skip_bytes++;
+         }
+       if (skip_bytes)
+         D(emitcode (";     genPlus shortcut",""));
+    }
+
+  while (size--)
+    {
+      if( offset >= skip_bytes )
+        {
+          if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
+            {
+              bool pushedB;
+              MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
+              pushedB = pushB ();
+              emitcode("xch", "a,b");
+              MOVA (aopGet (rightOp, offset, FALSE, TRUE));
+              emitcode (add, "a,b");
+              popB (pushedB);
+            }
+          else if (aopGetUsesAcc (leftOp, offset))
+            {
+              MOVA (aopGet (leftOp, offset, FALSE, TRUE));
+              emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
+            }
+          else
+            {
+              MOVA (aopGet (rightOp, offset, FALSE, TRUE));
+              emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
+            }
+          aopPut (IC_RESULT (ic), "a", offset);
+          add = "addc";  /* further adds must propagate carry */
+        }
+      else
+        {
+          if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
+              isOperandVolatile (IC_RESULT (ic), FALSE))
+            {
+              /* just move */
+              aopPut (IC_RESULT (ic),
+                      aopGet (leftOp, offset, FALSE, FALSE),
+                      offset);
             }
-            // faster than result <- left, anl result,right
-            // and better if result is SFR
-           if (AOP_TYPE(left) == AOP_ACC) 
-               emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
-           else {
-               MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
-               emitcode("orl","a,%s",
-                        aopGet(AOP(left),offset,FALSE,FALSE));
-           }
-           aopPut(AOP(result),"a",offset);                     
         }
+      offset++;
     }
 
-release :
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE);     
+  adjustArithmeticResult (ic);
+
+release:
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+  if (!swappedLR)
+    {
+      freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+      freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+    }
+  else
+    {
+      freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+      freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* genXor - code for xclusive or                                   */
+/* genMinusDec :- does subtraction with decrement if possible      */
 /*-----------------------------------------------------------------*/
-static void genXor (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;
 
-#ifdef DEBUG_TYPE
-    emitcode("","; Type res[%d] = l[%d]&r[%d]",
-             AOP_TYPE(result),
-             AOP_TYPE(left), AOP_TYPE(right));
-    emitcode("","; Size res[%d] = l[%d]&r[%d]",
-             AOP_SIZE(result),
-             AOP_SIZE(left), AOP_SIZE(right));
-#endif
+  /* if 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)) > 4)
+    return FALSE;
 
-    /* if left is a literal & right is not ||
-       if left needs acc & right does not */
-    if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
-       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
-        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(bit ^ yy)
-    // xx = bit ^ yy;
-    if (AOP_TYPE(left) == AOP_CRY){
-        if(AOP_TYPE(right) == AOP_LIT){
-            // c = bit & literal;
-            if(lit>>1){
-                // lit>>1  != 0 => result = 1
-                if(AOP_TYPE(result) == AOP_CRY){
-                    if(size)
-                        emitcode("setb","%s",AOP(result)->aopu.aop_dir);
-                    else if(ifx)
-                        continueIfTrue(ifx);
-                    goto release;
-                }
-                emitcode("setb","c");
-            } else{
-                // lit == (0 or 1)
-                if(lit == 0){
-                    // lit == 0, result = left
-                    if(size && sameRegs(AOP(result),AOP(left)))
-                        goto release;
-                    emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-                } else{
-                    // lit == 1, result = not(left)
-                    if(size && sameRegs(AOP(result),AOP(left))){
-                        emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
-                        goto release;
-                    } else {
-                        emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-                        emitcode("cpl","c");
-                    }
-                }
-            }
+  D (emitcode (";", "genMinusDec"));
 
-        } else {
-            // right != literal
-            symbol *tlbl = newiTempLabel(NULL);
-            if (AOP_TYPE(right) == AOP_CRY){
-                // c = bit ^ bit;
-                emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
-            }
-            else{
-                int sizer = AOP_SIZE(right);
-                // c = bit ^ val
-                // if val>>1 != 0, result = 1
-                emitcode("setb","c");
-                while(sizer){
-                    MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
-                    if(sizer == 1)
-                        // test the msb of the lsb
-                        emitcode("anl","a,#0xfe");
-                    emitcode("jnz","%05d$",tlbl->key+100);
-                   sizer--;
-                }
-                // val = (0,1)
-                emitcode("rrc","a");
-            }
-            emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
-            emitcode("cpl","c");
-            emitcode("","%05d$:",(tlbl->key+100));
-        }
-        // bit = c
-        // val = c
-        if(size)
-            outBitC(result);
-        // if(bit | ...)
-        else if((AOP_TYPE(result) == AOP_CRY) && ifx)
-            genIfxJump(ifx, "c");           
-        goto release ;
-    }
-
-    if(sameRegs(AOP(result),AOP(left))){
-        /* if left is same as result */
-        for(;size--; offset++) {
-            if(AOP_TYPE(right) == AOP_LIT){
-                if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
-                    continue;
-                else
-                   if (IS_AOP_PREG(left)) {
-                       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
-                       emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
-                       aopPut(AOP(result),"a",offset);
-                   } else 
-                       emitcode("xrl","%s,%s",
-                                aopGet(AOP(left),offset,FALSE,TRUE),
-                                aopGet(AOP(right),offset,FALSE,FALSE));
-            } else {
-               if (AOP_TYPE(left) == AOP_ACC)
-                   emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
-               else {
-                   MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
-                   if (IS_AOP_PREG(left)) {
-                       emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
-                       aopPut(AOP(result),"a",offset);
-                   } else
-                       emitcode("xrl","%s,a",
-                                aopGet(AOP(left),offset,FALSE,TRUE));
-               }
-            }
-        }
-    } else {
-        // left & result in different registers
-        if(AOP_TYPE(result) == AOP_CRY){
-            // result = bit
-            // if(size), result in bit
-            // if(!size && ifx), conditional oper: if(left ^ right)
-            symbol *tlbl = newiTempLabel(NULL);
-            int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
-            if(size)
-                emitcode("setb","c");
-            while(sizer--){
-                if((AOP_TYPE(right) == AOP_LIT) &&
-                   (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
-                    MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
-                } else {
-                    MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
-                    emitcode("xrl","a,%s",
-                             aopGet(AOP(left),offset,FALSE,FALSE));
-                }
-                emitcode("jnz","%05d$",tlbl->key+100);
-                offset++;
+  /* if decrement >=16 bits in register or direct space */
+  if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
+      sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
+      (size > 1) &&
+      (icount == 1))
+    {
+      symbol *tlbl;
+      int emitTlbl;
+      int labelRange;
+
+      /* If the next instruction is a goto and the goto target
+       * is <= 10 instructions previous to this, we can generate
+       * jumps straight to that target.
+       */
+      if (ic->next && ic->next->op == GOTO
+          && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
+          && labelRange <= 10)
+        {
+          D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
+          tlbl = IC_LABEL (ic->next);
+          emitTlbl = 0;
+        }
+      else
+        {
+          tlbl = newiTempLabel (NULL);
+          emitTlbl = 1;
+        }
+
+      emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
+      if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
+          IS_AOP_PREG (IC_RESULT (ic)))
+        emitcode ("cjne", "%s,#0xff,%05d$"
+                  ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
+                  ,tlbl->key + 100);
+      else
+        {
+          emitcode ("mov", "a,#0xff");
+          emitcode ("cjne", "a,%s,%05d$"
+                    ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
+                    ,tlbl->key + 100);
+        }
+      emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
+      if (size > 2)
+        {
+          if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
+              IS_AOP_PREG (IC_RESULT (ic)))
+            emitcode ("cjne", "%s,#0xff,%05d$"
+                      ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
+                      ,tlbl->key + 100);
+          else
+            {
+              emitcode ("cjne", "a,%s,%05d$"
+                        ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
+                        ,tlbl->key + 100);
             }
-            if(size){
-                CLRC;
-                emitcode("","%05d$:",tlbl->key+100);
-                outBitC(result);
-            } else if(ifx)
-                jmpTrueOrFalse(ifx, tlbl);
-        } 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,FALSE),
-                           offset);
-                    continue;
-                }
+          emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
+        }
+      if (size > 3)
+        {
+          if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
+              IS_AOP_PREG (IC_RESULT (ic)))
+            emitcode ("cjne", "%s,#0xff,%05d$"
+                      ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
+                      ,tlbl->key + 100);
+          else
+            {
+              emitcode ("cjne", "a,%s,%05d$"
+                        ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
+                        ,tlbl->key + 100);
             }
-            // faster than result <- left, anl result,right
-            // and better if result is SFR
-           if (AOP_TYPE(left) == AOP_ACC)
-               emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
-           else {
-               MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
-               emitcode("xrl","a,%s",
-                        aopGet(AOP(left),offset,FALSE,TRUE));
-           }
-           aopPut(AOP(result),"a",offset);
+          emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
+        }
+      if (emitTlbl)
+        {
+          emitLabel (tlbl);
+        }
+      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))))
+    {
+      char *l;
+
+      if (aopGetUsesAcc (IC_LEFT (ic), 0))
+        {
+          MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
+          l = "a";
+        }
+      else
+        {
+          l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
         }
+
+      while (icount--)
+        {
+          emitcode ("dec", "%s", l);
+        }
+
+      if (AOP_NEEDSACC (IC_RESULT (ic)))
+        aopPut (IC_RESULT (ic), "a", 0);
+
+      return TRUE;
     }
 
-release :
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE);     
+  return FALSE;
 }
 
 /*-----------------------------------------------------------------*/
-/* genInline - write the inline code out                           */
+/* addSign - complete with sign                                    */
 /*-----------------------------------------------------------------*/
-static void genInline (iCode *ic)
-{
-    char buffer[MAX_INLINEASM];
-    char *bp = buffer;
-    char *bp1= buffer;
-    
-    _G.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++;
+static void
+addSign (operand * result, int offset, int sign)
+{
+  int size = (getDataSize (result) - offset);
+  if (size > 0)
+    {
+      if (sign)
+        {
+          emitcode ("rlc", "a");
+          emitcode ("subb", "a,acc");
+          while (size--)
+            {
+              aopPut (result, "a", offset++);
+            }
+        }
+      else
+        {
+          while (size--)
+            {
+              aopPut (result, zero, offset++);
+            }
         }
     }
-    if (bp1 != bp)
-        emitcode(bp1,"");
-    /*     emitcode("",buffer); */
-    _G.inLine -= (!options.asmpeep);
 }
 
 /*-----------------------------------------------------------------*/
-/* genRRC - rotate right with carry                                */
+/* genMinusBits - generates code for subtraction  of two bits      */
+/*-----------------------------------------------------------------*/
+static void
+genMinusBits (iCode * ic)
+{
+  symbol *lbl = newiTempLabel (NULL);
+
+  D (emitcode (";", "genMinusBits"));
+
+  if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
+    {
+      emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
+      emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
+      emitcode ("cpl", "c");
+      emitLabel (lbl);
+      outBitC (IC_RESULT (ic));
+    }
+  else
+    {
+      emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
+      emitcode ("subb", "a,acc");
+      emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
+      emitcode ("inc", "a");
+      emitLabel (lbl);
+      aopPut (IC_RESULT (ic), "a", 0);
+      addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genMinus - generates code for subtraction                       */
+/*-----------------------------------------------------------------*/
+static void
+genMinus (iCode * ic)
+{
+  int size, offset = 0;
+
+  D (emitcode (";", "genMinus"));
+
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  aopOp (IC_RIGHT (ic), ic, FALSE);
+  aopOp (IC_RESULT (ic), ic, TRUE);
+
+  /* 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)
+    {
+      genMinusBits (ic);
+      goto release;
+    }
+
+  /* if I can do an decrement instead
+     of subtract then GOOD for ME */
+  if (genMinusDec (ic) == TRUE)
+    goto release;
+
+  size = getDataSize (IC_RESULT (ic));
+
+  /* if literal, add a,#-lit, else normal subb */
+  if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
+    {
+      unsigned long lit = 0L;
+      bool useCarry = FALSE;
+
+      lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+      lit = -(long) lit;
+
+      while (size--)
+        {
+          if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
+            {
+              MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
+              if (!offset && !size && lit== (unsigned long) -1)
+                {
+                  emitcode ("dec", "a");
+                }
+              else if (!useCarry)
+                {
+                  /* first add without previous c */
+                  emitcode ("add", "a,#0x%02x",
+                            (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
+                  useCarry = TRUE;
+                }
+              else
+                {
+                  emitcode ("addc", "a,#0x%02x",
+                            (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
+                }
+              aopPut (IC_RESULT (ic), "a", offset++);
+            }
+          else
+            {
+              /* no need to add zeroes */
+              if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
+                {
+                  aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
+                          offset);
+                }
+              offset++;
+            }
+        }
+    }
+  else
+    {
+      operand *leftOp, *rightOp;
+
+      leftOp = IC_LEFT(ic);
+      rightOp = IC_RIGHT(ic);
+
+      while (size--)
+        {
+          if (aopGetUsesAcc(rightOp, offset)) {
+            if (aopGetUsesAcc(leftOp, offset)) {
+              bool pushedB;
+
+              MOVA (aopGet (rightOp, offset, FALSE, FALSE));
+              pushedB = pushB ();
+              emitcode ("mov", "b,a");
+              if (offset == 0)
+                CLRC;
+              MOVA (aopGet (leftOp, offset, FALSE, FALSE));
+              emitcode ("subb", "a,b");
+              popB (pushedB);
+            } else {
+              /* reverse subtraction with 2's complement */
+              if (offset == 0)
+                emitcode( "setb", "c");
+              else
+                emitcode( "cpl", "c");
+              wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
+              MOVA (aopGet(rightOp, offset, FALSE, TRUE));
+              emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
+              emitcode("cpl", "a");
+              if (size) /* skip if last byte */
+                emitcode( "cpl", "c");
+            }
+          } else {
+            MOVA (aopGet (leftOp, offset, FALSE, FALSE));
+            if (offset == 0)
+              CLRC;
+            emitcode ("subb", "a,%s",
+                      aopGet(rightOp, offset, FALSE, TRUE));
+          }
+
+          aopPut (IC_RESULT (ic), "a", offset++);
+        }
+    }
+
+  adjustArithmeticResult (ic);
+
+release:
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+  freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genMultbits :- multiplication of bits                           */
+/*-----------------------------------------------------------------*/
+static void
+genMultbits (operand * left,
+             operand * right,
+             operand * result)
+{
+  D (emitcode (";", "genMultbits"));
+
+  emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
+  emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
+  outBitC (result);
+}
+
+/*-----------------------------------------------------------------*/
+/* genMultOneByte : 8*8=8/16 bit multiplication                    */
+/*-----------------------------------------------------------------*/
+static void
+genMultOneByte (operand * left,
+                operand * right,
+                operand * result)
+{
+  symbol *lbl;
+  int size = AOP_SIZE (result);
+  bool runtimeSign, compiletimeSign;
+  bool lUnsigned, rUnsigned, pushedB;
+
+  D (emitcode (";", "genMultOneByte"));
+
+  if (size < 1 || size > 2)
+    {
+      /* this should never happen */
+      fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
+               AOP_SIZE(result), __FILE__, lineno);
+      exit (1);
+    }
+
+  /* (if two literals: the value is computed before) */
+  /* if one literal, literal on the right */
+  if (AOP_TYPE (left) == AOP_LIT)
+    {
+      operand *t = right;
+      right = left;
+      left = t;
+      /* emitcode (";", "swapped left and right"); */
+    }
+  /* if no literal, unsigned on the right: shorter code */
+  if (   AOP_TYPE (right) != AOP_LIT
+      && SPEC_USIGN (getSpec (operandType (left))))
+    {
+      operand *t = right;
+      right = left;
+      left = t;
+    }
+
+  lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+  rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
+
+  pushedB = pushB ();
+
+  if (size == 1 /* no, this is not a bug; with a 1 byte result there's
+                   no need to take care about the signedness! */
+      || (lUnsigned && rUnsigned))
+    {
+      /* just an unsigned 8 * 8 = 8 multiply
+         or 8u * 8u = 16u */
+      /* emitcode (";","unsigned"); */
+      /* TODO: check for accumulator clash between left & right aops? */
+
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          /* moving to accumulator first helps peepholes */
+          MOVA (aopGet (left, 0, FALSE, FALSE));
+          emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
+        }
+      else
+        {
+          emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
+          MOVA (aopGet (left, 0, FALSE, FALSE));
+        }
+
+      emitcode ("mul", "ab");
+      aopPut (result, "a", 0);
+      if (size == 2)
+        aopPut (result, "b", 1);
+
+      popB (pushedB);
+      return;
+    }
+
+  /* we have to do a signed multiply */
+  /* emitcode (";", "signed"); */
+
+  /* now sign adjust for both left & right */
+
+  /* let's see what's needed: */
+  /* apply negative sign during runtime */
+  runtimeSign = FALSE;
+  /* negative sign from literals */
+  compiletimeSign = FALSE;
+
+  if (!lUnsigned)
+    {
+      if (AOP_TYPE(left) == AOP_LIT)
+        {
+          /* signed literal */
+          signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+          if (val < 0)
+            compiletimeSign = TRUE;
+        }
+      else
+        /* signed but not literal */
+        runtimeSign = TRUE;
+    }
+
+  if (!rUnsigned)
+    {
+      if (AOP_TYPE(right) == AOP_LIT)
+        {
+          /* signed literal */
+          signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+          if (val < 0)
+            compiletimeSign ^= TRUE;
+        }
+      else
+        /* signed but not literal */
+        runtimeSign = TRUE;
+    }
+
+  /* initialize F0, which stores the runtime sign */
+  if (runtimeSign)
+    {
+      if (compiletimeSign)
+        emitcode ("setb", "F0"); /* set sign flag */
+      else
+        emitcode ("clr", "F0"); /* reset sign flag */
+    }
+
+  /* save the signs of the operands */
+  if (AOP_TYPE(right) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+
+      if (!rUnsigned && val < 0)
+        emitcode ("mov", "b,#0x%02x", -val);
+      else
+        emitcode ("mov", "b,#0x%02x", (unsigned char) val);
+    }
+  else /* ! literal */
+    {
+      if (rUnsigned)  /* emitcode (";", "signed"); */
+        emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
+      else
+        {
+          MOVA (aopGet (right, 0, FALSE, FALSE));
+          lbl = newiTempLabel (NULL);
+          emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+          emitcode ("cpl", "F0"); /* complement sign flag */
+          emitcode ("cpl", "a");  /* 2's complement */
+          emitcode ("inc", "a");
+          emitLabel (lbl);
+          emitcode ("mov", "b,a");
+        }
+    }
+
+  if (AOP_TYPE(left) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+
+      if (!lUnsigned && val < 0)
+        emitcode ("mov", "a,#0x%02x", -val);
+      else
+        emitcode ("mov", "a,#0x%02x", (unsigned char) val);
+    }
+  else /* ! literal */
+    {
+      MOVA (aopGet (left, 0, FALSE, FALSE));
+
+      if (!lUnsigned)
+        {
+          lbl = newiTempLabel (NULL);
+          emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+          emitcode ("cpl", "F0"); /* complement sign flag */
+          emitcode ("cpl", "a"); /* 2's complement */
+          emitcode ("inc", "a");
+          emitLabel (lbl);
+        }
+    }
+
+  /* now the multiplication */
+  emitcode ("mul", "ab");
+  if (runtimeSign || compiletimeSign)
+    {
+      lbl = newiTempLabel (NULL);
+      if (runtimeSign)
+        emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
+      emitcode ("cpl", "a"); /* lsb 2's complement */
+      if (size != 2)
+        emitcode ("inc", "a"); /* inc doesn't set carry flag */
+      else
+        {
+          emitcode ("add", "a,#1"); /* this sets carry flag */
+          emitcode ("xch", "a,b");
+          emitcode ("cpl", "a"); /* msb 2's complement */
+          emitcode ("addc", "a,#0");
+          emitcode ("xch", "a,b");
+        }
+      emitLabel (lbl);
+    }
+  aopPut (result, "a", 0);
+  if (size == 2)
+    aopPut (result, "b", 1);
+
+  popB (pushedB);
+}
+
+/*-----------------------------------------------------------------*/
+/* genMult - generates code for multiplication                     */
+/*-----------------------------------------------------------------*/
+static void
+genMult (iCode * ic)
+{
+  operand *left = IC_LEFT (ic);
+  operand *right = IC_RIGHT (ic);
+  operand *result = IC_RESULT (ic);
+
+  D (emitcode (";", "genMult"));
+
+  /* assign the asmops */
+  aopOp (left, ic, FALSE);
+  aopOp (right, ic, FALSE);
+  aopOp (result, ic, TRUE);
+
+  /* special cases first */
+  /* both are bits */
+  if (AOP_TYPE (left) == AOP_CRY &&
+      AOP_TYPE (right) == AOP_CRY)
+    {
+      genMultbits (left, right, result);
+      goto release;
+    }
+
+  /* if both are of size == 1 */
+#if 0 // one of them can be a sloc shared with the result
+    if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
+#else
+  if (getSize(operandType(left)) == 1 &&
+      getSize(operandType(right)) == 1)
+#endif
+    {
+      genMultOneByte (left, right, result);
+      goto release;
+    }
+
+  /* should have been converted to function call */
+    fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
+             getSize(OP_SYMBOL(right)->type));
+  assert (0);
+
+release:
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+}
+
+/*-----------------------------------------------------------------*/
+/* genDivbits :- division of bits                                  */
+/*-----------------------------------------------------------------*/
+static void
+genDivbits (operand * left,
+            operand * right,
+            operand * result)
+{
+  char *l;
+  bool pushedB;
+
+  D(emitcode (";     genDivbits",""));
+
+  pushedB = pushB ();
+
+  /* the result must be bit */
+  emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
+  l = aopGet (left, 0, FALSE, FALSE);
+
+  MOVA (l);
+
+  emitcode ("div", "ab");
+  emitcode ("rrc", "a");
+
+  popB (pushedB);
+
+  aopPut (result, "c", 0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genDivOneByte : 8 bit division                                  */
+/*-----------------------------------------------------------------*/
+static void
+genDivOneByte (operand * left,
+               operand * right,
+               operand * result)
+{
+  bool lUnsigned, rUnsigned, pushedB;
+  bool runtimeSign, compiletimeSign;
+  bool accuse = FALSE;
+  bool pushedA = FALSE;
+  symbol *lbl;
+  int size, offset;
+
+  D(emitcode (";     genDivOneByte",""));
+
+  /* Why is it necessary that genDivOneByte() can return an int result?
+     Have a look at:
+
+        volatile unsigned char uc;
+        volatile signed char sc1, sc2;
+        volatile int i;
+
+        uc  = 255;
+        sc1 = -1;
+        i = uc / sc1;
+
+     Or:
+
+        sc1 = -128;
+        sc2 = -1;
+        i = sc1 / sc2;
+
+     In all cases a one byte result would overflow, the following cast to int
+     would return the wrong result.
+
+     Two possible solution:
+        a) cast operands to int, if ((unsigned) / (signed)) or
+           ((signed) / (signed))
+        b) return an 16 bit signed int; this is what we're doing here!
+  */
+
+  size = AOP_SIZE (result) - 1;
+  offset = 1;
+  lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+  rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
+
+  pushedB = pushB ();
+
+  /* signed or unsigned */
+  if (lUnsigned && rUnsigned)
+    {
+      /* unsigned is easy */
+      emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
+      MOVA (aopGet (left, 0, FALSE, FALSE));
+      emitcode ("div", "ab");
+      aopPut (result, "a", 0);
+      while (size--)
+        aopPut (result, zero, offset++);
+
+      popB (pushedB);
+      return;
+    }
+
+  /* signed is a little bit more difficult */
+
+  /* now sign adjust for both left & right */
+
+  /* let's see what's needed: */
+  /* apply negative sign during runtime */
+  runtimeSign = FALSE;
+  /* negative sign from literals */
+  compiletimeSign = FALSE;
+
+  if (!lUnsigned)
+    {
+      if (AOP_TYPE(left) == AOP_LIT)
+        {
+          /* signed literal */
+          signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+          if (val < 0)
+            compiletimeSign = TRUE;
+        }
+      else
+        /* signed but not literal */
+        runtimeSign = TRUE;
+    }
+
+  if (!rUnsigned)
+    {
+      if (AOP_TYPE(right) == AOP_LIT)
+        {
+          /* signed literal */
+          signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+          if (val < 0)
+            compiletimeSign ^= TRUE;
+        }
+      else
+        /* signed but not literal */
+        runtimeSign = TRUE;
+    }
+
+  /* initialize F0, which stores the runtime sign */
+  if (runtimeSign)
+    {
+      if (compiletimeSign)
+        emitcode ("setb", "F0"); /* set sign flag */
+      else
+        emitcode ("clr", "F0"); /* reset sign flag */
+    }
+
+  /* save the signs of the operands */
+  if (AOP_TYPE(right) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+
+      if (!rUnsigned && val < 0)
+        emitcode ("mov", "b,#0x%02x", -val);
+      else
+        emitcode ("mov", "b,#0x%02x", (unsigned char) val);
+    }
+  else /* ! literal */
+    {
+      if (rUnsigned)
+        emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
+      else
+        {
+          MOVA (aopGet (right, 0, FALSE, FALSE));
+          lbl = newiTempLabel (NULL);
+          emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+          emitcode ("cpl", "F0"); /* complement sign flag */
+          emitcode ("cpl", "a");  /* 2's complement */
+          emitcode ("inc", "a");
+          emitLabel (lbl);
+          emitcode ("mov", "b,a");
+        }
+    }
+
+  if (AOP_TYPE(left) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+
+      if (!lUnsigned && val < 0)
+        emitcode ("mov", "a,#0x%02x", -val);
+      else
+        emitcode ("mov", "a,#0x%02x", (unsigned char) val);
+    }
+  else /* ! literal */
+    {
+      MOVA (aopGet (left, 0, FALSE, FALSE));
+
+      if (!lUnsigned)
+        {
+          lbl = newiTempLabel (NULL);
+          emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+          emitcode ("cpl", "F0"); /* complement sign flag */
+          emitcode ("cpl", "a");  /* 2's complement */
+          emitcode ("inc", "a");
+          emitLabel (lbl);
+        }
+    }
+
+  /* now the division */
+  emitcode ("div", "ab");
+
+  if (runtimeSign || compiletimeSign)
+    {
+      lbl = newiTempLabel (NULL);
+      if (runtimeSign)
+        emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
+      emitcode ("cpl", "a"); /* lsb 2's complement */
+      emitcode ("inc", "a");
+      emitLabel (lbl);
+
+      accuse = aopPut (result, "a", 0);
+      if (size > 0)
+        {
+          /* msb is 0x00 or 0xff depending on the sign */
+          if (runtimeSign)
+            {
+              if (accuse)
+                {
+                  emitcode ("push", "acc");
+                  pushedA = TRUE;
+                }
+              emitcode ("mov", "c,F0");
+              emitcode ("subb", "a,acc");
+              while (size--)
+                aopPut (result, "a", offset++);
+            }
+          else /* compiletimeSign */
+            {
+              if (aopPutUsesAcc (result, "#0xFF", offset))
+                {
+                  emitcode ("push", "acc");
+                  pushedA = TRUE;
+                }
+              while (size--)
+                aopPut (result, "#0xff", offset++);
+            }
+        }
+    }
+  else
+    {
+      aopPut (result, "a", 0);
+      while (size--)
+        aopPut (result, zero, offset++);
+    }
+
+  if (pushedA)
+    emitcode ("pop", "acc");
+  popB (pushedB);
+}
+
+/*-----------------------------------------------------------------*/
+/* genDiv - generates code for division                            */
+/*-----------------------------------------------------------------*/
+static void
+genDiv (iCode * ic)
+{
+  operand *left = IC_LEFT (ic);
+  operand *right = IC_RIGHT (ic);
+  operand *result = IC_RESULT (ic);
+
+  D (emitcode (";", "genDiv"));
+
+  /* assign the amsops */
+  aopOp (left, ic, FALSE);
+  aopOp (right, ic, FALSE);
+  aopOp (result, ic, TRUE);
+
+  /* special cases first */
+  /* both are bits */
+  if (AOP_TYPE (left) == AOP_CRY &&
+      AOP_TYPE (right) == AOP_CRY)
+    {
+      genDivbits (left, right, result);
+      goto release;
+    }
+
+  /* if both are of size == 1 */
+  if (AOP_SIZE (left) == 1 &&
+      AOP_SIZE (right) == 1)
+    {
+      genDivOneByte (left, right, result);
+      goto release;
+    }
+
+  /* should have been converted to function call */
+  assert (0);
+release:
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+}
+
+/*-----------------------------------------------------------------*/
+/* genModbits :- modulus of bits                                   */
+/*-----------------------------------------------------------------*/
+static void
+genModbits (operand * left,
+            operand * right,
+            operand * result)
+{
+  char *l;
+  bool pushedB;
+
+  D (emitcode (";", "genModbits"));
+
+  pushedB = pushB ();
+
+  /* the result must be bit */
+  emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
+  l = aopGet (left, 0, FALSE, FALSE);
+
+  MOVA (l);
+
+  emitcode ("div", "ab");
+  emitcode ("mov", "a,b");
+  emitcode ("rrc", "a");
+
+  popB (pushedB);
+
+  aopPut (result, "c", 0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genModOneByte : 8 bit modulus                                   */
+/*-----------------------------------------------------------------*/
+static void
+genModOneByte (operand * left,
+               operand * right,
+               operand * result)
+{
+  bool lUnsigned, rUnsigned, pushedB;
+  bool runtimeSign, compiletimeSign;
+  symbol *lbl;
+  int size, offset;
+
+  D (emitcode (";", "genModOneByte"));
+
+  size = AOP_SIZE (result) - 1;
+  offset = 1;
+  lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+  rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
+
+  /* if right is a literal, check it for 2^n */
+  if (AOP_TYPE(right) == AOP_LIT)
+    {
+      unsigned char val = abs((int) operandLitValue(right));
+      symbol *lbl2 = NULL;
+
+      switch (val)
+        {
+          case 1: /* sometimes it makes sense (on tricky code and hardware)... */
+          case 2:
+          case 4:
+          case 8:
+          case 16:
+          case 32:
+          case 64:
+          case 128:
+            if (lUnsigned)
+              werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                      "modulus of unsigned char by 2^n literal shouldn't be processed here");
+              /* because iCode should have been changed to genAnd  */
+              /* see file "SDCCopt.c", function "convertToFcall()" */
+
+            MOVA (aopGet (left, 0, FALSE, FALSE));
+            emitcode ("mov", "c,acc.7");
+            emitcode ("anl", "a,#0x%02x", val - 1);
+            lbl = newiTempLabel (NULL);
+            emitcode ("jz", "%05d$", (lbl->key + 100));
+            emitcode ("jnc", "%05d$", (lbl->key + 100));
+            emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
+            if (size)
+              {
+                int size2 = size;
+                int offs2 = offset;
+
+                aopPut (result, "a", 0);
+                while (size2--)
+                  aopPut (result, "#0xff", offs2++);
+                lbl2 = newiTempLabel (NULL);
+                emitcode ("sjmp", "%05d$", (lbl2->key + 100));
+              }
+            emitLabel (lbl);
+            aopPut (result, "a", 0);
+            while (size--)
+              aopPut (result, zero, offset++);
+            if (lbl2)
+              {
+                emitLabel (lbl2);
+              }
+            return;
+
+          default:
+            break;
+        }
+    }
+
+  pushedB = pushB ();
+
+  /* signed or unsigned */
+  if (lUnsigned && rUnsigned)
+    {
+      /* unsigned is easy */
+      emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
+      MOVA (aopGet (left, 0, FALSE, FALSE));
+      emitcode ("div", "ab");
+      aopPut (result, "b", 0);
+      while (size--)
+        aopPut (result, zero, offset++);
+
+      popB (pushedB);
+      return;
+    }
+
+  /* signed is a little bit more difficult */
+
+  /* now sign adjust for both left & right */
+
+  /* modulus: sign of the right operand has no influence on the result! */
+  if (AOP_TYPE(right) == AOP_LIT)
+    {
+      signed char val = (char) operandLitValue(right);
+
+      if (!rUnsigned && val < 0)
+        emitcode ("mov", "b,#0x%02x", -val);
+      else
+        emitcode ("mov", "b,#0x%02x", (unsigned char) val);
+    }
+  else /* not literal */
+    {
+      if (rUnsigned)
+        emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
+      else
+        {
+          MOVA (aopGet (right, 0, FALSE, FALSE));
+          lbl = newiTempLabel (NULL);
+          emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+          emitcode ("cpl", "a"); /* 2's complement */
+          emitcode ("inc", "a");
+          emitLabel (lbl);
+          emitcode ("mov", "b,a");
+        }
+    }
+
+  /* let's see what's needed: */
+  /* apply negative sign during runtime */
+  runtimeSign = FALSE;
+  /* negative sign from literals */
+  compiletimeSign = FALSE;
+
+  /* sign adjust left side */
+  if (AOP_TYPE(left) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+
+      if (!lUnsigned && val < 0)
+        {
+          compiletimeSign = TRUE; /* set sign flag */
+          emitcode ("mov", "a,#0x%02x", -val);
+        }
+      else
+        emitcode ("mov", "a,#0x%02x", (unsigned char) val);
+    }
+  else /* ! literal */
+    {
+      MOVA (aopGet (left, 0, FALSE, FALSE));
+
+      if (!lUnsigned)
+        {
+          runtimeSign = TRUE;
+          emitcode ("clr", "F0"); /* clear sign flag */
+
+          lbl = newiTempLabel (NULL);
+          emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+          emitcode ("setb", "F0"); /* set sign flag */
+          emitcode ("cpl", "a");   /* 2's complement */
+          emitcode ("inc", "a");
+          emitLabel (lbl);
+        }
+    }
+
+  /* now the modulus */
+  emitcode ("div", "ab");
+
+  if (runtimeSign || compiletimeSign)
+    {
+      emitcode ("mov", "a,b");
+      lbl = newiTempLabel (NULL);
+      if (runtimeSign)
+        emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
+      emitcode ("cpl", "a"); /* 2's complement */
+      emitcode ("inc", "a");
+      emitLabel (lbl);
+
+      aopPut (result, "a", 0);
+      if (size > 0)
+        {
+          /* msb is 0x00 or 0xff depending on the sign */
+          if (runtimeSign)
+            {
+              emitcode ("mov", "c,F0");
+              emitcode ("subb", "a,acc");
+              while (size--)
+                aopPut (result, "a", offset++);
+            }
+          else /* compiletimeSign */
+            while (size--)
+              aopPut (result, "#0xff", offset++);
+        }
+    }
+  else
+    {
+      aopPut (result, "b", 0);
+      while (size--)
+        aopPut (result, zero, offset++);
+    }
+
+  popB (pushedB);
+}
+
+/*-----------------------------------------------------------------*/
+/* genMod - generates code for division                            */
+/*-----------------------------------------------------------------*/
+static void
+genMod (iCode * ic)
+{
+  operand *left = IC_LEFT (ic);
+  operand *right = IC_RIGHT (ic);
+  operand *result = IC_RESULT (ic);
+
+  D (emitcode (";", "genMod"));
+
+  /* assign the asmops */
+  aopOp (left, ic, FALSE);
+  aopOp (right, ic, FALSE);
+  aopOp (result, ic, TRUE);
+
+  /* special cases first */
+  /* both are bits */
+  if (AOP_TYPE (left) == AOP_CRY &&
+      AOP_TYPE (right) == AOP_CRY)
+    {
+      genModbits (left, right, result);
+      goto release;
+    }
+
+  /* if both are of size == 1 */
+  if (AOP_SIZE (left) == 1 &&
+      AOP_SIZE (right) == 1)
+    {
+      genModOneByte (left, right, result);
+      goto release;
+    }
+
+  /* should have been converted to function call */
+  assert (0);
+
+release:
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+}
+
+/*-----------------------------------------------------------------*/
+/* genIfxJump :- will create a jump depending on the ifx           */
+/*-----------------------------------------------------------------*/
+static void
+genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
+{
+  symbol *jlbl;
+  symbol *tlbl = newiTempLabel (NULL);
+  char *inst;
+
+  D (emitcode (";", "genIfxJump"));
+
+  /* if true label then we jump if condition
+     supplied is true */
+  if (IC_TRUE (ic))
+    {
+      jlbl = IC_TRUE (ic);
+      inst = ((strcmp (jval, "a") == 0 ? "jz" :
+               (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
+    }
+  else
+    {
+      /* false label is present */
+      jlbl = IC_FALSE (ic);
+      inst = ((strcmp (jval, "a") == 0 ? "jnz" :
+               (strcmp (jval, "c") == 0 ? "jc" : "jb")));
+    }
+  if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
+    emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
+  else
+    emitcode (inst, "%05d$", tlbl->key + 100);
+  freeForBranchAsmop (result);
+  freeForBranchAsmop (right);
+  freeForBranchAsmop (left);
+  emitcode ("ljmp", "%05d$", jlbl->key + 100);
+  emitLabel (tlbl);
+
+  /* mark the icode as generated */
+  ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* genCmp :- greater or less than comparison                       */
+/*-----------------------------------------------------------------*/
+static void
+genCmp (operand * left, operand * right,
+        operand * result, iCode * ifx, int sign, iCode *ic)
+{
+  int size, offset = 0;
+  unsigned long lit = 0L;
+  bool rightInB;
+
+  D (emitcode (";", "genCmp"));
+
+  /* if left & right are bit variables */
+  if (AOP_TYPE (left) == AOP_CRY &&
+      AOP_TYPE (right) == AOP_CRY)
+    {
+      emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
+      emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
+    }
+  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, do cjne left,#right,zz */
+      if ((size == 1) && !sign &&
+          (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
+        {
+          symbol *lbl = newiTempLabel (NULL);
+          emitcode ("cjne", "%s,%s,%05d$",
+                    aopGet (left, offset, FALSE, FALSE),
+                    aopGet (right, offset, FALSE, FALSE),
+                    lbl->key + 100);
+          emitLabel (lbl);
+        }
+      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)
+                    {
+                      CLRC;
+                    }
+                  else
+                    {
+                      MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
+                      if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
+                        {
+                          genIfxJump (ifx, "acc.7", left, right, result);
+                          freeAsmop (right, NULL, ic, TRUE);
+                          freeAsmop (left, NULL, ic, TRUE);
+
+                          return;
+                        }
+                      else
+                        {
+                          emitcode ("rlc", "a");
+                        }
+                    }
+                  goto release;
+                }
+              else
+                {//nonzero literal
+                  int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
+                  while (size && (bytelit == 0))
+                    {
+                      offset++;
+                      bytelit = ((lit >> (offset * 8)) & 0x0FFL);
+                      size--;
+                    }
+                  CLRC;
+                  while (size--)
+                    {
+                      MOVA (aopGet (left, offset, FALSE, FALSE));
+                      if (sign && size == 0)
+                        {
+                          emitcode ("xrl", "a,#0x80");
+                          emitcode ("subb", "a,#0x%02x",
+                                    0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
+                        }
+                      else
+                        {
+                          emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                        }
+                      offset++;
+                    }
+                  goto release;
+                }
+            }
+          CLRC;
+          while (size--)
+            {
+              bool pushedB = FALSE;
+              rightInB = aopGetUsesAcc(right, offset);
+              if (rightInB)
+                {
+                  pushedB = pushB ();
+                  emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
+                }
+              MOVA (aopGet (left, offset, FALSE, FALSE));
+              if (sign && size == 0)
+                {
+                  emitcode ("xrl", "a,#0x80");
+                  if (!rightInB)
+                    {
+                      pushedB = pushB ();
+                      rightInB++;
+                      MOVB (aopGet (right, offset, FALSE, FALSE));
+                    }
+                  emitcode ("xrl", "b,#0x80");
+                  emitcode ("subb", "a,b");
+                }
+              else
+                {
+                  if (rightInB)
+                    emitcode ("subb", "a,b");
+                  else
+                    emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                }
+              if (rightInB)
+                popB (pushedB);
+              offset++;
+            }
+        }
+    }
+
+release:
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  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", NULL, NULL, result);
+        }
+      else
+        {
+          outBitC (result);
+        }
+      /* leave the result in acc */
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genCmpGt :- greater than comparison                             */
+/*-----------------------------------------------------------------*/
+static void
+genCmpGt (iCode * ic, iCode * ifx)
+{
+  operand *left, *right, *result;
+  sym_link *letype, *retype;
+  int sign;
+
+  D (emitcode (";", "genCmpGt"));
+
+  left = IC_LEFT (ic);
+  right = IC_RIGHT (ic);
+  result = IC_RESULT (ic);
+
+  letype = getSpec (operandType (left));
+  retype = getSpec (operandType (right));
+  sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
+           (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
+  /* assign the amsops */
+  aopOp (result, ic, TRUE);
+  aopOp (left, ic, FALSE);
+  aopOp (right, ic, FALSE);
+
+  genCmp (right, left, result, ifx, sign, ic);
+
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genCmpLt - less than comparisons                                */
+/*-----------------------------------------------------------------*/
+static void
+genCmpLt (iCode * ic, iCode * ifx)
+{
+  operand *left, *right, *result;
+  sym_link *letype, *retype;
+  int sign;
+
+  D (emitcode (";", "genCmpLt"));
+
+  left = IC_LEFT (ic);
+  right = IC_RIGHT (ic);
+  result = IC_RESULT (ic);
+
+  letype = getSpec (operandType (left));
+  retype = getSpec (operandType (right));
+  sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
+           (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
+  /* assign the amsops */
+  aopOp (result, ic, TRUE);
+  aopOp (left, ic, FALSE);
+  aopOp (right, ic, FALSE);
+
+  genCmp (left, right, result, ifx, sign, ic);
+
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* 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;
+
+  D (emitcode (";", "gencjneshort"));
+
+  /* if the left side is a literal or
+     if the right is in a pointer register and left
+     is not */
+  if ((AOP_TYPE (left) == AOP_LIT) ||
+      (AOP_TYPE (left) == AOP_IMMD) ||
+      (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
+    {
+      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  &&
+      AOP_TYPE (left) != AOP_IMMD)
+    {
+      while (size--)
+        {
+          emitcode ("cjne", "%s,%s,%05d$",
+                    aopGet (left, offset, FALSE, FALSE),
+                    aopGet (right, offset, FALSE, FALSE),
+                    lbl->key + 100);
+          offset++;
+        }
+    }
+
+  /* if the right side is in a register or in direct space or
+     if the left is a pointer register & right is not */
+  else if (AOP_TYPE (right) == AOP_REG ||
+           AOP_TYPE (right) == AOP_DIR ||
+           AOP_TYPE (right) == AOP_LIT ||
+           AOP_TYPE (right) == AOP_IMMD ||
+           (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
+           (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
+    {
+      while (size--)
+        {
+          MOVA (aopGet (left, offset, FALSE, FALSE));
+          if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
+              ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
+            emitcode ("jnz", "%05d$", lbl->key + 100);
+          else
+            emitcode ("cjne", "a,%s,%05d$",
+                      aopGet (right, offset, FALSE, TRUE),
+                      lbl->key + 100);
+          offset++;
+        }
+    }
+  else
+    {
+      /* right is a pointer reg need both a & b */
+      while (size--)
+        {
+          //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
+          wassertl(!BINUSE, "B was in use");
+          MOVB (aopGet (left, offset, FALSE, FALSE));
+          MOVA (aopGet (right, offset, FALSE, FALSE));
+          emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
+          offset++;
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* gencjne - compare and jump if not equal                         */
+/*-----------------------------------------------------------------*/
+static void
+gencjne (operand * left, operand * right, symbol * lbl)
+{
+  symbol *tlbl = newiTempLabel (NULL);
+
+  D (emitcode (";", "gencjne"));
+
+  gencjneshort (left, right, lbl);
+
+  emitcode ("mov", "a,%s", one);
+  emitcode ("sjmp", "%05d$", tlbl->key + 100);
+  emitLabel (lbl);
+  emitcode ("clr", "a");
+  emitLabel (tlbl);
+}
+
+/*-----------------------------------------------------------------*/
+/* genCmpEq - generates code for equal to                          */
+/*-----------------------------------------------------------------*/
+static void
+genCmpEq (iCode * ic, iCode * ifx)
+{
+  bool swappedLR = FALSE;
+  operand *left, *right, *result;
+
+  D (emitcode (";", "genCmpEq"));
+
+  aopOp ((left = IC_LEFT (ic)), ic, FALSE);
+  aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
+  aopOp ((result = IC_RESULT (ic)), ic, TRUE);
+
+  /* if literal, literal on the right or
+     if the right is in a pointer register and left
+     is not */
+  if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
+      (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
+    {
+      operand *t = IC_RIGHT (ic);
+      IC_RIGHT (ic) = IC_LEFT (ic);
+      IC_LEFT (ic) = t;
+      swappedLR = TRUE;
+    }
+
+  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)))
+        {
+          if (AOP_TYPE (right) == AOP_LIT)
+            {
+              unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+              if (lit == 0L)
+                {
+                  emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
+                  emitcode ("cpl", "c");
+                }
+              else if (lit == 1L)
+                {
+                  emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
+                }
+              else
+                {
+                  emitcode ("clr", "c");
+                }
+              /* AOP_TYPE(right) == AOP_CRY */
+            }
+          else
+            {
+              symbol *lbl = newiTempLabel (NULL);
+              emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
+              emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
+              emitcode ("cpl", "c");
+              emitLabel (lbl);
+            }
+          /* if true label then we jump if condition
+             supplied is true */
+          tlbl = newiTempLabel (NULL);
+          if (IC_TRUE (ifx))
+            {
+              emitcode ("jnc", "%05d$", tlbl->key + 100);
+              freeForBranchAsmop (result);
+              freeForBranchAsmop (right);
+              freeForBranchAsmop (left);
+              emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
+            }
+          else
+            {
+              emitcode ("jc", "%05d$", tlbl->key + 100);
+              freeForBranchAsmop (result);
+              freeForBranchAsmop (right);
+              freeForBranchAsmop (left);
+              emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
+            }
+          emitLabel (tlbl);
+        }
+      else
+        {
+          tlbl = newiTempLabel (NULL);
+          gencjneshort (left, right, tlbl);
+          if (IC_TRUE (ifx))
+            {
+              freeForBranchAsmop (result);
+              freeForBranchAsmop (right);
+              freeForBranchAsmop (left);
+              emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
+              emitLabel (tlbl);
+            }
+          else
+            {
+              symbol *lbl = newiTempLabel (NULL);
+              emitcode ("sjmp", "%05d$", lbl->key + 100);
+              emitLabel (tlbl);
+              freeForBranchAsmop (result);
+              freeForBranchAsmop (right);
+              freeForBranchAsmop (left);
+              emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
+              emitLabel (lbl);
+            }
+        }
+      /* 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)))
+    {
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+          if (lit == 0L)
+            {
+              emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
+              emitcode ("cpl", "c");
+            }
+          else if (lit == 1L)
+            {
+              emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
+            }
+          else
+            {
+              emitcode ("clr", "c");
+            }
+          /* AOP_TYPE(right) == AOP_CRY */
+        }
+      else
+        {
+          symbol *lbl = newiTempLabel (NULL);
+          emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
+          emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
+          emitcode ("cpl", "c");
+          emitLabel (lbl);
+        }
+      /* c = 1 if egal */
+      if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
+        {
+          outBitC (result);
+          goto release;
+        }
+      if (ifx)
+        {
+          genIfxJump (ifx, "c", left, right, result);
+          goto release;
+        }
+      /* if the result is used in an arithmetic operation
+         then put the result in place */
+      outBitC (result);
+    }
+  else
+    {
+      gencjne (left, right, newiTempLabel (NULL));
+      if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
+        {
+          aopPut (result, "a", 0);
+          goto release;
+        }
+      if (ifx)
+        {
+          genIfxJump (ifx, "a", left, right, result);
+          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 */
+    }
+
+release:
+  freeAsmop (result, NULL, ic, TRUE);
+  if (!swappedLR)
+    {
+      freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+      freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+    }
+  else
+    {
+      freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+      freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* ifxForOp - returns the icode containing the ifx for operand     */
+/*-----------------------------------------------------------------*/
+static iCode *
+ifxForOp (operand * op, 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;
+}
+
+/*-----------------------------------------------------------------*/
+/* hasInc - operand is incremented before any other use            */
+/*-----------------------------------------------------------------*/
+static iCode *
+hasInc (operand *op, iCode *ic, int osize)
+{
+  sym_link *type = operandType(op);
+  sym_link *retype = getSpec (type);
+  iCode *lic = ic->next;
+  int isize ;
+
+  /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
+  if (!IS_SYMOP(op)) return NULL;
+
+  if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
+  if (IS_AGGREGATE(type->next)) return NULL;
+  if (osize != (isize = getSize(type->next))) return NULL;
+
+  while (lic) {
+    /* if operand of the form op = op + <sizeof *op> */
+    if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
+        isOperandEqual(IC_RESULT(lic),op) &&
+        isOperandLiteral(IC_RIGHT(lic)) &&
+        operandLitValue(IC_RIGHT(lic)) == isize) {
+      return lic;
+    }
+    /* if the operand used or deffed */
+    if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
+      return NULL;
+    }
+    /* if GOTO or IFX */
+    if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
+    lic = lic->next;
+  }
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* genAndOp - for && operation                                     */
+/*-----------------------------------------------------------------*/
+static void
+genAndOp (iCode * ic)
+{
+  operand *left, *right, *result;
+  symbol *tlbl;
+
+  D (emitcode (";", "genAndOp"));
+
+  /* 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 both are bit variables */
+  if (AOP_TYPE (left) == AOP_CRY &&
+      AOP_TYPE (right) == AOP_CRY)
+    {
+      emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
+      emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
+      outBitC (result);
+    }
+  else
+    {
+      tlbl = newiTempLabel (NULL);
+      toBoolean (left);
+      emitcode ("jz", "%05d$", tlbl->key + 100);
+      toBoolean (right);
+      emitLabel (tlbl);
+      outBitAcc (result);
+    }
+
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genOrOp - for || operation                                      */
+/*-----------------------------------------------------------------*/
+static void
+genOrOp (iCode * ic)
+{
+  operand *left, *right, *result;
+  symbol *tlbl;
+
+  D (emitcode (";", "genOrOp"));
+
+  /* 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 both are bit variables */
+  if (AOP_TYPE (left) == AOP_CRY &&
+      AOP_TYPE (right) == AOP_CRY)
+    {
+      emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
+      emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
+      outBitC (result);
+    }
+  else
+    {
+      tlbl = newiTempLabel (NULL);
+      toBoolean (left);
+      emitcode ("jnz", "%05d$", tlbl->key + 100);
+      toBoolean (right);
+      emitLabel (tlbl);
+      outBitAcc (result);
+    }
+
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+}
+
+/*-----------------------------------------------------------------*/
+/* isLiteralBit - test if lit == 2^n                               */
+/*-----------------------------------------------------------------*/
+static 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;
+}
+
+/*-----------------------------------------------------------------*/
+/* continueIfTrue -                                                */
+/*-----------------------------------------------------------------*/
+static void
+continueIfTrue (iCode * ic)
+{
+  if (IC_TRUE (ic))
+    emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
+  ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* jmpIfTrue -                                                     */
+/*-----------------------------------------------------------------*/
+static void
+jumpIfTrue (iCode * ic)
+{
+  if (!IC_TRUE (ic))
+    emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
+  ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* jmpTrueOrFalse -                                                */
+/*-----------------------------------------------------------------*/
+static void
+jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
+{
+  // ugly but optimized by peephole
+  if (IC_TRUE (ic))
+    {
+      symbol *nlbl = newiTempLabel (NULL);
+      emitcode ("sjmp", "%05d$", nlbl->key + 100);
+      emitLabel (tlbl);
+      freeForBranchAsmop (result);
+      freeForBranchAsmop (right);
+      freeForBranchAsmop (left);
+      emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
+      emitLabel (nlbl);
+    }
+  else
+    {
+      freeForBranchAsmop (result);
+      freeForBranchAsmop (right);
+      freeForBranchAsmop (left);
+      emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
+      emitLabel (tlbl);
+    }
+  ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* genAnd  - code for and                                          */
+/*-----------------------------------------------------------------*/
+static void
+genAnd (iCode * ic, iCode * ifx)
+{
+  operand *left, *right, *result;
+  int size, offset = 0;
+  unsigned long lit = 0L;
+  int bytelit = 0;
+  char buffer[10];
+
+  D (emitcode (";", "genAnd"));
+
+  aopOp ((left = IC_LEFT (ic)), ic, FALSE);
+  aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
+  aopOp ((result = IC_RESULT (ic)), ic, TRUE);
+
+#ifdef DEBUG_TYPE
+  emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
+            AOP_TYPE (result),
+            AOP_TYPE (left), AOP_TYPE (right));
+  emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
+            AOP_SIZE (result),
+            AOP_SIZE (left), AOP_SIZE (right));
+#endif
+
+  /* if left is a literal & right is not then exchange them */
+  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
+      AOP_NEEDSACC (left))
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
+    }
+
+  /* if result = right then exchange left and right */
+  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(bit & yy)
+  // result = bit & yy;
+  if (AOP_TYPE (left) == AOP_CRY)
+    {
+      // c = bit & literal;
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          if (lit & 1)
+            {
+              if (size && sameRegs (AOP (result), AOP (left)))
+                // no change
+                goto release;
+              emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
+            }
+          else
+            {
+              // bit(result) = 0;
+              if (size && (AOP_TYPE (result) == AOP_CRY))
+                {
+                  emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
+                  goto release;
+                }
+              if ((AOP_TYPE (result) == AOP_CRY) && ifx)
+                {
+                  jumpIfTrue (ifx);
+                  goto release;
+                }
+              emitcode ("clr", "c");
+            }
+        }
+      else
+        {
+          if (AOP_TYPE (right) == AOP_CRY)
+            {
+              // c = bit & bit;
+              emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
+              emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
+            }
+          else
+            {
+              // c = bit & val;
+              MOVA (aopGet (right, 0, FALSE, FALSE));
+              // c = lsb
+              emitcode ("rrc", "a");
+              emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
+            }
+        }
+      // bit = c
+      // val = c
+      if (size)
+        outBitC (result);
+      // if(bit & ...)
+      else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
+        genIfxJump (ifx, "c", left, right, result);
+      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 (left, posbit >> 3, FALSE, FALSE));
+          // bit = left & 2^n
+          if (size)
+            {
+              switch (posbit & 0x07)
+                {
+                  case 0: emitcode ("rrc", "a");
+                          break;
+                  case 7: emitcode ("rlc", "a");
+                          break;
+                  default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
+                          break;
+                }
+            }
+          // if(left &  2^n)
+          else
+            {
+              if (ifx)
+                {
+                  SNPRINTF (buffer, sizeof(buffer),
+                            "acc.%d", posbit & 0x07);
+                  genIfxJump (ifx, buffer, left, right, result);
+                }
+              else
+                {// what is this case? just found it in ds390/gen.c
+                  emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
+                }
+              goto release;
+            }
+        }
+      else
+        {
+          symbol *tlbl = newiTempLabel (NULL);
+          int sizel = AOP_SIZE (left);
+          if (size)
+            emitcode ("setb", "c");
+          while (sizel--)
+            {
+              if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
+                {
+                  MOVA (aopGet (left, offset, FALSE, FALSE));
+                  // byte ==  2^n ?
+                  if ((posbit = isLiteralBit (bytelit)) != 0)
+                    emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
+                  else
+                    {
+                      if (bytelit != 0x0FFL)
+                        emitcode ("anl", "a,%s",
+                                  aopGet (right, offset, FALSE, TRUE));
+                      emitcode ("jnz", "%05d$", tlbl->key + 100);
+                    }
+                }
+              offset++;
+            }
+          // bit = left & literal
+          if (size)
+            {
+              emitcode ("clr", "c");
+              emitLabel (tlbl);
+            }
+          // if(left & literal)
+          else
+            {
+              if (ifx)
+                jmpTrueOrFalse (ifx, tlbl, left, right, result);
+              else
+                emitLabel (tlbl);
+              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)
+            {
+              bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
+              if (bytelit == 0x0FF)
+                {
+                  /* dummy read of volatile operand */
+                  if (isOperandVolatile (left, FALSE))
+                    MOVA (aopGet (left, offset, FALSE, FALSE));
+                  else
+                    continue;
+                }
+              else if (bytelit == 0)
+                {
+                  aopPut (result, zero, offset);
+                }
+              else if (IS_AOP_PREG (result))
+                {
+                  MOVA (aopGet (left, offset, FALSE, TRUE));
+                  emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                  aopPut (result, "a", offset);
+                }
+              else
+                emitcode ("anl", "%s,%s",
+                          aopGet (left, offset, FALSE, TRUE),
+                          aopGet (right, offset, FALSE, FALSE));
+            }
+          else
+            {
+              if (AOP_TYPE (left) == AOP_ACC)
+                {
+                  if (offset)
+                    emitcode("mov", "a,b");
+                  emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                }
+              else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
+                {
+                  emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  emitcode ("anl", "a,b");
+                  aopPut (result, "a", offset);
+                }
+              else if (aopGetUsesAcc (left, offset))
+                {
+                  MOVA (aopGet (left, offset, FALSE, FALSE));
+                  emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                  aopPut (result, "a", offset);
+                }
+              else
+                {
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  if (IS_AOP_PREG (result))
+                    {
+                      emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
+                      aopPut (result, "a", offset);
+                    }
+                  else
+                    emitcode ("anl", "%s,a",
+                              aopGet (left, offset, FALSE, TRUE));
+                }
+            }
+        }
+    }
+  else
+    {
+      // left & result in different registers
+      if (AOP_TYPE (result) == AOP_CRY)
+        {
+          // result = bit
+          // if(size), result in bit
+          // if(!size && ifx), conditional oper: if(left & right)
+          symbol *tlbl = newiTempLabel (NULL);
+          int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
+          if (size)
+            emitcode ("setb", "c");
+          while (sizer--)
+            {
+              if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
+                  && AOP_TYPE(left)==AOP_ACC)
+                {
+                  if (offset)
+                    emitcode("mov", "a,b");
+                  emitcode ("anl", "a,%s",
+                            aopGet (right, offset, FALSE, FALSE));
+                } else {
+                  if (AOP_TYPE(left)==AOP_ACC)
+                    {
+                      if (!offset)
+                        {
+                          bool pushedB = pushB ();
+                          emitcode("mov", "b,a");
+                          MOVA (aopGet (right, offset, FALSE, FALSE));
+                          emitcode("anl", "a,b");
+                          popB (pushedB);
+                        }
+                      else
+                        {
+                          MOVA (aopGet (right, offset, FALSE, FALSE));
+                          emitcode("anl", "a,b");
+                        }
+                    } else {
+                      MOVA (aopGet (right, offset, FALSE, FALSE));
+                      emitcode ("anl", "a,%s",
+                                aopGet (left, offset, FALSE, FALSE));
+                    }
+                }
+              emitcode ("jnz", "%05d$", tlbl->key + 100);
+              offset++;
+            }
+          if (size)
+            {
+              CLRC;
+              emitLabel (tlbl);
+              outBitC (result);
+            }
+          else if (ifx)
+            jmpTrueOrFalse (ifx, tlbl, left, right, result);
+          else
+            emitLabel (tlbl);
+        }
+      else
+        {
+          for (; (size--); offset++)
+            {
+              // normal case
+              // result = left & right
+              if (AOP_TYPE (right) == AOP_LIT)
+                {
+                  bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
+                  if (bytelit == 0x0FF)
+                    {
+                      aopPut (result,
+                              aopGet (left, offset, FALSE, FALSE),
+                              offset);
+                      continue;
+                    }
+                  else if (bytelit == 0)
+                    {
+                      /* dummy read of volatile operand */
+                      if (isOperandVolatile (left, FALSE))
+                        MOVA (aopGet (left, offset, FALSE, FALSE));
+                      aopPut (result, zero, offset);
+                      continue;
+                    }
+                  else if (AOP_TYPE (left) == AOP_ACC)
+                    {
+                      if (!offset)
+                        {
+                          emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                          aopPut (result, "a", offset);
+                          continue;
+                        }
+                      else
+                        {
+                          emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
+                          aopPut (result, "b", offset);
+                          continue;
+                        }
+                    }
+                }
+              // faster than result <- left, anl result,right
+              // and better if result is SFR
+              if (AOP_TYPE (left) == AOP_ACC)
+                {
+                  if (offset)
+                    emitcode("mov", "a,b");
+                  emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                }
+              else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
+                {
+                  emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  emitcode ("anl", "a,b");
+                }
+              else if (aopGetUsesAcc (left, offset))
+                {
+                  MOVA (aopGet (left, offset, FALSE, FALSE));
+                  emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                }
+              else
+                {
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
+                }
+              aopPut (result, "a", offset);
+            }
+        }
+    }
+
+release:
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+}
+
+/*-----------------------------------------------------------------*/
+/* genOr  - code for or                                            */
+/*-----------------------------------------------------------------*/
+static void
+genOr (iCode * ic, iCode * ifx)
+{
+  operand *left, *right, *result;
+  int size, offset = 0;
+  unsigned long lit = 0L;
+  int bytelit = 0;
+
+  D (emitcode (";", "genOr"));
+
+  aopOp ((left = IC_LEFT (ic)), ic, FALSE);
+  aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
+  aopOp ((result = IC_RESULT (ic)), ic, TRUE);
+
+#ifdef DEBUG_TYPE
+  emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
+            AOP_TYPE (result),
+            AOP_TYPE (left), AOP_TYPE (right));
+  emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
+            AOP_SIZE (result),
+            AOP_SIZE (left), AOP_SIZE (right));
+#endif
+
+  /* if left is a literal & right is not then exchange them */
+  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
+      AOP_NEEDSACC (left))
+    {
+      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(bit | yy)
+  // xx = bit | yy;
+  if (AOP_TYPE (left) == AOP_CRY)
+    {
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          // c = bit | literal;
+          if (lit)
+            {
+              // lit != 0 => result = 1
+              if (AOP_TYPE (result) == AOP_CRY)
+                {
+                  if (size)
+                    emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
+                  else if (ifx)
+                    continueIfTrue (ifx);
+                  goto release;
+                }
+              emitcode ("setb", "c");
+            }
+          else
+            {
+              // lit == 0 => result = left
+              if (size && sameRegs (AOP (result), AOP (left)))
+                goto release;
+              emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
+            }
+        }
+      else
+        {
+          if (AOP_TYPE (right) == AOP_CRY)
+            {
+              // c = bit | bit;
+              emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
+              emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
+            }
+          else
+            {
+              // c = bit | val;
+              symbol *tlbl = newiTempLabel (NULL);
+              if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
+                emitcode ("setb", "c");
+              emitcode ("jb", "%s,%05d$",
+                        AOP (left)->aopu.aop_dir, tlbl->key + 100);
+              toBoolean (right);
+              emitcode ("jnz", "%05d$", tlbl->key + 100);
+              if ((AOP_TYPE (result) == AOP_CRY) && ifx)
+                {
+                  jmpTrueOrFalse (ifx, tlbl, left, right, result);
+                  goto release;
+                }
+              else
+                {
+                  CLRC;
+                  emitLabel (tlbl);
+                }
+            }
+        }
+      // bit = c
+      // val = c
+      if (size)
+        outBitC (result);
+      // if(bit | ...)
+      else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
+        genIfxJump (ifx, "c", left, right, result);
+      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))
+    {
+      if (lit)
+        {
+          // result = 1
+          if (size)
+            emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
+          else
+            continueIfTrue (ifx);
+          goto release;
+        }
+      else
+        {
+          // lit = 0, result = boolean(left)
+          if (size)
+            emitcode ("setb", "c");
+          toBoolean (right);
+          if (size)
+            {
+              symbol *tlbl = newiTempLabel (NULL);
+              emitcode ("jnz", "%05d$", tlbl->key + 100);
+              CLRC;
+              emitLabel (tlbl);
+            }
+          else
+            {
+              genIfxJump (ifx, "a", left, right, result);
+              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)
+            {
+              bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
+              if (bytelit == 0)
+                {
+                  /* dummy read of volatile operand */
+                  if (isOperandVolatile (left, FALSE))
+                    MOVA (aopGet (left, offset, FALSE, FALSE));
+                  else
+                    continue;
+                }
+              else if (bytelit == 0x0FF)
+                {
+                  aopPut (result, "#0xFF", offset);
+                }
+              else if (IS_AOP_PREG (left))
+                {
+                  MOVA (aopGet (left, offset, FALSE, TRUE));
+                  emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                  aopPut (result, "a", offset);
+                }
+              else
+                {
+                  emitcode ("orl", "%s,%s",
+                            aopGet (left, offset, FALSE, TRUE),
+                            aopGet (right, offset, FALSE, FALSE));
+                }
+            }
+          else
+            {
+              if (AOP_TYPE (left) == AOP_ACC)
+                {
+                  if (offset)
+                    emitcode("mov", "a,b");
+                  emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                }
+              else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
+                {
+                  emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  emitcode ("orl", "a,b");
+                  aopPut (result, "a", offset);
+                }
+              else if (aopGetUsesAcc (left, offset))
+                {
+                  MOVA (aopGet (left, offset, FALSE, FALSE));
+                  emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                  aopPut (result, "a", offset);
+                }
+              else
+                {
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  if (IS_AOP_PREG (left))
+                    {
+                      emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
+                      aopPut (result, "a", offset);
+                    }
+                  else
+                    {
+                      emitcode ("orl", "%s,a",
+                                aopGet (left, offset, FALSE, TRUE));
+                    }
+                }
+            }
+        }
+    }
+  else
+    {
+      // left & result in different registers
+      if (AOP_TYPE (result) == AOP_CRY)
+        {
+          // result = bit
+          // if(size), result in bit
+          // if(!size && ifx), conditional oper: if(left | right)
+          symbol *tlbl = newiTempLabel (NULL);
+          int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
+          if (size)
+            emitcode ("setb", "c");
+          while (sizer--)
+            {
+              if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
+                if (offset)
+                  emitcode("mov", "a,b");
+                emitcode ("orl", "a,%s",
+                          aopGet (right, offset, FALSE, FALSE));
+              } else {
+                MOVA (aopGet (right, offset, FALSE, FALSE));
+                emitcode ("orl", "a,%s",
+                          aopGet (left, offset, FALSE, FALSE));
+              }
+              emitcode ("jnz", "%05d$", tlbl->key + 100);
+              offset++;
+            }
+          if (size)
+            {
+              CLRC;
+              emitLabel (tlbl);
+              outBitC (result);
+            }
+          else if (ifx)
+            jmpTrueOrFalse (ifx, tlbl, left, right, result);
+          else
+            emitLabel (tlbl);
+        }
+      else
+        {
+          for (; (size--); offset++)
+            {
+              // normal case
+              // result = left | right
+              if (AOP_TYPE (right) == AOP_LIT)
+                {
+                  bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
+                  if (bytelit == 0)
+                    {
+                      aopPut (result,
+                              aopGet (left, offset, FALSE, FALSE),
+                              offset);
+                      continue;
+                    }
+                  else if (bytelit == 0x0FF)
+                    {
+                      /* dummy read of volatile operand */
+                      if (isOperandVolatile (left, FALSE))
+                        MOVA (aopGet (left, offset, FALSE, FALSE));
+                      aopPut (result, "#0xFF", offset);
+                      continue;
+                    }
+                }
+              // faster than result <- left, anl result,right
+              // and better if result is SFR
+              if (AOP_TYPE (left) == AOP_ACC)
+                {
+                  if (offset)
+                    emitcode("mov", "a,b");
+                  emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                }
+              else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
+                {
+                  emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  emitcode ("orl", "a,b");
+                }
+              else if (aopGetUsesAcc (left, offset))
+                {
+                  MOVA (aopGet (left, offset, FALSE, FALSE));
+                  emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                }
+              else
+                {
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
+                }
+              aopPut (result, "a", offset);
+            }
+        }
+    }
+
+release:
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+}
+
+/*-----------------------------------------------------------------*/
+/* genXor - code for xclusive or                                   */
+/*-----------------------------------------------------------------*/
+static void
+genXor (iCode * ic, iCode * ifx)
+{
+  operand *left, *right, *result;
+  int size, offset = 0;
+  unsigned long lit = 0L;
+  int bytelit = 0;
+
+  D (emitcode (";", "genXor"));
+
+  aopOp ((left = IC_LEFT (ic)), ic, FALSE);
+  aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
+  aopOp ((result = IC_RESULT (ic)), ic, TRUE);
+
+#ifdef DEBUG_TYPE
+  emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
+            AOP_TYPE (result),
+            AOP_TYPE (left), AOP_TYPE (right));
+  emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
+            AOP_SIZE (result),
+            AOP_SIZE (left), AOP_SIZE (right));
+#endif
+
+  /* if left is a literal & right is not ||
+     if left needs acc & right does not */
+  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
+      (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
+    {
+      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(bit ^ yy)
+  // xx = bit ^ yy;
+  if (AOP_TYPE (left) == AOP_CRY)
+    {
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          // c = bit & literal;
+          if (lit >> 1)
+            {
+              // lit>>1  != 0 => result = 1
+              if (AOP_TYPE (result) == AOP_CRY)
+                {
+                  if (size)
+                    emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
+                  else if (ifx)
+                    continueIfTrue (ifx);
+                  goto release;
+                }
+              emitcode ("setb", "c");
+            }
+          else
+            {
+              // lit == (0 or 1)
+              if (lit == 0)
+                {
+                  // lit == 0, result = left
+                  if (size && sameRegs (AOP (result), AOP (left)))
+                    goto release;
+                  emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
+                }
+              else
+                {
+                  // lit == 1, result = not(left)
+                  if (size && sameRegs (AOP (result), AOP (left)))
+                    {
+                      emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
+                      goto release;
+                    }
+                  else
+                    {
+                      emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
+                      emitcode ("cpl", "c");
+                    }
+                }
+            }
+
+        }
+      else
+        {
+          // right != literal
+          symbol *tlbl = newiTempLabel (NULL);
+          if (AOP_TYPE (right) == AOP_CRY)
+            {
+              // c = bit ^ bit;
+              emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
+            }
+          else
+            {
+              int sizer = AOP_SIZE (right);
+              // c = bit ^ val
+              // if val>>1 != 0, result = 1
+              emitcode ("setb", "c");
+              while (sizer)
+                {
+                  MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
+                  if (sizer == 1)
+                    // test the msb of the lsb
+                    emitcode ("anl", "a,#0xfe");
+                  emitcode ("jnz", "%05d$", tlbl->key + 100);
+                  sizer--;
+                }
+              // val = (0,1)
+              emitcode ("rrc", "a");
+            }
+          emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
+          emitcode ("cpl", "c");
+          emitLabel (tlbl);
+        }
+      // bit = c
+      // val = c
+      if (size)
+        outBitC (result);
+      // if(bit | ...)
+      else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
+        genIfxJump (ifx, "c", left, right, result);
+      goto release;
+    }
+
+  /* if left is same as result */
+  if (sameRegs (AOP (result), AOP (left)))
+    {
+      for (; size--; offset++)
+        {
+          if (AOP_TYPE (right) == AOP_LIT)
+            {
+              bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
+              if (bytelit == 0)
+                {
+                  /* dummy read of volatile operand */
+                  if (isOperandVolatile (left, FALSE))
+                    MOVA (aopGet (left, offset, FALSE, FALSE));
+                  else
+                    continue;
+                }
+              else if (IS_AOP_PREG (left))
+                {
+                  MOVA (aopGet (left, offset, FALSE, TRUE));
+                  emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                  aopPut (result, "a", offset);
+                }
+              else
+                {
+                  emitcode ("xrl", "%s,%s",
+                            aopGet (left, offset, FALSE, TRUE),
+                            aopGet (right, offset, FALSE, FALSE));
+                }
+            }
+          else
+            {
+              if (AOP_TYPE (left) == AOP_ACC)
+                {
+                  if (offset)
+                    emitcode("mov", "a,b");
+                  emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                }
+              else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
+                {
+                  emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  emitcode ("xrl", "a,b");
+                  aopPut (result, "a", offset);
+                }
+              else if (aopGetUsesAcc (left, offset))
+                {
+                  MOVA (aopGet (left, offset, FALSE, FALSE));
+                  emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                  aopPut (result, "a", offset);
+                }
+              else
+                {
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  if (IS_AOP_PREG (left))
+                    {
+                      emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
+                      aopPut (result, "a", offset);
+                    }
+                  else
+                    emitcode ("xrl", "%s,a",
+                              aopGet (left, offset, FALSE, TRUE));
+                }
+            }
+        }
+    }
+  else
+    {
+      // left & result in different registers
+      if (AOP_TYPE (result) == AOP_CRY)
+        {
+          // result = bit
+          // if(size), result in bit
+          // if(!size && ifx), conditional oper: if(left ^ right)
+          symbol *tlbl = newiTempLabel (NULL);
+          int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
+
+          if (size)
+            emitcode ("setb", "c");
+          while (sizer--)
+            {
+              if ((AOP_TYPE (right) == AOP_LIT) &&
+                  (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
+                {
+                  MOVA (aopGet (left, offset, FALSE, FALSE));
+                }
+              else
+                {
+                  if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
+                    if (offset)
+                      emitcode("mov", "a,b");
+                    emitcode ("xrl", "a,%s",
+                              aopGet (right, offset, FALSE, FALSE));
+                  } else {
+                    MOVA (aopGet (right, offset, FALSE, FALSE));
+                    emitcode ("xrl", "a,%s",
+                              aopGet (left, offset, FALSE, FALSE));
+                  }
+                }
+              emitcode ("jnz", "%05d$", tlbl->key + 100);
+              offset++;
+            }
+          if (size)
+            {
+              CLRC;
+              emitLabel (tlbl);
+              outBitC (result);
+            }
+          else if (ifx)
+            jmpTrueOrFalse (ifx, tlbl, left, right, result);
+        }
+      else
+        {
+          for (; (size--); offset++)
+            {
+              // normal case
+              // result = left ^ right
+              if (AOP_TYPE (right) == AOP_LIT)
+                {
+                  bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
+                  if (bytelit == 0)
+                    {
+                      aopPut (result,
+                              aopGet (left, offset, FALSE, FALSE),
+                              offset);
+                      continue;
+                    }
+                }
+              // faster than result <- left, anl result,right
+              // and better if result is SFR
+              if (AOP_TYPE (left) == AOP_ACC)
+                {
+                  if (offset)
+                    emitcode("mov", "a,b");
+                  emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                }
+              else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
+                {
+                  emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  emitcode ("xrl", "a,b");
+                }
+              else if (aopGetUsesAcc (left, offset))
+                {
+                  MOVA (aopGet (left, offset, FALSE, FALSE));
+                  emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                }
+              else
+                {
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
+                }
+              aopPut (result, "a", offset);
+            }
+        }
+    }
+
+release:
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+}
+
+/*-----------------------------------------------------------------*/
+/* genInline - write the inline code out                           */
+/*-----------------------------------------------------------------*/
+static void
+genInline (iCode * ic)
+{
+  char *buffer, *bp, *bp1;
+
+  D (emitcode (";", "genInline"));
+
+  _G.inLine += (!options.asmpeep);
+
+  buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
+
+  /* emit each line as a code */
+  while (*bp)
+    {
+      if (*bp == '\n')
+        {
+          *bp++ = '\0';
+          emitcode (bp1, "");
+          bp1 = bp;
+        }
+      else
+        {
+          /* Add \n for labels, not dirs such as c:\mydir */
+          if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
+            {
+              bp++;
+              *bp = '\0';
+              bp++;
+              emitcode (bp1, "");
+              bp1 = bp;
+            }
+          else
+            bp++;
+        }
+    }
+  if (bp1 != bp)
+    emitcode (bp1, "");
+  /*     emitcode("",buffer); */
+  _G.inLine -= (!options.asmpeep);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRRC - rotate right with carry                                */
+/*-----------------------------------------------------------------*/
+static void
+genRRC (iCode * ic)
+{
+  operand *left, *result;
+  int size, offset;
+  char *l;
+
+  D (emitcode (";", "genRRC"));
+
+  /* rotate right with carry */
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, FALSE);
+
+  /* move it to the result */
+  size = AOP_SIZE (result);
+  offset = size - 1;
+  if (size == 1) { /* special case for 1 byte */
+      l = aopGet (left, offset, FALSE, FALSE);
+      MOVA (l);
+      emitcode ("rr", "a");
+      goto release;
+  }
+  /* no need to clear carry, bit7 will be written later */
+  while (size--)
+    {
+      l = aopGet (left, offset, FALSE, FALSE);
+      MOVA (l);
+      emitcode ("rrc", "a");
+      if (AOP_SIZE (result) > 1)
+        aopPut (result, "a", offset--);
+    }
+  /* now we need to put the carry into the
+     highest order byte of the result */
+  if (AOP_SIZE (result) > 1)
+    {
+      l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
+      MOVA (l);
+    }
+  emitcode ("mov", "acc.7,c");
+ release:
+  aopPut (result, "a", AOP_SIZE (result) - 1);
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRLC - generate code for rotate left with carry               */
+/*-----------------------------------------------------------------*/
+static void
+genRLC (iCode * ic)
+{
+  operand *left, *result;
+  int size, offset;
+  char *l;
+
+  D (emitcode (";", "genRLC"));
+
+  /* rotate right with carry */
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, FALSE);
+
+  /* move it to the result */
+  size = AOP_SIZE (result);
+  offset = 0;
+  if (size--)
+    {
+      l = aopGet (left, offset, FALSE, FALSE);
+      MOVA (l);
+      if (size == 0) { /* special case for 1 byte */
+              emitcode("rl","a");
+              goto release;
+      }
+      emitcode("rlc","a"); /* bit0 will be written later */
+      if (AOP_SIZE (result) > 1)
+        {
+          aopPut (result, "a", offset++);
+        }
+
+      while (size--)
+        {
+          l = aopGet (left, offset, FALSE, FALSE);
+          MOVA (l);
+          emitcode ("rlc", "a");
+          if (AOP_SIZE (result) > 1)
+            aopPut (result, "a", offset++);
+        }
+    }
+  /* now we need to put the carry into the
+     highest order byte of the result */
+  if (AOP_SIZE (result) > 1)
+    {
+      l = aopGet (result, 0, FALSE, FALSE);
+      MOVA (l);
+    }
+  emitcode ("mov", "acc.0,c");
+ release:
+  aopPut (result, "a", 0);
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genGetHbit - generates code get highest order bit               */
+/*-----------------------------------------------------------------*/
+static void
+genGetHbit (iCode * ic)
+{
+  operand *left, *result;
+
+  D (emitcode (";", "genGetHbit"));
+
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, FALSE);
+
+  /* get the highest order byte into a */
+  MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
+  if (AOP_TYPE (result) == AOP_CRY)
+    {
+      emitcode ("rlc", "a");
+      outBitC (result);
+    }
+  else
+    {
+      emitcode ("rl", "a");
+      emitcode ("anl", "a,#0x01");
+      outAcc (result);
+    }
+
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genGetAbit - generates code get a single bit                    */
+/*-----------------------------------------------------------------*/
+static void
+genGetAbit (iCode * ic)
+{
+  operand *left, *right, *result;
+  int shCount;
+
+  D (emitcode (";", "genGetAbit"));
+
+  left = IC_LEFT (ic);
+  right = IC_RIGHT (ic);
+  result = IC_RESULT (ic);
+  aopOp (left, ic, FALSE);
+  aopOp (right, ic, FALSE);
+  aopOp (result, ic, FALSE);
+
+  shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+
+  /* get the needed byte into a */
+  MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
+  shCount %= 8;
+  if (AOP_TYPE (result) == AOP_CRY)
+    {
+      if ((shCount) == 7)
+          emitcode ("rlc", "a");
+      else if ((shCount) == 0)
+          emitcode ("rrc", "a");
+      else
+          emitcode ("mov", "c,acc[%d]", shCount);
+      outBitC (result);
+    }
+  else
+    {
+      switch (shCount)
+        {
+        case 2:
+          emitcode ("rr", "a");
+          //fallthrough
+        case 1:
+          emitcode ("rr", "a");
+          //fallthrough
+        case 0:
+          emitcode ("anl", "a,#0x01");
+          break;
+        case 3:
+        case 5:
+          emitcode ("mov", "c,acc[%d]", shCount);
+          emitcode ("clr", "a");
+          emitcode ("rlc", "a");
+          break;
+        case 4:
+          emitcode ("swap", "a");
+          emitcode ("anl", "a,#0x01");
+          break;
+        case 6:
+          emitcode ("rl", "a");
+          //fallthrough
+        case 7:
+          emitcode ("rl", "a");
+          emitcode ("anl", "a,#0x01");
+          break;
+        }
+      outAcc (result);
+    }
+
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genGetByte - generates code get a single byte                   */
+/*-----------------------------------------------------------------*/
+static void
+genGetByte (iCode * ic)
+{
+  operand *left, *right, *result;
+  int offset;
+
+  D (emitcode (";", "genGetByte"));
+
+  left = IC_LEFT (ic);
+  right = IC_RIGHT (ic);
+  result = IC_RESULT (ic);
+  aopOp (left, ic, FALSE);
+  aopOp (right, ic, FALSE);
+  aopOp (result, ic, FALSE);
+
+  offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
+  aopPut (result,
+          aopGet (left, offset, FALSE, FALSE),
+          0);
+
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genGetWord - generates code get two bytes                       */
+/*-----------------------------------------------------------------*/
+static void
+genGetWord (iCode * ic)
+{
+  operand *left, *right, *result;
+  int offset;
+
+  D (emitcode (";", "genGetWord"));
+
+  left = IC_LEFT (ic);
+  right = IC_RIGHT (ic);
+  result = IC_RESULT (ic);
+  aopOp (left, ic, FALSE);
+  aopOp (right, ic, FALSE);
+  aopOp (result, ic, FALSE);
+
+  offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
+  aopPut (result,
+          aopGet (left, offset, FALSE, FALSE),
+          0);
+  aopPut (result,
+          aopGet (left, offset+1, FALSE, FALSE),
+          1);
+
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genSwap - generates code to swap nibbles or bytes               */
+/*-----------------------------------------------------------------*/
+static void
+genSwap (iCode * ic)
+{
+  operand *left, *result;
+
+  D(emitcode (";     genSwap",""));
+
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, FALSE);
+
+  switch (AOP_SIZE (left))
+    {
+    case 1: /* swap nibbles in byte */
+      MOVA (aopGet (left, 0, FALSE, FALSE));
+      emitcode ("swap", "a");
+      aopPut (result, "a", 0);
+      break;
+    case 2: /* swap bytes in word */
+      if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
+        {
+          MOVA (aopGet (left, 0, FALSE, FALSE));
+          aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
+          aopPut (result, "a", 1);
+        }
+      else if (operandsEqu (left, result))
+        {
+          char * reg = "a";
+          bool pushedB = FALSE, leftInB = FALSE;
+
+          MOVA (aopGet (left, 0, FALSE, FALSE));
+          if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
+            {
+              pushedB = pushB ();
+              emitcode ("mov", "b,a");
+              reg = "b";
+              leftInB = TRUE;
+            }
+          aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
+          aopPut (result, reg, 1);
+
+          if (leftInB)
+            popB (pushedB);
+        }
+      else
+        {
+          aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
+          aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
+        }
+      break;
+    default:
+      wassertl(FALSE, "unsupported SWAP operand size");
+    }
+
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* 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 ("swap", "a");
+      emitcode ("rr", "a");
+      break;
+    case 4:
+      emitcode ("swap", "a");
+      break;
+    case 5:
+      emitcode ("swap", "a");
+      emitcode ("rl", "a");
+      break;
+    case 6:
+      emitcode ("rr", "a");
+      emitcode ("rr", "a");
+      break;
+    case 7:
+      emitcode ("rr", "a");
+      break;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccLsh - left shift accumulator by known count                  */
+/*-----------------------------------------------------------------*/
+static void
+AccLsh (int shCount)
+{
+  if (shCount != 0)
+    {
+      if (shCount == 1)
+        emitcode ("add", "a,acc");
+      else if (shCount == 2)
+        {
+          emitcode ("add", "a,acc");
+          emitcode ("add", "a,acc");
+        }
+      else
+        {
+          /* rotate left accumulator */
+          AccRol (shCount);
+          /* and kill the lower order bits */
+          emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccRsh - right shift accumulator by known count                 */
+/*-----------------------------------------------------------------*/
+static void
+AccRsh (int shCount)
+{
+  if (shCount != 0)
+    {
+      if (shCount == 1)
+        {
+          CLRC;
+          emitcode ("rrc", "a");
+        }
+      else
+        {
+          /* rotate right accumulator */
+          AccRol (8 - shCount);
+          /* and kill the higher order bits */
+          emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccSRsh - signed right shift accumulator by known count                 */
+/*-----------------------------------------------------------------*/
+static void
+AccSRsh (int shCount)
+{
+  symbol *tlbl;
+  if (shCount != 0)
+    {
+      if (shCount == 1)
+        {
+          emitcode ("mov", "c,acc.7");
+          emitcode ("rrc", "a");
+        }
+      else if (shCount == 2)
+        {
+          emitcode ("mov", "c,acc.7");
+          emitcode ("rrc", "a");
+          emitcode ("mov", "c,acc.7");
+          emitcode ("rrc", "a");
+        }
+      else
+        {
+          tlbl = newiTempLabel (NULL);
+          /* rotate right accumulator */
+          AccRol (8 - shCount);
+          /* and kill the higher order bits */
+          emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
+          emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
+          emitcode ("orl", "a,#0x%02x",
+                    (unsigned char) ~SRMask[shCount]);
+          emitLabel (tlbl);
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftR1Left2Result - shift right one byte from left to result   */
+/*-----------------------------------------------------------------*/
+static void
+shiftR1Left2Result (operand * left, int offl,
+                    operand * result, int offr,
+                    int shCount, int sign)
+{
+  MOVA (aopGet (left, offl, FALSE, FALSE));
+  /* shift right accumulator */
+  if (sign)
+    AccSRsh (shCount);
+  else
+    AccRsh (shCount);
+  aopPut (result, "a", offr);
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftL1Left2Result - shift left one byte from left to result    */
+/*-----------------------------------------------------------------*/
+static void
+shiftL1Left2Result (operand * left, int offl,
+                    operand * result, int offr, int shCount)
+{
+  char *l;
+  l = aopGet (left, offl, FALSE, FALSE);
+  MOVA (l);
+  /* shift left accumulator */
+  AccLsh (shCount);
+  aopPut (result, "a", offr);
+}
+
+/*-----------------------------------------------------------------*/
+/* movLeft2Result - move byte from left to result                  */
+/*-----------------------------------------------------------------*/
+static void
+movLeft2Result (operand * left, int offl,
+                operand * result, int offr, int sign)
+{
+  char *l;
+  if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
+    {
+      l = aopGet (left, offl, FALSE, FALSE);
+
+      if (*l == '@' && (IS_AOP_PREG (result)))
+        {
+          emitcode ("mov", "a,%s", l);
+          aopPut (result, "a", offr);
+        }
+      else
+        {
+          if (!sign)
+            {
+              aopPut (result, l, offr);
+            }
+          else
+            {
+              /* MSB sign in acc.7 ! */
+              if (getDataSize (left) == offl + 1)
+                {
+                  MOVA (l);
+                  aopPut (result, "a", offr);
+                }
+            }
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXRrl1 - right rotate c->a:x->c by 1                         */
+/*-----------------------------------------------------------------*/
+static void
+AccAXRrl1 (char *x)
+{
+  emitcode ("rrc", "a");
+  emitcode ("xch", "a,%s", x);
+  emitcode ("rrc", "a");
+  emitcode ("xch", "a,%s", x);
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
+/*-----------------------------------------------------------------*/
+static void
+AccAXLrl1 (char *x)
+{
+  emitcode ("xch", "a,%s", x);
+  emitcode ("rlc", "a");
+  emitcode ("xch", "a,%s", x);
+  emitcode ("rlc", "a");
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXLsh1 - left shift a:x<-0 by 1                              */
+/*-----------------------------------------------------------------*/
+static void
+AccAXLsh1 (char *x)
+{
+  emitcode ("xch", "a,%s", x);
+  emitcode ("add", "a,acc");
+  emitcode ("xch", "a,%s", x);
+  emitcode ("rlc", "a");
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXLsh - left shift a:x by known count (0..7)                 */
+/*-----------------------------------------------------------------*/
+static void
+AccAXLsh (char *x, int shCount)
+{
+  switch (shCount)
+    {
+    case 0:
+      break;
+    case 1:
+      AccAXLsh1 (x);
+      break;
+    case 2:
+      AccAXLsh1 (x);
+      AccAXLsh1 (x);
+      break;
+    case 3:
+    case 4:
+    case 5:                     // AAAAABBB:CCCCCDDD
+
+      AccRol (shCount);         // BBBAAAAA:CCCCCDDD
+
+      emitcode ("anl", "a,#0x%02x",
+                SLMask[shCount]);       // BBB00000:CCCCCDDD
+
+      emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
+
+      AccRol (shCount);         // DDDCCCCC:BBB00000
+
+      emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
+
+      emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
+
+      emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
+
+      emitcode ("anl", "a,#0x%02x",
+                SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
+
+      emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
+
+      emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
+
+      break;
+    case 6:                     // AAAAAABB:CCCCCCDD
+      emitcode ("anl", "a,#0x%02x",
+                SRMask[shCount]);       // 000000BB:CCCCCCDD
+      emitcode ("mov", "c,acc.0");      // c = B
+      emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
+#if 0 // REMOVE ME
+      AccAXRrl1 (x);            // BCCCCCCD:D000000B
+      AccAXRrl1 (x);            // BBCCCCCC:DD000000
+#else
+      emitcode("rrc","a");
+      emitcode("xch","a,%s", x);
+      emitcode("rrc","a");
+      emitcode("mov","c,acc.0"); //<< get correct bit
+      emitcode("xch","a,%s", x);
+
+      emitcode("rrc","a");
+      emitcode("xch","a,%s", x);
+      emitcode("rrc","a");
+      emitcode("xch","a,%s", x);
+#endif
+      break;
+    case 7:                     // a:x <<= 7
+
+      emitcode ("anl", "a,#0x%02x",
+                SRMask[shCount]);       // 0000000B:CCCCCCCD
+
+      emitcode ("mov", "c,acc.0");      // c = B
+
+      emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
+
+      AccAXRrl1 (x);            // BCCCCCCC:D0000000
+
+      break;
+    default:
+      break;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXRsh - right shift a:x known count (0..7)                   */
+/*-----------------------------------------------------------------*/
+static void
+AccAXRsh (char *x, int shCount)
+{
+  switch (shCount)
+    {
+    case 0:
+      break;
+    case 1:
+      CLRC;
+      AccAXRrl1 (x);            // 0->a:x
+
+      break;
+    case 2:
+      CLRC;
+      AccAXRrl1 (x);            // 0->a:x
+
+      CLRC;
+      AccAXRrl1 (x);            // 0->a:x
+
+      break;
+    case 3:
+    case 4:
+    case 5:                     // AAAAABBB:CCCCCDDD = a:x
+
+      AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
+
+      emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
+
+      AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
+
+      emitcode ("anl", "a,#0x%02x",
+                SRMask[shCount]);       // 000CCCCC:BBBAAAAA
+
+      emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
+
+      emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
+
+      emitcode ("anl", "a,#0x%02x",
+                SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
+
+      emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
+
+      emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
+
+      emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
+
+      break;
+    case 6:                     // AABBBBBB:CCDDDDDD
+
+      emitcode ("mov", "c,acc.7");
+      AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
+
+      emitcode ("mov", "c,acc.7");
+      AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
+
+      emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
+
+      emitcode ("anl", "a,#0x%02x",
+                SRMask[shCount]);       // 000000AA:BBBBBBCC
+
+      break;
+    case 7:                     // ABBBBBBB:CDDDDDDD
+
+      emitcode ("mov", "c,acc.7");      // c = A
+
+      AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
+
+      emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
+
+      emitcode ("anl", "a,#0x%02x",
+                SRMask[shCount]);       // 0000000A:BBBBBBBC
+
+      break;
+    default:
+      break;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXRshS - right shift signed a:x known count (0..7)           */
+/*-----------------------------------------------------------------*/
+static void
+AccAXRshS (char *x, int shCount)
+{
+  symbol *tlbl;
+  switch (shCount)
+    {
+    case 0:
+      break;
+    case 1:
+      emitcode ("mov", "c,acc.7");
+      AccAXRrl1 (x);            // s->a:x
+
+      break;
+    case 2:
+      emitcode ("mov", "c,acc.7");
+      AccAXRrl1 (x);            // s->a:x
+
+      emitcode ("mov", "c,acc.7");
+      AccAXRrl1 (x);            // s->a:x
+
+      break;
+    case 3:
+    case 4:
+    case 5:                     // AAAAABBB:CCCCCDDD = a:x
+
+      tlbl = newiTempLabel (NULL);
+      AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
+
+      emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
+
+      AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
+
+      emitcode ("anl", "a,#0x%02x",
+                SRMask[shCount]);       // 000CCCCC:BBBAAAAA
+
+      emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
+
+      emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
+
+      emitcode ("anl", "a,#0x%02x",
+                SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
+
+      emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
+
+      emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
+
+      emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
+
+      emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
+      emitcode ("orl", "a,#0x%02x",
+                (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
+
+      emitLabel (tlbl);
+      break;                    // SSSSAAAA:BBBCCCCC
+
+    case 6:                     // AABBBBBB:CCDDDDDD
+
+      tlbl = newiTempLabel (NULL);
+      emitcode ("mov", "c,acc.7");
+      AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
+
+      emitcode ("mov", "c,acc.7");
+      AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
+
+      emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
+
+      emitcode ("anl", "a,#0x%02x",
+                SRMask[shCount]);       // 000000AA:BBBBBBCC
+
+      emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
+      emitcode ("orl", "a,#0x%02x",
+                (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
+
+      emitLabel (tlbl);
+      break;
+    case 7:                     // ABBBBBBB:CDDDDDDD
+
+      tlbl = newiTempLabel (NULL);
+      emitcode ("mov", "c,acc.7");      // c = A
+
+      AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
+
+      emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
+
+      emitcode ("anl", "a,#0x%02x",
+                SRMask[shCount]);       // 0000000A:BBBBBBBC
+
+      emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
+      emitcode ("orl", "a,#0x%02x",
+                (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
+
+      emitLabel (tlbl);
+      break;
+    default:
+      break;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftL2Left2Result - shift left two bytes from left to result   */
+/*-----------------------------------------------------------------*/
+static void
+shiftL2Left2Result (operand * left, int offl,
+                    operand * result, int offr, int shCount)
+{
+  char * x;
+  bool pushedB = FALSE;
+  bool usedB = FALSE;
+
+  if (sameRegs (AOP (result), AOP (left)) &&
+      ((offl + MSB16) == offr))
+    {
+      /* don't crash result[offr] */
+      MOVA (aopGet (left, offl, FALSE, FALSE));
+      x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
+      usedB = !strncmp(x, "b", 1);
+    }
+  else if (aopGetUsesAcc (result, offr))
+    {
+      movLeft2Result (left, offl, result, offr, 0);
+      pushedB = pushB ();
+      usedB = TRUE;
+      emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
+      MOVA (aopGet (result, offr, FALSE, FALSE));
+      emitcode ("xch", "a,b");
+      x = "b";
+    }
+  else
+    {
+      movLeft2Result (left, offl, result, offr, 0);
+      MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
+      x = aopGet (result, offr, FALSE, FALSE);
+    }
+  /* ax << shCount (x = lsb(result)) */
+  AccAXLsh (x, shCount);
+  if (usedB)
+    {
+      emitcode ("xch", "a,b");
+      aopPut (result, "a", offr);
+      aopPut (result, "b", offr + MSB16);
+      popB (pushedB);
+    }
+  else
+    {
+      aopPut (result, "a", offr + MSB16);
+    }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* shiftR2Left2Result - shift right two bytes from left to result  */
+/*-----------------------------------------------------------------*/
+static void
+shiftR2Left2Result (operand * left, int offl,
+                    operand * result, int offr,
+                    int shCount, int sign)
+{
+  char * x;
+  bool pushedB = FALSE;
+  bool usedB = FALSE;
+
+  if (sameRegs (AOP (result), AOP (left)) &&
+      ((offl + MSB16) == offr))
+    {
+      /* don't crash result[offr] */
+      MOVA (aopGet (left, offl, FALSE, FALSE));
+      x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
+      usedB = !strncmp(x, "b", 1);
+    }
+  else if (aopGetUsesAcc (result, offr))
+    {
+      movLeft2Result (left, offl, result, offr, 0);
+      pushedB = pushB ();
+      usedB = TRUE;
+      emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
+      MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
+      x = "b";
+    }
+  else
+    {
+      movLeft2Result (left, offl, result, offr, 0);
+      MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
+      x = aopGet (result, offr, FALSE, FALSE);
+    }
+  /* a:x >> shCount (x = lsb(result)) */
+  if (sign)
+    AccAXRshS (x, shCount);
+  else
+    AccAXRsh (x, shCount);
+  if (usedB)
+    {
+      emitcode ("xch", "a,b");
+      aopPut (result, "a", offr);
+      emitcode ("xch", "a,b");
+      popB (pushedB);
+    }
+  if (getDataSize (result) > 1)
+    aopPut (result, "a", offr + MSB16);
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftLLeftOrResult - shift left one byte from left, or to result */
+/*-----------------------------------------------------------------*/
+static void
+shiftLLeftOrResult (operand * left, int offl,
+                    operand * result, int offr, int shCount)
+{
+  MOVA (aopGet (left, offl, FALSE, FALSE));
+  /* shift left accumulator */
+  AccLsh (shCount);
+  /* or with result */
+  if (aopGetUsesAcc (result, offr))
+    {
+      emitcode ("xch", "a,b");
+      MOVA (aopGet (result, offr, FALSE, FALSE));
+      emitcode ("orl", "a,b");
+    }
+  else
+    {
+      emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
+    }
+  /* back to result */
+  aopPut (result, "a", offr);
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftRLeftOrResult - shift right one byte from left,or to result */
+/*-----------------------------------------------------------------*/
+static void
+shiftRLeftOrResult (operand * left, int offl,
+                    operand * result, int offr, int shCount)
+{
+  MOVA (aopGet (left, offl, FALSE, FALSE));
+  /* shift right accumulator */
+  AccRsh (shCount);
+  /* or with result */
+  if (aopGetUsesAcc(result, offr))
+    {
+      emitcode ("xch", "a,b");
+      MOVA (aopGet (result, offr, FALSE, FALSE));
+      emitcode ("orl", "a,b");
+    }
+  else
+    {
+      emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
+    }
+  /* back to result */
+  aopPut (result, "a", offr);
+}
+
+/*-----------------------------------------------------------------*/
+/* genlshOne - left shift a one byte quantity by known count       */
+/*-----------------------------------------------------------------*/
+static void
+genlshOne (operand * result, operand * left, int shCount)
+{
+  D (emitcode (";", "genlshOne"));
+
+  shiftL1Left2Result (left, LSB, result, LSB, shCount);
+}
+
+/*-----------------------------------------------------------------*/
+/* genlshTwo - left shift two bytes by known amount != 0           */
+/*-----------------------------------------------------------------*/
+static void
+genlshTwo (operand * result, operand * left, int shCount)
+{
+  int size;
+
+  D (emitcode (";", "genlshTwo"));
+
+  size = getDataSize (result);
+
+  /* if shCount >= 8 */
+  if (shCount >= 8)
+    {
+      shCount -= 8;
+
+      if (size > 1)
+        {
+          if (shCount)
+            shiftL1Left2Result (left, LSB, result, MSB16, shCount);
+          else
+            movLeft2Result (left, LSB, result, MSB16, 0);
+        }
+      aopPut (result, zero, LSB);
+    }
+
+  /*  1 <= shCount <= 7 */
+  else
+    {
+      if (size == 1)
+        shiftL1Left2Result (left, LSB, result, LSB, shCount);
+      else
+        shiftL2Left2Result (left, LSB, result, LSB, shCount);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftLLong - shift left one long from left to result            */
+/* offl = LSB or MSB16                                             */
+/*-----------------------------------------------------------------*/
+static void
+shiftLLong (operand * left, operand * result, int offr)
+{
+  char *l;
+  int size = AOP_SIZE (result);
+
+  if (size >= LSB + offr)
+    {
+      l = aopGet (left, LSB, FALSE, FALSE);
+      MOVA (l);
+      emitcode ("add", "a,acc");
+      if (sameRegs (AOP (left), AOP (result)) &&
+          size >= MSB16 + offr && offr != LSB)
+        xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
+      else
+        aopPut (result, "a", LSB + offr);
+    }
+
+  if (size >= MSB16 + offr)
+    {
+      if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
+        {
+          l = aopGet (left, MSB16, FALSE, FALSE);
+          MOVA (l);
+        }
+      emitcode ("rlc", "a");
+      if (sameRegs (AOP (left), AOP (result)) &&
+          size >= MSB24 + offr && offr != LSB)
+        xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
+      else
+        aopPut (result, "a", MSB16 + offr);
+    }
+
+  if (size >= MSB24 + offr)
+    {
+      if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
+        {
+          l = aopGet (left, MSB24, FALSE, FALSE);
+          MOVA (l);
+        }
+      emitcode ("rlc", "a");
+      if (sameRegs (AOP (left), AOP (result)) &&
+          size >= MSB32 + offr && offr != LSB)
+        xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
+      else
+        aopPut (result, "a", MSB24 + offr);
+    }
+
+  if (size > MSB32 + offr)
+    {
+      if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
+        {
+          l = aopGet (left, MSB32, FALSE, FALSE);
+          MOVA (l);
+        }
+      emitcode ("rlc", "a");
+      aopPut (result, "a", MSB32 + offr);
+    }
+  if (offr != LSB)
+    aopPut (result, zero, LSB);
+}
+
+/*-----------------------------------------------------------------*/
+/* genlshFour - shift four byte by a known amount != 0             */
+/*-----------------------------------------------------------------*/
+static void
+genlshFour (operand * result, operand * left, int shCount)
+{
+  int size;
+
+  D (emitcode (";", "genlshFour"));
+
+  size = AOP_SIZE (result);
+
+  /* if shifting more that 3 bytes */
+  if (shCount >= 24)
+    {
+      shCount -= 24;
+      if (shCount)
+        /* lowest order of left goes to the highest
+           order of the destination */
+        shiftL1Left2Result (left, LSB, result, MSB32, shCount);
+      else
+        movLeft2Result (left, LSB, result, MSB32, 0);
+      aopPut (result, zero, LSB);
+      aopPut (result, zero, MSB16);
+      aopPut (result, zero, MSB24);
+      return;
+    }
+
+  /* more than two bytes */
+  else if (shCount >= 16)
+    {
+      /* lower order two bytes goes to higher order two bytes */
+      shCount -= 16;
+      /* if some more remaining */
+      if (shCount)
+        shiftL2Left2Result (left, LSB, result, MSB24, shCount);
+      else
+        {
+          movLeft2Result (left, MSB16, result, MSB32, 0);
+          movLeft2Result (left, LSB, result, MSB24, 0);
+        }
+      aopPut (result, zero, MSB16);
+      aopPut (result, zero, LSB);
+      return;
+    }
+
+  /* if more than 1 byte */
+  else if (shCount >= 8)
+    {
+      /* lower order three bytes goes to higher order  three bytes */
+      shCount -= 8;
+      if (size == 2)
+        {
+          if (shCount)
+            shiftL1Left2Result (left, LSB, result, MSB16, shCount);
+          else
+            movLeft2Result (left, LSB, result, MSB16, 0);
+        }
+      else
+        {                       /* size = 4 */
+          if (shCount == 0)
+            {
+              movLeft2Result (left, MSB24, result, MSB32, 0);
+              movLeft2Result (left, MSB16, result, MSB24, 0);
+              movLeft2Result (left, LSB, result, MSB16, 0);
+              aopPut (result, zero, LSB);
+            }
+          else if (shCount == 1)
+            shiftLLong (left, result, MSB16);
+          else
+            {
+              shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
+              shiftL1Left2Result (left, LSB, result, MSB16, shCount);
+              shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
+              aopPut (result, zero, LSB);
+            }
+        }
+    }
+
+  /* 1 <= shCount <= 7 */
+  else if (shCount <= 2)
+    {
+      shiftLLong (left, result, LSB);
+      if (shCount == 2)
+        shiftLLong (result, result, LSB);
+    }
+  /* 3 <= shCount <= 7, optimize */
+  else
+    {
+      shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
+      shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
+      shiftL2Left2Result (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;
+
+  D (emitcode (";", "genLeftShiftLiteral"));
+
+  freeAsmop (right, NULL, ic, TRUE);
+
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, FALSE);
+
+  size = getSize (operandType (result));
+
+#if VIEW_SIZE
+  emitcode ("; shift left ", "result %d, left %d", size,
+            AOP_SIZE (left));
+#endif
+
+  /* I suppose that the left size >= result size */
+  if (shCount == 0)
+    {
+      while (size--)
+        {
+          movLeft2Result (left, size, result, size, 0);
+        }
+    }
+  else if (shCount >= (size * 8))
+    {
+      while (size--)
+        {
+          aopPut (result, zero, size);
+        }
+    }
+  else
+    {
+      switch (size)
+        {
+        case 1:
+          genlshOne (result, left, shCount);
+          break;
+
+        case 2:
+          genlshTwo (result, left, shCount);
+          break;
+
+        case 4:
+          genlshFour (result, left, shCount);
+          break;
+        default:
+          werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                  "*** ack! mystery literal shift!\n");
+          break;
+        }
+    }
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genLeftShift - generates code for left shifting                 */
+/*-----------------------------------------------------------------*/
+static void
+genLeftShift (iCode * ic)
+{
+  operand *left, *right, *result;
+  int size, offset;
+  char *l;
+  symbol *tlbl, *tlbl1;
+  bool pushedB;
+
+  D (emitcode (";", "genLeftShift"));
+
+  right = IC_RIGHT (ic);
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+
+  aopOp (right, ic, 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 ) */
+
+  pushedB = pushB ();
+  MOVB (aopGet (right, 0, FALSE, FALSE));
+  emitcode ("inc", "b");
+  freeAsmop (right, NULL, ic, TRUE);
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, 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 (left, offset, FALSE, TRUE);
+          if (*l == '@' && (IS_AOP_PREG (result)))
+            {
+
+              emitcode ("mov", "a,%s", l);
+              aopPut (result, "a", offset);
+            }
+          else
+            aopPut (result, l, offset);
+          offset++;
+        }
+    }
+
+  tlbl = newiTempLabel (NULL);
+  size = AOP_SIZE (result);
+  offset = 0;
+  tlbl1 = newiTempLabel (NULL);
+
+  /* if it is only one byte then */
+  if (size == 1)
+    {
+      symbol *tlbl1 = newiTempLabel (NULL);
+
+      l = aopGet (left, 0, FALSE, FALSE);
+      MOVA (l);
+      emitcode ("sjmp", "%05d$", tlbl1->key + 100);
+      emitLabel (tlbl);
+      emitcode ("add", "a,acc");
+      emitLabel (tlbl1);
+      emitcode ("djnz", "b,%05d$", tlbl->key + 100);
+      popB (pushedB);
+      aopPut (result, "a", 0);
+      goto release;
+    }
+
+  reAdjustPreg (AOP (result));
+
+  emitcode ("sjmp", "%05d$", tlbl1->key + 100);
+  emitLabel (tlbl);
+  l = aopGet (result, offset, FALSE, FALSE);
+  MOVA (l);
+  emitcode ("add", "a,acc");
+  aopPut (result, "a", offset++);
+  while (--size)
+    {
+      l = aopGet (result, offset, FALSE, FALSE);
+      MOVA (l);
+      emitcode ("rlc", "a");
+      aopPut (result, "a", offset++);
+    }
+  reAdjustPreg (AOP (result));
+
+  emitLabel (tlbl1);
+  emitcode ("djnz", "b,%05d$", tlbl->key + 100);
+  popB (pushedB);
+release:
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genrshOne - right shift a one byte quantity by known count      */
+/*-----------------------------------------------------------------*/
+static void
+genrshOne (operand * result, operand * left,
+           int shCount, int sign)
+{
+  D (emitcode (";", "genrshOne"));
+
+  shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
+}
+
+/*-----------------------------------------------------------------*/
+/* genrshTwo - right shift two bytes by known amount != 0          */
+/*-----------------------------------------------------------------*/
+static void
+genrshTwo (operand * result, operand * left,
+           int shCount, int sign)
+{
+  D (emitcode (";", "genrshTwo"));
+
+  /* if shCount >= 8 */
+  if (shCount >= 8)
+    {
+      shCount -= 8;
+      if (shCount)
+        shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
+      else
+        movLeft2Result (left, MSB16, result, LSB, sign);
+      addSign (result, MSB16, sign);
+    }
+
+  /*  1 <= shCount <= 7 */
+  else
+    shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftRLong - shift right one long from left to result           */
+/* offl = LSB or MSB16                                             */
+/*-----------------------------------------------------------------*/
+static void
+shiftRLong (operand * left, int offl,
+            operand * result, int sign)
+{
+  bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
+
+  if (overlapping && offl>1)
+    {
+      // we are in big trouble, but this shouldn't happen
+      werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
+    }
+
+  MOVA (aopGet (left, MSB32, FALSE, FALSE));
+
+  if (offl==MSB16)
+    {
+      // shift is > 8
+      if (sign)
+        {
+          emitcode ("rlc", "a");
+          emitcode ("subb", "a,acc");
+          if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
+            {
+              xch_a_aopGet (left, MSB32, FALSE, FALSE);
+            }
+          else
+            {
+              aopPut (result, "a", MSB32);
+              MOVA (aopGet (left, MSB32, FALSE, FALSE));
+            }
+        }
+      else
+        {
+          if (aopPutUsesAcc (result, zero, MSB32))
+            {
+              emitcode("xch", "a,b");
+              aopPut (result, zero, MSB32);
+              emitcode("xch", "a,b");
+            }
+          else
+            {
+              aopPut (result, zero, MSB32);
+            }
+        }
+    }
+
+  if (!sign)
+    {
+      emitcode ("clr", "c");
+    }
+  else
+    {
+      emitcode ("mov", "c,acc.7");
+    }
+
+  emitcode ("rrc", "a");
+
+  if (overlapping && offl==MSB16 &&
+      sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
+    {
+      xch_a_aopGet (left, MSB24, FALSE, FALSE);
+    }
+  else
+    {
+      aopPut (result, "a", MSB32 - offl);
+      MOVA (aopGet (left, MSB24, FALSE, FALSE));
+    }
+
+  emitcode ("rrc", "a");
+  if (overlapping && offl==MSB16 &&
+      sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
+    {
+      xch_a_aopGet (left, MSB16, FALSE, FALSE);
+    }
+  else
+    {
+      aopPut (result, "a", MSB24 - offl);
+      MOVA (aopGet (left, MSB16, FALSE, FALSE));
+    }
+
+  emitcode ("rrc", "a");
+  if (offl != LSB)
+    {
+      aopPut (result, "a", MSB16 - offl);
+    }
+  else
+    {
+      if (overlapping &&
+          sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
+        {
+          xch_a_aopGet (left, LSB, FALSE, FALSE);
+        }
+      else
+        {
+          aopPut (result, "a", MSB16 - offl);
+          MOVA (aopGet (left, LSB, FALSE, FALSE));
+        }
+      emitcode ("rrc", "a");
+      aopPut (result, "a", LSB);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genrshFour - shift four byte by a known amount != 0             */
+/*-----------------------------------------------------------------*/
+static void
+genrshFour (operand * result, operand * left,
+            int shCount, int sign)
+{
+  D (emitcode (";", "genrshFour"));
+
+  /* if shifting more that 3 bytes */
+  if (shCount >= 24)
+    {
+      shCount -= 24;
+      if (shCount)
+        shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
+      else
+        movLeft2Result (left, MSB32, result, LSB, sign);
+      addSign (result, MSB16, sign);
+    }
+  else if (shCount >= 16)
+    {
+      shCount -= 16;
+      if (shCount)
+        shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
+      else
+        {
+          movLeft2Result (left, MSB24, result, LSB, 0);
+          movLeft2Result (left, MSB32, result, MSB16, sign);
+        }
+      addSign (result, MSB24, sign);
+    }
+  else if (shCount >= 8)
+    {
+      shCount -= 8;
+      if (shCount == 1)
+        {
+          shiftRLong (left, MSB16, result, sign);
+        }
+      else if (shCount == 0)
+        {
+          movLeft2Result (left, MSB16, result, LSB, 0);
+          movLeft2Result (left, MSB24, result, MSB16, 0);
+          movLeft2Result (left, MSB32, result, MSB24, sign);
+          addSign (result, MSB32, sign);
+        }
+      else
+        {
+          shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
+          shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
+          /* the last shift is signed */
+          shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
+          addSign (result, MSB32, sign);
+        }
+    }
+  else
+    {
+      /* 1 <= shCount <= 7 */
+      if (shCount <= 2)
+        {
+          shiftRLong (left, LSB, result, sign);
+          if (shCount == 2)
+            shiftRLong (result, LSB, result, sign);
+        }
+      else
+        {
+          shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
+          shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
+          shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genRightShiftLiteral - right 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;
+
+  D (emitcode (";", "genRightShiftLiteral"));
+
+  freeAsmop (right, NULL, ic, TRUE);
+
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, FALSE);
+
+#if VIEW_SIZE
+  emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
+            AOP_SIZE (left));
+#endif
+
+  size = getDataSize (left);
+  /* test the LEFT size !!! */
+
+  /* I suppose that the left size >= result size */
+  if (shCount == 0)
+    {
+      size = getDataSize (result);
+      while (size--)
+        movLeft2Result (left, size, result, size, 0);
+    }
+
+  else if (shCount >= (size * 8))
+    {
+      if (sign)
+        {
+          /* get sign in acc.7 */
+          MOVA (aopGet (left, size - 1, FALSE, FALSE));
+        }
+      addSign (result, LSB, sign);
+    }
+  else
+    {
+      switch (size)
+        {
+        case 1:
+          genrshOne (result, left, shCount, sign);
+          break;
+
+        case 2:
+          genrshTwo (result, left, shCount, sign);
+          break;
+
+        case 4:
+          genrshFour (result, left, shCount, sign);
+          break;
+        default:
+          break;
+        }
+    }
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genSignedRightShift - right shift of signed number              */
+/*-----------------------------------------------------------------*/
+static void
+genSignedRightShift (iCode * ic)
+{
+  operand *right, *left, *result;
+  int size, offset;
+  char *l;
+  symbol *tlbl, *tlbl1;
+  bool pushedB;
+
+  D (emitcode (";", "genSignedRightShift"));
+
+  /* we do it the hard way put the shift count in b
+     and loop thru preserving the sign */
+
+  right = IC_RIGHT (ic);
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+
+  aopOp (right, ic, FALSE);
+
+
+  if (AOP_TYPE (right) == AOP_LIT)
+    {
+      genRightShiftLiteral (left, right, result, ic, 1);
+      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 ) */
+
+  pushedB = pushB ();
+  MOVB (aopGet (right, 0, FALSE, FALSE));
+  emitcode ("inc", "b");
+  freeAsmop (right, NULL, ic, TRUE);
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, 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 (left, offset, FALSE, TRUE);
+          if (*l == '@' && IS_AOP_PREG (result))
+            {
+
+              emitcode ("mov", "a,%s", l);
+              aopPut (result, "a", offset);
+            }
+          else
+            aopPut (result, l, offset);
+          offset++;
+        }
+    }
+
+  /* mov the highest order bit to OVR */
+  tlbl = newiTempLabel (NULL);
+  tlbl1 = newiTempLabel (NULL);
+
+  size = AOP_SIZE (result);
+  offset = size - 1;
+  MOVA (aopGet (left, offset, FALSE, FALSE));
+  emitcode ("rlc", "a");
+  emitcode ("mov", "ov,c");
+  /* if it is only one byte then */
+  if (size == 1)
+    {
+      l = aopGet (left, 0, FALSE, FALSE);
+      MOVA (l);
+      emitcode ("sjmp", "%05d$", tlbl1->key + 100);
+      emitLabel (tlbl);
+      emitcode ("mov", "c,ov");
+      emitcode ("rrc", "a");
+      emitLabel (tlbl1);
+      emitcode ("djnz", "b,%05d$", tlbl->key + 100);
+      popB (pushedB);
+      aopPut (result, "a", 0);
+      goto release;
+    }
+
+  reAdjustPreg (AOP (result));
+  emitcode ("sjmp", "%05d$", tlbl1->key + 100);
+  emitLabel (tlbl);
+  emitcode ("mov", "c,ov");
+  while (size--)
+    {
+      l = aopGet (result, offset, FALSE, FALSE);
+      MOVA (l);
+      emitcode ("rrc", "a");
+      aopPut (result, "a", offset--);
+    }
+  reAdjustPreg (AOP (result));
+  emitLabel (tlbl1);
+  emitcode ("djnz", "b,%05d$", tlbl->key + 100);
+  popB (pushedB);
+
+release:
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRightShift - generate code for right shifting                */
 /*-----------------------------------------------------------------*/
-static void genRRC (iCode *ic)
+static void
+genRightShift (iCode * ic)
 {
-    operand *left , *result ;
-    int size, offset = 0;
-    char *l;    
+  operand *right, *left, *result;
+  sym_link *letype;
+  int size, offset;
+  char *l;
+  symbol *tlbl, *tlbl1;
+  bool pushedB;
 
-    /* rotate right with carry */
-    left = IC_LEFT(ic);
-    result=IC_RESULT(ic);
-    aopOp (left,ic,FALSE);
-    aopOp (result,ic,FALSE);
+  D (emitcode (";", "genRightShift"));
 
-    /* move it to the result */
-    size = AOP_SIZE(result);    
-    offset = size - 1 ;
-    CLRC;
-    while (size--) {
-        l = aopGet(AOP(left),offset,FALSE,FALSE);
-        MOVA(l);
-        emitcode("rrc","a");
-        if (AOP_SIZE(result) > 1)
-            aopPut(AOP(result),"a",offset--);
-    }
-    /* now we need to put the carry into the
-    highest order byte of the result */
-    if (AOP_SIZE(result) > 1) {
-        l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
-        MOVA(l);
+  /* if signed then we do it the hard way preserve the
+     sign bit moving it inwards */
+  letype = getSpec (operandType (IC_LEFT (ic)));
+
+  if (!SPEC_USIGN (letype))
+    {
+      genSignedRightShift (ic);
+      return;
     }
-    emitcode("mov","acc.7,c");
-    aopPut(AOP(result),"a",AOP_SIZE(result)-1);
-    freeAsmop(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
-}
 
-/*-----------------------------------------------------------------*/
-/* genRLC - generate code for rotate left with carry               */
-/*-----------------------------------------------------------------*/
-static void genRLC (iCode *ic)
-{    
-    operand *left , *result ;
-    int size, offset = 0;
-    char *l;    
-
-    /* rotate right with carry */
-    left = IC_LEFT(ic);
-    result=IC_RESULT(ic);
-    aopOp (left,ic,FALSE);
-    aopOp (result,ic,FALSE);
-
-    /* move it to the result */
-    size = AOP_SIZE(result);    
-    offset = 0 ;
-    if (size--) {
-        l = aopGet(AOP(left),offset,FALSE,FALSE);
-        MOVA(l);
-        emitcode("add","a,acc");
-        if (AOP_SIZE(result) > 1)
-            aopPut(AOP(result),"a",offset++);
-        while (size--) {
-            l = aopGet(AOP(left),offset,FALSE,FALSE);
-            MOVA(l);
-            emitcode("rlc","a");
-            if (AOP_SIZE(result) > 1)
-                aopPut(AOP(result),"a",offset++);
-        }
-    }
-    /* now we need to put the carry into the
-    highest order byte of the result */
-    if (AOP_SIZE(result) > 1) {
-        l = aopGet(AOP(result),0,FALSE,FALSE);
-        MOVA(l);
-    }
-    emitcode("mov","acc.0,c");
-    aopPut(AOP(result),"a",0);
-    freeAsmop(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
-}
+  /* 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 */
 
-/*-----------------------------------------------------------------*/
-/* genGetHbit - generates code get highest order bit               */
-/*-----------------------------------------------------------------*/
-static void genGetHbit (iCode *ic)
-{
-    operand *left, *result;
-    left = IC_LEFT(ic);
-    result=IC_RESULT(ic);
-    aopOp (left,ic,FALSE);
-    aopOp (result,ic,FALSE);
+  right = IC_RIGHT (ic);
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+
+  aopOp (right, ic, 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, 0);
+      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 ) */
+
+  pushedB = pushB ();
+  MOVB (aopGet (right, 0, FALSE, FALSE));
+  emitcode ("inc", "b");
+  freeAsmop (right, NULL, ic, TRUE);
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, 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 (left, offset, FALSE, TRUE);
+          if (*l == '@' && IS_AOP_PREG (result))
+            {
 
-    /* get the highest order byte into a */
-    MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
-    if(AOP_TYPE(result) == AOP_CRY){
-        emitcode("rlc","a");
-        outBitC(result);
+              emitcode ("mov", "a,%s", l);
+              aopPut (result, "a", offset);
+            }
+          else
+            aopPut (result, l, offset);
+          offset++;
+        }
     }
-    else{
-        emitcode("rl","a");
-        emitcode("anl","a,#0x01");
-        outAcc(result);
+
+  tlbl = newiTempLabel (NULL);
+  tlbl1 = newiTempLabel (NULL);
+  size = AOP_SIZE (result);
+  offset = size - 1;
+
+  /* if it is only one byte then */
+  if (size == 1)
+    {
+      l = aopGet (left, 0, FALSE, FALSE);
+      MOVA (l);
+      emitcode ("sjmp", "%05d$", tlbl1->key + 100);
+      emitLabel (tlbl);
+      CLRC;
+      emitcode ("rrc", "a");
+      emitLabel (tlbl1);
+      emitcode ("djnz", "b,%05d$", tlbl->key + 100);
+      popB (pushedB);
+      aopPut (result, "a", 0);
+      goto release;
+    }
+
+  reAdjustPreg (AOP (result));
+  emitcode ("sjmp", "%05d$", tlbl1->key + 100);
+  emitLabel (tlbl);
+  CLRC;
+  while (size--)
+    {
+      l = aopGet (result, offset, FALSE, FALSE);
+      MOVA (l);
+      emitcode ("rrc", "a");
+      aopPut (result, "a", offset--);
     }
+  reAdjustPreg (AOP (result));
 
+  emitLabel (tlbl1);
+  emitcode ("djnz", "b,%05d$", tlbl->key + 100);
+  popB (pushedB);
 
-    freeAsmop(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
+release:
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* AccRol - rotate left accumulator by known count                 */
+/* emitPtrByteGet - emits code to get a byte into A through a      */
+/*                  pointer register (R0, R1, or DPTR). The        */
+/*                  original value of A can be preserved in B.     */
 /*-----------------------------------------------------------------*/
-static void AccRol (int shCount)
+static void
+emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
 {
-    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("swap","a");
-            emitcode("rr","a");
-            break;
-        case 4 :
-            emitcode("swap","a");
-            break;
-        case 5 :
-            emitcode("swap","a");
-            emitcode("rl","a");
-            break;
-        case 6 :
-            emitcode("rr","a");
-            emitcode("rr","a");
-            break;
-        case 7 :
-            emitcode("rr","a");
-            break;
+  switch (p_type)
+    {
+    case IPOINTER:
+    case POINTER:
+      if (preserveAinB)
+        emitcode ("mov", "b,a");
+      emitcode ("mov", "a,@%s", rname);
+      break;
+
+    case PPOINTER:
+      if (preserveAinB)
+        emitcode ("mov", "b,a");
+      emitcode ("movx", "a,@%s", rname);
+      break;
+
+    case FPOINTER:
+      if (preserveAinB)
+        emitcode ("mov", "b,a");
+      emitcode ("movx", "a,@dptr");
+      break;
+
+    case CPOINTER:
+      if (preserveAinB)
+        emitcode ("mov", "b,a");
+      emitcode ("clr", "a");
+      emitcode ("movc", "a,@a+dptr");
+      break;
+
+    case GPOINTER:
+      if (preserveAinB)
+        {
+          emitcode ("push", "b");
+          emitcode ("push", "acc");
+        }
+      emitcode ("lcall", "__gptrget");
+      if (preserveAinB)
+        emitcode ("pop", "b");
+      break;
     }
 }
 
 /*-----------------------------------------------------------------*/
-/* AccLsh - left shift accumulator by known count                  */
+/* emitPtrByteSet - emits code to set a byte from src through a    */
+/*                  pointer register (R0, R1, or DPTR).            */
 /*-----------------------------------------------------------------*/
-static void AccLsh (int shCount)
+static void
+emitPtrByteSet (char *rname, int p_type, char *src)
 {
-    if(shCount != 0){
-        if(shCount == 1)
-            emitcode("add","a,acc");
-        else 
-           if(shCount == 2) {
-            emitcode("add","a,acc");
-            emitcode("add","a,acc");
-        } else {
-            /* rotate left accumulator */
-            AccRol(shCount);
-            /* and kill the lower order bits */
-            emitcode("anl","a,#0x%02x", SLMask[shCount]);
+  switch (p_type)
+    {
+    case IPOINTER:
+    case POINTER:
+      if (*src=='@')
+        {
+          MOVA (src);
+          emitcode ("mov", "@%s,a", rname);
         }
+      else
+        emitcode ("mov", "@%s,%s", rname, src);
+      break;
+
+    case PPOINTER:
+      MOVA (src);
+      emitcode ("movx", "@%s,a", rname);
+      break;
+
+    case FPOINTER:
+      MOVA (src);
+      emitcode ("movx", "@dptr,a");
+      break;
+
+    case GPOINTER:
+      MOVA (src);
+      emitcode ("lcall", "__gptrput");
+      break;
     }
 }
 
 /*-----------------------------------------------------------------*/
-/* AccRsh - right shift accumulator by known count                 */
+/* genUnpackBits - generates code for unpacking bits               */
 /*-----------------------------------------------------------------*/
-static void AccRsh (int shCount)
+static void
+genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
 {
-    if(shCount != 0){
-        if(shCount == 1){
-            CLRC;
-            emitcode("rrc","a");
-        } else {
-            /* rotate right accumulator */
-            AccRol(8 - shCount);
-            /* and kill the higher order bits */
-            emitcode("anl","a,#0x%02x", SRMask[shCount]);
+  int offset = 0;       /* result byte offset */
+  int rsize;            /* result size */
+  int rlen = 0;         /* remaining bitfield length */
+  sym_link *etype;      /* bitfield type information */
+  int blen;             /* bitfield length */
+  int bstr;             /* bitfield starting bit within byte */
+  char buffer[10];
+
+  D(emitcode (";     genUnpackBits",""));
+
+  etype = getSpec (operandType (result));
+  rsize = getSize (operandType (result));
+  blen = SPEC_BLEN (etype);
+  bstr = SPEC_BSTR (etype);
+
+  if (ifx && blen <= 8)
+    {
+      emitPtrByteGet (rname, ptype, FALSE);
+      if (blen == 1)
+        {
+          SNPRINTF (buffer, sizeof(buffer),
+                    "acc.%d", bstr);
+          genIfxJump (ifx, buffer, NULL, NULL, NULL);
         }
+      else
+        {
+          if (blen < 8)
+            emitcode ("anl", "a,#0x%02x",
+                      (((unsigned char) -1) >> (8 - blen)) << bstr);
+          genIfxJump (ifx, "a", NULL, NULL, NULL);
+        }
+      return;
     }
-}
+  wassert (!ifx);
 
-/*-----------------------------------------------------------------*/
-/* AccSRsh - signed right shift accumulator by known count                 */
-/*-----------------------------------------------------------------*/
-static void AccSRsh (int shCount)
-{
-    symbol *tlbl ;
-    if(shCount != 0){
-        if(shCount == 1){
-            emitcode("mov","c,acc.7");
-            emitcode("rrc","a");
-        } else if(shCount == 2){
-            emitcode("mov","c,acc.7");
-            emitcode("rrc","a");
-            emitcode("mov","c,acc.7");
-            emitcode("rrc","a");
-        } else {
-            tlbl = newiTempLabel(NULL);
-            /* rotate right accumulator */
-            AccRol(8 - shCount);
-            /* and kill the higher order bits */
-            emitcode("anl","a,#0x%02x", SRMask[shCount]);
-            emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
-            emitcode("orl","a,#0x%02x",
-                     (unsigned char)~SRMask[shCount]);
-            emitcode("","%05d$:",tlbl->key+100);
+  /* If the bitfield length is less than a byte */
+  if (blen < 8)
+    {
+      emitPtrByteGet (rname, ptype, FALSE);
+      AccRol (8 - bstr);
+      emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
+      if (!SPEC_USIGN (etype))
+        {
+          /* signed bitfield */
+          symbol *tlbl = newiTempLabel (NULL);
+
+          emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
+          emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
+          emitLabel (tlbl);
         }
+      aopPut (result, "a", offset++);
+      goto finish;
     }
-}
 
-/*-----------------------------------------------------------------*/
-/* shiftR1Left2Result - shift right one byte from left to result   */
-/*-----------------------------------------------------------------*/
-static void shiftR1Left2Result (operand *left, int offl,
-                                operand *result, int offr,
-                                int shCount, int sign)
-{
-    MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
-    /* shift right accumulator */
-    if(sign)
-        AccSRsh(shCount);
-    else
-        AccRsh(shCount);
-    aopPut(AOP(result),"a",offr);
-}
+  /* Bit field did not fit in a byte. Copy all
+     but the partial byte at the end.  */
+  for (rlen=blen;rlen>=8;rlen-=8)
+    {
+      emitPtrByteGet (rname, ptype, FALSE);
+      aopPut (result, "a", offset++);
+      if (rlen>8)
+        emitcode ("inc", "%s", rname);
+    }
 
-/*-----------------------------------------------------------------*/
-/* shiftL1Left2Result - shift left one byte from left to result    */
-/*-----------------------------------------------------------------*/
-static void shiftL1Left2Result (operand *left, int offl,
-                                operand *result, int offr, int shCount)
-{
-    char *l;
-    l = aopGet(AOP(left),offl,FALSE,FALSE);
-    MOVA(l);
-    /* shift left accumulator */
-    AccLsh(shCount);
-    aopPut(AOP(result),"a",offr);
-}
+  /* Handle the partial byte at the end */
+  if (rlen)
+    {
+      emitPtrByteGet (rname, ptype, FALSE);
+      emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
+      if (!SPEC_USIGN (etype))
+        {
+          /* signed bitfield */
+          symbol *tlbl = newiTempLabel (NULL);
 
-/*-----------------------------------------------------------------*/
-/* movLeft2Result - move byte from left to result                  */
-/*-----------------------------------------------------------------*/
-static void movLeft2Result (operand *left, int offl,
-                            operand *result, int offr, int sign)
-{
-    char *l;
-    if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
-        l = aopGet(AOP(left),offl,FALSE,FALSE);
+          emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
+          emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
+          emitLabel (tlbl);
+        }
+      aopPut (result, "a", offset++);
+    }
 
-        if (*l == '@' && (IS_AOP_PREG(result))) {
-            emitcode("mov","a,%s",l);
-            aopPut(AOP(result),"a",offr);
-        } else {
-            if(!sign)
-                aopPut(AOP(result),l,offr);
-            else{
-                /* MSB sign in acc.7 ! */
-                if(getDataSize(left) == offl+1){
-                    emitcode("mov","a,%s",l);
-                    aopPut(AOP(result),"a",offr);
-                }
-            }
+finish:
+  if (offset < rsize)
+    {
+      char *source;
+
+      if (SPEC_USIGN (etype))
+        source = zero;
+      else
+        {
+          /* signed bitfield: sign extension with 0x00 or 0xff */
+          emitcode ("rlc", "a");
+          emitcode ("subb", "a,acc");
+
+          source = "a";
         }
+      rsize -= offset;
+      while (rsize--)
+        aopPut (result, source, offset++);
     }
 }
 
-/*-----------------------------------------------------------------*/
-/* AccAXRrl1 - right rotate c->a:x->c by 1                         */
-/*-----------------------------------------------------------------*/
-static void AccAXRrl1 (char *x)
-{
-    emitcode("rrc","a");
-    emitcode("xch","a,%s", x);
-    emitcode("rrc","a");
-    emitcode("xch","a,%s", x);
-}
 
 /*-----------------------------------------------------------------*/
-/* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
+/* genDataPointerGet - generates code when ptr offset is known     */
 /*-----------------------------------------------------------------*/
-static void AccAXLrl1 (char *x)
+static void
+genDataPointerGet (operand * left,
+                   operand * result,
+                   iCode * ic)
 {
-    emitcode("xch","a,%s",x);
-    emitcode("rlc","a");
-    emitcode("xch","a,%s",x);
-    emitcode("rlc","a");
-}
+  char *l;
+  char buffer[256];
+  int size, offset = 0;
 
-/*-----------------------------------------------------------------*/
-/* AccAXLsh1 - left shift a:x<-0 by 1                              */
-/*-----------------------------------------------------------------*/
-static void AccAXLsh1 (char *x)
-{
-    emitcode("xch","a,%s",x);
-    emitcode("add","a,acc");
-    emitcode("xch","a,%s",x);
-    emitcode("rlc","a");
-}
+  D (emitcode (";", "genDataPointerGet"));
 
-/*-----------------------------------------------------------------*/
-/* AccAXLsh - left shift a:x by known count (0..7)                 */
-/*-----------------------------------------------------------------*/
-static void AccAXLsh (char *x, int shCount)
-{
-    switch(shCount){
-        case 0 :
-            break;
-        case 1 :
-            AccAXLsh1(x);
-            break;
-        case 2 :
-            AccAXLsh1(x);
-            AccAXLsh1(x);
-            break;
-        case 3 :
-        case 4 :
-        case 5 :                        // AAAAABBB:CCCCCDDD
-            AccRol(shCount);            // BBBAAAAA:CCCCCDDD
-            emitcode("anl","a,#0x%02x",
-                     SLMask[shCount]);  // BBB00000:CCCCCDDD
-            emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
-            AccRol(shCount);            // DDDCCCCC:BBB00000
-            emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
-            emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
-            emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
-            emitcode("anl","a,#0x%02x",
-                     SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
-            emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
-            emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
-            break;
-        case 6 :                        // AAAAAABB:CCCCCCDD
-            emitcode("anl","a,#0x%02x",
-                     SRMask[shCount]);  // 000000BB:CCCCCCDD
-            emitcode("mov","c,acc.0");  // c = B
-            emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
-            AccAXRrl1(x);               // BCCCCCCD:D000000B
-            AccAXRrl1(x);               // BBCCCCCC:DD000000
-            break;
-        case 7 :                        // a:x <<= 7
-            emitcode("anl","a,#0x%02x",
-                     SRMask[shCount]);  // 0000000B:CCCCCCCD
-            emitcode("mov","c,acc.0");  // c = B
-            emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
-            AccAXRrl1(x);               // BCCCCCCC:D0000000
-            break;
-        default :
-            break;
+  aopOp (result, ic, TRUE);
+
+  /* get the string representation of the name */
+  l = aopGet (left, 0, FALSE, TRUE);
+  size = AOP_SIZE (result);
+  while (size--)
+    {
+      if (offset)
+        {
+          SNPRINTF (buffer, sizeof(buffer),
+                    "(%s + %d)", l + 1, offset);
+        }
+      else
+        {
+          SNPRINTF (buffer, sizeof(buffer),
+                    "%s", l + 1);
+        }
+      aopPut (result, buffer, offset++);
     }
+
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* AccAXRsh - right shift a:x known count (0..7)                   */
+/* genNearPointerGet - emitcode for near pointer fetch             */
 /*-----------------------------------------------------------------*/
-static void AccAXRsh (char *x, int shCount)
-{   
-    switch(shCount){
-        case 0 :
-            break;
-        case 1 :
-            CLRC;
-            AccAXRrl1(x);               // 0->a:x
-            break;
-        case 2 :
-            CLRC;
-            AccAXRrl1(x);               // 0->a:x
-            CLRC;
-            AccAXRrl1(x);               // 0->a:x
-            break;
-        case 3 :
-        case 4 :
-        case 5 :                        // AAAAABBB:CCCCCDDD = a:x
-            AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
-            emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
-            AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
-            emitcode("anl","a,#0x%02x",
-                     SRMask[shCount]);  // 000CCCCC:BBBAAAAA
-            emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
-            emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
-            emitcode("anl","a,#0x%02x",
-                     SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
-            emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
-            emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
-            emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
-            break;
-        case 6 :                        // AABBBBBB:CCDDDDDD
-            emitcode("mov","c,acc.7");
-            AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
-            AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
-            emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
-            emitcode("anl","a,#0x%02x",
-                     SRMask[shCount]);  // 000000AA:BBBBBBCC
-            break;
-        case 7 :                        // ABBBBBBB:CDDDDDDD
-            emitcode("mov","c,acc.7");  // c = A
-            AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
-            emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
-            emitcode("anl","a,#0x%02x",
-                     SRMask[shCount]);  // 0000000A:BBBBBBBC
-            break;
-        default :
-            break;
+static void
+genNearPointerGet (operand * left,
+                   operand * result,
+                   iCode * ic,
+                   iCode * pi,
+                   iCode * ifx)
+{
+  asmop *aop = NULL;
+  regs *preg = NULL;
+  char *rname;
+  sym_link *rtype, *retype;
+  sym_link *ltype = operandType (left);
+  char buffer[80];
+
+  D (emitcode (";", "genNearPointerGet"));
+
+  rtype = operandType (result);
+  retype = getSpec (rtype);
+
+  aopOp (left, ic, FALSE);
+
+  /* if left is rematerialisable and
+     result is not bitfield variable type and
+     the left is pointer to data space i.e
+     lower 128 bytes of space */
+  if (AOP_TYPE (left) == AOP_IMMD &&
+      !IS_BITFIELD (retype) &&
+      DCL_TYPE (ltype) == POINTER)
+    {
+      genDataPointerGet (left, result, ic);
+      return;
     }
-}
 
-/*-----------------------------------------------------------------*/
-/* AccAXRshS - right shift signed a:x known count (0..7)           */
-/*-----------------------------------------------------------------*/
-static void AccAXRshS (char *x, int shCount)
-{   
-    symbol *tlbl ;
-    switch(shCount){
-        case 0 :
-            break;
-        case 1 :
-            emitcode("mov","c,acc.7");
-            AccAXRrl1(x);               // s->a:x
-            break;
-        case 2 :
-            emitcode("mov","c,acc.7");
-            AccAXRrl1(x);               // s->a:x
-            emitcode("mov","c,acc.7");
-            AccAXRrl1(x);               // s->a:x
-            break;
-        case 3 :
-        case 4 :
-        case 5 :                        // AAAAABBB:CCCCCDDD = a:x
-            tlbl = newiTempLabel(NULL);
-            AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
-            emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
-            AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
-            emitcode("anl","a,#0x%02x",
-                     SRMask[shCount]);  // 000CCCCC:BBBAAAAA
-            emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
-            emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
-            emitcode("anl","a,#0x%02x",
-                     SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
-            emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
-            emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
-            emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
-            emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
-            emitcode("orl","a,#0x%02x",
-                     (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
-            emitcode("","%05d$:",tlbl->key+100);
-            break;                      // SSSSAAAA:BBBCCCCC
-        case 6 :                        // AABBBBBB:CCDDDDDD
-            tlbl = newiTempLabel(NULL);
-            emitcode("mov","c,acc.7");
-            AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
-            AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
-            emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
-            emitcode("anl","a,#0x%02x",
-                     SRMask[shCount]);  // 000000AA:BBBBBBCC
-            emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
-            emitcode("orl","a,#0x%02x",
-                     (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
-            emitcode("","%05d$:",tlbl->key+100);
-            break;
-        case 7 :                        // ABBBBBBB:CDDDDDDD
-            tlbl = newiTempLabel(NULL);
-            emitcode("mov","c,acc.7");  // c = A
-            AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
-            emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
-            emitcode("anl","a,#0x%02x",
-                     SRMask[shCount]);  // 0000000A:BBBBBBBC
-            emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
-            emitcode("orl","a,#0x%02x",
-                     (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
-            emitcode("","%05d$:",tlbl->key+100);
-            break;
-        default :
-            break;
+ /* if the value is already in a pointer register
+     then don't need anything more */
+  if (!AOP_INPREG (AOP (left)))
+    {
+      if (IS_AOP_PREG (left))
+        {
+          // Aha, it is a pointer, just in disguise.
+          rname = aopGet (left, 0, FALSE, FALSE);
+          if (*rname != '@')
+            {
+              fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
+                      __FILE__, __LINE__);
+            }
+          else
+            {
+              // Expected case.
+              emitcode ("mov", "a%s,%s", rname + 1, rname);
+              rname++;  // skip the '@'.
+            }
+        }
+      else
+        {
+          /* otherwise get a free pointer register */
+          aop = newAsmop (0);
+          preg = getFreePtr (ic, &aop, FALSE);
+          emitcode ("mov", "%s,%s",
+                    preg->name,
+                    aopGet (left, 0, FALSE, TRUE));
+          rname = preg->name;
+        }
     }
-}
+  else
+    rname = aopGet (left, 0, FALSE, FALSE);
 
-/*-----------------------------------------------------------------*/
-/* shiftL2Left2Result - shift left two bytes from left to result   */
-/*-----------------------------------------------------------------*/
-static void shiftL2Left2Result (operand *left, int offl,
-                                operand *result, int offr, int shCount)
-{
-    if(sameRegs(AOP(result), AOP(left)) &&
-       ((offl + MSB16) == offr)){
-       /* don't crash result[offr] */
-       MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
-       emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
-    } else {
-       movLeft2Result(left,offl, result, offr, 0);
-       MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
+  //aopOp (result, ic, FALSE);
+  aopOp (result, ic, result?TRUE:FALSE);
+
+  /* if bitfield then unpack the bits */
+  if (IS_BITFIELD (retype))
+    genUnpackBits (result, rname, POINTER, ifx);
+  else
+    {
+      /* we have can just get the values */
+      int size = AOP_SIZE (result);
+      int offset = 0;
+
+      while (size--)
+        {
+          if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
+            {
+
+              emitcode ("mov", "a,@%s", rname);
+              if (!ifx)
+                aopPut (result, "a", offset);
+            }
+          else
+            {
+              SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
+              aopPut (result, buffer, offset);
+            }
+          offset++;
+          if (size || pi)
+            emitcode ("inc", "%s", rname);
+        }
     }
-    /* ax << shCount (x = lsb(result))*/
-    AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
-    aopPut(AOP(result),"a",offr+MSB16);
-}
 
+  /* now some housekeeping stuff */
+  if (aop)       /* we had to allocate for this iCode */
+    {
+      if (pi) { /* post increment present */
+        aopPut (left, rname, 0);
+      }
+      freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
+    }
+  else
+    {
+      /* we did not allocate which means left
+         already in a pointer register, then
+         if size > 0 && this could be used again
+         we have to point it back to where it
+         belongs */
+      if ((AOP_SIZE (result) > 1 &&
+           !OP_SYMBOL (left)->remat &&
+           (OP_SYMBOL (left)->liveTo > ic->seq ||
+            ic->depth)) &&
+          !pi)
+        {
+          int size = AOP_SIZE (result) - 1;
+          while (size--)
+            emitcode ("dec", "%s", rname);
+        }
+    }
 
-/*-----------------------------------------------------------------*/
-/* shiftR2Left2Result - shift right two bytes from left to result  */
-/*-----------------------------------------------------------------*/
-static void shiftR2Left2Result (operand *left, int offl,
-                                operand *result, int offr,
-                                int shCount, int sign)
-{
-    if(sameRegs(AOP(result), AOP(left)) &&
-       ((offl + MSB16) == offr)){
-       /* don't crash result[offr] */
-       MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
-       emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
-    } else {
-       movLeft2Result(left,offl, result, offr, 0);
-       MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
-    }
-    /* a:x >> shCount (x = lsb(result))*/
-    if(sign)
-        AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
-    else
-        AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
-    if(getDataSize(result) > 1)
-        aopPut(AOP(result),"a",offr+MSB16);
-}
+  if (ifx && !ifx->generated)
+    {
+      genIfxJump (ifx, "a", left, NULL, result);
+    }
 
-/*-----------------------------------------------------------------*/
-/* shiftLLeftOrResult - shift left one byte from left, or to result*/
-/*-----------------------------------------------------------------*/
-static void shiftLLeftOrResult (operand *left, int offl,
-                                operand *result, int offr, int shCount)
-{
-    MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
-    /* shift left accumulator */
-    AccLsh(shCount);
-    /* or with result */
-    emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
-    /* back to result */
-    aopPut(AOP(result),"a",offr);
+  /* done */
+  freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+  if (pi) pi->generated = 1;
 }
 
 /*-----------------------------------------------------------------*/
-/* shiftRLeftOrResult - shift right one byte from left,or to result*/
+/* genPagedPointerGet - emitcode for paged pointer fetch           */
 /*-----------------------------------------------------------------*/
-static void shiftRLeftOrResult (operand *left, int offl,
-                                operand *result, int offr, int shCount)
+static void
+genPagedPointerGet (operand * left,
+                    operand * result,
+                    iCode * ic,
+                    iCode *pi,
+                    iCode *ifx)
 {
-    MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
-    /* shift right accumulator */
-    AccRsh(shCount);
-    /* or with result */
-    emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
-    /* back to result */
-    aopPut(AOP(result),"a",offr);
-}
+  asmop *aop = NULL;
+  regs *preg = NULL;
+  char *rname;
+  sym_link *rtype, *retype;
 
-/*-----------------------------------------------------------------*/
-/* 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);
-}
+  D (emitcode (";", "genPagedPointerGet"));
 
-/*-----------------------------------------------------------------*/
-/* genlshTwo - left shift two bytes by known amount != 0           */
-/*-----------------------------------------------------------------*/
-static void genlshTwo (operand *result,operand *left, int shCount)
-{
-    int size;
-    
-    size = getDataSize(result);
+  rtype = operandType (result);
+  retype = getSpec (rtype);
+
+  aopOp (left, ic, FALSE);
+
+  /* if the value is already in a pointer register
+     then don't need anything more */
+  if (!AOP_INPREG (AOP (left)))
+    {
+      /* otherwise get a free pointer register */
+      aop = newAsmop (0);
+      preg = getFreePtr (ic, &aop, FALSE);
+      emitcode ("mov", "%s,%s",
+                preg->name,
+                aopGet (left, 0, FALSE, TRUE));
+      rname = preg->name;
+    }
+  else
+    rname = aopGet (left, 0, FALSE, FALSE);
+
+  aopOp (result, ic, FALSE);
+
+  /* if bitfield then unpack the bits */
+  if (IS_BITFIELD (retype))
+    genUnpackBits (result, rname, PPOINTER, ifx);
+  else
+    {
+      /* we have can just get the values */
+      int size = AOP_SIZE (result);
+      int offset = 0;
+
+      while (size--)
+        {
+
+          emitcode ("movx", "a,@%s", rname);
+          if (!ifx)
+            aopPut (result, "a", offset);
 
-    /* if shCount >= 8 */
-    if (shCount >= 8) {
-        shCount -= 8 ;
+          offset++;
 
-        if (size > 1){
-            if (shCount)
-                shiftL1Left2Result(left, LSB, result, MSB16, shCount);
-            else 
-                movLeft2Result(left, LSB, result, MSB16, 0);
+          if (size || pi)
+            emitcode ("inc", "%s", rname);
+        }
+    }
+
+  /* now some housekeeping stuff */
+  if (aop) /* we had to allocate for this iCode */
+    {
+      if (pi)
+        aopPut (left, rname, 0);
+      freeAsmop (NULL, aop, ic, TRUE);
+    }
+  else
+    {
+      /* we did not allocate which means left
+         already in a pointer register, then
+         if size > 0 && this could be used again
+         we have to point it back to where it
+         belongs */
+      if ((AOP_SIZE (result) > 1 &&
+           !OP_SYMBOL (left)->remat &&
+           (OP_SYMBOL (left)->liveTo > ic->seq ||
+            ic->depth)) &&
+          !pi)
+        {
+          int size = AOP_SIZE (result) - 1;
+          while (size--)
+            emitcode ("dec", "%s", rname);
         }
-        aopPut(AOP(result),zero,LSB);   
     }
 
-    /*  1 <= shCount <= 7 */
-    else {  
-        if(size == 1)
-            shiftL1Left2Result(left, LSB, result, LSB, shCount); 
-        else 
-            shiftL2Left2Result(left, LSB, result, LSB, shCount);
+  if (ifx && !ifx->generated)
+    {
+      genIfxJump (ifx, "a", left, NULL, result);
     }
+
+  /* done */
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+  if (pi) pi->generated = 1;
 }
 
-/*-----------------------------------------------------------------*/
-/* shiftLLong - shift left one long from left to result            */
-/* offl = LSB or MSB16                                             */
-/*-----------------------------------------------------------------*/
-static void shiftLLong (operand *left, operand *result, int offr )
-{
-    char *l;
-    int size = AOP_SIZE(result);
-
-    if(size >= LSB+offr){
-        l = aopGet(AOP(left),LSB,FALSE,FALSE);
-        MOVA(l);
-        emitcode("add","a,acc");
-       if (sameRegs(AOP(left),AOP(result)) && 
-           size >= MSB16+offr && offr != LSB )
-           emitcode("xch","a,%s",
-                    aopGet(AOP(left),LSB+offr,FALSE,FALSE));
-       else        
-           aopPut(AOP(result),"a",LSB+offr);
-    }
-
-    if(size >= MSB16+offr){
-       if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
-           l = aopGet(AOP(left),MSB16,FALSE,FALSE);
-           MOVA(l);
-       }
-        emitcode("rlc","a");
-       if (sameRegs(AOP(left),AOP(result)) && 
-           size >= MSB24+offr && offr != LSB)
-           emitcode("xch","a,%s",
-                    aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
-       else        
-           aopPut(AOP(result),"a",MSB16+offr);
-    }
-
-    if(size >= MSB24+offr){
-       if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
-           l = aopGet(AOP(left),MSB24,FALSE,FALSE);
-           MOVA(l);
-       }
-        emitcode("rlc","a");
-       if (sameRegs(AOP(left),AOP(result)) && 
-           size >= MSB32+offr && offr != LSB )
-           emitcode("xch","a,%s",
-                    aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
-       else        
-           aopPut(AOP(result),"a",MSB24+offr);
-    }
-
-    if(size > MSB32+offr){
-       if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
-           l = aopGet(AOP(left),MSB32,FALSE,FALSE);
-           MOVA(l);    
-       }
-        emitcode("rlc","a");
-        aopPut(AOP(result),"a",MSB32+offr);
-    }
-    if(offr != LSB)
-        aopPut(AOP(result),zero,LSB);       
+/*--------------------------------------------------------------------*/
+/* loadDptrFromOperand - load dptr (and optionally B) from operand op */
+/*--------------------------------------------------------------------*/
+static void
+loadDptrFromOperand (operand *op, bool loadBToo)
+{
+  if (AOP_TYPE (op) != AOP_STR)
+    {
+      /* if this is rematerializable */
+      if (AOP_TYPE (op) == AOP_IMMD)
+        {
+          emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
+          if (loadBToo)
+            {
+              if (AOP(op)->aopu.aop_immd.from_cast_remat)
+                emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
+              else
+                {
+                  wassertl(FALSE, "need pointerCode");
+                  emitcode ("", "; mov b,???");
+                  /* genPointerGet and genPointerSet originally did different
+                  ** things for this case. Both seem wrong.
+                  ** from genPointerGet:
+                  **  emitcode ("mov", "b,#%d", pointerCode (retype));
+                  ** from genPointerSet:
+                  **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
+                  */
+                }
+            }
+        }
+      else if (AOP_TYPE (op) == AOP_DPTR)
+        {
+          if (loadBToo)
+            {
+              MOVA (aopGet (op, 0, FALSE, FALSE));
+              emitcode ("push", "acc");
+              MOVA (aopGet (op, 1, FALSE, FALSE));
+              emitcode ("push", "acc");
+              emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
+              emitcode ("pop", "dph");
+              emitcode ("pop", "dpl");
+            }
+          else
+            {
+              MOVA (aopGet (op, 0, FALSE, FALSE));
+              emitcode ("push", "acc");
+              emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
+              emitcode ("pop", "dpl");
+            }
+        }
+      else
+        {                       /* we need to get it byte by byte */
+          emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
+          emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
+          if (loadBToo)
+            emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
+        }
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* genlshFour - shift four byte by a known amount != 0             */
+/* genFarPointerGet - get value from far space                     */
 /*-----------------------------------------------------------------*/
-static void genlshFour (operand *result, operand *left, int shCount)
+static void
+genFarPointerGet (operand * left,
+                  operand * result, iCode * ic, iCode * pi, iCode * ifx)
 {
-    int size;
+  int size, offset;
+  sym_link *retype = getSpec (operandType (result));
 
-    size = AOP_SIZE(result);
+  D (emitcode (";", "genFarPointerGet"));
 
-    /* if shifting more that 3 bytes */
-    if (shCount >= 24 ) {
-        shCount -= 24;
-        if (shCount)
-            /* lowest order of left goes to the highest
-            order of the destination */
-            shiftL1Left2Result(left, LSB, result, MSB32, shCount);
-        else
-            movLeft2Result(left, LSB, result, MSB32, 0);
-        aopPut(AOP(result),zero,LSB);
-        aopPut(AOP(result),zero,MSB16);
-        aopPut(AOP(result),zero,MSB32);
-        return;
-    }
+  aopOp (left, ic, FALSE);
+  loadDptrFromOperand (left, FALSE);
 
-    /* more than two bytes */
-    else if ( shCount >= 16 ) {
-        /* lower order two bytes goes to higher order two bytes */
-        shCount -= 16;
-        /* if some more remaining */
-        if (shCount)
-            shiftL2Left2Result(left, LSB, result, MSB24, shCount);
-        else {
-            movLeft2Result(left, MSB16, result, MSB32, 0);
-            movLeft2Result(left, LSB, result, MSB24, 0);
-        }
-        aopPut(AOP(result),zero,MSB16);
-        aopPut(AOP(result),zero,LSB);
-        return;
-    }    
-
-    /* if more than 1 byte */
-    else if ( shCount >= 8 ) {
-        /* lower order three bytes goes to higher order  three bytes */
-        shCount -= 8;
-        if(size == 2){
-            if(shCount)
-                shiftL1Left2Result(left, LSB, result, MSB16, shCount);
-            else
-                movLeft2Result(left, LSB, result, MSB16, 0);
-        }
-        else{   /* size = 4 */
-            if(shCount == 0){
-                movLeft2Result(left, MSB24, result, MSB32, 0);
-                movLeft2Result(left, MSB16, result, MSB24, 0);
-                movLeft2Result(left, LSB, result, MSB16, 0);
-                aopPut(AOP(result),zero,LSB);
-            }
-            else if(shCount == 1)
-                shiftLLong(left, result, MSB16);
-            else{
-                shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
-                shiftL1Left2Result(left, LSB, result, MSB16, shCount);
-                shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
-                aopPut(AOP(result),zero,LSB);
-            }
+  /* so dptr now contains the address */
+  aopOp (result, ic, FALSE);
+
+  /* if bit then unpack */
+  if (IS_BITFIELD (retype))
+    genUnpackBits (result, "dptr", FPOINTER, ifx);
+  else
+    {
+      size = AOP_SIZE (result);
+      offset = 0;
+
+      while (size--)
+        {
+          emitcode ("movx", "a,@dptr");
+          if (!ifx)
+            aopPut (result, "a", offset++);
+          if (size || pi)
+            emitcode ("inc", "dptr");
         }
     }
 
-    /* 1 <= shCount <= 7 */
-    else if(shCount <= 2){
-        shiftLLong(left, result, LSB);
-        if(shCount == 2)
-            shiftLLong(result, result, LSB);
+  if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
+    {
+      aopPut (left, "dpl", 0);
+      aopPut (left, "dph", 1);
+      pi->generated = 1;
     }
-    /* 3 <= shCount <= 7, optimize */
-    else{
-        shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
-        shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
-        shiftL2Left2Result(left, LSB, result, LSB, shCount);
+
+  if (ifx && !ifx->generated)
+    {
+      genIfxJump (ifx, "a", left, NULL, result);
     }
+
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genLeftShiftLiteral - left shifting by known count              */
+/* genCodePointerGet - get value from code space                   */
 /*-----------------------------------------------------------------*/
-static void genLeftShiftLiteral (operand *left,
-                                 operand *right,
-                                 operand *result,
-                                 iCode *ic)
-{    
-    int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
-    int size;
+static void
+genCodePointerGet (operand * left,
+                    operand * result, iCode * ic, iCode *pi, iCode *ifx)
+{
+  int size, offset;
+  sym_link *retype = getSpec (operandType (result));
 
-    freeAsmop(right,NULL,ic,TRUE);
+  D (emitcode (";", "genCodePointerGet"));
 
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,FALSE);
+  aopOp (left, ic, FALSE);
+  loadDptrFromOperand (left, FALSE);
 
-    size = getSize(operandType(result));
+  /* so dptr now contains the address */
+  aopOp (result, ic, FALSE);
 
-#if VIEW_SIZE
-    emitcode("; shift left ","result %d, left %d",size,
-             AOP_SIZE(left));
-#endif
+  /* if bit then unpack */
+  if (IS_BITFIELD (retype))
+    genUnpackBits (result, "dptr", CPOINTER, ifx);
+  else
+    {
+      size = AOP_SIZE (result);
+      offset = 0;
 
-    /* I suppose that the left size >= result size */
-    if(shCount == 0){
-        while(size--){
-            movLeft2Result(left, size, result, size, 0);
+      while (size--)
+        {
+          emitcode ("clr", "a");
+          emitcode ("movc", "a,@a+dptr");
+          if (!ifx)
+            aopPut (result, "a", offset++);
+          if (size || pi)
+            emitcode ("inc", "dptr");
         }
     }
 
-    else if(shCount >= (size * 8))
-        while(size--)
-            aopPut(AOP(result),zero,size);
-    else{
-        switch (size) {
-            case 1:
-                genlshOne (result,left,shCount);
-                break;
-
-            case 2:
-            case 3:
-                genlshTwo (result,left,shCount);
-                break;
-
-            case 4:
-                genlshFour (result,left,shCount);
-                break;
-        }
+  if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
+    {
+      aopPut (left, "dpl", 0);
+      aopPut (left, "dph", 1);
+      pi->generated = 1;
     }
-    freeAsmop(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
-}
 
-/*-----------------------------------------------------------------*/
-/* genLeftShift - generates code for left shifting                 */
-/*-----------------------------------------------------------------*/
-static void genLeftShift (iCode *ic)
-{
-    operand *left,*right, *result;
-    int size, offset;
-    char *l;
-    symbol *tlbl , *tlbl1;
-
-    right = IC_RIGHT(ic);
-    left  = IC_LEFT(ic);
-    result = IC_RESULT(ic);
-
-    aopOp(right,ic,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 ) */  
-
-    emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
-    emitcode("inc","b");
-    freeAsmop (right,NULL,ic,TRUE);
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,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,TRUE);
-            if (*l == '@' && (IS_AOP_PREG(result))) {
-
-                emitcode("mov","a,%s",l);
-                aopPut(AOP(result),"a",offset);
-            } else
-                aopPut(AOP(result),l,offset);
-            offset++;
-        }
+  if (ifx && !ifx->generated)
+    {
+      genIfxJump (ifx, "a", left, NULL, result);
     }
 
-    tlbl = newiTempLabel(NULL);
-    size = AOP_SIZE(result);
-    offset = 0 ;   
-    tlbl1 = newiTempLabel(NULL);
-
-    /* if it is only one byte then */
-    if (size == 1) {
-       symbol *tlbl1 = newiTempLabel(NULL);
-
-        l = aopGet(AOP(left),0,FALSE,FALSE);
-        MOVA(l);
-       emitcode("sjmp","%05d$",tlbl1->key+100); 
-        emitcode("","%05d$:",tlbl->key+100);
-        emitcode("add","a,acc");
-       emitcode("","%05d$:",tlbl1->key+100);
-        emitcode("djnz","b,%05d$",tlbl->key+100);      
-        aopPut(AOP(result),"a",0);
-        goto release ;
-    }
-    
-    reAdjustPreg(AOP(result));    
-    
-    emitcode("sjmp","%05d$",tlbl1->key+100); 
-    emitcode("","%05d$:",tlbl->key+100);    
-    l = aopGet(AOP(result),offset,FALSE,FALSE);
-    MOVA(l);
-    emitcode("add","a,acc");         
-    aopPut(AOP(result),"a",offset++);
-    while (--size) {
-        l = aopGet(AOP(result),offset,FALSE,FALSE);
-        MOVA(l);
-        emitcode("rlc","a");         
-        aopPut(AOP(result),"a",offset++);
-    }
-    reAdjustPreg(AOP(result));
-
-    emitcode("","%05d$:",tlbl1->key+100);
-    emitcode("djnz","b,%05d$",tlbl->key+100);
-release:
-    freeAsmop(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
-}
-
-/*-----------------------------------------------------------------*/
-/* genrshOne - right shift a one byte quantity by known count      */
-/*-----------------------------------------------------------------*/
-static void genrshOne (operand *result, operand *left,
-                       int shCount, int sign)
-{
-    shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genrshTwo - right shift two bytes by known amount != 0          */
+/* genGenPointerGet - get value from generic pointer space         */
 /*-----------------------------------------------------------------*/
-static void genrshTwo (operand *result,operand *left,
-                       int shCount, int sign)
+static void
+genGenPointerGet (operand * left,
+                  operand * result, iCode * ic, iCode *pi, iCode *ifx)
 {
-    /* if shCount >= 8 */
-    if (shCount >= 8) {
-        shCount -= 8 ;
-        if (shCount)
-            shiftR1Left2Result(left, MSB16, result, LSB,
-                               shCount, sign);
-        else 
-            movLeft2Result(left, MSB16, result, LSB, sign);
-        addSign(result, MSB16, sign);
-    }
+  int size, offset;
+  sym_link *retype = getSpec (operandType (result));
 
-    /*  1 <= shCount <= 7 */
-    else
-        shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
-}
-
-/*-----------------------------------------------------------------*/
-/* shiftRLong - shift right one long from left to result           */
-/* offl = LSB or MSB16                                             */
-/*-----------------------------------------------------------------*/
-static void shiftRLong (operand *left, int offl,
-                        operand *result, int sign)
-{
-    if(!sign)
-        emitcode("clr","c");
-    MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
-    if(sign)
-        emitcode("mov","c,acc.7");
-    emitcode("rrc","a");
-    aopPut(AOP(result),"a",MSB32-offl);
-    if(offl == MSB16)
-        /* add sign of "a" */
-        addSign(result, MSB32, sign);
+  D (emitcode (";", "genGenPointerGet"));
 
-    MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
-    emitcode("rrc","a");
-    aopPut(AOP(result),"a",MSB24-offl);
+  aopOp (left, ic, FALSE);
+  loadDptrFromOperand (left, TRUE);
 
-    MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
-    emitcode("rrc","a");
-    aopPut(AOP(result),"a",MSB16-offl);
+  /* so dptr now contains the address */
+  aopOp (result, ic, FALSE);
 
-    if(offl == LSB){
-        MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
-        emitcode("rrc","a");
-        aopPut(AOP(result),"a",LSB);
+  /* if bit then unpack */
+  if (IS_BITFIELD (retype))
+    {
+      genUnpackBits (result, "dptr", GPOINTER, ifx);
     }
-}
+  else
+    {
+      size = AOP_SIZE (result);
+      offset = 0;
 
-/*-----------------------------------------------------------------*/
-/* genrshFour - shift four byte by a known amount != 0             */
-/*-----------------------------------------------------------------*/
-static void genrshFour (operand *result, operand *left,
-                        int shCount, int sign)
-{
-    /* if shifting more that 3 bytes */
-    if(shCount >= 24 ) {
-        shCount -= 24;
-        if(shCount)
-            shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
-        else
-            movLeft2Result(left, MSB32, result, LSB, sign);
-        addSign(result, MSB16, sign);
-    }
-    else if(shCount >= 16){
-        shCount -= 16;
-        if(shCount)
-            shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
-        else{
-            movLeft2Result(left, MSB24, result, LSB, 0);
-            movLeft2Result(left, MSB32, result, MSB16, sign);
+      while (size--)
+        {
+          emitcode ("lcall", "__gptrget");
+          if (!ifx)
+            aopPut (result, "a", offset++);
+          if (size || pi)
+            emitcode ("inc", "dptr");
         }
-        addSign(result, MSB24, sign);
     }
-    else if(shCount >= 8){
-        shCount -= 8;
-        if(shCount == 1)
-            shiftRLong(left, MSB16, result, sign);
-        else if(shCount == 0){
-            movLeft2Result(left, MSB16, result, LSB, 0);
-            movLeft2Result(left, MSB24, result, MSB16, 0);
-            movLeft2Result(left, MSB32, result, MSB24, sign);
-            addSign(result, MSB32, sign);
-        }
-        else{
-            shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
-            shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
-            /* the last shift is signed */
-            shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
-            addSign(result, MSB32, sign);
-        }
+
+  if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
+    {
+      aopPut (left, "dpl", 0);
+      aopPut (left, "dph", 1);
+      pi->generated = 1;
     }
-    else{   /* 1 <= shCount <= 7 */
-        if(shCount <= 2){
-            shiftRLong(left, LSB, result, sign);
-            if(shCount == 2)
-                shiftRLong(result, LSB, result, sign);
-        }
-        else{
-            shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
-            shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
-            shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
-        }
+
+  if (ifx && !ifx->generated)
+    {
+      genIfxJump (ifx, "a", left, NULL, result);
     }
+
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genRightShiftLiteral - right shifting by known count            */
+/* genPointerGet - generate code for pointer get                   */
 /*-----------------------------------------------------------------*/
-static void genRightShiftLiteral (operand *left,
-                                  operand *right,
-                                  operand *result,
-                                  iCode *ic,
-                                  int sign)
-{    
-    int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
-    int size;
+static void
+genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
+{
+  operand *left, *result;
+  sym_link *type, *etype;
+  int p_type;
 
-    freeAsmop(right,NULL,ic,TRUE);
+  D (emitcode (";", "genPointerGet"));
 
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,FALSE);
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
 
-#if VIEW_SIZE
-    emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
-             AOP_SIZE(left));
-#endif
+  if (getSize (operandType (result))>1)
+    ifx = NULL;
 
-    size = getDataSize(left);
-    /* test the LEFT size !!! */
+  /* depending on the type of pointer we need to
+     move it to the correct pointer register */
+  type = operandType (left);
+  etype = getSpec (type);
+  /* if left is of type of pointer then it is simple */
+  if (IS_PTR (type) && !IS_FUNC (type->next))
+    p_type = DCL_TYPE (type);
+  else
+    {
+      /* we have to go by the storage class */
+      p_type = PTR_TYPE (SPEC_OCLS (etype));
+    }
 
-    /* I suppose that the left size >= result size */
-    if(shCount == 0){
-        size = getDataSize(result);
-        while(size--)
-            movLeft2Result(left, size, result, size, 0);
+  /* special case when cast remat */
+  if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
+      IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
+    {
+      left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
+      type = operandType (left);
+      p_type = DCL_TYPE (type);
     }
+  /* now that we have the pointer type we assign
+     the pointer values */
+  switch (p_type)
+    {
 
-    else if(shCount >= (size * 8)){
-        if(sign)
-            /* get sign in acc.7 */
-            MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
-        addSign(result, LSB, sign);
-    } else{
-        switch (size) {
-            case 1:
-                genrshOne (result,left,shCount,sign);
-                break;
+    case POINTER:
+    case IPOINTER:
+      genNearPointerGet (left, result, ic, pi, ifx);
+      break;
 
-            case 2:
-                genrshTwo (result,left,shCount,sign);
-                break;
+    case PPOINTER:
+      genPagedPointerGet (left, result, ic, pi, ifx);
+      break;
 
-            case 4:
-                genrshFour (result,left,shCount,sign);
-                break;
-            default :
-                break;
-        }
+    case FPOINTER:
+      genFarPointerGet (left, result, ic, pi, ifx);
+      break;
+
+    case CPOINTER:
+      genCodePointerGet (left, result, ic, pi, ifx);
+      break;
 
-        freeAsmop(left,NULL,ic,TRUE);
-        freeAsmop(result,NULL,ic,TRUE);
+    case GPOINTER:
+      genGenPointerGet (left, result, ic, pi, ifx);
+      break;
     }
 }
 
+
 /*-----------------------------------------------------------------*/
-/* genSignedRightShift - right shift of signed number              */
+/* genPackBits - generates code for packed bit storage             */
 /*-----------------------------------------------------------------*/
-static void genSignedRightShift (iCode *ic)
+static void
+genPackBits (sym_link * etype,
+             operand * right,
+             char *rname, int p_type)
 {
-    operand *right, *left, *result;
-    int size, offset;
-    char *l;
-    symbol *tlbl, *tlbl1 ;
+  int offset = 0;       /* source byte offset */
+  int rlen = 0;         /* remaining bitfield length */
+  int blen;             /* bitfield length */
+  int bstr;             /* bitfield starting bit within byte */
+  int litval;           /* source literal value (if AOP_LIT) */
+  unsigned char mask;   /* bitmask within current byte */
 
-    /* we do it the hard way put the shift count in b
-    and loop thru preserving the sign */
+  D(emitcode (";     genPackBits",""));
 
-    right = IC_RIGHT(ic);
-    left  = IC_LEFT(ic);
-    result = IC_RESULT(ic);
+  blen = SPEC_BLEN (etype);
+  bstr = SPEC_BSTR (etype);
 
-    aopOp(right,ic,FALSE);  
+  /* If the bitfield length is less than a byte */
+  if (blen < 8)
+    {
+      mask = ((unsigned char) (0xFF << (blen + bstr)) |
+              (unsigned char) (0xFF >> (8 - bstr)));
 
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          /* Case with a bitfield length <8 and literal source
+          */
+          litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+          litval <<= bstr;
+          litval &= (~mask) & 0xff;
+          emitPtrByteGet (rname, p_type, FALSE);
+          if ((mask|litval)!=0xff)
+            emitcode ("anl","a,#0x%02x", mask);
+          if (litval)
+            emitcode ("orl","a,#0x%02x", litval);
+        }
+      else
+        {
+          if ((blen==1) && (p_type!=GPOINTER))
+            {
+              /* Case with a bitfield length == 1 and no generic pointer
+              */
+              if (AOP_TYPE (right) == AOP_CRY)
+                emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
+              else
+                {
+                  MOVA (aopGet (right, 0, FALSE, FALSE));
+                  emitcode ("rrc","a");
+                }
+              emitPtrByteGet (rname, p_type, FALSE);
+              emitcode ("mov","acc.%d,c",bstr);
+            }
+          else
+            {
+              bool pushedB;
+              /* Case with a bitfield length < 8 and arbitrary source
+              */
+              MOVA (aopGet (right, 0, FALSE, FALSE));
+              /* shift and mask source value */
+              AccLsh (bstr);
+              emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
+
+              pushedB = pushB ();
+              /* transfer A to B and get next byte */
+              emitPtrByteGet (rname, p_type, TRUE);
+
+              emitcode ("anl", "a,#0x%02x", mask);
+              emitcode ("orl", "a,b");
+              if (p_type == GPOINTER)
+                emitcode ("pop", "b");
+
+              popB (pushedB);
+           }
+        }
 
-    if ( AOP_TYPE(right) == AOP_LIT) {
-       genRightShiftLiteral (left,right,result,ic,1);
-       return ;
+      emitPtrByteSet (rname, p_type, "a");
+      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 ) */  
 
-    emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
-    emitcode("inc","b");
-    freeAsmop (right,NULL,ic,TRUE);
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,FALSE);
-
-    /* now move the left to the result if they are not the
-    same */
-    if (!sameRegs(AOP(left),AOP(result)) && 
-        AOP_SIZE(result) > 1) {
+  /* Bit length is greater than 7 bits. In this case, copy  */
+  /* all except the partial byte at the end                 */
+  for (rlen=blen;rlen>=8;rlen-=8)
+    {
+      emitPtrByteSet (rname, p_type,
+                      aopGet (right, offset++, FALSE, TRUE) );
+      if (rlen>8)
+        emitcode ("inc", "%s", rname);
+    }
 
-        size = AOP_SIZE(result);
-        offset=0;
-        while (size--) {
-            l = aopGet(AOP(left),offset,FALSE,TRUE);
-            if (*l == '@' && IS_AOP_PREG(result)) {
+  /* If there was a partial byte at the end */
+  if (rlen)
+    {
+      mask = (((unsigned char) -1 << rlen) & 0xff);
 
-                emitcode("mov","a,%s",l);
-                aopPut(AOP(result),"a",offset);
-            } else
-                aopPut(AOP(result),l,offset);
-            offset++;
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          /* Case with partial byte and literal source
+          */
+          litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+          litval >>= (blen-rlen);
+          litval &= (~mask) & 0xff;
+          emitPtrByteGet (rname, p_type, FALSE);
+          if ((mask|litval)!=0xff)
+            emitcode ("anl","a,#0x%02x", mask);
+          if (litval)
+            emitcode ("orl","a,#0x%02x", litval);
+        }
+      else
+        {
+          bool pushedB;
+          /* Case with partial byte and arbitrary source
+          */
+          MOVA (aopGet (right, offset++, FALSE, FALSE));
+          emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
+
+          pushedB = pushB ();
+          /* transfer A to B and get next byte */
+          emitPtrByteGet (rname, p_type, TRUE);
+
+          emitcode ("anl", "a,#0x%02x", mask);
+          emitcode ("orl", "a,b");
+          if (p_type == GPOINTER)
+            emitcode ("pop", "b");
+
+          popB (pushedB);
         }
+      emitPtrByteSet (rname, p_type, "a");
     }
-
-    /* mov the highest order bit to OVR */    
-    tlbl = newiTempLabel(NULL);
-    tlbl1= newiTempLabel(NULL);
-
-    size = AOP_SIZE(result);
-    offset = size - 1;
-    emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
-    emitcode("rlc","a");
-    emitcode("mov","ov,c");
-    /* if it is only one byte then */
-    if (size == 1) {
-        l = aopGet(AOP(left),0,FALSE,FALSE);
-        MOVA(l);
-       emitcode("sjmp","%05d$",tlbl1->key+100);
-        emitcode("","%05d$:",tlbl->key+100);
-        emitcode("mov","c,ov");
-        emitcode("rrc","a");
-       emitcode("","%05d$:",tlbl1->key+100);
-        emitcode("djnz","b,%05d$",tlbl->key+100);
-        aopPut(AOP(result),"a",0);
-        goto release ;
-    }
-
-    reAdjustPreg(AOP(result));
-    emitcode("sjmp","%05d$",tlbl1->key+100);
-    emitcode("","%05d$:",tlbl->key+100);    
-    emitcode("mov","c,ov");
-    while (size--) {
-        l = aopGet(AOP(result),offset,FALSE,FALSE);
-        MOVA(l);
-        emitcode("rrc","a");         
-        aopPut(AOP(result),"a",offset--);
-    }
-    reAdjustPreg(AOP(result));
-    emitcode("","%05d$:",tlbl1->key+100);
-    emitcode("djnz","b,%05d$",tlbl->key+100);
-
-release:
-    freeAsmop(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
 }
 
+
 /*-----------------------------------------------------------------*/
-/* genRightShift - generate code for right shifting                */
+/* genDataPointerSet - remat pointer to data space                 */
 /*-----------------------------------------------------------------*/
-static void genRightShift (iCode *ic)
-{
-    operand *right, *left, *result;
-    link *retype ;
-    int size, offset;
-    char *l;
-    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)));
-
-    if (!SPEC_USIGN(retype)) {
-        genSignedRightShift (ic);
-        return ;
-    }
-
-    /* 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);
-
-    /* if the shift count is known then do it 
-    as efficiently as possible */
-    if (AOP_TYPE(right) == AOP_LIT) {
-        genRightShiftLiteral (left,right,result,ic, 0);
-        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 ) */  
-
-    emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
-    emitcode("inc","b");
-    freeAsmop (right,NULL,ic,TRUE);
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,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,TRUE);
-            if (*l == '@' && IS_AOP_PREG(result)) {
-
-                emitcode("mov","a,%s",l);
-                aopPut(AOP(result),"a",offset);
-            } else
-                aopPut(AOP(result),l,offset);
-            offset++;
-        }
-    }
+static void
+genDataPointerSet (operand * right,
+                   operand * result,
+                   iCode * ic)
+{
+  int size, offset = 0;
+  char *l, buffer[256];
 
-    tlbl = newiTempLabel(NULL);
-    tlbl1= newiTempLabel(NULL);
-    size = AOP_SIZE(result);
-    offset = size - 1;
+  D (emitcode (";", "genDataPointerSet"));
 
-    /* if it is only one byte then */
-    if (size == 1) {
-        l = aopGet(AOP(left),0,FALSE,FALSE);
-        MOVA(l);
-       emitcode("sjmp","%05d$",tlbl1->key+100);
-        emitcode("","%05d$:",tlbl->key+100);
-        CLRC;
-        emitcode("rrc","a");
-       emitcode("","%05d$:",tlbl1->key+100);
-        emitcode("djnz","b,%05d$",tlbl->key+100);
-        aopPut(AOP(result),"a",0);
-        goto release ;
-    }
+  aopOp (right, ic, FALSE);
 
-    reAdjustPreg(AOP(result));
-    emitcode("sjmp","%05d$",tlbl1->key+100);
-    emitcode("","%05d$:",tlbl->key+100);    
-    CLRC;
-    while (size--) {
-        l = aopGet(AOP(result),offset,FALSE,FALSE);
-        MOVA(l);
-        emitcode("rrc","a");         
-        aopPut(AOP(result),"a",offset--);
+  l = aopGet (result, 0, FALSE, TRUE);
+  size = AOP_SIZE (right);
+  while (size--)
+    {
+      if (offset)
+        SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
+      else
+        SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
+      emitcode ("mov", "%s,%s", buffer,
+                aopGet (right, offset++, FALSE, FALSE));
     }
-    reAdjustPreg(AOP(result));
-
-    emitcode("","%05d$:",tlbl1->key+100);
-    emitcode("djnz","b,%05d$",tlbl->key+100);
 
-release:
-    freeAsmop(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genUnpackBits - generates code for unpacking bits               */
+/* genNearPointerSet - emitcode for near pointer put                */
 /*-----------------------------------------------------------------*/
-static void genUnpackBits (operand *result, char *rname, int ptype)
-{    
-    int shCnt ;
-    int rlen = 0 ;
-    link *etype;
-    int offset = 0 ;
+static void
+genNearPointerSet (operand * right,
+                   operand * result,
+                   iCode * ic,
+                   iCode * pi)
+{
+  asmop *aop = NULL;
+  regs *preg = NULL;
+  char *rname, *l;
+  sym_link *retype, *letype;
+  sym_link *ptype = operandType (result);
 
-    etype = getSpec(operandType(result));
+  D (emitcode (";", "genNearPointerSet"));
 
-    /* read the first byte  */
-    switch (ptype) {
+  retype = getSpec (operandType (right));
+  letype = getSpec (ptype);
 
-    case POINTER:
-    case IPOINTER:
-       emitcode("mov","a,@%s",rname);
-       break;
-       
-    case PPOINTER:
-       emitcode("movx","a,@%s",rname);
-       break;
-       
-    case FPOINTER:
-       emitcode("movx","a,@dptr");
-       break;
+  aopOp (result, ic, FALSE);
 
-    case CPOINTER:
-       emitcode("clr","a");
-       emitcode("movc","a","@a+dptr");
-       break;
+  /* if the result is rematerializable &
+     in data space & not a bit variable */
+  if (AOP_TYPE (result) == AOP_IMMD &&
+      DCL_TYPE (ptype) == POINTER &&
+      !IS_BITVAR (retype) &&
+      !IS_BITVAR (letype))
+    {
+      genDataPointerSet (right, result, ic);
+      return;
+    }
 
-    case GPOINTER:
-       emitcode("lcall","__gptrget");
-       break;
-    }
-
-    /* if we have bitdisplacement then it fits   */
-    /* into this byte completely or if length is */
-    /* less than a byte                          */
-    if ((shCnt = SPEC_BSTR(etype)) || 
-        (SPEC_BLEN(etype) <= 8))  {
-
-        /* shift right acc */
-        AccRsh(shCnt);
-
-        emitcode("anl","a,#0x%02x",
-                 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
-        aopPut(AOP(result),"a",offset);
-        return ;
-    }
-
-    /* bit field did not fit in a byte  */
-    rlen = SPEC_BLEN(etype) - 8;
-    aopPut(AOP(result),"a",offset++);
-
-    while (1)  {
-
-       switch (ptype) {
-       case POINTER:
-       case IPOINTER:
-           emitcode("inc","%s",rname);
-           emitcode("mov","a,@%s",rname);
-           break;
-           
-       case PPOINTER:
-           emitcode("inc","%s",rname);
-           emitcode("movx","a,@%s",rname);
-           break;
-
-       case FPOINTER:
-           emitcode("inc","dptr");
-           emitcode("movx","a,@dptr");
-           break;
-           
-       case CPOINTER:
-           emitcode("clr","a");
-           emitcode("inc","dptr");
-           emitcode("movc","a","@a+dptr");
-           break;
-           
-       case GPOINTER:
-           emitcode("inc","dptr");
-           emitcode("lcall","__gptrget");
-           break;
-       }
-
-       rlen -= 8;            
-       /* if we are done */
-       if ( rlen <= 0 )
-           break ;
-       
-       aopPut(AOP(result),"a",offset++);
-                                     
-    }
-    
-    if (rlen) {
-       emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
-       aopPut(AOP(result),"a",offset);        
-    }
-    
-    return ;
-}
+  /* if the value is already in a pointer register
+     then don't need anything more */
+  if (!AOP_INPREG (AOP (result)))
+    {
+        if (
+            //AOP_TYPE (result) == AOP_STK
+            IS_AOP_PREG(result)
+            )
+        {
+            // Aha, it is a pointer, just in disguise.
+            rname = aopGet (result, 0, FALSE, FALSE);
+            if (*rname != '@')
+            {
+                fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
+                        __FILE__, __LINE__);
+            }
+            else
+            {
+                // Expected case.
+                emitcode ("mov", "a%s,%s", rname + 1, rname);
+                rname++;  // skip the '@'.
+            }
+        }
+        else
+        {
+            /* otherwise get a free pointer register */
+            aop = newAsmop (0);
+            preg = getFreePtr (ic, &aop, FALSE);
+            emitcode ("mov", "%s,%s",
+                      preg->name,
+                      aopGet (result, 0, FALSE, TRUE));
+            rname = preg->name;
+        }
+    }
+    else
+    {
+        rname = aopGet (result, 0, FALSE, FALSE);
+    }
 
+  aopOp (right, ic, FALSE);
 
-/*-----------------------------------------------------------------*/
-/* genDataPointerGet - generates code when ptr offset is known     */
-/*-----------------------------------------------------------------*/
-static void genDataPointerGet (operand *left, 
-                              operand *result, 
-                              iCode *ic)
-{
-    char *l;
-    char buffer[256];
-    int size , offset = 0;
-    aopOp(result,ic,TRUE);
+  /* if bitfield then unpack the bits */
+  if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
+    genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
+  else
+    {
+      /* we can just get the values */
+      int size = AOP_SIZE (right);
+      int offset = 0;
 
-    /* get the string representation of the name */
-    l = aopGet(AOP(left),0,FALSE,TRUE);
-    size = AOP_SIZE(result);
-    while (size--) {
-       if (offset)
-           sprintf(buffer,"(%s + %d)",l+1,offset);
-       else
-           sprintf(buffer,"%s",l+1);
-       aopPut(AOP(result),buffer,offset++);
+      while (size--)
+        {
+          l = aopGet (right, offset, FALSE, TRUE);
+          if ((*l == '@') || (strcmp (l, "acc") == 0))
+            {
+              MOVA (l);
+              emitcode ("mov", "@%s,a", rname);
+            }
+          else
+            emitcode ("mov", "@%s,%s", rname, l);
+          if (size || pi)
+            emitcode ("inc", "%s", rname);
+          offset++;
+        }
     }
 
-    freeAsmop(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
-}
+  /* now some housekeeping stuff */
+  if (aop) /* we had to allocate for this iCode */
+    {
+      if (pi)
+        aopPut (result, rname, 0);
+      freeAsmop (NULL, aop, ic, TRUE);
+    }
+  else
+    {
+      /* we did not allocate which means left
+         already in a pointer register, then
+         if size > 0 && this could be used again
+         we have to point it back to where it
+         belongs */
+      if ((AOP_SIZE (right) > 1 &&
+           !OP_SYMBOL (result)->remat &&
+           (OP_SYMBOL (result)->liveTo > ic->seq ||
+            ic->depth)) &&
+          !pi)
+        {
+          int size = AOP_SIZE (right) - 1;
+          while (size--)
+            emitcode ("dec", "%s", rname);
+        }
+    }
 
-/*-----------------------------------------------------------------*/
-/* genNearPointerGet - emitcode for near pointer fetch             */
-/*-----------------------------------------------------------------*/
-static void genNearPointerGet (operand *left, 
-                              operand *result, 
-                              iCode *ic)
-{
-    asmop *aop = NULL;
-    regs *preg = NULL ;
-    char *rname ;
-    link *rtype, *retype;
-    link *ltype = operandType(left);    
-    char buffer[80];
-
-    rtype = operandType(result);
-    retype= getSpec(rtype);
-    
-    aopOp(left,ic,FALSE);
-    
-    /* if left is rematerialisable and
-       result is not bit variable type and
-       the left is pointer to data space i.e
-       lower 128 bytes of space */
-    if (AOP_TYPE(left) == AOP_IMMD &&
-       !IS_BITVAR(retype)         &&
-       DCL_TYPE(ltype) == POINTER) {
-       genDataPointerGet (left,result,ic);
-       return ;
-    }
-    
-       /* if the value is already in a pointer register
-       then don't need anything more */
-    if (!AOP_INPREG(AOP(left))) {
-       /* otherwise get a free pointer register */
-       aop = newAsmop(0);
-       preg = getFreePtr(ic,&aop,FALSE);
-       emitcode("mov","%s,%s",
-               preg->name,
-               aopGet(AOP(left),0,FALSE,TRUE));
-       rname = preg->name ;
-    } else
-       rname = aopGet(AOP(left),0,FALSE,FALSE);
-    
-    freeAsmop(left,NULL,ic,TRUE);
-    aopOp (result,ic,FALSE);
-    
-      /* if bitfield then unpack the bits */
-    if (IS_BITVAR(retype)) 
-       genUnpackBits (result,rname,POINTER);
-    else {
-       /* we have can just get the values */
-       int size = AOP_SIZE(result);
-       int offset = 0 ;        
-       
-       while (size--) {
-           if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
-
-               emitcode("mov","a,@%s",rname);
-               aopPut(AOP(result),"a",offset);
-           } else {
-               sprintf(buffer,"@%s",rname);
-               aopPut(AOP(result),buffer,offset);
-           }
-           offset++ ;
-           if (size)
-               emitcode("inc","%s",rname);
-       }
-    }
-
-    /* now some housekeeping stuff */
-    if (aop) {
-       /* we had to allocate for this iCode */
-       freeAsmop(NULL,aop,ic,TRUE);
-    } else { 
-       /* we did not allocate which means left
-          already in a pointer register, then
-          if size > 0 && this could be used again
-          we have to point it back to where it 
-          belongs */
-       if (AOP_SIZE(result) > 1 &&
-           !OP_SYMBOL(left)->remat &&
-           ( OP_SYMBOL(left)->liveTo > ic->seq ||
-             ic->depth )) {
-           int size = AOP_SIZE(result) - 1;
-           while (size--)
-               emitcode("dec","%s",rname);
-       }
-    }
-
-    /* done */
-    freeAsmop(result,NULL,ic,TRUE);
-     
+  /* done */
+  if (pi) pi->generated = 1;
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genPagedPointerGet - emitcode for paged pointer fetch           */
+/* genPagedPointerSet - emitcode for Paged pointer put             */
 /*-----------------------------------------------------------------*/
-static void genPagedPointerGet (operand *left, 
-                              operand *result, 
-                              iCode *ic)
+static void
+genPagedPointerSet (operand * right,
+                    operand * result,
+                    iCode * ic,
+                    iCode * pi)
 {
-    asmop *aop = NULL;
-    regs *preg = NULL ;
-    char *rname ;
-    link *rtype, *retype;    
+  asmop *aop = NULL;
+  regs *preg = NULL;
+  char *rname, *l;
+  sym_link *retype, *letype;
 
-    rtype = operandType(result);
-    retype= getSpec(rtype);
-    
-    aopOp(left,ic,FALSE);
+  D (emitcode (";", "genPagedPointerSet"));
+
+  retype = getSpec (operandType (right));
+  letype = getSpec (operandType (result));
+
+  aopOp (result, ic, FALSE);
 
   /* if the value is already in a pointer register
-       then don't need anything more */
-    if (!AOP_INPREG(AOP(left))) {
-       /* otherwise get a free pointer register */
-       aop = newAsmop(0);
-       preg = getFreePtr(ic,&aop,FALSE);
-       emitcode("mov","%s,%s",
-               preg->name,
-               aopGet(AOP(left),0,FALSE,TRUE));
-       rname = preg->name ;
-    } else
-       rname = aopGet(AOP(left),0,FALSE,FALSE);
-    
-    freeAsmop(left,NULL,ic,TRUE);
-    aopOp (result,ic,FALSE);
-
-    /* if bitfield then unpack the bits */
-    if (IS_BITVAR(retype)) 
-       genUnpackBits (result,rname,PPOINTER);
-    else {
-       /* we have can just get the values */
-       int size = AOP_SIZE(result);
-       int offset = 0 ;        
-       
-       while (size--) {
-           
-           emitcode("movx","a,@%s",rname);
-           aopPut(AOP(result),"a",offset);
-           
-           offset++ ;
-           
-           if (size)
-               emitcode("inc","%s",rname);
-       }
-    }
-
-    /* now some housekeeping stuff */
-    if (aop) {
-       /* we had to allocate for this iCode */
-       freeAsmop(NULL,aop,ic,TRUE);
-    } else { 
-       /* we did not allocate which means left
-          already in a pointer register, then
-          if size > 0 && this could be used again
-          we have to point it back to where it 
-          belongs */
-       if (AOP_SIZE(result) > 1 &&
-           !OP_SYMBOL(left)->remat &&
-           ( OP_SYMBOL(left)->liveTo > ic->seq ||
-             ic->depth )) {
-           int size = AOP_SIZE(result) - 1;
-           while (size--)
-               emitcode("dec","%s",rname);
-       }
-    }
-
-    /* done */
-    freeAsmop(result,NULL,ic,TRUE);
-    
-       
-}
-
-/*-----------------------------------------------------------------*/
-/* genFarPointerGet - gget value from far space                    */
-/*-----------------------------------------------------------------*/
-static void genFarPointerGet (operand *left,
-                              operand *result, iCode *ic)
-{
-    int size, offset ;
-    link *retype = getSpec(operandType(result));
-
-    aopOp(left,ic,FALSE);
-
-    /* if the operand is already in dptr 
-    then we do nothing else we move the value to dptr */
-    if (AOP_TYPE(left) != AOP_STR) {
-        /* if this is remateriazable */
-        if (AOP_TYPE(left) == AOP_IMMD)
-            emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
-        else { /* we need to get it byte by byte */
-            emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
-            emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
-            if (options.model == MODEL_FLAT24)
-            {
-               emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
-            }
-        }
-    }
-    /* so dptr know contains the address */
-    freeAsmop(left,NULL,ic,TRUE);
-    aopOp(result,ic,FALSE);
-
-    /* if bit then unpack */
-    if (IS_BITVAR(retype)) 
-        genUnpackBits(result,"dptr",FPOINTER);
-    else {
-        size = AOP_SIZE(result);
-        offset = 0 ;
-
-        while (size--) {
-            emitcode("movx","a,@dptr");
-            aopPut(AOP(result),"a",offset++);
-            if (size)
-                emitcode("inc","dptr");
+     then don't need anything more */
+  if (!AOP_INPREG (AOP (result)))
+    {
+      /* otherwise get a free pointer register */
+      aop = newAsmop (0);
+      preg = getFreePtr (ic, &aop, FALSE);
+      emitcode ("mov", "%s,%s",
+                preg->name,
+                aopGet (result, 0, FALSE, TRUE));
+      rname = preg->name;
+    }
+  else
+    rname = aopGet (result, 0, FALSE, FALSE);
+
+  aopOp (right, ic, FALSE);
+
+  /* if bitfield then unpack the bits */
+  if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
+    genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
+  else
+    {
+      /* we have can just get the values */
+      int size = AOP_SIZE (right);
+      int offset = 0;
+
+      while (size--)
+        {
+          l = aopGet (right, offset, FALSE, TRUE);
+          MOVA (l);
+          emitcode ("movx", "@%s,a", rname);
+
+          if (size || pi)
+            emitcode ("inc", "%s", rname);
+
+          offset++;
+        }
+    }
+
+  /* now some housekeeping stuff */
+  if (aop) /* we had to allocate for this iCode */
+    {
+      if (pi)
+        aopPut (result, rname, 0);
+      freeAsmop (NULL, aop, ic, TRUE);
+    }
+  else
+    {
+      /* we did not allocate which means left
+         already in a pointer register, then
+         if size > 0 && this could be used again
+         we have to point it back to where it
+         belongs */
+      if (AOP_SIZE (right) > 1 &&
+          !OP_SYMBOL (result)->remat &&
+          (OP_SYMBOL (result)->liveTo > ic->seq ||
+           ic->depth))
+        {
+          int size = AOP_SIZE (right) - 1;
+          while (size--)
+            emitcode ("dec", "%s", rname);
         }
     }
 
-    freeAsmop(result,NULL,ic,TRUE);
+  /* done */
+  if (pi) pi->generated = 1;
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* emitcodePointerGet - gget value from code space                  */
+/* genFarPointerSet - set value from far space                     */
 /*-----------------------------------------------------------------*/
-static void emitcodePointerGet (operand *left,
-                                operand *result, iCode *ic)
+static void
+genFarPointerSet (operand * right,
+                  operand * result, iCode * ic, iCode * pi)
 {
-    int size, offset ;
-    link *retype = getSpec(operandType(result));
+  int size, offset;
+  sym_link *retype = getSpec (operandType (right));
+  sym_link *letype = getSpec (operandType (result));
 
-    aopOp(left,ic,FALSE);
+  D(emitcode (";     genFarPointerSet",""));
 
-    /* if the operand is already in dptr 
-    then we do nothing else we move the value to dptr */
-    if (AOP_TYPE(left) != AOP_STR) {
-        /* if this is remateriazable */
-        if (AOP_TYPE(left) == AOP_IMMD)
-            emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
-        else { /* we need to get it byte by byte */
-            emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
-            emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
-            if (options.model == MODEL_FLAT24)
-            {
-               emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
-            }
-        }
-    }
-    /* so dptr know contains the address */
-    freeAsmop(left,NULL,ic,TRUE);
-    aopOp(result,ic,FALSE);
+  aopOp (result, ic, FALSE);
+  loadDptrFromOperand (result, FALSE);
 
-    /* if bit then unpack */
-    if (IS_BITVAR(retype)) 
-        genUnpackBits(result,"dptr",CPOINTER);
-    else {
-        size = AOP_SIZE(result);
-        offset = 0 ;
+  /* so dptr now contains the address */
+  aopOp (right, ic, FALSE);
 
-        while (size--) {
-            emitcode("clr","a");
-            emitcode("movc","a,@a+dptr");
-            aopPut(AOP(result),"a",offset++);
-            if (size)
-                emitcode("inc","dptr");
+  /* if bit then unpack */
+  if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
+    genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
+  else
+    {
+      size = AOP_SIZE (right);
+      offset = 0;
+
+      while (size--)
+        {
+          char *l = aopGet (right, offset++, FALSE, FALSE);
+          MOVA (l);
+          emitcode ("movx", "@dptr,a");
+          if (size || pi)
+            emitcode ("inc", "dptr");
         }
     }
-
-    freeAsmop(result,NULL,ic,TRUE);
+  if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
+    aopPut (result, "dpl", 0);
+    aopPut (result, "dph", 1);
+    pi->generated=1;
+  }
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genGenPointerGet - gget value from generic pointer space        */
+/* genGenPointerSet - set value from generic pointer space         */
 /*-----------------------------------------------------------------*/
-static void genGenPointerGet (operand *left,
-                              operand *result, iCode *ic)
+static void
+genGenPointerSet (operand * right,
+                  operand * result, iCode * ic, iCode * pi)
 {
-    int size, offset ;
-    link *retype = getSpec(operandType(result));
+  int size, offset;
+  sym_link *retype = getSpec (operandType (right));
+  sym_link *letype = getSpec (operandType (result));
 
-    aopOp(left,ic,FALSE);
+  D (emitcode (";", "genGenPointerSet"));
 
-    /* if the operand is already in dptr 
-    then we do nothing else we move the value to dptr */
-    if (AOP_TYPE(left) != AOP_STR) {
-        /* if this is remateriazable */
-        if (AOP_TYPE(left) == AOP_IMMD) {
-            emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
-           emitcode("mov","b,#%d",pointerCode(retype));
-       }
-        else { /* we need to get it byte by byte */
-            emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
-            emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
-            if (options.model == MODEL_FLAT24)
-            {
-               emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
-               emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
-            }
-            else
-            {
-               emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
-            }
-        }
-    }
-    /* so dptr know contains the address */
-    freeAsmop(left,NULL,ic,TRUE);
-    aopOp(result,ic, /* FALSE */ TRUE); 
+  aopOp (result, ic, FALSE);
+  loadDptrFromOperand (result, TRUE);
 
-    /* if bit then unpack */
-    if (IS_BITVAR(retype)) 
-        genUnpackBits(result,"dptr",GPOINTER);
-    else {
-        size = AOP_SIZE(result);
-        offset = 0 ;
+  /* so dptr now contains the address */
+  aopOp (right, ic, FALSE);
 
-        while (size--) {
-            emitcode("lcall","__gptrget");
-            aopPut(AOP(result),"a",offset++);
-            if (size)
-                emitcode("inc","dptr");
+  /* if bit then unpack */
+  if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
+    {
+      genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
+    }
+  else
+    {
+      size = AOP_SIZE (right);
+      offset = 0;
+
+      while (size--)
+        {
+          char *l = aopGet (right, offset++, FALSE, FALSE);
+          MOVA (l);
+          emitcode ("lcall", "__gptrput");
+          if (size || pi)
+            emitcode ("inc", "dptr");
         }
     }
 
-    freeAsmop(result,NULL,ic,TRUE);
+  if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
+    aopPut (result, "dpl", 0);
+    aopPut (result, "dph", 1);
+    pi->generated=1;
+  }
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genPointerGet - generate code for pointer get                   */
+/* genPointerSet - stores the value into a pointer location        */
 /*-----------------------------------------------------------------*/
-static void genPointerGet (iCode *ic)
-{
-    operand *left, *result ;
-    link *type, *etype;
-    int p_type;
-
-    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);
-    /* if left is of type of pointer then it is simple */
-    if (IS_PTR(type) && !IS_FUNC(type->next)) 
-        p_type = DCL_TYPE(type);
-    else {
-       /* we have to go by the storage class */
-       p_type = PTR_TYPE(SPEC_OCLS(etype));
-
-/*     if (SPEC_OCLS(etype)->codesp ) { */
-/*         p_type = CPOINTER ;  */
-/*     } */
-/*     else */
-/*         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
-/*             p_type = FPOINTER ; */
-/*         else */
-/*             if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
-/*                 p_type = PPOINTER; */
-/*             else */
-/*                 if (SPEC_OCLS(etype) == idata ) */
-/*                     p_type = IPOINTER; */
-/*                 else */
-/*                     p_type = POINTER ; */
-    }
-
-    /* now that we have the pointer type we assign
-    the pointer values */
-    switch (p_type) {
-
-    case POINTER:      
+static void
+genPointerSet (iCode * ic, iCode *pi)
+{
+  operand *right, *result;
+  sym_link *type, *etype;
+  int p_type;
+
+  D (emitcode (";", "genPointerSet"));
+
+  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);
+  /* if left is of type of pointer then it is simple */
+  if (IS_PTR (type) && !IS_FUNC (type->next))
+    {
+      p_type = DCL_TYPE (type);
+    }
+  else
+    {
+      /* we have to go by the storage class */
+      p_type = PTR_TYPE (SPEC_OCLS (etype));
+    }
+
+  /* special case when cast remat */
+  if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
+      IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
+          result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
+          type = operandType (result);
+          p_type = DCL_TYPE (type);
+  }
+
+  /* now that we have the pointer type we assign
+     the pointer values */
+  switch (p_type)
+    {
+
+    case POINTER:
     case IPOINTER:
-       genNearPointerGet (left,result,ic);
-       break;
+      genNearPointerSet (right, result, ic, pi);
+      break;
 
     case PPOINTER:
-       genPagedPointerGet(left,result,ic);
-       break;
+      genPagedPointerSet (right, result, ic, pi);
+      break;
 
     case FPOINTER:
-       genFarPointerGet (left,result,ic);
-       break;
-
-    case CPOINTER:
-       emitcodePointerGet (left,result,ic);
-       break;
+      genFarPointerSet (right, result, ic, pi);
+      break;
 
     case GPOINTER:
-       genGenPointerGet (left,result,ic);
-       break;
-    }
+      genGenPointerSet (right, result, ic, pi);
+      break;
 
+    default:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+              "genPointerSet: illegal pointer type");
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* genPackBits - generates code for packed bit storage             */
+/* genIfx - generate code for Ifx statement                        */
 /*-----------------------------------------------------------------*/
-static void genPackBits (link    *etype ,
-                         operand *right ,
-                         char *rname, int p_type)
+static void
+genIfx (iCode * ic, iCode * popIc)
 {
-    int shCount = 0 ;
-    int offset = 0  ;
-    int rLen = 0 ;
-    int blen, bstr ;   
-    char *l ;
+  operand *cond = IC_COND (ic);
+  int isbit = 0;
+  char *dup = NULL;
+
+  D (emitcode (";", "genIfx"));
+
+  aopOp (cond, ic, FALSE);
+
+  /* get the value into acc */
+  if (AOP_TYPE (cond) != AOP_CRY)
+    {
+      toBoolean (cond);
+    }
+  else
+    {
+      isbit = 1;
+      if (AOP(cond)->aopu.aop_dir)
+        dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
+    }
 
-    blen = SPEC_BLEN(etype);
-    bstr = SPEC_BSTR(etype);
+  /* the result is now in the accumulator or a directly addressable bit */
+  freeAsmop (cond, NULL, ic, TRUE);
 
-    l = aopGet(AOP(right),offset++,FALSE,FALSE);
-    MOVA(l);   
+  /* if there was something to be popped then do it */
+  if (popIc)
+    genIpop (popIc);
 
-    /* if the bit lenth is less than or    */
-    /* it exactly fits a byte then         */
-    if (SPEC_BLEN(etype) <= 8 )  {
-        shCount = SPEC_BSTR(etype) ;
+  /* if the condition is a bit variable */
+  if (isbit && dup)
+    genIfxJump(ic, dup, NULL, NULL, NULL);
+  else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
+    genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
+  else if (isbit && !IS_ITEMP (cond))
+    genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
+  else
+    genIfxJump (ic, "a", NULL, NULL, NULL);
 
-        /* shift left acc */
-        AccLsh(shCount);
+  ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* genAddrOf - generates code for address of                       */
+/*-----------------------------------------------------------------*/
+static void
+genAddrOf (iCode * ic)
+{
+  symbol *sym = OP_SYMBOL (IC_LEFT (ic));
+  int size, offset;
+
+  D (emitcode (";", "genAddrOf"));
+
+  aopOp (IC_RESULT (ic), ic, FALSE);
 
-        if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
+  /* 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 (sym->stack)
+        {
+          emitcode ("mov", "a,%s", SYM_BP (sym));
+          emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
+                                         ((char) (sym->stack - _G.nRegsSaved)) :
+                                         ((char) sym->stack)) & 0xff);
+          aopPut (IC_RESULT (ic), "a", 0);
+        }
+      else
+        {
+          /* we can just move _bp */
+          aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
+        }
+      /* fill the result with zero */
+      size = AOP_SIZE (IC_RESULT (ic)) - 1;
 
+      offset = 1;
+      while (size--)
+        {
+          aopPut (IC_RESULT (ic), zero, offset++);
+        }
+      goto release;
+    }
 
-            switch (p_type) {
-                case POINTER:
-                    emitcode ("mov","b,a");
-                    emitcode("mov","a,@%s",rname);
-                    break;
+  /* object not on stack then we need the name */
+  size = AOP_SIZE (IC_RESULT (ic));
+  offset = 0;
 
-                case FPOINTER:
-                    emitcode ("mov","b,a");
-                    emitcode("movx","a,@dptr");
-                    break;
+  while (size--)
+    {
+      char s[SDCC_NAME_MAX];
+      if (offset)
+        sprintf (s, "#(%s >> %d)",
+                 sym->rname,
+                 offset * 8);
+      else
+        SNPRINTF (s, sizeof(s), "#%s", sym->rname);
+      aopPut (IC_RESULT (ic), s, offset++);
+    }
 
-                case GPOINTER:
-                    emitcode ("push","b");
-                    emitcode ("push","acc");
-                    emitcode ("lcall","__gptrget");
-                    emitcode ("pop","b");
-                    break;
-            }
+release:
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
 
-            emitcode ("anl","a,#0x%02x",(unsigned char)
-                      ((unsigned char)(0xFF << (blen+bstr)) | 
-                       (unsigned char)(0xFF >> (8-bstr)) ) );
-            emitcode ("orl","a,b");
-            if (p_type == GPOINTER)
-                emitcode("pop","b");
-        }
-    }
+}
 
-    switch (p_type) {
-        case POINTER:
-            emitcode("mov","@%s,a",rname);
-            break;
+/*-----------------------------------------------------------------*/
+/* genFarFarAssign - assignment when both are in far space         */
+/*-----------------------------------------------------------------*/
+static void
+genFarFarAssign (operand * result, operand * right, iCode * ic)
+{
+  int size = AOP_SIZE (right);
+  int offset = 0;
+  char *l;
 
-        case FPOINTER:
-            emitcode("movx","@dptr,a");
-            break;
+  D (emitcode (";", "genFarFarAssign"));
 
-        case GPOINTER:
-            emitcode("lcall","__gptrput");
-            break;
+  /* first push the right side on to the stack */
+  while (size--)
+    {
+      l = aopGet (right, offset++, FALSE, FALSE);
+      MOVA (l);
+      emitcode ("push", "acc");
     }
 
-    /* if we r done */
-    if ( SPEC_BLEN(etype) <= 8 )
-        return ;
-
-    emitcode("inc","%s",rname);
-    rLen = SPEC_BLEN(etype) ;     
+  freeAsmop (right, NULL, ic, FALSE);
+  /* now assign DPTR to result */
+  aopOp (result, ic, FALSE);
+  size = AOP_SIZE (result);
+  while (size--)
+    {
+      emitcode ("pop", "acc");
+      aopPut (result, "a", --offset);
+    }
+  freeAsmop (result, NULL, ic, FALSE);
+}
 
-    /* now generate for lengths greater than one byte */
-    while (1) {
+/*-----------------------------------------------------------------*/
+/* genAssign - generate code for assignment                        */
+/*-----------------------------------------------------------------*/
+static void
+genAssign (iCode * ic)
+{
+  operand *result, *right;
+  int size, offset;
+  unsigned long lit = 0L;
 
-        l = aopGet(AOP(right),offset++,FALSE,TRUE);
+  D (emitcode (";", "genAssign"));
 
-        rLen -= 8 ;
-        if (rLen <= 0 )
-            break ;
+  result = IC_RESULT (ic);
+  right = IC_RIGHT (ic);
 
-        switch (p_type) {
-            case POINTER:
-                if (*l == '@') {
-                    MOVA(l);
-                    emitcode("mov","@%s,a",rname);
-                } else
-                    emitcode("mov","@%s,%s",rname,l);
-                break;
+  /* if they are the same */
+  if (operandsEqu (result, right) &&
+      !isOperandVolatile (result, FALSE) &&
+      !isOperandVolatile (right, FALSE))
+    return;
 
-            case FPOINTER:
-                MOVA(l);
-                emitcode("movx","@dptr,a");
-                break;
+  aopOp (right, ic, FALSE);
 
-            case GPOINTER:
-                MOVA(l);
-                emitcode("lcall","__gptrput");
-                break;  
-        }   
-        emitcode ("inc","%s",rname);
+  /* special case both in far space */
+  if (AOP_TYPE (right) == AOP_DPTR &&
+      IS_TRUE_SYMOP (result) &&
+      isOperandInFarSpace (result))
+    {
+      genFarFarAssign (result, right, ic);
+      return;
     }
 
-    MOVA(l);
+  aopOp (result, ic, TRUE);
 
-    /* last last was not complete */
-    if (rLen)   {
-        /* save the byte & read byte */
-        switch (p_type) {
-            case POINTER:
-                emitcode ("mov","b,a");
-                emitcode("mov","a,@%s",rname);
-                break;
+  /* if they are the same registers */
+  if (sameRegs (AOP (right), AOP (result)) &&
+      !isOperandVolatile (result, FALSE) &&
+      !isOperandVolatile (right, FALSE))
+    goto release;
 
-            case FPOINTER:
-                emitcode ("mov","b,a");
-                emitcode("movx","a,@dptr");
-                break;
+  /* if the result is a bit */
+  if (AOP_TYPE (result) == AOP_CRY)
+    {
+      /* if the right size is a literal then
+         we know what the value is */
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          if (((int) operandLitValue (right)))
+            aopPut (result, one, 0);
+          else
+            aopPut (result, zero, 0);
+          goto release;
+        }
 
-            case GPOINTER:
-                emitcode ("push","b");
-                emitcode ("push","acc");
-                emitcode ("lcall","__gptrget");
-                emitcode ("pop","b");
-                break;
+      /* the right is also a bit variable */
+      if (AOP_TYPE (right) == AOP_CRY)
+        {
+          emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
+          aopPut (result, "c", 0);
+          goto release;
         }
 
-        emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
-        emitcode ("orl","a,b");
+      /* we need to or */
+      toBoolean (right);
+      aopPut (result, "a", 0);
+      goto release;
     }
 
-    if (p_type == GPOINTER)
-        emitcode("pop","b");
-
-    switch (p_type) {
+  /* bit variables done */
+  /* general case */
+  size = AOP_SIZE (result);
+  offset = 0;
+  if (AOP_TYPE (right) == AOP_LIT)
+    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
 
-    case POINTER:
-       emitcode("mov","@%s,a",rname);
-       break;
-       
-    case FPOINTER:
-       emitcode("movx","@dptr,a");
-       break;
-       
-    case GPOINTER:
-       emitcode("lcall","__gptrput");
-       break;                  
+  if ((size > 1) &&
+      (AOP_TYPE (result) != AOP_REG) &&
+      (AOP_TYPE (right) == AOP_LIT) &&
+      !IS_FLOAT (operandType (right)) &&
+      (lit < 256L))
+    {
+      while ((size) && (lit))
+        {
+          aopPut (result,
+                  aopGet (right, offset, FALSE, FALSE),
+                  offset);
+          lit >>= 8;
+          offset++;
+          size--;
+        }
+      /* And now fill the rest with zeros. */
+      if (size)
+        {
+          emitcode ("clr", "a");
+        }
+      while (size--)
+        {
+          aopPut (result, "a", offset);
+          offset++;
+        }
     }
+  else
+    {
+      while (size--)
+        {
+          aopPut (result,
+                  aopGet (right, offset, FALSE, FALSE),
+                  offset);
+          offset++;
+        }
+    }
+
+release:
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
 }
+
 /*-----------------------------------------------------------------*/
-/* genDataPointerSet - remat pointer to data space                 */
+/* genJumpTab - generates code for jump table                      */
 /*-----------------------------------------------------------------*/
-static void genDataPointerSet(operand *right,
-                             operand *result,
-                             iCode *ic)
+static void
+genJumpTab (iCode * ic)
 {
-    int size, offset = 0 ;
-    char *l, buffer[256];
+  symbol *jtab,*jtablo,*jtabhi;
+  char *l;
+  unsigned int count;
 
-    aopOp(right,ic,FALSE);
-    
-    l = aopGet(AOP(result),0,FALSE,TRUE);
-    size = AOP_SIZE(right);
-    while (size--) {
-       if (offset)
-           sprintf(buffer,"(%s + %d)",l+1,offset);
-       else
-           sprintf(buffer,"%s",l+1);
-       emitcode("mov","%s,%s",buffer,
-                aopGet(AOP(right),offset++,FALSE,FALSE));
-    }
+  D (emitcode (";", "genJumpTab"));
 
-    freeAsmop(right,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
-}
+  count = elementsInSet( IC_JTLABELS (ic) );
 
-/*-----------------------------------------------------------------*/
-/* genNearPointerSet - emitcode for near pointer put                */
-/*-----------------------------------------------------------------*/
-static void genNearPointerSet (operand *right,
-                               operand *result, 
-                               iCode *ic)
-{
-    asmop *aop = NULL;
-    regs *preg = NULL ;
-    char *rname , *l;
-    link *retype;
-    link *ptype = operandType(result);
-    
-    retype= getSpec(operandType(right));
-
-    aopOp(result,ic,FALSE);
-    
-    /* if the result is rematerializable &
-       in data space & not a bit variable */
-    if (AOP_TYPE(result) == AOP_IMMD &&
-       DCL_TYPE(ptype) == POINTER   &&
-       !IS_BITVAR(retype)) {
-       genDataPointerSet (right,result,ic);
-       return;
-    }
-
-    /* if the value is already in a pointer register
-    then don't need anything more */
-    if (!AOP_INPREG(AOP(result))) {
-        /* otherwise get a free pointer register */
-        aop = newAsmop(0);
-        preg = getFreePtr(ic,&aop,FALSE);
-        emitcode("mov","%s,%s",
-                 preg->name,
-                 aopGet(AOP(result),0,FALSE,TRUE));
-        rname = preg->name ;
-    } else
-        rname = aopGet(AOP(result),0,FALSE,FALSE);
-
-    freeAsmop(result,NULL,ic,TRUE);
-    aopOp (right,ic,FALSE);
-
-    /* if bitfield then unpack the bits */
-    if (IS_BITVAR(retype)) 
-        genPackBits (retype,right,rname,POINTER);
-    else {
-        /* we have can just get the values */
-        int size = AOP_SIZE(right);
-        int offset = 0 ;    
-
-        while (size--) {
-            l = aopGet(AOP(right),offset,FALSE,TRUE);
-            if (*l == '@' ) {
-                MOVA(l);
-                emitcode("mov","@%s,a",rname);
-            } else
-                emitcode("mov","@%s,%s",rname,l);
-            if (size)
-                emitcode("inc","%s",rname);
-            offset++;
+  if( count <= 16 )
+    {
+      /* this algorithm needs 9 cycles and 7 + 3*n bytes
+         if the switch argument is in a register.
+         (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
+      /* Peephole may not convert ljmp to sjmp or ret
+         labelIsReturnOnly & labelInRange must check
+         currPl->ic->op != JUMPTABLE */
+      aopOp (IC_JTCOND (ic), ic, FALSE);
+      /* get the condition into accumulator */
+      l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
+      MOVA (l);
+      /* multiply by three */
+      if (aopGetUsesAcc (IC_JTCOND (ic), 0))
+        {
+          emitcode ("mov", "b,#3");
+          emitcode ("mul", "ab");
         }
-    }
-
-    /* now some housekeeping stuff */
-    if (aop) {
-        /* we had to allocate for this iCode */
-        freeAsmop(NULL,aop,ic,TRUE);
-    } else { 
-        /* we did not allocate which means left
-        already in a pointer register, then
-        if size > 0 && this could be used again
-        we have to point it back to where it 
-        belongs */
-        if (AOP_SIZE(right) > 1 &&
-            !OP_SYMBOL(result)->remat &&
-            ( OP_SYMBOL(result)->liveTo > ic->seq ||
-              ic->depth )) {
-            int size = AOP_SIZE(right) - 1;
-            while (size--)
-                emitcode("dec","%s",rname);
+      else
+        {
+          emitcode ("add", "a,acc");
+          emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
+        }
+      freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
+
+      jtab = newiTempLabel (NULL);
+      emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
+      emitcode ("jmp", "@a+dptr");
+      emitLabel (jtab);
+      /* now generate the jump labels */
+      for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
+           jtab = setNextItem (IC_JTLABELS (ic)))
+        emitcode ("ljmp", "%05d$", jtab->key + 100);
+    }
+  else
+    {
+      /* this algorithm needs 14 cycles and 13 + 2*n bytes
+         if the switch argument is in a register.
+         For n>6 this algorithm may be more compact */
+      jtablo = newiTempLabel (NULL);
+      jtabhi = newiTempLabel (NULL);
+
+      /* get the condition into accumulator.
+         Using b as temporary storage, if register push/pop is needed */
+      aopOp (IC_JTCOND (ic), ic, FALSE);
+      l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
+      if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
+          (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
+        {
+          // (MB) what if B is in use???
+          wassertl(!BINUSE, "B was in use");
+          emitcode ("mov", "b,%s", l);
+          l = "b";
+        }
+      freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
+      MOVA (l);
+      if( count <= 112 )
+        {
+          emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
+          emitcode ("movc", "a,@a+pc");
+          emitcode ("push", "acc");
+
+          MOVA (l);
+          emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
+          emitcode ("movc", "a,@a+pc");
+          emitcode ("push", "acc");
+        }
+      else
+        {
+          /* this scales up to n<=255, but needs two more bytes
+             and changes dptr */
+          emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
+          emitcode ("movc", "a,@a+dptr");
+          emitcode ("push", "acc");
+
+          MOVA (l);
+          emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
+          emitcode ("movc", "a,@a+dptr");
+          emitcode ("push", "acc");
         }
-    }
-
-    /* done */
-    freeAsmop(right,NULL,ic,TRUE);
 
+      emitcode ("ret", "");
 
-}
+      /* now generate jump table, LSB */
+      emitLabel (jtablo);
+      for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
+           jtab = setNextItem (IC_JTLABELS (ic)))
+        emitcode (".db", "%05d$", jtab->key + 100);
 
-/*-----------------------------------------------------------------*/
-/* genPagedPointerSet - emitcode for Paged pointer put             */
-/*-----------------------------------------------------------------*/
-static void genPagedPointerSet (operand *right,
-                              operand *result, 
-                              iCode *ic)
-{
-    asmop *aop = NULL;
-    regs *preg = NULL ;
-    char *rname , *l;
-    link *retype;
-       
-    retype= getSpec(operandType(right));
-    
-    aopOp(result,ic,FALSE);
-    
-    /* if the value is already in a pointer register
-       then don't need anything more */
-    if (!AOP_INPREG(AOP(result))) {
-       /* otherwise get a free pointer register */
-       aop = newAsmop(0);
-       preg = getFreePtr(ic,&aop,FALSE);
-       emitcode("mov","%s,%s",
-               preg->name,
-               aopGet(AOP(result),0,FALSE,TRUE));
-       rname = preg->name ;
-    } else
-       rname = aopGet(AOP(result),0,FALSE,FALSE);
-    
-    freeAsmop(result,NULL,ic,TRUE);
-    aopOp (right,ic,FALSE);
-
-    /* if bitfield then unpack the bits */
-    if (IS_BITVAR(retype)) 
-       genPackBits (retype,right,rname,PPOINTER);
-    else {
-       /* we have can just get the values */
-       int size = AOP_SIZE(right);
-       int offset = 0 ;        
-       
-       while (size--) {
-           l = aopGet(AOP(right),offset,FALSE,TRUE);
-           
-           MOVA(l);
-           emitcode("movx","@%s,a",rname);
-
-           if (size)
-               emitcode("inc","%s",rname);
-
-           offset++;
-       }
-    }
-    
-    /* now some housekeeping stuff */
-    if (aop) {
-       /* we had to allocate for this iCode */
-       freeAsmop(NULL,aop,ic,TRUE);
-    } else { 
-       /* we did not allocate which means left
-          already in a pointer register, then
-          if size > 0 && this could be used again
-          we have to point it back to where it 
-          belongs */
-       if (AOP_SIZE(right) > 1 &&
-           !OP_SYMBOL(result)->remat &&
-           ( OP_SYMBOL(result)->liveTo > ic->seq ||
-             ic->depth )) {
-           int size = AOP_SIZE(right) - 1;
-           while (size--)
-               emitcode("dec","%s",rname);
-       }
-    }
-
-    /* done */
-    freeAsmop(right,NULL,ic,TRUE);
-    
-       
+      /* now generate jump table, MSB */
+      emitLabel (jtabhi);
+      for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
+           jtab = setNextItem (IC_JTLABELS (ic)))
+         emitcode (".db", "%05d$>>8", jtab->key + 100);
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* genFarPointerSet - set value from far space                     */
+/* genCast - gen code for casting                                  */
 /*-----------------------------------------------------------------*/
-static void genFarPointerSet (operand *right,
-                              operand *result, iCode *ic)
+static void
+genCast (iCode * ic)
 {
-    int size, offset ;
-    link *retype = getSpec(operandType(right));
+  operand *result = IC_RESULT (ic);
+  sym_link *ctype = operandType (IC_LEFT (ic));
+  sym_link *rtype = operandType (IC_RIGHT (ic));
+  operand *right = IC_RIGHT (ic);
+  int size, offset;
 
-    aopOp(result,ic,FALSE);
+  D (emitcode (";", "genCast"));
 
-    /* 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("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
-        else { /* we need to get it byte by byte */
-            emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
-            emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
-            if (options.model == MODEL_FLAT24)
-            {
-               emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
-            }
+  /* if they are equivalent then do nothing */
+  if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
+    return;
+
+  aopOp (right, ic, FALSE);
+  aopOp (result, ic, FALSE);
+
+  /* if the result is a bit (and not a bitfield) */
+  if (IS_BIT (OP_SYMBOL (result)->type))
+    {
+      /* if the right size is a literal then
+         we know what the value is */
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          if (((int) operandLitValue (right)))
+            aopPut (result, one, 0);
+          else
+            aopPut (result, zero, 0);
+
+          goto release;
+        }
+
+      /* the right is also a bit variable */
+      if (AOP_TYPE (right) == AOP_CRY)
+        {
+          emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
+          aopPut (result, "c", 0);
+          goto release;
         }
+
+      /* we need to or */
+      toBoolean (right);
+      aopPut (result, "a", 0);
+      goto release;
     }
-    /* so dptr know contains the address */
-    freeAsmop(result,NULL,ic,TRUE);
-    aopOp(right,ic,FALSE);
 
-    /* if bit then unpack */
-    if (IS_BITVAR(retype)) 
-        genPackBits(retype,right,"dptr",FPOINTER);
-    else {
-        size = AOP_SIZE(right);
-        offset = 0 ;
+  /* if they are the same size : or less */
+  if (AOP_SIZE (result) <= AOP_SIZE (right))
+    {
 
-        while (size--) {
-            char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
-            MOVA(l);
-            emitcode("movx","@dptr,a");
-            if (size)
-                emitcode("inc","dptr");
+      /* 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 (result,
+                  aopGet (right, offset, FALSE, FALSE),
+                  offset);
+          offset++;
         }
+      goto release;
     }
 
-    freeAsmop(right,NULL,ic,TRUE);
-}
+  /* if the result is of type pointer */
+  if (IS_PTR (ctype))
+    {
 
-/*-----------------------------------------------------------------*/
-/* genGenPointerSet - set value from generic pointer space         */
-/*-----------------------------------------------------------------*/
-static void genGenPointerSet (operand *right,
-                              operand *result, iCode *ic)
-{
-    int size, offset ;
-    link *retype = getSpec(operandType(right));
+      int p_type;
+      sym_link *type = operandType (right);
+      sym_link *etype = getSpec (type);
 
-    aopOp(result,ic,FALSE);
+      /* pointer to generic pointer */
+      if (IS_GENPTR (ctype))
+        {
+          if (IS_PTR (type))
+            {
+              p_type = DCL_TYPE (type);
+            }
+          else
+            {
+              if (SPEC_SCLS(etype)==S_REGISTER) {
+                // let's assume it is a generic pointer
+                p_type=GPOINTER;
+              } else {
+                /* we have to go by the storage class */
+                p_type = PTR_TYPE (SPEC_OCLS (etype));
+              }
+            }
 
-    /* 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("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
-            emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
-        }
-        else { /* we need to get it byte by byte */
-            emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
-            emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
-            if (options.model == MODEL_FLAT24)
+          /* the first two bytes are known */
+          size = GPTRSIZE - 1;
+          offset = 0;
+          while (size--)
             {
-               emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
-               emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
+              aopPut (result,
+                      aopGet (right, offset, FALSE, FALSE),
+                      offset);
+              offset++;
             }
-            else
+          /* the last byte depending on type */
             {
-               emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
+                int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
+                char gpValStr[10];
+
+                if (gpVal == -1)
+                {
+                    // pointerTypeToGPByte will have bitched.
+                    exit(1);
+                }
+
+                sprintf(gpValStr, "#0x%x", gpVal);
+                aopPut (result, gpValStr, GPTRSIZE - 1);
             }
+          goto release;
+        }
+
+      /* just copy the pointers */
+      size = AOP_SIZE (result);
+      offset = 0;
+      while (size--)
+        {
+          aopPut (result,
+                  aopGet (right, offset, FALSE, FALSE),
+                  offset);
+          offset++;
         }
+      goto release;
     }
-    /* so dptr know contains the address */
-    freeAsmop(result,NULL,ic,TRUE);
-    aopOp(right,ic,FALSE);
 
-    /* if bit then unpack */
-    if (IS_BITVAR(retype)) 
-        genPackBits(retype,right,"dptr",GPOINTER);
-    else {
-        size = AOP_SIZE(right);
-        offset = 0 ;
+  /* 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 (result,
+              aopGet (right, offset, FALSE, FALSE),
+              offset);
+      offset++;
+    }
 
-        while (size--) {
-            char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
-            MOVA(l);
-            emitcode("lcall","__gptrput");
-            if (size)
-                emitcode("inc","dptr");
-        }
+  /* now depending on the sign of the source && destination */
+  size = AOP_SIZE (result) - AOP_SIZE (right);
+  /* if unsigned or not an integral type */
+  if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
+    {
+      while (size--)
+        aopPut (result, zero, offset++);
+    }
+  else
+    {
+      /* we need to extend the sign :{ */
+      char *l = aopGet (right, AOP_SIZE (right) - 1,
+                        FALSE, FALSE);
+      MOVA (l);
+      emitcode ("rlc", "a");
+      emitcode ("subb", "a,acc");
+      while (size--)
+        aopPut (result, "a", offset++);
     }
 
-    freeAsmop(right,NULL,ic,TRUE);
+  /* we are done hurray !!!! */
+
+release:
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genPointerSet - stores the value into a pointer location        */
+/* genDjnz - generate decrement & jump if not zero instrucion      */
 /*-----------------------------------------------------------------*/
-static void genPointerSet (iCode *ic)
-{    
-    operand *right, *result ;
-    link *type, *etype;
-    int p_type;
-
-    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);
-    /* if left is of type of pointer then it is simple */
-    if (IS_PTR(type) && !IS_FUNC(type->next)) {
-        p_type = DCL_TYPE(type);
-    }
-    else {
-       /* we have to go by the storage class */
-       p_type = PTR_TYPE(SPEC_OCLS(etype));
-
-/*     if (SPEC_OCLS(etype)->codesp ) { */
-/*         p_type = CPOINTER ;  */
-/*     } */
-/*     else */
-/*         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
-/*             p_type = FPOINTER ; */
-/*         else */
-/*             if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
-/*                 p_type = PPOINTER ; */
-/*             else */
-/*                 if (SPEC_OCLS(etype) == idata ) */
-/*                     p_type = IPOINTER ; */
-/*                 else */
-/*                     p_type = POINTER ; */
-    }
-
-    /* now that we have the pointer type we assign
-    the pointer values */
-    switch (p_type) {
+static int
+genDjnz (iCode * ic, iCode * ifx)
+{
+  symbol *lbl, *lbl1;
+  if (!ifx)
+    return 0;
 
-    case POINTER:
-    case IPOINTER:
-       genNearPointerSet (right,result,ic);
-       break;
+  /* if the if condition has a false label
+     then we cannot save */
+  if (IC_FALSE (ifx))
+    return 0;
 
-    case PPOINTER:
-       genPagedPointerSet (right,result,ic);
-       break;
+  /* if the minus is not of the form a = a - 1 */
+  if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
+      !IS_OP_LITERAL (IC_RIGHT (ic)))
+    return 0;
 
-    case FPOINTER:
-       genFarPointerSet (right,result,ic);
-       break;
+  if (operandLitValue (IC_RIGHT (ic)) != 1)
+    return 0;
 
-    case GPOINTER:
-       genGenPointerSet (right,result,ic);
-       break;
+  /* if the size of this greater than one then no
+     saving */
+  if (getSize (operandType (IC_RESULT (ic))) > 1)
+    return 0;
+
+  /* otherwise we can save BIG */
+
+  D (emitcode (";", "genDjnz"));
+
+  lbl = newiTempLabel (NULL);
+  lbl1 = newiTempLabel (NULL);
+
+  aopOp (IC_RESULT (ic), ic, FALSE);
+
+  if (AOP_NEEDSACC(IC_RESULT(ic)))
+  {
+      /* If the result is accessed indirectly via
+       * the accumulator, we must explicitly write
+       * it back after the decrement.
+       */
+      char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
+
+      if (strcmp(rByte, "a"))
+      {
+           /* Something is hopelessly wrong */
+           fprintf(stderr, "*** warning: internal error at %s:%d\n",
+                   __FILE__, __LINE__);
+           /* We can just give up; the generated code will be inefficient,
+            * but what the hey.
+            */
+           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+           return 0;
+      }
+      emitcode ("dec", "%s", rByte);
+      aopPut (IC_RESULT (ic), rByte, 0);
+      emitcode ("jnz", "%05d$", lbl->key + 100);
+  }
+  else if (IS_AOP_PREG (IC_RESULT (ic)))
+    {
+      emitcode ("dec", "%s",
+                aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
+      MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
+      freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+      ifx->generated = 1;
+      emitcode ("jnz", "%05d$", lbl->key + 100);
+    }
+  else
+    {
+      emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
+                lbl->key + 100);
     }
+  emitcode ("sjmp", "%05d$", lbl1->key + 100);
+  emitLabel (lbl);
+  emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
+  emitLabel (lbl1);
 
+  if (!ifx->generated)
+      freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+  ifx->generated = 1;
+  return 1;
 }
 
 /*-----------------------------------------------------------------*/
-/* genIfx - generate code for Ifx statement                        */
+/* genReceive - generate code for a receive iCode                  */
 /*-----------------------------------------------------------------*/
-static void genIfx (iCode *ic, iCode *popIc)
+static void
+genReceive (iCode * ic)
 {
-    operand *cond = IC_COND(ic);
-    int isbit =0;
+  int size = getSize (operandType (IC_RESULT (ic)));
+  int offset = 0;
 
-    aopOp(cond,ic,FALSE);
+  D (emitcode (";", "genReceive"));
 
-    /* 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,TRUE);
-
-    /* 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;
-}
+  if (ic->argreg == 1)
+    { /* first parameter */
+      if ((isOperandInFarSpace (IC_RESULT (ic)) ||
+           isOperandInPagedSpace (IC_RESULT (ic))) &&
+          (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
+           IS_TRUE_SYMOP (IC_RESULT (ic))))
+        {
+          regs *tempRegs[4];
+          int receivingA = 0;
+          int roffset = 0;
 
-/*-----------------------------------------------------------------*/
-/* genAddrOf - generates code for address of                       */
-/*-----------------------------------------------------------------*/
-static void genAddrOf (iCode *ic)
-{
-    symbol *sym = OP_SYMBOL(IC_LEFT(ic));
-    int size, offset ;
+          for (offset = 0; offset<size; offset++)
+            if (!strcmp (fReturn[offset], "a"))
+              receivingA = 1;
 
-    aopOp(IC_RESULT(ic),ic,FALSE);
+          if (!receivingA)
+            {
+              if (size==1 || getTempRegs(tempRegs, size-1, ic))
+                {
+                  for (offset = size-1; offset>0; offset--)
+                    emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
+                  emitcode("mov","a,%s", fReturn[0]);
+                  _G.accInUse++;
+                  aopOp (IC_RESULT (ic), ic, FALSE);
+                  _G.accInUse--;
+                  aopPut (IC_RESULT (ic), "a", offset);
+                  for (offset = 1; offset<size; offset++)
+                    aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
+                  goto release;
+                }
+            }
+          else
+            {
+              if (getTempRegs(tempRegs, size, ic))
+                {
+                  for (offset = 0; offset<size; offset++)
+                    emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
+                  aopOp (IC_RESULT (ic), ic, FALSE);
+                  for (offset = 0; offset<size; offset++)
+                    aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
+                  goto release;
+                }
+            }
 
-    /* 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 (sym->stack) {
-            emitcode("mov","a,_bp");
-            emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
-            aopPut(AOP(IC_RESULT(ic)),"a",0);       
-        } else {
-            /* we can just move _bp */
-            aopPut(AOP(IC_RESULT(ic)),"_bp",0);
-        }
-        /* fill the result with zero */
-        size = AOP_SIZE(IC_RESULT(ic)) - 1;
-        
-        
-        if (options.stack10bit && size < (FPTRSIZE - 1))
-        {
-            fprintf(stderr, 
-                   "*** warning: pointer to stack var truncated.\n");
-        }
-        
-        offset = 1;
-        while (size--)
-        {
-            /* Yuck! */
-            if (options.stack10bit && offset == 2)
+          offset = fReturnSizeMCS51 - size;
+          while (size--)
             {
-                aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
+              emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
+                                       fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
+              offset++;
             }
-            else
+          aopOp (IC_RESULT (ic), ic, FALSE);
+          size = AOP_SIZE (IC_RESULT (ic));
+          offset = 0;
+          while (size--)
             {
-               aopPut(AOP(IC_RESULT(ic)),zero,offset++);
+              emitcode ("pop", "acc");
+              aopPut (IC_RESULT (ic), "a", offset++);
             }
         }
-
-        goto release;
+      else
+        {
+          _G.accInUse++;
+          aopOp (IC_RESULT (ic), ic, FALSE);
+          _G.accInUse--;
+          assignResultValue (IC_RESULT (ic), NULL);
+        }
     }
-
-    /* object not on stack then we need the name */
-    size = AOP_SIZE(IC_RESULT(ic));
-    offset = 0;
-
-    while (size--) {
-        char s[SDCC_NAME_MAX];
-        if (offset) 
-            sprintf(s,"#(%s >> %d)",
-                    sym->rname,
-                    offset*8);
-        else
-            sprintf(s,"#%s",sym->rname);
-        aopPut(AOP(IC_RESULT(ic)),s,offset++);
+  else if (ic->argreg > 12)
+    { /* bit parameters */
+      if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
+        {
+          aopOp (IC_RESULT (ic), ic, FALSE);
+          emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
+          outBitC(IC_RESULT (ic));
+        }
+    }
+  else
+    { /* other parameters */
+      int rb1off ;
+      aopOp (IC_RESULT (ic), ic, FALSE);
+      rb1off = ic->argreg;
+      while (size--)
+        {
+          aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
+        }
     }
 
 release:
-    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
-
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genFarFarAssign - assignment when both are in far space         */
+/* genDummyRead - generate code for dummy read of volatiles        */
 /*-----------------------------------------------------------------*/
-static void genFarFarAssign (operand *result, operand *right, iCode *ic)
+static void
+genDummyRead (iCode * ic)
 {
-    int size = AOP_SIZE(right);
-    int offset = 0;
-    char *l ;
-    /* first push the right side on to the stack */
-    while (size--) {
-       l = aopGet(AOP(right),offset++,FALSE,FALSE);
-       MOVA(l);
-       emitcode ("push","acc");
-    }
-    
-    freeAsmop(right,NULL,ic,FALSE);
-    /* now assign DPTR to result */
-    aopOp(result,ic,FALSE);
-    size = AOP_SIZE(result);
-    while (size--) {
-       emitcode ("pop","acc");
-       aopPut(AOP(result),"a",--offset);
-    }
-    freeAsmop(result,NULL,ic,FALSE);
-       
-}
+  operand *op;
+  int size, offset;
 
-/*-----------------------------------------------------------------*/
-/* 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 they are the same */
-    if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
-        return ;
-
-    aopOp(right,ic,FALSE);
-    
-    /* special case both in far space */
-    /* However, if we are using 10 bit stack mode,
-     * the result should be held in DPTR2,
-     * so we can operate without the special case.
-     *
-     * I think.
-     */
-    if (AOP_TYPE(right) == AOP_DPTR &&
-       IS_TRUE_SYMOP(result)       &&
-       isOperandInFarSpace(result)) {
-       
-       if (!options.stack10bit)
-       {
-           genFarFarAssign (result,right,ic);
-            return ;
-        }
-        else
+  D (emitcode(";", "genDummyRead"));
+
+  op = IC_RIGHT (ic);
+  if (op && IS_SYMOP (op))
+    {
+      aopOp (op, ic, FALSE);
+
+      /* if the result is a bit */
+      if (AOP_TYPE (op) == AOP_CRY)
+        emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
+      else
         {
-            fprintf(stderr, "*** 10bit stack opt 1\n");
-            emitcode(";", "look at me: optimization possible?\n");
+          /* bit variables done */
+          /* general case */
+          size = AOP_SIZE (op);
+          offset = 0;
+          while (size--)
+          {
+            MOVA (aopGet (op, offset, FALSE, FALSE));
+            offset++;
+          }
         }
-    }
 
-    aopOp(result,ic,TRUE);
+      freeAsmop (op, NULL, ic, TRUE);
+    }
 
-    /* if they are the same registers */
-    if (sameRegs(AOP(right),AOP(result)))
-        goto release;
+  op = IC_LEFT (ic);
+  if (op && IS_SYMOP (op))
+    {
+      aopOp (op, ic, FALSE);
 
-    /* if the result is a bit */
-    if (AOP_TYPE(result) == AOP_CRY) {
+      /* if the result is a bit */
+      if (AOP_TYPE (op) == AOP_CRY)
+        emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
+      else
+        {
+          /* bit variables done */
+          /* general case */
+          size = AOP_SIZE (op);
+          offset = 0;
+          while (size--)
+          {
+            MOVA (aopGet (op, offset, FALSE, FALSE));
+            offset++;
+          }
+        }
 
-        /* if the right size is a literal then
-        we know what the value is */
-        if (AOP_TYPE(right) == AOP_LIT) {
-            if (((int) operandLitValue(right))) 
-                aopPut(AOP(result),one,0);
-            else
-                aopPut(AOP(result),zero,0);
-            goto release;
-        }
-
-        /* the right is also a bit variable */
-        if (AOP_TYPE(right) == AOP_CRY) {
-            emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
-            aopPut(AOP(result),"c",0);
-            goto release ;
-        }
-
-        /* we need to or */
-        toBoolean(right);
-        aopPut(AOP(result),"a",0);
-        goto release ;
-    }
-
-    /* bit variables done */
-    /* 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)){
-       emitcode("clr","a");
-       while (size--) {
-           if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
-               aopPut(AOP(result),"a",size);
-           else
-               aopPut(AOP(result),
-                      aopGet(AOP(right),size,FALSE,FALSE),
-                      size);
-       }
-    } else {
-       while (size--) {
-           aopPut(AOP(result),
-                  aopGet(AOP(right),offset,FALSE,FALSE),
-                  offset);
-           offset++;
-       }
-    }
-    
-release:
-    freeAsmop (right,NULL,ic,FALSE);
-    freeAsmop (result,NULL,ic,TRUE);
-}   
+      freeAsmop (op, NULL, ic, TRUE);
+    }
+}
 
 /*-----------------------------------------------------------------*/
-/* genJumpTab - genrates code for jump table                       */
+/* genCritical - generate code for start of a critical sequence    */
 /*-----------------------------------------------------------------*/
-static void genJumpTab (iCode *ic)
+static void
+genCritical (iCode *ic)
 {
-    symbol *jtab;
-    char *l;
+  symbol *tlbl = newiTempLabel (NULL);
 
-    aopOp(IC_JTCOND(ic),ic,FALSE);
-    /* get the condition into accumulator */
-    l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
-    MOVA(l);
-    /* multiply by three */
-    emitcode("add","a,acc");
-    emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
-    freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
-
-    jtab = newiTempLabel(NULL);
-    emitcode("mov","dptr,#%05d$",jtab->key+100);
-    emitcode("jmp","@a+dptr");
-    emitcode("","%05d$:",jtab->key+100);
-    /* now generate the jump labels */
-    for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
-         jtab = setNextItem(IC_JTLABELS(ic)))
-        emitcode("ljmp","%05d$",jtab->key+100);
+  D (emitcode(";", "genCritical"));
 
+  if (IC_RESULT (ic))
+    {
+      aopOp (IC_RESULT (ic), ic, TRUE);
+      aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
+      emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
+      aopPut (IC_RESULT (ic), zero, 0);
+      emitLabel (tlbl);
+      freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+    }
+  else
+    {
+      emitcode ("setb", "c");
+      emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
+      emitcode ("clr", "c");
+      emitLabel (tlbl);
+      emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* genCast - gen code for casting                                  */
+/* genEndCritical - generate code for end of a critical sequence   */
 /*-----------------------------------------------------------------*/
-static void genCast (iCode *ic)
+static void
+genEndCritical (iCode *ic)
 {
-    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 ;
+  D(emitcode(";     genEndCritical",""));
 
-    aopOp(right,ic,FALSE) ;
-    aopOp(result,ic,FALSE);
-
-    /* if the result is a bit */
-    if (AOP_TYPE(result) == AOP_CRY) {
-        /* if the right size is a literal then
-        we know what the value is */
-        if (AOP_TYPE(right) == AOP_LIT) {
-            if (((int) operandLitValue(right))) 
-                aopPut(AOP(result),one,0);
-            else
-                aopPut(AOP(result),zero,0);
-
-            goto release;
+  if (IC_RIGHT (ic))
+    {
+      aopOp (IC_RIGHT (ic), ic, FALSE);
+      if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
+        {
+          emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
+          emitcode ("mov", "ea,c");
         }
-
-        /* the right is also a bit variable */
-        if (AOP_TYPE(right) == AOP_CRY) {
-            emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
-            aopPut(AOP(result),"c",0);
-            goto release ;
+      else
+        {
+          if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
+            MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
+          emitcode ("rrc", "a");
+          emitcode ("mov", "ea,c");
         }
-
-        /* we need to or */
-        toBoolean(right);
-        aopPut(AOP(result),"a",0);
-        goto release ;
+      freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
     }
+  else
+    {
+      emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
+      emitcode ("mov", "ea,c");
+    }
+}
 
-    /* if they are the same size : or less */
-    if (AOP_SIZE(result) <= AOP_SIZE(right)) {
+/*-----------------------------------------------------------------*/
+/* gen51Code - generate code for 8051 based controllers            */
+/*-----------------------------------------------------------------*/
+void
+gen51Code (iCode * lic)
+{
+  iCode *ic;
+  int cln = 0;
+  /* int cseq = 0; */
 
-        /* if they are in the same place */
-        if (sameRegs(AOP(right),AOP(result)))
-            goto release;
+  _G.currentFunc = NULL;
+  lineHead = lineCurr = NULL;
 
-        /* if they in different places then copy */
-        size = AOP_SIZE(result);
-        offset = 0 ;
-        while (size--) {
-            aopPut(AOP(result),
-                   aopGet(AOP(right),offset,FALSE,FALSE),
-                   offset);
-            offset++;
-        }
-        goto release;
+  /* print the allocation information */
+  if (allocInfo && currFunc)
+    printAllocInfo (currFunc, codeOutFile);
+  /* if debug information required */
+  if (options.debug && currFunc)
+    {
+      debugFile->writeFunction (currFunc, lic);
     }
+  /* stack pointer name */
+  if (options.useXstack)
+    spname = "_spx";
+  else
+    spname = "sp";
 
 
-    /* if the result is of type pointer */
-    if (IS_PTR(ctype)) {
-
-       int p_type;
-       link *type = operandType(right);
-       link *etype = getSpec(type);
-
-       /* pointer to generic pointer */
-       if (IS_GENPTR(ctype)) {
-           char *l = zero;
-           
-           if (IS_PTR(type)) 
-               p_type = DCL_TYPE(type);
-           else {
-               /* we have to go by the storage class */
-               p_type = PTR_TYPE(SPEC_OCLS(etype));
-
-/*             if (SPEC_OCLS(etype)->codesp )  */
-/*                 p_type = CPOINTER ;  */
-/*             else */
-/*                 if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
-/*                     p_type = FPOINTER ; */
-/*                 else */
-/*                     if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
-/*                         p_type = PPOINTER; */
-/*                     else */
-/*                         if (SPEC_OCLS(etype) == idata ) */
-/*                             p_type = IPOINTER ; */
-/*                         else */
-/*                             p_type = POINTER ; */
-           }
-               
-           /* the first two bytes are known */
-           size = GPTRSIZE - 1; 
-           offset = 0 ;
-           while (size--) {
-               aopPut(AOP(result),
-                      aopGet(AOP(right),offset,FALSE,FALSE),
-                      offset);
-               offset++;
-           }
-           /* the last byte depending on type */
-           switch (p_type) {
-           case IPOINTER:
-           case POINTER:
-               l = zero;
-               break;
-           case FPOINTER:
-               l = one;
-               break;
-           case CPOINTER:
-               l = "#0x02";
-               break;                          
-           case PPOINTER:
-               l = "#0x03";
-               break;
-               
-           default:
-               /* this should never happen */
-               werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-                      "got unknown pointer type");
-               exit(1);
-           }
-           aopPut(AOP(result),l, GPTRSIZE - 1);            
-           goto release ;
-       }
-       
-       /* just copy the pointers */
-       size = AOP_SIZE(result);
-       offset = 0 ;
-       while (size--) {
-           aopPut(AOP(result),
-                  aopGet(AOP(right),offset,FALSE,FALSE),
-                  offset);
-           offset++;
-       }
-       goto release ;
-    }
-    
-    /* 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,FALSE),
-               offset);
-        offset++;
-    }
-
-    /* now depending on the sign of the destination */
-    size = AOP_SIZE(result) - AOP_SIZE(right);
-    /* if unsigned or not an integral type */
-    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,FALSE);
-        MOVA(l);
-        emitcode("rlc","a");
-        emitcode("subb","a,acc");
-        while (size--)
-            aopPut(AOP(result),"a",offset++);   
-    }
-
-    /* we are done hurray !!!! */
-
-release:
-    freeAsmop(right,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
-
-}
+  for (ic = lic; ic; ic = ic->next)
+    {
+      _G.current_iCode = ic;
 
-/*-----------------------------------------------------------------*/
-/* genDjnz - generate decrement & jump if not zero instrucion      */
-/*-----------------------------------------------------------------*/
-static int genDjnz (iCode *ic, iCode *ifx)
-{
-    symbol *lbl, *lbl1;
-    if (!ifx)
-       return 0;
-    
-    /* if the if condition has a false label
-       then we cannot save */
-    if (IC_FALSE(ifx))
-       return 0;
-
-    /* if the minus is not of the form 
-       a = a - 1 */
-    if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
-       !IS_OP_LITERAL(IC_RIGHT(ic)))
-       return 0;
-
-    if (operandLitValue(IC_RIGHT(ic)) != 1)
-       return 0;
-
-    /* if the size of this greater than one then no
-       saving */
-    if (getSize(operandType(IC_RESULT(ic))) > 1)
-       return 0;
-
-    /* otherwise we can save BIG */
-    lbl = newiTempLabel(NULL);
-    lbl1= newiTempLabel(NULL);
-
-    aopOp(IC_RESULT(ic),ic,FALSE);
-    
-    if (IS_AOP_PREG(IC_RESULT(ic))) {
-       emitcode("dec","%s",
-                aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
-       emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
-       emitcode("jnz","%05d$",lbl->key+100);
-    } else {   
-       emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
-                 lbl->key+100);
-    }
-    emitcode ("sjmp","%05d$",lbl1->key+100);
-    emitcode ("","%05d$:",lbl->key+100);
-    emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
-    emitcode ("","%05d$:",lbl1->key+100);
-    
-    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
-    ifx->generated = 1;
-    return 1;
-}
+      if (ic->lineno && cln != ic->lineno)
+        {
+          if (options.debug)
+            {
+              debugFile->writeCLine (ic);
+            }
+          if (!options.noCcodeInAsm) {
+            emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
+                      printCLine(ic->filename, ic->lineno));
+          }
+          cln = ic->lineno;
+        }
+      #if 0
+      if (ic->seqPoint && ic->seqPoint != cseq)
+        {
+          emitcode ("", "; sequence point %d", ic->seqPoint);
+          cseq = ic->seqPoint;
+        }
+      #endif
+      if (options.iCodeInAsm) {
+        char regsInUse[80];
+        int i;
 
-/*-----------------------------------------------------------------*/
-/* 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))) ) {
-
-       int size = getSize(operandType(IC_RESULT(ic)));
-       int offset =  fReturnSize - size;
-       while (size--) {
-           emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
-                                   fReturn[fReturnSize - offset - 1] : "acc"));
-           offset++;
-       }
-       aopOp(IC_RESULT(ic),ic,FALSE);  
-       size = AOP_SIZE(IC_RESULT(ic));
-       offset = 0;
-       while (size--) {
-           emitcode ("pop","acc");
-           aopPut (AOP(IC_RESULT(ic)),"a",offset++);
-       }
-       
-    } else {
-       _G.accInUse++;
-       aopOp(IC_RESULT(ic),ic,FALSE);  
-       _G.accInUse--;
-       assignResultValue(IC_RESULT(ic));       
-    }
-
-    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
-}
+        #if 0
+        for (i=0; i<8; i++) {
+          sprintf (&regsInUse[i],
+                   "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
+        regsInUse[i]=0;
+        #else
+        strcpy (regsInUse, "--------");
+        for (i=0; i < 8; i++) {
+          if (bitVectBitValue (ic->rMask, i))
+            {
+              int offset = regs8051[i].offset;
+              regsInUse[offset] = offset + '0'; /* show rMask */
+            }
+        #endif
+        }
+        emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
+      }
+      /* 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 '!':
+          genNot (ic);
+          break;
+
+        case '~':
+          genCpl (ic);
+          break;
+
+        case UNARYMINUS:
+          genUminus (ic);
+          break;
+
+        case IPUSH:
+          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)))
+            genIfx (ic->next, ic);
+          else
+            genIpop (ic);
+          break;
+
+        case CALL:
+          genCall (ic);
+          break;
+
+        case PCALL:
+          genPcall (ic);
+          break;
+
+        case FUNCTION:
+          genFunction (ic);
+          break;
+
+        case ENDFUNCTION:
+          genEndFunction (ic);
+          break;
+
+        case RETURN:
+          genRet (ic);
+          break;
+
+        case LABEL:
+          genLabel (ic);
+          break;
+
+        case GOTO:
+          genGoto (ic);
+          break;
+
+        case '+':
+          genPlus (ic);
+          break;
+
+        case '-':
+          if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
+            genMinus (ic);
+          break;
+
+        case '*':
+          genMult (ic);
+          break;
+
+        case '/':
+          genDiv (ic);
+          break;
+
+        case '%':
+          genMod (ic);
+          break;
+
+        case '>':
+          genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
+          break;
+
+        case '<':
+          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
+             in decorateType() in SDCCast.c */
+          werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                  "got '>=' or '<=' shouldn't have come here");
+          break;
+
+        case EQ_OP:
+          genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
+          break;
+
+        case AND_OP:
+          genAndOp (ic);
+          break;
+
+        case OR_OP:
+          genOrOp (ic);
+          break;
+
+        case '^':
+          genXor (ic, ifxForOp (IC_RESULT (ic), ic));
+          break;
+
+        case '|':
+          genOr (ic, ifxForOp (IC_RESULT (ic), ic));
+          break;
+
+        case BITWISEAND:
+          genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
+          break;
+
+        case INLINEASM:
+          genInline (ic);
+          break;
+
+        case RRC:
+          genRRC (ic);
+          break;
+
+        case RLC:
+          genRLC (ic);
+          break;
+
+        case GETHBIT:
+          genGetHbit (ic);
+          break;
+
+        case GETABIT:
+          genGetAbit (ic);
+          break;
+
+        case GETBYTE:
+          genGetByte (ic);
+          break;
+
+        case GETWORD:
+          genGetWord (ic);
+          break;
+
+        case LEFT_OP:
+          genLeftShift (ic);
+          break;
+
+        case RIGHT_OP:
+          genRightShift (ic);
+          break;
+
+        case GET_VALUE_AT_ADDRESS:
+          genPointerGet (ic,
+                         hasInc (IC_LEFT (ic), ic,
+                                 getSize (operandType (IC_RESULT (ic)))),
+                         ifxForOp (IC_RESULT (ic), ic) );
+          break;
+
+        case '=':
+          if (POINTER_SET (ic))
+            genPointerSet (ic,
+                           hasInc (IC_RESULT (ic), ic,
+                                   getSize (operandType (IC_RIGHT (ic)))));
+          else
+            genAssign (ic);
+          break;
+
+        case IFX:
+          genIfx (ic, NULL);
+          break;
+
+        case ADDRESS_OF:
+          genAddrOf (ic);
+          break;
+
+        case JUMPTABLE:
+          genJumpTab (ic);
+          break;
+
+        case CAST:
+          genCast (ic);
+          break;
+
+        case RECEIVE:
+          genReceive (ic);
+          break;
+
+        case SEND:
+          addSet (&_G.sendSet, ic);
+          break;
+
+        case DUMMY_READ_VOLATILE:
+          genDummyRead (ic);
+          break;
+
+        case CRITICAL:
+          genCritical (ic);
+          break;
+
+        case ENDCRITICAL:
+          genEndCritical (ic);
+          break;
+
+        case SWAP:
+          genSwap (ic);
+          break;
+
+        default:
+          ic = ic;
+        }
+    }
 
-/*-----------------------------------------------------------------*/
-/* gen51Code - generate code for 8051 based controllers            */
-/*-----------------------------------------------------------------*/
-void gen51Code (iCode *lic)
-{
-    iCode *ic;
-    int cln = 0;
+  _G.current_iCode = NULL;
 
-    lineHead = lineCurr = NULL;
+  /* now we are ready to call the
+     peep hole optimizer */
+  if (!options.nopeep)
+    peepHole (&lineHead);
 
-    /* if debug information required */
-/*     if (options.debug && currFunc) { */
-    if (currFunc) {
-       cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
-       _G.debugLine = 1;
-       if (IS_STATIC(currFunc->etype))
-           emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
-       else
-           emitcode("","G$%s$0$0 ==.",currFunc->name);
-       _G.debugLine = 0;
-    }
-    /* stack pointer name */
-    if (options.useXstack)
-       spname = "_spx";
-    else
-       spname = "sp";
-    
-    for (ic = lic ; ic ; ic = ic->next ) {
-       
-       if ( cln != ic->lineno ) {
-           if ( options.debug ) {
-               _G.debugLine = 1;
-               emitcode("","C$%s$%d$%d$%d ==.",
-                        ic->filename,ic->lineno,
-                        ic->level,ic->block);
-               _G.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 ;
-       
-       /* depending on the operation */
-       switch (ic->op) {
-       case '!' :
-           genNot(ic);
-           break;
-           
-       case '~' :
-           genCpl(ic);
-           break;
-           
-       case UNARYMINUS:
-           genUminus (ic);
-           break;
-           
-       case IPUSH:
-           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))) 
-               genIfx (ic->next,ic);
-           else
-               genIpop (ic);
-           break; 
-           
-       case CALL:
-           genCall (ic);
-           break;
-           
-       case PCALL:
-           genPcall (ic);
-           break;
-           
-       case FUNCTION:
-           genFunction (ic);
-           break;
-           
-       case ENDFUNCTION:
-           genEndFunction (ic);
-           break;
-           
-       case RETURN:
-           genRet (ic);
-           break;
-           
-       case LABEL:
-           genLabel (ic);
-           break;
-           
-       case GOTO:
-           genGoto (ic);
-           break;
-           
-       case '+' :
-           genPlus (ic) ;
-           break;
-           
-       case '-' :
-           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
-               genMinus (ic);
-           break;
-           
-       case '*' :
-           genMult (ic);
-           break;
-           
-       case '/' :
-           genDiv (ic) ;
-           break;
-           
-       case '%' :
-           genMod (ic);
-           break;
-           
-       case '>' :
-           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
-           break;
-           
-       case '<' :
-           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
-           break;
-           
-       case LE_OP:
-       case GE_OP:
-       case NE_OP:
-           
-           /* note these two are xlated by algebraic equivalence
-              during parsing SDCC.y */
-           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-                  "got '>=' or '<=' shouldn't have come here");
-           break;      
-           
-       case EQ_OP:
-           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
-           break;          
-           
-       case AND_OP:
-           genAndOp (ic);
-           break;
-           
-       case OR_OP:
-           genOrOp (ic);
-           break;
-           
-       case '^' :
-           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
-           break;
-           
-       case '|' :
-               genOr (ic,ifxForOp(IC_RESULT(ic),ic));
-           break;
-           
-       case BITWISEAND:
-            genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
-           break;
-           
-       case INLINEASM:
-           genInline (ic);
-           break;
-           
-       case RRC:
-           genRRC (ic);
-           break;
-           
-       case RLC:
-           genRLC (ic);
-           break;
-           
-       case GETHBIT:
-           genGetHbit (ic);
-           break;
-           
-       case LEFT_OP:
-           genLeftShift (ic);
-           break;
-           
-       case RIGHT_OP:
-           genRightShift (ic);
-           break;
-           
-       case GET_VALUE_AT_ADDRESS:
-           genPointerGet(ic);
-           break;
-           
-       case '=' :
-           if (POINTER_SET(ic))
-               genPointerSet(ic);
-           else
-               genAssign(ic);
-           break;
-           
-       case IFX:
-           genIfx (ic,NULL);
-           break;
-           
-       case ADDRESS_OF:
-           genAddrOf (ic);
-           break;
-           
-       case JUMPTABLE:
-           genJumpTab (ic);
-           break;
-           
-       case CAST:
-           genCast (ic);
-           break;
-           
-       case RECEIVE:
-           genReceive(ic);
-           break;
-           
-       case SEND:
-           addSet(&_G.sendSet,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 do the actual printing */
+  printLine (lineHead, codeOutFile);
+  return;
 }