* device/lib/Makefile.in (Z80SOURCES): enabled float support
[fw/sdcc] / src / mcs51 / gen.c
index b7e238f841060d0e778384e6e100935b71cecdce..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!
 
+  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
 -------------------------------------------------------------------------*/
 
+//#define D(x)
+#define D(x) x
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 #include "SDCCglobl.h"
+#include "newalloc.h"
 
-#ifdef HAVE_SYS_ISA_DEFS_H
-#include <sys/isa_defs.h>
-#else
-#ifdef HAVE_ENDIAN_H
-#include <endian.h>
-#else
-#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
-
-#include "SDCCast.h"
-#include "SDCCmem.h"
-#include "SDCCy.h"
-#include "SDCChasht.h"
-#include "SDCCbitv.h"
-#include "SDCCset.h"
-#include "SDCCicode.h"
-#include "SDCClabel.h"
-#include "SDCCBBlock.h"
-#include "SDCCloop.h"
-#include "SDCCcse.h"
-#include "SDCCcflow.h"
-#include "SDCCdflow.h"
-#include "SDCClrange.h"
-#include "SDCCralloc.h"
-#include "SDCCgen51.h"
+#include "common.h"
 #include "SDCCpeeph.h"
+#include "ralloc.h"
+#include "gen.h"
+
+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 
-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 */
+/* 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 *fReturn[] = {"dpl","dph","b","a" };
-static char *accUse[] = {"a","b"};
-short r0Pushed = 0;
-short r1Pushed = 0;
-short rbank = -1;
-short accInUse = 0 ;
-short inLine = 0;
-short debugLine = 0;
-short nregssaved = 0;
-extern int ptrRegReq ;
-extern int nRegs;
+static char *one = "#0x01";
+static char *spname;
+
+char *fReturn8051[] =
+{"dpl", "dph", "b", "a"};
+unsigned fReturnSizeMCS51 = 4;  /* shared with ralloc.c */
+char **fReturn = fReturn8051;
+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) )))
+
+#define SYM_BP(sym)   (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
+
+#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;
+    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 FILE *codeOutFile;
-set *sendSet = NULL;
-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)
 
-lineNode *lineHead = NULL;
-lineNode *lineCurr = NULL;
+#define CLRC     emitcode("clr","c")
+#define SETC     emitcode("setb","c")
 
-unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
-0xE0, 0xC0, 0x80, 0x00};
-unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
-0x07, 0x03, 0x01, 0x00};
+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};
 
 #define LSB     0
 #define MSB16   1
@@ -105,886 +148,1557 @@ unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
 /*-----------------------------------------------------------------*/
 /* emitcode - writes the code into a file : for now it is simple    */
 /*-----------------------------------------------------------------*/
-void emitcode (char *inst,char *fmt, ...)
+static void
+emitcode (char *inst, const char *fmt,...)
 {
-    va_list ap;
-    char lb[MAX_INLINEASM];  
-    char *lbp = lb;
+  va_list ap;
+  char lb[INITIAL_INLINEASM];
+  char *lbp = lb;
+
+  va_start (ap, fmt);
+
+  if (inst && *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);
+    }
 
-    va_start(ap,fmt);   
+  while (isspace ((unsigned char)*lbp))
+    {
+      lbp++;
+    }
 
-    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);
+  if (lbp && *lbp)
+    {
+      lineCurr = (lineCurr ?
+                  connectLine (lineCurr, newLineNode (lb)) :
+                  (lineHead = newLineNode (lb)));
+    }
 
-    while (isspace(*lbp)) lbp++;
+  lineCurr->isInline = _G.inLine;
+  lineCurr->isDebug = _G.debugLine;
+  lineCurr->ic = _G.current_iCode;
+  lineCurr->isComment = (*lbp==';');
+  va_end (ap);
+}
 
-    if (lbp && *lbp) 
-        lineCurr = (lineCurr ?
-                    connectLine(lineCurr,newLineNode(lb)) :
-                    (lineHead = newLineNode(lb)));
-    lineCurr->isInline = inLine;
-    lineCurr->isDebug  = debugLine;
-    va_end(ap);
+static void
+emitLabel (symbol *tlbl)
+{
+  emitcode ("", "%05d$:", tlbl->key + 100);
 }
 
 /*-----------------------------------------------------------------*/
-/* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
+/* mcs51_emitDebuggerSymbol - associate the current code location  */
+/*   with a debugger symbol                                        */
 /*-----------------------------------------------------------------*/
-static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
+void
+mcs51_emitDebuggerSymbol (char * debugSym)
 {
-    bool r0iu = FALSE , r1iu = FALSE;
-    bool r0ou = FALSE , r1ou = FALSE;
+  _G.debugLine = 1;
+  emitcode ("", "%s ==.", debugSym);
+  _G.debugLine = 0;
+}
 
-    /* the logic: if r0 & r1 used in the instruction
-    then we are in trouble otherwise */
+/*-----------------------------------------------------------------*/
+/* 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;
 
-    /* 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))) 
-        goto endOfWorld;      
+  emitcode("mov", "a,%s", x);
+}
 
+/*-----------------------------------------------------------------*/
+/* movb - moves specified value into register b                    */
+/*-----------------------------------------------------------------*/
+static void
+movb (const char *x)
+{
+  /* do some early peephole optimization */
+  if (!strncmp(x, "b", 2))
+    return;
 
-    r0ou = bitVectBitValue(ic->rMask,R0_IDX);
-    r1ou = bitVectBitValue(ic->rMask,R1_IDX);
+  emitcode("mov","b,%s", x);
+}
 
-    /* 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 = regWithIdx(R0_IDX);
+/*-----------------------------------------------------------------*/
+/* 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");
     }
+}
 
-    /* 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 = regWithIdx(R1_IDX);
-    }    
+/*-----------------------------------------------------------------*/
+/* pushB - saves register B if necessary                           */
+/*-----------------------------------------------------------------*/
+static bool
+pushB (void)
+{
+  bool pushedB = FALSE;
 
-    /* now we know they both have usage */
-    /* if r0 not used in this instruction */
-    if (!r0iu) {
-        /* push it if not already pushed */
-        if (!r0Pushed) {
-            emitcode ("push","%s",
-                      regWithIdx(R0_IDX)->dname);
-            r0Pushed++ ;
-        }
+  if (BINUSE)
+    {
+      emitcode ("push", "b");
+//    printf("B was in use !\n");
+      pushedB = TRUE;
+    }
+  else
+    {
+      OPINB++;
+    }
+  return pushedB;
+}
+
+/*-----------------------------------------------------------------*/
+/* popB - restores value of register B if necessary                */
+/*-----------------------------------------------------------------*/
+static void
+popB (bool pushedB)
+{
+  if (pushedB)
+    {
+      emitcode ("pop", "b");
+    }
+  else
+    {
+      OPINB--;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* 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;
+}
+
+/*-----------------------------------------------------------------*/
+/* popReg - restores register                                      */
+/*-----------------------------------------------------------------*/
+static bool
+popReg (int index, bool bits_popped)
+{
+  regs * reg = REG_WITH_INDEX (index);
+  if (reg->type == REG_BIT)
+    {
+      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);
 
-        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 = regWithIdx(R0_IDX);
+      return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
     }
 
-    /* if r1 not used then */
+  /* 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 = REG_WITH_INDEX (R1_IDX);
+    }
 
-    if (!r1iu) {
-        /* push it if not already pushed */
-        if (!r1Pushed) {
-            emitcode ("push","%s",
-                      regWithIdx(R1_IDX)->dname);
-            r1Pushed++ ;
+  /* 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,R1_IDX);
-        (*aopp)->type = AOP_R1;
-        return regWithIdx(R1_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 */
 
-endOfWorld :
-    /* I said end of world but not quite end of world yet */
-    /* if this is a result then we canpush it on the stack*/
-    if (result) {
-        (*aopp)->type = AOP_STK;    
-        return NULL;
+  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 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);
     }
 
-    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);
+  /* now this is REALLY the end of the world */
+  werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+          "getFreePtr should never reach here");
+  exit (1);
 }
 
+
 /*-----------------------------------------------------------------*/
-/* newAsmop - creates a new asmOp                                  */
+/* 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.  */
 /*-----------------------------------------------------------------*/
-static asmop *newAsmop (short type)
+int
+getTempRegs(regs **tempRegs, int size, iCode *ic)
 {
-    asmop *aop;
+  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);
+
+  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;
+        }
+    }
 
-    ALLOC(aop,sizeof(asmop));
-    aop->type = type;
-    return aop;
+  freeBitVect(freeRegs);
+  return 0;
 }
 
+
 /*-----------------------------------------------------------------*/
-/* pointerCode - returns the code for a pointer type               */
+/* newAsmop - creates a new asmOp                                  */
 /*-----------------------------------------------------------------*/
-static int pointerCode (link *etype)
+static asmop *
+newAsmop (short type)
 {
-    int p_type;
-    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;
+  asmop *aop;
+
+  aop = Safe_calloc (1, sizeof (asmop));
+  aop->type = type;
+  aop->allocated = 1;
+  return aop;
 }
 
 /*-----------------------------------------------------------------*/
-/* aopForSym - for a true symbol                                   */
+/* pointerCode - returns the code for a pointer type               */
 /*-----------------------------------------------------------------*/
-static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
+static int
+pointerCode (sym_link * etype)
 {
-    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 || 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) {
+  return PTR_TYPE (SPEC_OCLS (etype));
 
-            if (sym->onStack) {
-
-                    if ( accInUse )
-                        emitcode("push","acc");
+}
 
-                    emitcode("mov","a,_bp");
-                    emitcode("add","a,#0x%02x",
-                             ((sym->stack < 0) ?
-                             ((char)(sym->stack - nregssaved )) :
-                             ((char)sym->stack)) & 0xff);
-                    emitcode("mov","%s,a",
-                             aop->aopu.aop_ptr->name);
+/*-----------------------------------------------------------------*/
+/* leftRightUseAcc - returns size of accumulator use by operands   */
+/*-----------------------------------------------------------------*/
+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 ( accInUse )
-                        emitcode("pop","acc");
+  if (accuseSize)
+    return accuseSize;
+  else
+    return accuse;
+}
 
-            } 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;
+/*-----------------------------------------------------------------*/
+/* aopForSym - for a true symbol                                   */
+/*-----------------------------------------------------------------*/
+static asmop *
+aopForSym (iCode * ic, symbol * sym, bool result)
+{
+  asmop *aop;
+  memmap *space;
+  bool accuse = leftRightUseAcc (ic) || _G.accInUse;
+
+  wassertl (ic != NULL, "Got a null iCode");
+  wassertl (sym != NULL, "Got a null symbol");
+
+  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;
     }
 
-    /* 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 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;
+  /* 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);    
-        ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
-        strcpy(aop->aopu.aop_immd,sym->rname);
-        aop->size = 2;
-        return aop;
+  /* special case for a function */
+  if (IS_FUNC (sym->type))
+    {
+      sym->aop = aop = newAsmop (AOP_IMMD);
+      aop->aopu.aop_immd.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);
+  /* 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;
+  /* if it is in code space */
+  if (IN_CODESPACE (space))
+    aop->code = 1;
 
-    return aop;     
+  return aop;
 }
 
 /*-----------------------------------------------------------------*/
 /* aopForRemat - rematerialzes an object                           */
 /*-----------------------------------------------------------------*/
-static asmop *aopForRemat (symbol *sym)
+static asmop *
+aopForRemat (symbol * sym)
 {
-    char *s = buffer;   
-    iCode *ic = sym->rematiCode;
-    asmop *aop = newAsmop(AOP_IMMD);
+  iCode *ic = sym->rematiCode;
+  asmop *aop = newAsmop (AOP_IMMD);
+  int ptr_type = 0;
+  int val = 0;
 
-    while (1) {
+  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;
 
-        /* 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 ;
-        }
+      ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+    }
 
-        /* we reached the end */
-        sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
-        break;
+  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       */
 /*-----------------------------------------------------------------*/
-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                                        */
 /*-----------------------------------------------------------------*/
-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;
+}
+
+/*-----------------------------------------------------------------*/
+/* 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;
 
-    if (IS_ITEMP(op2)  && 
-        !IS_ITEMP(op1) &&
-        sym2->isspilt  &&
-       sym1->level > 0 &&
-        (sym2->usl.spillLoc == sym1))
-        return TRUE ;
+  if (aop1->type != aop2->type)
+    return FALSE;
 
-    return FALSE ;
+  if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
+    return FALSE;
+
+  return TRUE;
 }
 
 /*-----------------------------------------------------------------*/
 /* sameRegs - two asmops have the same registers                   */
 /*-----------------------------------------------------------------*/
-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 && aop1->type != AOP_CRY)
+    return FALSE;
 
-    if (aop1->type != AOP_REG ||
-        aop2->type != AOP_REG )
-        return FALSE ;
+  if (aop1->type != aop2->type)
+    return FALSE;
 
-    if (aop1->size != aop2->size )
-        return FALSE ;
+  if (aop1->size != aop2->size)
+    return FALSE;
 
-    for (i = 0 ; i < aop1->size ; i++ )
-        if (aop1->aopu.aop_reg[i] !=
-            aop2->aopu.aop_reg[i] )
-            return FALSE ;
+  for (i = 0; i < aop1->size; i++)
+    if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
+      return FALSE;
 
-    return TRUE ;
+  return TRUE;
 }
 
 /*-----------------------------------------------------------------*/
 /* aopOp - allocates an asmop for an operand  :                    */
 /*-----------------------------------------------------------------*/
-static void aopOp (operand *op, iCode *ic, bool result)
+static void
+aopOp (operand * op, iCode * ic, bool result)
 {
-    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 < 4 ; 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;
+    }
+
+  /* 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];
+  /* 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 (r0Pushed ) {
-                if (pop) {
-                    emitcode ("pop","ar0");     
-                    r0Pushed--;
-                }
-            }
-            bitVectUnSetBit(ic->rUsed,R0_IDX);
-            break;
+static void
+freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
+{
+  asmop *aop;
 
-        case AOP_R1 :
-            if (r1Pushed ) {
-                if (pop) {
-                    emitcode ("pop","ar1");
-                    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 (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);
+  aop->allocated--;
 
-            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 (r0Pushed) {
-                emitcode("pop","ar0");
-                r0Pushed--;
+  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)
+            {
+              emitcode ("pop", "ar0");
+              _G.r0Pushed--;
             }
+        }
+      bitVectUnSetBit (ic->rUsed, R0_IDX);
+      break;
 
-            if (r1Pushed) {
-                emitcode("pop","ar1");
-                r1Pushed--;
-            }       
+    case AOP_R1:
+      if (R1INB)
+        {
+          emitcode ("mov", "r1,b");
+          R1INB--;
+        }
+      else if (_G.r1Pushed)
+        {
+          if (pop)
+            {
+              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;
         }
     }
 }
 
-/*-----------------------------------------------------------------*/
-/* aopLiteral - string from a literal value                        */
-/*-----------------------------------------------------------------*/
-char *aopLiteral (value *val, int offset)
+/*------------------------------------------------------------------*/
+/* freeForBranchAsmop - partial free up of Asmop for a branch; just */
+/*                      pop r0 or r1 off stack if pushed            */
+/*------------------------------------------------------------------*/
+static void
+freeForBranchAsmop (operand * op)
 {
-    char *rs;
-    union {
-        float f;
-        unsigned char c[4];
-    } fl;
+  asmop *aop;
+
+  if (!op)
+    return;
 
-    /* if it is a float then it gets tricky */
-    /* otherwise it is fairly simple */
-    if (!IS_FLOAT(val->type)) {
-        unsigned long v = floatFromVal(val);
+  aop = op->aop;
 
-        v >>= (offset * 8);
-        sprintf(buffer,"#0x%02x",((char) v) & 0xff);
-        ALLOC_ATOMIC(rs,strlen(buffer)+1);
-        return strcpy (rs,buffer);
+  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");
+      }
     }
 
-    /* it is type float */
-    fl.f = (float) floatFromVal(val);
-#ifdef _BIG_ENDIAN    
-    sprintf(buffer,"#0x%02x",fl.c[3-offset]);
-#else
-    sprintf(buffer,"#0x%02x",fl.c[offset]);
-#endif
-    ALLOC_ATOMIC(rs,strlen(buffer)+1);
-    return strcpy (rs,buffer);
 }
 
 /*-----------------------------------------------------------------*/
-/* 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)
 {
-    char *s = buffer ;
-    char *rs;
+  asmop * aop = AOP (oper);
+
+  if (offset > (aop->size - 1))
+    return FALSE;
 
-    /* offset is greater than
-    size then zero */
-    if (offset > (aop->size - 1) &&
-        aop->type != AOP_LIT)
-        return zero;
+  switch (aop->type)
+    {
 
-    /* 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 (aop->paged)
+        return TRUE;
+      return FALSE;
     case AOP_DPTR:
-       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");
-       
-       
+      return TRUE;
     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;
-       
+      return FALSE;
     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;
-       
+      return FALSE;
     case AOP_REG:
-       if (dname) 
-           return aop->aopu.aop_reg[offset]->dname;
-       else
-           return aop->aopu.aop_reg[offset]->name;
-       
+      wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
+      return FALSE;
     case AOP_CRY:
-       emitcode("clr","a");
-       emitcode("mov","c,%s",aop->aopu.aop_dir);
-       emitcode("rlc","a") ;
-       return (dname ? "acc" : "a");
-       
+      return TRUE;
     case AOP_ACC:
-       if (!offset && dname)
-           return "acc";
-       return aop->aopu.aop_str[offset];
-
+      if (offset)
+        return FALSE;
+      return TRUE;
     case AOP_LIT:
-       return aopLiteral (aop->aopu.aop_lit,offset);
-       
+      return FALSE;
     case AOP_STR:
-       aop->coff = offset ;
-       if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
-           dname)
-           return "acc";
-       
-       return aop->aopu.aop_str[offset];
-       
+      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;
     }
-
-    werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-           "aopget got unsupported aop->type");
-    exit(0);
 }
-/*-----------------------------------------------------------------*/
-/* aopPut - puts a string for a aop                                */
-/*-----------------------------------------------------------------*/
-static void aopPut (asmop *aop, char *s, int offset)
+
+/*-------------------------------------------------------------------*/
+/* aopGet - for fetching value of the aop                            */
+/*-------------------------------------------------------------------*/
+static char *
+aopGet (operand * oper, int offset, bool bit16, bool dname)
 {
-    char *d = buffer ;
-    symbol *lbl ;
+  asmop * aop = AOP (oper);
 
-    if (aop->size && offset > ( aop->size - 1)) {
-        werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-               "aopPut got offset > aop->size");
-        exit(0);
-    }
+  /* 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;
+
+    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");
+        }
+      SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
+      return Safe_strdup(buffer);
+
+    case AOP_DPTR:
+      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 (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 (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;
+
+    case AOP_CRY:
+      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];
+
+    case AOP_LIT:
+      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];
+
+    }
+
+  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 and indicates if acc is in use */
+/*-----------------------------------------------------------------*/
+static bool
+aopPut (operand * result, const char *s, int offset)
+{
+  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 (1);
+    }
+
+  /* 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 (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;
 
-    /* will assign value to value */
-    /* depending on where it is ofcourse */
-    switch (aop->type) {
-    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;
-       
     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:
-       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");
-       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("cjne","a,#0x01,%05d$",lbl->key+100);
-                       emitcode("","%05d$:",lbl->key+100);
-                       emitcode("cpl","c");
-                       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;
+
+      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(0);    
-    }    
+    default:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+              "aopPut got unsupported aop->type");
+      exit (1);
+    }
 
+    return accuse;
 }
 
 
@@ -992,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;
     }
 
 }
@@ -1017,107 +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 : 
-            while (size--)
-                emitcode("lcall","__decdptr");
-            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(x)->paged)) 
-
-#define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
-                      (x->aopu.aop_reg[0] == regWithIdx(R0_IDX) || \
-                      x->aopu.aop_reg[0] == 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;
+  sym_link *type = operandType (op);
 
-    l = aopGet(op->aop,offset++,FALSE,FALSE);
-    MOVA(l);    
-
-    while(size--) {
-        emitcode("orl","a,%s",
-                 aopGet(op->aop,
-                        offset++,FALSE,FALSE));
+  if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
+    {
+      return 1;
     }
-    tlbl = newiTempLabel(NULL);
-
-    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++);
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* getDataSize - get the operand data size                         */
 /*-----------------------------------------------------------------*/
-int getDataSize(operand *op)
+static int
+getDataSize (operand * op)
 {
-    int size;
-    size = AOP_SIZE(op);
-    if(size == 3)
-        /* pointer */
-        size--;
-    return size;
+  int size;
+  size = AOP_SIZE (op);
+  if (size == GPTRSIZE)
+    {
+      sym_link *type = operandType (op);
+      if (IS_GENPTR (type))
+        {
+          /* generic pointer; arithmetic operations
+           * should ignore the high byte (pointer type).
+           */
+          size--;
+        }
+    }
+  return size;
 }
 
 /*-----------------------------------------------------------------*/
 /* outAcc - output Acc                                             */
 /*-----------------------------------------------------------------*/
-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++);
         }
     }
 }
@@ -1125,2220 +1818,4190 @@ void outAcc(operand *result)
 /*-----------------------------------------------------------------*/
 /* outBitC - output a bit C                                        */
 /*-----------------------------------------------------------------*/
-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)                */
 /*-----------------------------------------------------------------*/
-void toBoolean(operand *oper)
+static void
+toBoolean (operand * oper)
+{
+  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)
 {
-    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));
+  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 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 < nRegs ; i++) {
-           if (bitVectBitValue(rsave,i)) {
-               if (i == R0_IDX)
-                   emitcode("mov","a,b");
-               else
-                   emitcode("mov","a,%s",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 < nRegs ; i++) {
-           if (bitVectBitValue(rsave,i))
-               emitcode("push","%s",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);
+  if (!ic)
+    {
+      fprintf (stderr, "found parameter push with no function call\n");
+      return;
+    }
 
-}
-/*-----------------------------------------------------------------*/
-/* unsaveRegisters - pop the pushed registers                      */
-/*-----------------------------------------------------------------*/
-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 =  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",regWithIdx(i)->name);
-           }       
+  /* 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;
 
-       }
-       emitcode("mov","%s,r0",spname);
-       if (bitVectBitValue(rsave,R0_IDX))
-           emitcode("mov","r0,b");
-    } else
-       for (i =  nRegs ; i >= 0 ; i--) {
-           if (bitVectBitValue(rsave,i))
-               emitcode("pop","%s",regWithIdx(i)->dname);
-       }
+  /* 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));
+        }
 
-/*-----------------------------------------------------------------*/
-/* pushSide -                                                     */
-/*-----------------------------------------------------------------*/
-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);
-       }
+      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);
+            }
+        }
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* assignResultValue -                                            */
+/* unsaveRegisters - pop the pushed registers                      */
 /*-----------------------------------------------------------------*/
-void assignResultValue(operand * oper)
+static void
+unsaveRegisters (iCode * ic)
 {
-       int offset = 0;
-       int size = AOP_SIZE(oper);
-       while (size--) {
-               aopPut(AOP(oper),fReturn[offset],offset);
-               offset++;
-       }
-}
-
+  int i;
+  bitVect *rsave;
 
-/*-----------------------------------------------------------------*/
-/* genXpush - pushes onto the external stack                       */
-/*-----------------------------------------------------------------*/
-static void genXpush (iCode *ic)
-{
-    asmop *aop = newAsmop(0);
-    regs *r ;
-    int size,offset = 0;
+  /* 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)));
 
-    aopOp(IC_LEFT(ic),ic,FALSE);
-    r = getFreePtr(ic,&aop,FALSE);
+  if (options.useXstack)
+    {
+      bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
+      int nBits = bitVectnBitsOn (rsavebits);
+      int count = bitVectnBitsOn (rsave);
 
-    
-    emitcode("mov","%s,_spx",r->name);
+      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 -                                                      */
+/*-----------------------------------------------------------------*/
+static void
+pushSide (operand * oper, int size)
+{
+  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 - also indicates if acc is in use afterwards  */
+/*-----------------------------------------------------------------*/
+static bool
+assignResultValue (operand * oper, operand * func)
+{
+  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)
+{
+  asmop *aop = newAsmop (0);
+  regs *r;
+  int size, offset = 0;
+
+  D (emitcode (";", "genXpush"));
+
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  r = getFreePtr (ic, &aop, FALSE);
+
+  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);
+
+      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);
+}
+
+/*-----------------------------------------------------------------*/
+/* genIpush - generate code for pushing this gets a little complex */
+/*-----------------------------------------------------------------*/
+static void
+genIpush (iCode * ic)
+{
+  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)
+    {
+
+      /* 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 (IC_LEFT (ic), offset++, FALSE, TRUE);
+          if (*l == '#')
+            {
+              MOVA (l);
+              l = "acc";
+            }
+          emitcode ("push", "%s", l);
+        }
+      return;
+    }
+
+  /* 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;
+    }
+
+  /* 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));
+
+  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);
+}
+
+/*-----------------------------------------------------------------*/
+/* genIpop - recover the registers: can happen only for spilling   */
+/*-----------------------------------------------------------------*/
+static void
+genIpop (iCode * ic)
+{
+  int size, offset;
+
+  D (emitcode (";", "genIpop"));
+
+  /* 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 (IC_LEFT (ic), offset--,
+                                     FALSE, TRUE));
+    }
+
+  freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* saveRBank - saves an entire register bank on the stack          */
+/*-----------------------------------------------------------------*/
+static void
+saveRBank (int bank, iCode * ic, bool pushPsw)
+{
+  int i;
+  int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
+  asmop *aop = NULL;
+  regs *r = NULL;
+
+  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 = 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);
+    }
+
+  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 (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);
+    }
+
+  if (aop)
+    {
+      freeAsmop (NULL, aop, ic, TRUE);
+    }
+
+  if (ic)
+  {
+    ic->bankSaved = 1;
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* unsaveRBank - restores the register bank from stack             */
+/*-----------------------------------------------------------------*/
+static void
+unsaveRBank (int bank, iCode * ic, bool popPsw)
+{
+  int i;
+  asmop *aop = NULL;
+  regs *r = NULL;
+
+  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);
+    }
+
+  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 = 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 (options.useXstack)
+    {
+      emitcode ("mov", "%s,%s", spname, r->name);
+    }
+
+  if (aop)
+    {
+      freeAsmop (NULL, aop, ic, TRUE);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genSend - gen code for SEND                                     */
+/*-----------------------------------------------------------------*/
+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 (bit_count)
+    {
+      saveRegisters (setFirstItem (sendSet));
+      emitcode ("mov", "bits,b");
+    }
+
+  /* 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);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genCall - generates a call statement                            */
+/*-----------------------------------------------------------------*/
+static void
+genCall (iCode * ic)
+{
+  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"));
+
+  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 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);
+
+  if (swapBanks)
+    {
+        emitcode ("mov", "psw,#0x%02x",
+           ((FUNC_REGBANK(dtype)) << 3) & 0xff);
+    }
+
+  /* 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");
+        }
+    }
+  else
+    {
+      emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
+                                OP_SYMBOL (IC_LEFT (ic))->rname :
+                                OP_SYMBOL (IC_LEFT (ic))->name));
+    }
+
+  if (swapBanks)
+    {
+      selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
+    }
+
+  /* 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--;
+
+      accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
+      assignResultGenerated = TRUE;
+
+      freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+    }
+
+  /* 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;
+            }
+
+          emitcode ("mov", "a,%s", spname);
+          emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
+          emitcode ("mov", "%s,a", spname);
+
+          /* 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);
+    }
+
+  /* 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);
+
+  if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
+    {
+      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);
+    }
+
+  if (accPushed)
+    emitcode ("pop", "acc");
+}
+
+/*-----------------------------------------------------------------*/
+/* genPcall - generates a call by pointer statement                */
+/*-----------------------------------------------------------------*/
+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
+    }
+
+  if (IS_LITERAL(etype))
+    {
+      /* if send set is not empty then assign */
+      if (_G.sendSet)
+        {
+          genSend(reverseSet(_G.sendSet));
+          _G.sendSet = NULL;
+        }
+
+      if (swapBanks)
+        {
+          emitcode ("mov", "psw,#0x%02x",
+           ((FUNC_REGBANK(dtype)) << 3) & 0xff);
+        }
+
+      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);
+
+              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
+    {
+      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 (!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));
+                }
+
+              freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
+
+              /* if send set is not empty then assign */
+              if (_G.sendSet)
+                {
+                  genSend(reverseSet(_G.sendSet));
+                  _G.sendSet = NULL;
+                }
+
+              if (swapBanks)
+                {
+                  emitcode ("mov", "psw,#0x%02x",
+                   ((FUNC_REGBANK(dtype)) << 3) & 0xff);
+                }
+
+              /* 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");
+
+          /* 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)
+            {
+              genSend(reverseSet(_G.sendSet));
+              _G.sendSet = NULL;
+            }
+
+          if (swapBanks)
+            {
+              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 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)))
+    {
+
+      _G.accInUse++;
+      aopOp (IC_RESULT (ic), ic, FALSE);
+      _G.accInUse--;
+
+      assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
+
+      freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+    }
+
+  /* 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;
+            }
+
+          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);
+    }
+
+//  /* 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);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* resultRemat - result  is rematerializable                       */
+/*-----------------------------------------------------------------*/
+static int
+resultRemat (iCode * ic)
+{
+  if (SKIP_IC (ic) || ic->op == IFX)
+    return 0;
+
+  if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
+    {
+      symbol *sym = OP_SYMBOL (IC_RESULT (ic));
+      if (sym->remat && !POINTER_SET (ic))
+        return 1;
+    }
+
+  return 0;
+}
+
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+#define STRCASECMP stricmp
+#else
+#define STRCASECMP strcasecmp
+#endif
+
+/*-----------------------------------------------------------------*/
+/* inExcludeList - return 1 if the string is in exclude Reg list   */
+/*-----------------------------------------------------------------*/
+static int
+regsCmp(void *p1, void *p2)
+{
+  return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
+}
+
+static bool
+inExcludeList (char *s)
+{
+  const char *p = setFirstItem(options.excludeRegsSet);
+
+  if (p == NULL || STRCASECMP(p, "none") == 0)
+    return FALSE;
+
+
+  return isinSetWith(options.excludeRegsSet, s, regsCmp);
+}
+
+/*-----------------------------------------------------------------*/
+/* genFunction - generated code for function entry                 */
+/*-----------------------------------------------------------------*/
+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;
+
+      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);
+            }
+        }
+    }
+
+  /* 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;
+
+          /* 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;
+
+            if (IFFUNC_HASFCALL(sym->type))
+            {
+
+#define MAX_REGISTER_BANKS 4
+
+                iCode *i;
+                int ix;
+
+                for (i = ic; i; i = i->next)
+                {
+                    if (i->op == ENDFUNCTION)
+                    {
+                        /* we got to the end OK. */
+                        break;
+                    }
+
+                    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);
+                    }
+                }
+
+                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;
+        }
+
+      /* 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. */
+
+      /* 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;
+
+          /* 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 (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");
+            }
+        }
+    }
+
+  /* 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));
+
+      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;
+        }
+
+      /* 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;
+
+          _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;
+
+          _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;
+        }
+    }
+
+  /* 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. */
+
+          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");
+    }
+
+  if (sym->xstack)
+    {
+      char i = ((char) sym->xstack & 0xff);
+
+      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 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 */
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genEndFunction - generates epilogue for functions               */
+/*-----------------------------------------------------------------*/
+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 ((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");
+        }
+    }
+
+  /* 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 (IFFUNC_ISISR (sym->type))
+    {
+
+      /* 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);
+                    }
+                }
+            }
+          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);
+            }
+        }
+        else
+        {
+            /* 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;
+
+            for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
+            {
+                if (savedBanks & (1 << ix))
+                {
+                    unsaveRBank(ix, NULL, FALSE);
+                }
+            }
+
+            if (options.useXstack)
+            {
+                /* Restore bank AFTER calling unsaveRBank,
+                 * since it can trash r0.
+                 */
+                emitcode ("pop", "psw");
+            }
+        }
+
+      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);
+        }
+
+      emitcode ("reti", "");
+    }
+  else
+    {
+      if (IFFUNC_CALLEESAVES(sym->type))
+        {
+          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", 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);
+            }
+
+        }
+
+      /* if debug then send end of function */
+      if (options.debug && currFunc)
+        {
+          debugFile->writeEndFunction (currFunc, ic, 1);
+        }
+
+      if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
+        {
+          emitcode ("ljmp", "__sdcc_banked_ret");
+        }
+      else
+        {
+          emitcode ("ret", "");
+        }
+    }
+
+  if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
+    return;
+
+  /* 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;
+
+  /* There are no push/pops to optimize if not callee-saves or ISR */
+  if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
+    return;
+
+  /* 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;
+
+  /* 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));
+
+      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;
+    }
+
+  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);
+
+  /* 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);
+    }
+
+  /* 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);
+                }
+            }
+          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);
+                }
+            }
+        }
+      lnp = lnp->next;
+    }
+
+  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);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRet - generate code for return statement                     */
+/*-----------------------------------------------------------------*/
+static void
+genRet (iCode * ic)
+{
+  int size, offset = 0, pushed = 0;
+
+  D (emitcode (";", "genRet"));
+
+  /* if we have no return value then
+     just generate the "ret" */
+  if (!IC_LEFT (ic))
+    goto jumpret;
+
+  /* we have something to return then
+     move the return value into place */
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  size = AOP_SIZE (IC_LEFT (ic));
+
+  if (IS_BIT(_G.currentFunc->etype))
+    {
+      movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
+      size = 0;
+    }
+
+  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);
+        }
+    }
+
+  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));
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genLabel - generates a label                                    */
+/*-----------------------------------------------------------------*/
+static void
+genLabel (iCode * ic)
+{
+  /* special case never generate */
+  if (IC_LABEL (ic) == entryLabel)
+    return;
+
+  emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
+}
+
+/*-----------------------------------------------------------------*/
+/* genGoto - generates a ljmp                                      */
+/*-----------------------------------------------------------------*/
+static void
+genGoto (iCode * ic)
+{
+  emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
+}
+
+/*-----------------------------------------------------------------*/
+/* 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)
+    {
+      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;
+}
+
+/*-----------------------------------------------------------------*/
+/* 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;
+
+  icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+
+  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);
+            }
+          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;
 
-    size = AOP_SIZE(IC_LEFT(ic));
-    while(size--) {
+      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;
+    }
 
-       char *l = aopGet(AOP(IC_LEFT(ic)),
-                        offset++,FALSE,FALSE); 
-       MOVA(l);            
-       emitcode("movx","@%s,a",r->name);       
-       emitcode("inc","%s",r->name);
+  /* 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));
+            }
+        }
 
+      return TRUE;
     }
 
-       
-    emitcode("mov","_spx,%s",r->name);
+  return FALSE;
+}
 
-    freeAsmop(NULL,aop,ic,TRUE);
-    freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
+/*-----------------------------------------------------------------*/
+/* 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);
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* genIpush - genrate code for pushing this gets a little complex  */
+/* genPlusBits - generates code for addition of two bits           */
 /*-----------------------------------------------------------------*/
-static void genIpush (iCode *ic)
+static void
+genPlusBits (iCode * ic)
 {
-    int size, offset = 0 ;
-    char *l;
+  D (emitcode (";", "genPlusBits"));
+
+  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));
+    }
+}
+
+#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 this is not a parm push : ie. it is spill push 
-    and spill push is always done on the local stack */
-    if (!ic->parmPush) {
+/*-----------------------------------------------------------------*/
+/* 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));
+        }
+      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++);
+            }
+        }
+      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;
+    }
 
-        /* and the item is spilt then do nothing */
-        if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
-            return ;
+  /* 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",""));
+    }
 
-        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";
+  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);
             }
-            emitcode("push","%s",l);
         }
-        return ;        
+      offset++;
+    }
+
+  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));
+    }
+}
 
-    /* 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);
+/*-----------------------------------------------------------------*/
+/* genMinusDec :- does subtraction with decrement 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;
+
+  D (emitcode (";", "genMinusDec"));
+
+  /* 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;
+        }
 
-    /* if use external stack then call the external
-    stack pushing routine */
-    if (options.useXstack) {
-        genXpush(ic);
-        return ;
+      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);
+            }
+          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);
+            }
+          emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
+        }
+      if (emitTlbl)
+        {
+          emitLabel (tlbl);
+        }
+      return TRUE;
     }
 
-    /* then do the push */
-    aopOp(IC_LEFT(ic),ic,FALSE);
+  /* if the sizes are greater than 1 then we cannot */
+  if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
+      AOP_SIZE (IC_LEFT (ic)) > 1)
+    return FALSE;
+
+  /* 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);
 
-       // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
-    size = AOP_SIZE(IC_LEFT(ic));
+      return TRUE;
+    }
 
-    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);
-    }       
+  return FALSE;
+}
 
-    freeAsmop(IC_LEFT(ic),NULL,ic,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 (result, "a", offset++);
+            }
+        }
+      else
+        {
+          while (size--)
+            {
+              aopPut (result, zero, offset++);
+            }
+        }
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* genIpop - recover the registers: can happen only for spilling   */
+/* genMinusBits - generates code for subtraction  of two bits      */
 /*-----------------------------------------------------------------*/
-static void genIpop (iCode *ic)
+static void
+genMinusBits (iCode * ic)
 {
-    int size,offset ;
-
+  symbol *lbl = newiTempLabel (NULL);
 
-    /* if the temp was not pushed then */
-    if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
-        return ;
+  D (emitcode (";", "genMinusBits"));
 
-    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));
-
-    freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
+  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)))));
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* unsaverbank - restores the resgister bank from stack            */
+/* genMinus - generates code for subtraction                       */
 /*-----------------------------------------------------------------*/
-static void unsaverbank (int bank,iCode *ic,bool popPsw)
+static void
+genMinus (iCode * ic)
 {
-    int i;
-    asmop *aop ;
-    regs *r = NULL;
+  int size, offset = 0;
 
-    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");
-    }
+  D (emitcode (";", "genMinus"));
 
-    for (i = (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);
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  aopOp (IC_RIGHT (ic), ic, FALSE);
+  aopOp (IC_RESULT (ic), ic, TRUE);
 
-        } else 
-            emitcode("pop","(%s+%d)",
-                     regs8051[i].base,8*bank+regs8051[i].offset);
+  /* 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 (options.useXstack) {
+  /* if I can do an decrement instead
+     of subtract then GOOD for ME */
+  if (genMinusDec (ic) == TRUE)
+    goto release;
 
-       emitcode("mov","_spx,%s",r->name);
-       freeAsmop(NULL,aop,ic,TRUE);
+  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;
 
-/*-----------------------------------------------------------------*/
-/* saverbank - saves an entire register bank on the stack          */
-/*-----------------------------------------------------------------*/
-static void saverbank (int bank, iCode *ic, bool pushPsw)
-{
-    int i;
-    asmop *aop ;
-    regs *r = NULL;
+      lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+      lit = -(long) lit;
 
-    if (options.useXstack) {
+      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;
 
-       aop = newAsmop(0);
-       r = getFreePtr(ic,&aop,FALSE);  
-       emitcode("mov","%s,_spx",r->name);
+      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++);
+        }
     }
 
-    for (i = 0 ; i < 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);
-    }
-    
-    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);
-    }
-    ic->bankSaved = 1;
+  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));
 }
 
+
 /*-----------------------------------------------------------------*/
-/* genCall - generates a call statement                            */
+/* genMultbits :- multiplication of bits                           */
 /*-----------------------------------------------------------------*/
-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 (sendSet) {
-       iCode *sic ;
-
-       for (sic = setFirstItem(sendSet) ; sic ; 
-            sic = setNextItem(sendSet)) {
-           int size, offset = 0;
-           aopOp(IC_LEFT(sic),sic,FALSE);
-           size = AOP_SIZE(IC_LEFT(sic));
-           while (size--) {
-               char *l = aopGet(AOP(IC_LEFT(sic)),offset,
-                               FALSE,FALSE);
-               if (strcmp(l,fReturn[offset]))
-                   emitcode("mov","%s,%s",
-                            fReturn[offset],
-                            l);
-               offset++;
-           }
-           freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
-       }
-       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)) ) {
-
-        accInUse++;
-        aopOp(IC_RESULT(ic),ic,FALSE);
-        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);
-
-    }
-
-    /* if register bank was saved then pop them */
-    if (ic->bankSaved)
-        unsaverbank(SPEC_BANK(detype),ic,TRUE);
-
-    /* if we hade saved some registers then unsave them */
-    if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
-        unsaveRegisters (ic);
-
+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);
 }
 
 /*-----------------------------------------------------------------*/
-/* genPcall - generates a call by pointer statement                */
+/* genMultOneByte : 8*8=8/16 bit multiplication                    */
 /*-----------------------------------------------------------------*/
-static void genPcall (iCode *ic)
+static void
+genMultOneByte (operand * left,
+                operand * right,
+                operand * result)
 {
-    link *detype;
-    symbol *rlbl = newiTempLabel(NULL);
-
-
-    /* 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        && 
-       IS_ISR(currFunc->etype) &&
-        (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
-        saverbank(SPEC_BANK(detype),ic,TRUE);
-
-
-    /* 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");
-
-    /* now push the calling address */
-    aopOp(IC_LEFT(ic),ic,FALSE);
-
-    pushSide(IC_LEFT(ic), 2);
-
-    freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
+  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));
+        }
 
-    /* if send set is not empty the assign */
-    if (sendSet) {
-       iCode *sic ;
+      emitcode ("mul", "ab");
+      aopPut (result, "a", 0);
+      if (size == 2)
+        aopPut (result, "b", 1);
 
-       for (sic = setFirstItem(sendSet) ; sic ; 
-            sic = setNextItem(sendSet)) {
-           int size, offset = 0;
-           aopOp(IC_LEFT(sic),sic,FALSE);
-           size = AOP_SIZE(IC_LEFT(sic));
-           while (size--) {
-               char *l = aopGet(AOP(IC_LEFT(sic)),offset,
-                               FALSE,FALSE);
-               if (strcmp(l,fReturn[offset]))
-                   emitcode("mov","%s,%s",
-                            fReturn[offset],
-                            l);
-               offset++;
-           }
-           freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
-       }
-       sendSet = NULL;
+      popB (pushedB);
+      return;
     }
 
-    emitcode("ret","");
-    emitcode("","%05d$:",(rlbl->key+100));
+  /* we have to do a signed multiply */
+  /* emitcode (";", "signed"); */
 
+  /* now sign adjust for both left & right */
 
-    /* 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)) ) {
+  /* let's see what's needed: */
+  /* apply negative sign during runtime */
+  runtimeSign = FALSE;
+  /* negative sign from literals */
+  compiletimeSign = FALSE;
 
-        accInUse++;
-        aopOp(IC_RESULT(ic),ic,FALSE);
-        accInUse--;
-       
-       assignResultValue(IC_RESULT(ic));
+  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;
+    }
 
-        freeAsmop(IC_RESULT(ic),NULL,ic,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");
+        }
     }
 
-    /* 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 (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 register bank was saved then unsave them */
-    if (detype        && 
-        (SPEC_BANK(currFunc->etype) != 
-         SPEC_BANK(detype)))
-        unsaverbank(SPEC_BANK(detype),ic,TRUE);
+      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);
+        }
+    }
 
-    /* if we hade saved some registers then
-    unsave them */
-    if (ic->regsSaved)
-        unsaveRegisters (ic);
+  /* 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);
 }
 
 /*-----------------------------------------------------------------*/
-/* resultRemat - result  is rematerializable                       */
+/* genMult - generates code for multiplication                     */
 /*-----------------------------------------------------------------*/
-static int resultRemat (iCode *ic)
+static void
+genMult (iCode * ic)
 {
-    if (SKIP_IC(ic) || ic->op == IFX)
-        return 0;
+  operand *left = IC_LEFT (ic);
+  operand *right = IC_RIGHT (ic);
+  operand *result = IC_RESULT (ic);
 
-    if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
-        symbol *sym = OP_SYMBOL(IC_RESULT(ic));
-        if (sym->remat && !POINTER_SET(ic)) 
-            return 1;
-    }
+  D (emitcode (";", "genMult"));
 
-    return 0;
-}
+  /* assign the asmops */
+  aopOp (left, ic, FALSE);
+  aopOp (right, ic, FALSE);
+  aopOp (result, ic, 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 ;
+  /* special cases first */
+  /* both are bits */
+  if (AOP_TYPE (left) == AOP_CRY &&
+      AOP_TYPE (right) == AOP_CRY)
+    {
+      genMultbits (left, right, result);
+      goto release;
+    }
 
-    for ( i = 0 ; options.excludeRegs[i]; i++) {
-       if (options.excludeRegs[i] &&
-           strcasecmp(s,options.excludeRegs[i]) == 0)
-           return TRUE;
+  /* 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;
     }
-    return FALSE ;
+
+  /* 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));
 }
 
 /*-----------------------------------------------------------------*/
-/* genFunction - generated code for function entry                 */
+/* genDivbits :- division of bits                                  */
 /*-----------------------------------------------------------------*/
-static void genFunction (iCode *ic)
+static void
+genDivbits (operand * left,
+            operand * right,
+            operand * result)
 {
-    symbol *sym;
-    link *fetype;
+  char *l;
+  bool pushedB;
 
-    nregssaved = 0;
-    /* create the function header */
-    emitcode(";","-----------------------------------------");
-    emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
-    emitcode(";","-----------------------------------------");
+  D(emitcode (";     genDivbits",""));
 
-    emitcode("","%s:",sym->rname);
-    fetype = getSpec(operandType(IC_LEFT(ic)));
+  pushedB = pushB ();
 
-    /* if critical function then turn interrupts off */
-    if (SPEC_CRTCL(fetype))
-        emitcode("clr","ea");
+  /* the result must be bit */
+  emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
+  l = aopGet (left, 0, FALSE, FALSE);
 
-    /* here we need to generate the equates for the
-       register bank if required */
-    if (SPEC_BANK(fetype) != rbank) {
-        int i ;
+  MOVA (l);
 
-        rbank = SPEC_BANK(fetype);
-        for ( i = 0 ; i < 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 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) ||
-                          (ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
-                           emitcode("push","%s",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) ||
-                      (ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
-                       emitcode("push","%s",regWithIdx(i)->dname);
-                       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) ||
-                          (ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
-                           emitcode("pop","%s",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 (!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) {
-           debugLine = 1;
-           emitcode("","C$%s$%d$%d$%d ==.",
-                    ic->filename,currFunc->lastLine,
-                    ic->level,ic->block); 
-           if (IS_STATIC(currFunc->etype))         
-               emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
-           else
-               emitcode("","XG$%s$0$0 ==.",currFunc->name);
-           debugLine = 0;
-       }
-       
-        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) ||
-                      (ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
-                       emitcode("pop","%s",regWithIdx(i)->dname);
-               }
-           }
-           
-       }
-
-       /* if debug then send end of function */
-/*     if (options.debug && currFunc) { */
-       if (currFunc) {
-           debugLine = 1;
-           emitcode("","C$%s$%d$%d$%d ==.",
-                    ic->filename,currFunc->lastLine,
-                    ic->level,ic->block); 
-           if (IS_STATIC(currFunc->etype))         
-               emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
-           else
-               emitcode("","XG$%s$0$0 ==.",currFunc->name);
-           debugLine = 0;
-       }
-
-        emitcode ("ret","");
-    }
+  emitcode ("div", "ab");
+  emitcode ("rrc", "a");
 
-}
+  popB (pushedB);
 
-/*-----------------------------------------------------------------*/
-/* 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) {
-                   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));
-    
+  aopPut (result, "c", 0);
 }
 
 /*-----------------------------------------------------------------*/
-/* genLabel - generates a label                                    */
+/* genDivOneByte : 8 bit division                                  */
 /*-----------------------------------------------------------------*/
-static void genLabel (iCode *ic)
+static void
+genDivOneByte (operand * left,
+               operand * right,
+               operand * result)
 {
-    /* special case never generate */
-    if (IC_LABEL(ic) == entryLabel)
-        return ;
+  bool lUnsigned, rUnsigned, pushedB;
+  bool runtimeSign, compiletimeSign;
+  bool accuse = FALSE;
+  bool pushedA = FALSE;
+  symbol *lbl;
+  int size, offset;
 
-    emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
-}
-
-/*-----------------------------------------------------------------*/
-/* genGoto - generates a ljmp                                      */
-/*-----------------------------------------------------------------*/
-static void genGoto (iCode *ic)
-{
-    emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
-}
+  D(emitcode (";     genDivOneByte",""));
 
-/*-----------------------------------------------------------------*/
-/* 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 = newiTempLabel(NULL);
-       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 == 4){
-           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(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));
-       }
-       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));
-        }
-       
-        return TRUE ;
-    }
-    
-    return FALSE ;
-}
+  /* Why is it necessary that genDivOneByte() can return an int result?
+     Have a look at:
 
-/*-----------------------------------------------------------------*/
-/* outBitAcc - output a bit in acc                                 */
-/*-----------------------------------------------------------------*/
-void outBitAcc(operand *result)
-{
-    symbol *tlbl = newiTempLabel(NULL);
-    /* if the result is a bit */
-    if (AOP_TYPE(result) == AOP_CRY){
-        aopPut(AOP(result),"a",0);
-    }
-    else {
-        emitcode("jz","%05d$",tlbl->key+100);
-        emitcode("mov","a,%s",one);
-        emitcode("","%05d$:",tlbl->key+100);
-        outAcc(result);
-    }
-}
+        volatile unsigned char uc;
+        volatile signed char sc1, sc2;
+        volatile int i;
 
-/*-----------------------------------------------------------------*/
-/* 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));
-    }
-}
+        uc  = 255;
+        sc1 = -1;
+        i = uc / sc1;
 
-/*-----------------------------------------------------------------*/
-/* genPlus - generates code for addition                           */
-/*-----------------------------------------------------------------*/
-static void genPlus (iCode *ic)
-{
-    int size, offset = 0;
+     Or:
 
-    /* special cases :- */
+        sc1 = -128;
+        sc2 = -1;
+        i = sc1 / sc2;
 
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RIGHT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
+     In all cases a one byte result would overflow, the following cast to int
+     would return the wrong result.
 
-    /* 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;
-    }
+     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!
+  */
 
-    /* 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 ;
-    }
+  size = AOP_SIZE (result) - 1;
+  offset = 1;
+  lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+  rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
 
-    /* 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++);      
-    }
-
-    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);
-     }
-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 ;
-
-       size = getDataSize(IC_RESULT(ic));
-    /* if decrement 16 bits in register */
-    if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
-        (size > 1) &&
-        (icount == 1)) {
-        symbol *tlbl = newiTempLabel(NULL);
-               emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,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 == 4){
-                       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(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));
-               }
-               emitcode("","%05d$:",tlbl->key+100);
-        return TRUE;
-    }
+  pushedB = pushB ();
 
-    /* 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 ;
+  /* 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++);
 
-    /* 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)))) {
+      popB (pushedB);
+      return;
+    }
 
-        while (icount--) 
-            emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+  /* signed is a little bit more difficult */
 
-        return TRUE ;
-    }
+  /* now sign adjust for both left & right */
 
-    return FALSE ;
-}
+  /* let's see what's needed: */
+  /* apply negative sign during runtime */
+  runtimeSign = FALSE;
+  /* negative sign from literals */
+  compiletimeSign = FALSE;
 
-/*-----------------------------------------------------------------*/
-/* 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++);
+  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;
     }
-}
 
-/*-----------------------------------------------------------------*/
-/* 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 (!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");
+        }
     }
-}
 
-/*-----------------------------------------------------------------*/
-/* genMinus - generates code for subtraction                       */
-/*-----------------------------------------------------------------*/
-static void genMinus (iCode *ic)
-{
-    int size, offset = 0;
-    unsigned long lit = 0L;
+  if (AOP_TYPE(left) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
 
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RIGHT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
+      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));
 
-    /* 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 (!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);
+        }
     }
 
-    /* if I can do an decrement instead
-    of subtract then GOOD for ME */
-    if (genMinusDec (ic) == TRUE)
-        goto release;   
+  /* now the division */
+  emitcode ("div", "ab");
 
-    size = getDataSize(IC_RESULT(ic));   
+  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);
 
-    if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
-        CLRC;
+      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{
-        lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
-        lit = - (long)lit;
+  else
+    {
+      aopPut (result, "a", 0);
+      while (size--)
+        aopPut (result, zero, offset++);
     }
 
-    /* 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 (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);
-    }
-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);
+  if (pushedA)
+    emitcode ("pop", "acc");
+  popB (pushedB);
 }
 
-
 /*-----------------------------------------------------------------*/
-/* genMultbits :- multiplication of bits                           */
+/* genDiv - generates code for division                            */
 /*-----------------------------------------------------------------*/
-static void genMultbits (operand *left, 
-                         operand *right, 
-                         operand *result)
+static void
+genDiv (iCode * ic)
 {
-    emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
-    emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
-    outBitC(result);
-}
+  operand *left = IC_LEFT (ic);
+  operand *right = IC_RIGHT (ic);
+  operand *result = IC_RESULT (ic);
 
+  D (emitcode (";", "genDiv"));
 
-/*-----------------------------------------------------------------*/
-/* genMultOneByte : 8 bit multiplication & division                */
-/*-----------------------------------------------------------------*/
-static void genMultOneByte (operand *left,
-                            operand *right,
-                            operand *result)
-{
-    link *opetype = operandType(result);
-    char *l ;
-    symbol *lbl ;
-    int size,offset;
+  /* assign the amsops */
+  aopOp (left, ic, FALSE);
+  aopOp (right, ic, FALSE);
+  aopOp (result, ic, TRUE);
 
-    /* (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;
+  /* special cases first */
+  /* both are bits */
+  if (AOP_TYPE (left) == AOP_CRY &&
+      AOP_TYPE (right) == AOP_CRY)
+    {
+      genDivbits (left, right, result);
+      goto release;
     }
 
-    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");
-
-            /* 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++);
+  /* 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));
 }
 
 /*-----------------------------------------------------------------*/
-/* genMult - generates code for multiplication                     */
+/* genModbits :- modulus of bits                                   */
 /*-----------------------------------------------------------------*/
-static void genMult (iCode *ic)
+static void
+genModbits (operand * left,
+            operand * right,
+            operand * result)
 {
-    operand *left = IC_LEFT(ic);
-    operand *right = IC_RIGHT(ic);
-    operand *result= IC_RESULT(ic);   
+  char *l;
+  bool pushedB;
 
-    /* assign the amsops */
-    aopOp (left,ic,FALSE);
-    aopOp (right,ic,FALSE);
-    aopOp (result,ic,TRUE);
+  D (emitcode (";", "genModbits"));
 
-    /* special cases first */
-    /* both are bits */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right)== AOP_CRY) {
-        genMultbits(left,right,result);
-        goto release ;
-    }
+  pushedB = pushB ();
 
-    /* if both are of size == 1 */
-    if (AOP_SIZE(left) == 1 &&
-        AOP_SIZE(right) == 1 ) {
-        genMultOneByte(left,right,result);
-        goto release ;
-    }
+  /* the result must be bit */
+  emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
+  l = aopGet (left, 0, FALSE, FALSE);
+
+  MOVA (l);
 
-    /* should have been converted to function call */       
-    assert(1) ;
+  emitcode ("div", "ab");
+  emitcode ("mov", "a,b");
+  emitcode ("rrc", "a");
 
-release :
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE); 
+  popB (pushedB);
+
+  aopPut (result, "c", 0);
 }
 
 /*-----------------------------------------------------------------*/
-/* genDivbits :- division of bits                                  */
+/* genModOneByte : 8 bit modulus                                   */
 /*-----------------------------------------------------------------*/
-static void genDivbits (operand *left, 
-                        operand *right, 
-                        operand *result)
+static void
+genModOneByte (operand * left,
+               operand * right,
+               operand * result)
 {
+  bool lUnsigned, rUnsigned, pushedB;
+  bool runtimeSign, compiletimeSign;
+  symbol *lbl;
+  int size, offset;
 
-    char *l;
+  D (emitcode (";", "genModOneByte"));
 
-    /* the result must be bit */    
-    emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
-    l = aopGet(AOP(left),0,FALSE,FALSE);
+  size = AOP_SIZE (result) - 1;
+  offset = 1;
+  lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+  rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
 
-    MOVA(l);    
+  /* 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;
 
-    emitcode("div","ab");
-    emitcode("rrc","a");
-    aopPut(AOP(result),"c",0);
-}
+      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;
 
-/*-----------------------------------------------------------------*/
-/* 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));
+          default:
+            break;
+        }
+    }
+
+  pushedB = pushB ();
 
-    /* now we are done */
-    aopPut(AOP(result),"b",0);
-    if(size > 0){
-        emitcode("mov","c,b.7");
-        emitcode("subb","a,acc");   
+  /* 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;
     }
-    while (size--)
-        aopPut(AOP(result),"a",offset++);
 
-}
+  /* signed is a little bit more difficult */
 
-/*-----------------------------------------------------------------*/
-/* 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);   
+  /* now sign adjust for both left & right */
 
-    /* assign the amsops */
-    aopOp (left,ic,FALSE);
-    aopOp (right,ic,FALSE);
-    aopOp (result,ic,TRUE);
+  /* modulus: sign of the right operand has no influence on the result! */
+  if (AOP_TYPE(right) == AOP_LIT)
+    {
+      signed char val = (char) operandLitValue(right);
 
-    /* special cases first */
-    /* both are bits */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right)== AOP_CRY) {
-        genDivbits(left,right,result);
-        goto release ;
+      if (!rUnsigned && val < 0)
+        emitcode ("mov", "b,#0x%02x", -val);
+      else
+        emitcode ("mov", "b,#0x%02x", (unsigned char) val);
     }
-
-    /* if both are of size == 1 */
-    if (AOP_SIZE(left) == 1 &&
-        AOP_SIZE(right) == 1 ) {
-        genDivOneByte(left,right,result);
-        goto release ;
+  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");
+        }
     }
 
-    /* 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); 
-}
+  /* let's see what's needed: */
+  /* apply negative sign during runtime */
+  runtimeSign = FALSE;
+  /* negative sign from literals */
+  compiletimeSign = FALSE;
 
-/*-----------------------------------------------------------------*/
-/* genModbits :- modulus of bits                                   */
-/*-----------------------------------------------------------------*/
-static void genModbits (operand *left, 
-                        operand *right, 
-                        operand *result)
-{
+  /* sign adjust left side */
+  if (AOP_TYPE(left) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
 
-    char *l;
+      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));
 
-    /* the result must be bit */    
-    emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
-    l = aopGet(AOP(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);
+        }
+    }
 
-    MOVA(l);       
+  /* now the modulus */
+  emitcode ("div", "ab");
 
-    emitcode("div","ab");
-    emitcode("mov","a,b");
-    emitcode("rrc","a");
-    aopPut(AOP(result),"c",0);
-}
+  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);
 
-/*-----------------------------------------------------------------*/
-/* 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);
+      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)
+static void
+genMod (iCode * ic)
 {
-    operand *left = IC_LEFT(ic);
-    operand *right = IC_RIGHT(ic);
-    operand *result= IC_RESULT(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);
+  D (emitcode (";", "genMod"));
 
-    /* special cases first */
-    /* both are bits */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right)== AOP_CRY) {
-        genModbits(left,right,result);
-        goto release ;
+  /* 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 ;
+  /* 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(1);
+  /* should have been converted to function call */
+  assert (0);
 
-release :
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE); 
+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)
+static void
+genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
 {
-    symbol *jlbl ;
-    symbol *tlbl = newiTempLabel(NULL);
-    char *inst;
-
-    /* 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);
-    emitcode("ljmp","%05d$",jlbl->key+100);
-    emitcode("","%05d$:",tlbl->key+100);                
-
-    /* mark the icode as generated */
-    ic->generated = 1;
+  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)
-{
-    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;
+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(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
-                        if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
-                            genIfxJump (ifx,"acc.7");
-                            return;
+                  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");
                         }
-                        else    
-                            emitcode("rlc","a");
                     }
-                    goto release;
+                  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--) {
-                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");
+          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));
                     }
-                } else      
-                    emitcode("subb","a,%s",aopGet(AOP(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:
-    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 */
+  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)
+static void
+genCmpGt (iCode * ic, iCode * ifx)
 {
-    operand *left, *right, *result;
-    link *letype , *retype;
-    int sign ;
+  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);
+  left = IC_LEFT (ic);
+  right = IC_RIGHT (ic);
+  result = IC_RESULT (ic);
 
-    letype = getSpec(operandType(left));
-    retype =getSpec(operandType(right));
-    sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
-    /* assign the amsops */
-    aopOp (left,ic,FALSE);
-    aopOp (right,ic,FALSE);
-    aopOp (result,ic,TRUE);
+  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);
+  genCmp (right, left, result, ifx, sign, ic);
 
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE); 
+  freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
 /* genCmpLt - less than comparisons                                */
 /*-----------------------------------------------------------------*/
-static void genCmpLt (iCode *ic, iCode *ifx)
+static void
+genCmpLt (iCode * ic, iCode * ifx)
 {
-    operand *left, *right, *result;
-    link *letype , *retype;
-    int sign ;
+  operand *left, *right, *result;
+  sym_link *letype, *retype;
+  int sign;
 
-    left = IC_LEFT(ic);
-    right= IC_RIGHT(ic);
-    result = IC_RESULT(ic);
+  D (emitcode (";", "genCmpLt"));
 
-    letype = getSpec(operandType(left));
-    retype =getSpec(operandType(right));
-    sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
+  left = IC_LEFT (ic);
+  right = IC_RIGHT (ic);
+  result = IC_RESULT (ic);
 
-    /* assign the amsops */
-    aopOp (left,ic,FALSE);
-    aopOp (right,ic,FALSE);
-    aopOp (result,ic,TRUE);
+  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);
+  genCmp (left, right, result, ifx, sign, ic);
 
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE); 
+  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;
-
-    /* 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++;
+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(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++;
+  /* 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--) {
-            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++;
+    }
+  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++;
         }
     }
 }
@@ -3346,1167 +6009,1901 @@ static void gencjneshort(operand *left, operand *right, symbol *lbl)
 /*-----------------------------------------------------------------*/
 /* gencjne - compare and jump if not equal                         */
 /*-----------------------------------------------------------------*/
-static void gencjne(operand *left, operand *right, symbol *lbl)
+static void
+gencjne (operand * left, operand * right, symbol * lbl)
 {
-    symbol *tlbl  = newiTempLabel(NULL);
+  symbol *tlbl = newiTempLabel (NULL);
+
+  D (emitcode (";", "gencjne"));
 
-    gencjneshort(left, right, lbl);
+  gencjneshort (left, right, lbl);
 
-    emitcode("mov","a,%s",one);
-    emitcode("sjmp","%05d$",tlbl->key+100);
-    emitcode("","%05d$:",lbl->key+100);
-    emitcode("clr","a");
-    emitcode("","%05d$:",tlbl->key+100);
+  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)
-{
-    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");
+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");
                 }
-                /* 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);
+              else if (lit == 1L)
+                {
+                  emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
+                }
+              else
+                {
+                  emitcode ("clr", "c");
+                }
+              /* AOP_TYPE(right) == AOP_CRY */
             }
-            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");
+          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);
             }
-            /* 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 */
+          /* 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(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE);
+  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 )
+static iCode *
+ifxForOp (operand * op, iCode * ic)
 {
-    /* if true symbol then needs to be assigned */
-    if (IS_TRUE_SYMOP(op))
-        return NULL ;
+  /* 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;
+  /* 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;
+  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)
+static void
+genAndOp (iCode * ic)
 {
-    operand *left,*right, *result;
-    symbol *tlbl;
+  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);
+  D (emitcode (";", "genAndOp"));
 
-    /* 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);
+  /* 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(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE);
+  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)
+static void
+genOrOp (iCode * ic)
 {
-    operand *left,*right, *result;
-    symbol *tlbl;
+  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);
+  D (emitcode (";", "genOrOp"));
 
-    /* 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);
+  /* 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(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE);            
+  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                               */
 /*-----------------------------------------------------------------*/
-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;
+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)
+static void
+continueIfTrue (iCode * ic)
 {
-    if(IC_TRUE(ic))
-        emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
-    ic->generated = 1;
+  if (IC_TRUE (ic))
+    emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
+  ic->generated = 1;
 }
 
 /*-----------------------------------------------------------------*/
 /* jmpIfTrue -                                                     */
 /*-----------------------------------------------------------------*/
-static void jumpIfTrue (iCode *ic)
+static void
+jumpIfTrue (iCode * ic)
 {
-    if(!IC_TRUE(ic))
-        emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
-    ic->generated = 1;
+  if (!IC_TRUE (ic))
+    emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
+  ic->generated = 1;
 }
 
 /*-----------------------------------------------------------------*/
 /* jmpTrueOrFalse -                                                */
 /*-----------------------------------------------------------------*/
-static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
+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);                 
-        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;
+  // 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)
+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];
+  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);
+  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));
+  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)
-    // 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 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;
+              if ((AOP_TYPE (result) == AOP_CRY) && ifx)
+                {
+                  jumpIfTrue (ifx);
+                  goto release;
                 }
-                emitcode("clr","c");
+              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);
+        }
+      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;
                 }
-                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);
+          // 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++;
+              offset++;
             }
-            // bit = left & literal
-            if(size){
-                emitcode("clr","c");
-                emitcode("","%05d$:",tlbl->key+100);
+          // bit = left & literal
+          if (size)
+            {
+              emitcode ("clr", "c");
+              emitLabel (tlbl);
             }
-            // if(left & literal)
-            else{
-                if(ifx)
-                    jmpTrueOrFalse(ifx, tlbl);
-                goto release ;
+          // if(left & literal)
+          else
+            {
+              if (ifx)
+                jmpTrueOrFalse (ifx, tlbl, left, right, result);
+              else
+                emitLabel (tlbl);
+              goto release;
             }
         }
-        outBitC(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){
-                if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
+  /* 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(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);     
+                }
+              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)
+static void
+genOr (iCode * ic, iCode * ifx)
 {
-    operand *left, *right, *result;
-    int size, offset=0;
-    unsigned long lit = 0L;
+  operand *left, *right, *result;
+  int size, offset = 0;
+  unsigned long lit = 0L;
+  int bytelit = 0;
 
-    aopOp((left = IC_LEFT(ic)),ic,FALSE);
-    aopOp((right= IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,TRUE);
+  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));
+  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;
+  /* 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);
+              emitcode ("setb", "c");
             }
-        } 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);
+          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;
-                } else {
-                    CLRC;
-                    emitcode("","%05d$:",tlbl->key+100);
+                  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");
+                    }
                 }
             }
+
         }
-        // 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
+        {
+          // 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);
         }
-        outBitC(result);
-        goto release ;
-    }
-
-    /* if left is same as result */
-    if(sameRegs(AOP(result),AOP(left))){
-        for(;size--; offset++) {
-            if(AOP_TYPE(right) == AOP_LIT){
-                if(((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;
+      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);
             }
-            // 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);                     
         }
     }
 
-release :
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE);     
+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                                   */
+/* genInline - write the inline code out                           */
 /*-----------------------------------------------------------------*/
-static void genXor (iCode *ic, iCode *ifx)
+static void
+genInline (iCode * ic)
 {
-    operand *left, *right, *result;
-    int size, offset=0;
-    unsigned long lit = 0L;
+  char *buffer, *bp, *bp1;
 
-    aopOp((left = IC_LEFT(ic)),ic,FALSE);
-    aopOp((right= IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,TRUE);
+  D (emitcode (";", "genInline"));
 
-#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
+  _G.inLine += (!options.asmpeep);
 
-    /* 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");
-                    }
-                }
-            }
+  buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
 
-        } 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);
-                }
-                // 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(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;
-                }
+  /* 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;
             }
-            // 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);
+          else
+            bp++;
         }
     }
+  if (bp1 != bp)
+    emitcode (bp1, "");
+  /*     emitcode("",buffer); */
+  _G.inLine -= (!options.asmpeep);
+}
 
-release :
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE);     
+/*-----------------------------------------------------------------*/
+/* 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);
 }
 
 /*-----------------------------------------------------------------*/
-/* genInline - write the inline code out                           */
+/* genRLC - generate code for rotate left with carry               */
 /*-----------------------------------------------------------------*/
-static void genInline (iCode *ic)
-{
-    char buffer[MAX_INLINEASM];
-    char *bp = buffer;
-    char *bp1= buffer;
-    
-    inLine += (!options.asmpeep);
-    strcpy(buffer,IC_INLINE(ic));
-
-    /* emit each line as a code */
-    while (*bp) {
-        if (*bp == '\n') {
-            *bp++ = '\0';
-            emitcode(bp1,"");
-            bp1 = bp;
-        } else {
-            if (*bp == ':') {
-                bp++;
-                *bp = '\0';
-                bp++;
-                emitcode(bp1,"");
-                bp1 = bp;
-            } else
-                bp++;
+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++);
         }
     }
-    if (bp1 != bp)
-        emitcode(bp1,"");
-    /*     emitcode("",buffer); */
-    inLine -= (!options.asmpeep);
+  /* 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);
 }
 
 /*-----------------------------------------------------------------*/
-/* genRRC - rotate right with carry                                */
+/* genGetHbit - generates code get highest order bit               */
 /*-----------------------------------------------------------------*/
-static void genRRC (iCode *ic)
+static void
+genGetHbit (iCode * ic)
 {
-    operand *left , *result ;
-    int size, offset = 0;
-    char *l;    
+  operand *left, *result;
 
-    /* rotate right with carry */
-    left = IC_LEFT(ic);
-    result=IC_RESULT(ic);
-    aopOp (left,ic,FALSE);
-    aopOp (result,ic,FALSE);
+  D (emitcode (";", "genGetHbit"));
 
-    /* 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--);
+  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);
     }
-    /* 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);
+  else
+    {
+      emitcode ("rl", "a");
+      emitcode ("anl", "a,#0x01");
+      outAcc (result);
     }
-    emitcode("mov","acc.7,c");
-    aopPut(AOP(result),"a",AOP_SIZE(result)-1);
-    freeAsmop(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
+
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genRLC - generate code for rotate left with carry               */
+/* genGetAbit - generates code get a single bit                    */
 /*-----------------------------------------------------------------*/
-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);
+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);
 }
 
 /*-----------------------------------------------------------------*/
-/* genGetHbit - generates code get highest order bit               */
+/* genGetByte - generates code get a single byte                   */
 /*-----------------------------------------------------------------*/
-static void genGetHbit (iCode *ic)
+static void
+genGetByte (iCode * ic)
 {
-    operand *left, *result;
-    left = IC_LEFT(ic);
-    result=IC_RESULT(ic);
-    aopOp (left,ic,FALSE);
-    aopOp (result,ic,FALSE);
+  operand *left, *right, *result;
+  int offset;
 
-    /* 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);
-    }
-    else{
-        emitcode("rl","a");
-        emitcode("anl","a,#0x01");
-        outAcc(result);
-    }
+  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(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
 /* AccRol - rotate left accumulator by known count                 */
 /*-----------------------------------------------------------------*/
-static void AccRol (int shCount)
+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;
+  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)
+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]);
+  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]);
         }
     }
 }
@@ -4514,17 +7911,22 @@ static void AccLsh (int shCount)
 /*-----------------------------------------------------------------*/
 /* AccRsh - right shift accumulator by known count                 */
 /*-----------------------------------------------------------------*/
-static void AccRsh (int shCount)
+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]);
+  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]);
         }
     }
 }
@@ -4532,28 +7934,35 @@ static void AccRsh (int 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]);
-            emitcode("","%05d$:",tlbl->key+100);
+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);
         }
     }
 }
@@ -4561,54 +7970,65 @@ static void AccSRsh (int shCount)
 /*-----------------------------------------------------------------*/
 /* shiftR1Left2Result - shift right one byte from left to result   */
 /*-----------------------------------------------------------------*/
-static void shiftR1Left2Result (operand *left, int offl,
-                                operand *result, int offr,
-                                int shCount, int sign)
+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);
+  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)
+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);
+  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)
+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);
+  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(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);
+      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);
                 }
             }
         }
@@ -4618,324 +8038,500 @@ static void movLeft2Result (operand *left, int offl,
 /*-----------------------------------------------------------------*/
 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
 /*-----------------------------------------------------------------*/
-static void AccAXRrl1 (char *x)
+static void
+AccAXRrl1 (char *x)
 {
-    emitcode("rrc","a");
-    emitcode("xch","a,%s", x);
-    emitcode("rrc","a");
-    emitcode("xch","a,%s", 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)
+static void
+AccAXLrl1 (char *x)
 {
-    emitcode("xch","a,%s",x);
-    emitcode("rlc","a");
-    emitcode("xch","a,%s",x);
-    emitcode("rlc","a");
+  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)
+static void
+AccAXLsh1 (char *x)
 {
-    emitcode("xch","a,%s",x);
-    emitcode("add","a,acc");
-    emitcode("xch","a,%s",x);
-    emitcode("rlc","a");
+  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)
+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;
+  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
-            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
+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
-            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;
+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)
+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));
+  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);
     }
-    /* ax << shCount (x = lsb(result))*/
-    AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
-    aopPut(AOP(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)
-{
-    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);
-}
-
-/*-----------------------------------------------------------------*/
-/* shiftLLeftOrResult - shift left one byte from left, or to result*/
-/*-----------------------------------------------------------------*/
-static void shiftLLeftOrResult (operand *left, int offl,
-                                operand *result, int offr, int shCount)
+static void
+shiftR2Left2Result (operand * left, int offl,
+                    operand * result, int offr,
+                    int shCount, int sign)
 {
-    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);
+  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*/
+/* shiftRLeftOrResult - shift right one byte from left,or to result */
 /*-----------------------------------------------------------------*/
-static void shiftRLeftOrResult (operand *left, int offl,
-                                operand *result, int offr, int shCount)
+static void
+shiftRLeftOrResult (operand * left, int offl,
+                    operand * result, int offr, int shCount)
 {
-    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);
+  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)
-{       
-    shiftL1Left2Result(left, LSB, result, LSB, shCount);
+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)
+static void
+genlshTwo (operand * result, operand * left, int shCount)
 {
-    int size = AOP_SIZE(result);
+  int size;
+
+  D (emitcode (";", "genlshTwo"));
 
-    if (size == 3)
-        size--;
+  size = getDataSize (result);
 
-    /* if shCount >= 8 */
-    if (shCount >= 8) {
-        shCount -= 8 ;
+  /* 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);
+      if (size > 1)
+        {
+          if (shCount)
+            shiftL1Left2Result (left, LSB, result, MSB16, shCount);
+          else
+            movLeft2Result (left, LSB, result, MSB16, 0);
         }
-        aopPut(AOP(result),zero,LSB);   
+      aopPut (result, zero, LSB);
     }
 
-    /*  1 <= shCount <= 7 */
-    else {  
-        if(size == 1)
-            shiftL1Left2Result(left, LSB, result, LSB, shCount); 
-        else 
-            shiftL2Left2Result(left, LSB, result, LSB, shCount);
+  /*  1 <= shCount <= 7 */
+  else
+    {
+      if (size == 1)
+        shiftL1Left2Result (left, LSB, result, LSB, shCount);
+      else
+        shiftL2Left2Result (left, LSB, result, LSB, shCount);
     }
 }
 
@@ -4943,412 +8539,550 @@ static void genlshTwo (operand *result,operand *left, int 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(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);       
+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)
+static void
+genlshFour (operand * result, operand * left, int shCount)
 {
-    int size;
-
-    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(AOP(result),zero,LSB);
-        aopPut(AOP(result),zero,MSB16);
-        aopPut(AOP(result),zero,MSB32);
-        return;
+  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;
     }
 
-    /* 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);
+  /* 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
+        {                       /* 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(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 (result, zero, LSB);
             }
         }
     }
 
-    /* 1 <= shCount <= 7 */
-    else if(shCount <= 2){
-        shiftLLong(left, result, LSB);
-        if(shCount == 2)
-            shiftLLong(result, result, 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);
+  /* 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;
+static void
+genLeftShiftLiteral (operand * left,
+                     operand * right,
+                     operand * result,
+                     iCode * ic)
+{
+  int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+  int size;
 
-    freeAsmop(right,NULL,ic,TRUE);
+  D (emitcode (";", "genLeftShiftLiteral"));
 
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,FALSE);
+  freeAsmop (right, NULL, ic, TRUE);
 
-    size = getSize(operandType(result));
+  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));
+  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);
+  /* 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 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;
+  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(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
+  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;
-
-    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++;
+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(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);
+  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(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
+  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)
+static void
+genrshOne (operand * result, operand * left,
+           int shCount, int sign)
 {
-    shiftR1Left2Result(left, LSB, result, LSB, shCount, 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)
+static void
+genrshTwo (operand * result, operand * left,
+           int shCount, int sign)
 {
-    /* if shCount >= 8 */
-    if (shCount >= 8) {
-        shCount -= 8 ;
-        if (shCount)
-            shiftR1Left2Result(left, MSB16, result, LSB,
-                               shCount, sign);
-        else 
-            movLeft2Result(left, MSB16, result, LSB, sign);
-        addSign(result, MSB16, 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); 
+  /*  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)
+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);
+  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));
 
-    MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
-    emitcode("rrc","a");
-    aopPut(AOP(result),"a",MSB24-offl);
+  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));
+    }
 
-    MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
-    emitcode("rrc","a");
-    aopPut(AOP(result),"a",MSB16-offl);
+  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));
+    }
 
-    if(offl == LSB){
-        MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
-        emitcode("rrc","a");
-        aopPut(AOP(result),"a",LSB);
+  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)
+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);
+  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);
+      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 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
+        {
+          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
+    {
+      /* 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);
+      else
+        {
+          shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
+          shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
+          shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
         }
     }
 }
@@ -5356,2028 +9090,2776 @@ static void genrshFour (operand *result, operand *left,
 /*-----------------------------------------------------------------*/
 /* 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;
+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);
+  freeAsmop (right, NULL, ic, TRUE);
 
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,FALSE);
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, FALSE);
 
 #if VIEW_SIZE
-    emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
-             AOP_SIZE(left));
+  emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
+            AOP_SIZE (left));
 #endif
 
-    size = getDataSize(left);
-    /* test the LEFT size !!! */
+  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);
+  /* 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(AOP(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;
+  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(left,NULL,ic,TRUE);
-        freeAsmop(result,NULL,ic,TRUE);
     }
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
 /* genSignedRightShift - right shift of signed number              */
 /*-----------------------------------------------------------------*/
-static void genSignedRightShift (iCode *ic)
+static void
+genSignedRightShift (iCode * ic)
 {
-    operand *right, *left, *result;
-    int size, offset;
-    char *l;
-    symbol *tlbl, *tlbl1 ;
-
-    /* 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);  
-
+  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))
+            {
 
-    if ( AOP_TYPE(right) == AOP_LIT) {
-       genRightShiftLiteral (left,right,result,ic,1);
-       return ;
+              emitcode ("mov", "a,%s", l);
+              aopPut (result, "a", offset);
+            }
+          else
+            aopPut (result, l, offset);
+          offset++;
+        }
     }
-        /* 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);
+  /* 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);
 
-    /* now move the left to the result if they are not the
-    same */
-    if (!sameRegs(AOP(left),AOP(result)) && 
-        AOP_SIZE(result) > 1) {
+release:
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+}
 
-        size = AOP_SIZE(result);
-        offset=0;
-        while (size--) {
-            l = aopGet(AOP(left),offset,FALSE,TRUE);
-            if (*l == '@' && IS_AOP_PREG(result)) {
+/*-----------------------------------------------------------------*/
+/* genRightShift - generate code for right shifting                */
+/*-----------------------------------------------------------------*/
+static void
+genRightShift (iCode * ic)
+{
+  operand *right, *left, *result;
+  sym_link *letype;
+  int size, offset;
+  char *l;
+  symbol *tlbl, *tlbl1;
+  bool pushedB;
+
+  D (emitcode (";", "genRightShift"));
+
+  /* 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;
+    }
+
+  /* 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 ) */
+
+  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(AOP(result),"a",offset);
-            } else
-                aopPut(AOP(result),l,offset);
-            offset++;
+              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;
-    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);
+  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);
 
 release:
-    freeAsmop(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genRightShift - generate code for right shifting                */
+/* 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 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
+emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
+{
+  switch (p_type)
+    {
+    case IPOINTER:
+    case POINTER:
+      if (preserveAinB)
+        emitcode ("mov", "b,a");
+      emitcode ("mov", "a,@%s", rname);
+      break;
 
-    tlbl = newiTempLabel(NULL);
-    tlbl1= newiTempLabel(NULL);
-    size = AOP_SIZE(result);
-    offset = size - 1;
+    case PPOINTER:
+      if (preserveAinB)
+        emitcode ("mov", "b,a");
+      emitcode ("movx", "a,@%s", rname);
+      break;
 
-    /* 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 ;
-    }
+    case FPOINTER:
+      if (preserveAinB)
+        emitcode ("mov", "b,a");
+      emitcode ("movx", "a,@dptr");
+      break;
 
-    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--);
+    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;
     }
-    reAdjustPreg(AOP(result));
+}
+
+/*-----------------------------------------------------------------*/
+/* emitPtrByteSet - emits code to set a byte from src through a    */
+/*                  pointer register (R0, R1, or DPTR).            */
+/*-----------------------------------------------------------------*/
+static void
+emitPtrByteSet (char *rname, int p_type, char *src)
+{
+  switch (p_type)
+    {
+    case IPOINTER:
+    case POINTER:
+      if (*src=='@')
+        {
+          MOVA (src);
+          emitcode ("mov", "@%s,a", rname);
+        }
+      else
+        emitcode ("mov", "@%s,%s", rname, src);
+      break;
 
-    emitcode("","%05d$:",tlbl1->key+100);
-    emitcode("djnz","b,%05d$",tlbl->key+100);
+    case PPOINTER:
+      MOVA (src);
+      emitcode ("movx", "@%s,a", rname);
+      break;
 
-release:
-    freeAsmop(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
+    case FPOINTER:
+      MOVA (src);
+      emitcode ("movx", "@dptr,a");
+      break;
+
+    case GPOINTER:
+      MOVA (src);
+      emitcode ("lcall", "__gptrput");
+      break;
+    }
 }
 
 /*-----------------------------------------------------------------*/
 /* genUnpackBits - generates code for unpacking bits               */
 /*-----------------------------------------------------------------*/
-static void genUnpackBits (operand *result, char *rname, int ptype)
-{    
-    int shCnt ;
-    int rlen = 0 ;
-    link *etype;
-    int offset = 0 ;
+static void
+genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
+{
+  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);
+
+  /* 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);
 
-    etype = getSpec(operandType(result));
+          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;
+    }
+
+  /* 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);
+    }
+
+  /* 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);
 
-    /* read the first byte  */
-    switch (ptype) {
+          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++);
+    }
 
-    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;
+finish:
+  if (offset < rsize)
+    {
+      char *source;
 
-    case CPOINTER:
-       emitcode("clr","a");
-       emitcode("movc","a","@a+dptr");
-       break;
+      if (SPEC_USIGN (etype))
+        source = zero;
+      else
+        {
+          /* signed bitfield: sign extension with 0x00 or 0xff */
+          emitcode ("rlc", "a");
+          emitcode ("subb", "a,acc");
 
-    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 ;
+          source = "a";
+        }
+      rsize -= offset;
+      while (rsize--)
+        aopPut (result, source, offset++);
+    }
 }
 
 
 /*-----------------------------------------------------------------*/
 /* genDataPointerGet - generates code when ptr offset is known     */
 /*-----------------------------------------------------------------*/
-static void genDataPointerGet (operand *left, 
-                              operand *result, 
-                              iCode *ic)
+static void
+genDataPointerGet (operand * left,
+                   operand * result,
+                   iCode * ic)
 {
-    char *l;
-    char buffer[256];
-    int size , offset = 0;
-    aopOp(result,ic,TRUE);
+  char *l;
+  char buffer[256];
+  int size, offset = 0;
+
+  D (emitcode (";", "genDataPointerGet"));
 
-    /* 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++);
+  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(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
 /* 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);
-     
+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;
+    }
+
+ /* 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);
+
+  //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);
+        }
+    }
+
+  /* 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);
+        }
+    }
+
+  if (ifx && !ifx->generated)
+    {
+      genIfxJump (ifx, "a", left, NULL, result);
+    }
+
+  /* done */
+  freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+  if (pi) pi->generated = 1;
 }
 
 /*-----------------------------------------------------------------*/
 /* genPagedPointerGet - emitcode for paged pointer fetch           */
 /*-----------------------------------------------------------------*/
-static void genPagedPointerGet (operand *left, 
-                              operand *result, 
-                              iCode *ic)
+static void
+genPagedPointerGet (operand * left,
+                    operand * result,
+                    iCode * ic,
+                    iCode *pi,
+                    iCode *ifx)
 {
-    asmop *aop = NULL;
-    regs *preg = NULL ;
-    char *rname ;
-    link *rtype, *retype;    
+  asmop *aop = NULL;
+  regs *preg = NULL;
+  char *rname;
+  sym_link *rtype, *retype;
+
+  D (emitcode (";", "genPagedPointerGet"));
 
-    rtype = operandType(result);
-    retype= getSpec(rtype);
-    
-    aopOp(left,ic,FALSE);
+  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(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));
-        }
-    }
-    /* 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 (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);
+
+          offset++;
+
+          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);
         }
     }
 
-    freeAsmop(result,NULL,ic,TRUE);
+  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;
+}
+
+/*--------------------------------------------------------------------*/
+/* 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));
+        }
+    }
 }
 
 /*-----------------------------------------------------------------*/
-/* emitcodePointerGet - gget value from code space                  */
+/* genFarPointerGet - get value from far space                     */
 /*-----------------------------------------------------------------*/
-static void emitcodePointerGet (operand *left,
-                                operand *result, iCode *ic)
+static void
+genFarPointerGet (operand * left,
+                  operand * result, iCode * ic, iCode * pi, iCode * ifx)
 {
-    int size, offset ;
-    link *retype = getSpec(operandType(result));
+  int size, offset;
+  sym_link *retype = getSpec (operandType (result));
+
+  D (emitcode (";", "genFarPointerGet"));
+
+  aopOp (left, ic, FALSE);
+  loadDptrFromOperand (left, FALSE);
+
+  /* so dptr now contains the address */
+  aopOp (result, ic, FALSE);
 
-    aopOp(left,ic,FALSE);
+  /* if bit then unpack */
+  if (IS_BITFIELD (retype))
+    genUnpackBits (result, "dptr", FPOINTER, ifx);
+  else
+    {
+      size = AOP_SIZE (result);
+      offset = 0;
 
-    /* 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));
+      while (size--)
+        {
+          emitcode ("movx", "a,@dptr");
+          if (!ifx)
+            aopPut (result, "a", offset++);
+          if (size || pi)
+            emitcode ("inc", "dptr");
         }
     }
-    /* 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",CPOINTER);
-    else {
-        size = AOP_SIZE(result);
-        offset = 0 ;
+  if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
+    {
+      aopPut (left, "dpl", 0);
+      aopPut (left, "dph", 1);
+      pi->generated = 1;
+    }
 
-        while (size--) {
-            emitcode("clr","a");
-            emitcode("movc","a,@a+dptr");
-            aopPut(AOP(result),"a",offset++);
-            if (size)
-                emitcode("inc","dptr");
-        }
+  if (ifx && !ifx->generated)
+    {
+      genIfxJump (ifx, "a", left, NULL, result);
     }
 
-    freeAsmop(result,NULL,ic,TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genGenPointerGet - gget value from generic pointer space        */
+/* genCodePointerGet - get value from code space                   */
 /*-----------------------------------------------------------------*/
-static void genGenPointerGet (operand *left,
-                              operand *result, iCode *ic)
+static void
+genCodePointerGet (operand * left,
+                    operand * result, iCode * ic, iCode *pi, iCode *ifx)
 {
-    int size, offset ;
-    link *retype = getSpec(operandType(result));
+  int size, offset;
+  sym_link *retype = getSpec (operandType (result));
 
-    aopOp(left,ic,FALSE);
+  D (emitcode (";", "genCodePointerGet"));
 
-    /* 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));
-            emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
+  aopOp (left, ic, FALSE);
+  loadDptrFromOperand (left, FALSE);
+
+  /* so dptr now contains the address */
+  aopOp (result, ic, FALSE);
+
+  /* if bit then unpack */
+  if (IS_BITFIELD (retype))
+    genUnpackBits (result, "dptr", CPOINTER, ifx);
+  else
+    {
+      size = AOP_SIZE (result);
+      offset = 0;
+
+      while (size--)
+        {
+          emitcode ("clr", "a");
+          emitcode ("movc", "a,@a+dptr");
+          if (!ifx)
+            aopPut (result, "a", offset++);
+          if (size || pi)
+            emitcode ("inc", "dptr");
         }
     }
-    /* 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",GPOINTER);
-    else {
-        size = AOP_SIZE(result);
-        offset = 0 ;
+  if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
+    {
+      aopPut (left, "dpl", 0);
+      aopPut (left, "dph", 1);
+      pi->generated = 1;
+    }
 
-        while (size--) {
-            emitcode("lcall","__gptrget");
-            aopPut(AOP(result),"a",offset++);
-            if (size)
-                emitcode("inc","dptr");
+  if (ifx && !ifx->generated)
+    {
+      genIfxJump (ifx, "a", left, NULL, result);
+    }
+
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genGenPointerGet - get value from generic pointer space         */
+/*-----------------------------------------------------------------*/
+static void
+genGenPointerGet (operand * left,
+                  operand * result, iCode * ic, iCode *pi, iCode *ifx)
+{
+  int size, offset;
+  sym_link *retype = getSpec (operandType (result));
+
+  D (emitcode (";", "genGenPointerGet"));
+
+  aopOp (left, ic, FALSE);
+  loadDptrFromOperand (left, TRUE);
+
+  /* so dptr now contains the address */
+  aopOp (result, ic, FALSE);
+
+  /* if bit then unpack */
+  if (IS_BITFIELD (retype))
+    {
+      genUnpackBits (result, "dptr", GPOINTER, ifx);
+    }
+  else
+    {
+      size = AOP_SIZE (result);
+      offset = 0;
+
+      while (size--)
+        {
+          emitcode ("lcall", "__gptrget");
+          if (!ifx)
+            aopPut (result, "a", offset++);
+          if (size || pi)
+            emitcode ("inc", "dptr");
         }
     }
 
-    freeAsmop(result,NULL,ic,TRUE);
+  if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
+    {
+      aopPut (left, "dpl", 0);
+      aopPut (left, "dph", 1);
+      pi->generated = 1;
+    }
+
+  if (ifx && !ifx->generated)
+    {
+      genIfxJump (ifx, "a", left, NULL, result);
+    }
+
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
 /* genPointerGet - generate code for pointer get                   */
 /*-----------------------------------------------------------------*/
-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 */
-       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
+genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
+{
+  operand *left, *result;
+  sym_link *type, *etype;
+  int p_type;
+
+  D (emitcode (";", "genPointerGet"));
+
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+
+  if (getSize (operandType (result))>1)
+    ifx = NULL;
+
+  /* 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));
+    }
+
+  /* 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)
+    {
+
+    case POINTER:
     case IPOINTER:
-       genNearPointerGet (left,result,ic);
-       break;
+      genNearPointerGet (left, result, ic, pi, ifx);
+      break;
 
     case PPOINTER:
-       genPagedPointerGet(left,result,ic);
-       break;
+      genPagedPointerGet (left, result, ic, pi, ifx);
+      break;
 
     case FPOINTER:
-       genFarPointerGet (left,result,ic);
-       break;
+      genFarPointerGet (left, result, ic, pi, ifx);
+      break;
+
+    case CPOINTER:
+      genCodePointerGet (left, result, ic, pi, ifx);
+      break;
+
+    case GPOINTER:
+      genGenPointerGet (left, result, ic, pi, ifx);
+      break;
+    }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genPackBits - generates code for packed bit storage             */
+/*-----------------------------------------------------------------*/
+static void
+genPackBits (sym_link * etype,
+             operand * right,
+             char *rname, int p_type)
+{
+  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 */
+
+  D(emitcode (";     genPackBits",""));
+
+  blen = SPEC_BLEN (etype);
+  bstr = SPEC_BSTR (etype);
+
+  /* If the bitfield length is less than a byte */
+  if (blen < 8)
+    {
+      mask = ((unsigned char) (0xFF << (blen + bstr)) |
+              (unsigned char) (0xFF >> (8 - bstr)));
+
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          /* Case with a bitfield length <8 and literal source
+          */
+          litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+          litval <<= bstr;
+          litval &= (~mask) & 0xff;
+          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);
+           }
+        }
+
+      emitPtrByteSet (rname, p_type, "a");
+      return;
+    }
+
+  /* Bit length is greater than 7 bits. In this case, copy  */
+  /* all except the partial byte at the end                 */
+  for (rlen=blen;rlen>=8;rlen-=8)
+    {
+      emitPtrByteSet (rname, p_type,
+                      aopGet (right, offset++, FALSE, TRUE) );
+      if (rlen>8)
+        emitcode ("inc", "%s", rname);
+    }
+
+  /* If there was a partial byte at the end */
+  if (rlen)
+    {
+      mask = (((unsigned char) -1 << rlen) & 0xff);
+
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          /* Case with partial byte and literal source
+          */
+          litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+          litval >>= (blen-rlen);
+          litval &= (~mask) & 0xff;
+          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");
+    }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genDataPointerSet - remat pointer to data space                 */
+/*-----------------------------------------------------------------*/
+static void
+genDataPointerSet (operand * right,
+                   operand * result,
+                   iCode * ic)
+{
+  int size, offset = 0;
+  char *l, buffer[256];
+
+  D (emitcode (";", "genDataPointerSet"));
 
-    case CPOINTER:
-       emitcodePointerGet (left,result,ic);
-       break;
+  aopOp (right, ic, FALSE);
 
-    case GPOINTER:
-       genGenPointerGet (left,result,ic);
-       break;
+  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));
     }
 
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genPackBits - generates code for packed bit storage             */
+/* genNearPointerSet - emitcode for near pointer put                */
 /*-----------------------------------------------------------------*/
-static void genPackBits (link    *etype ,
-                         operand *right ,
-                         char *rname, int p_type)
+static void
+genNearPointerSet (operand * right,
+                   operand * result,
+                   iCode * ic,
+                   iCode * pi)
 {
-    int shCount = 0 ;
-    int offset = 0  ;
-    int rLen = 0 ;
-    int blen, bstr ;   
-    char *l ;
-
-    blen = SPEC_BLEN(etype);
-    bstr = SPEC_BSTR(etype);
-
-    l = aopGet(AOP(right),offset++,FALSE,FALSE);
-    MOVA(l);   
-
-    /* if the bit lenth is less than or    */
-    /* it exactly fits a byte then         */
-    if (SPEC_BLEN(etype) <= 8 )  {
-        shCount = SPEC_BSTR(etype) ;
-
-        /* shift left acc */
-        AccLsh(shCount);
+  asmop *aop = NULL;
+  regs *preg = NULL;
+  char *rname, *l;
+  sym_link *retype, *letype;
+  sym_link *ptype = operandType (result);
 
-        if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
+  D (emitcode (";", "genNearPointerSet"));
 
+  retype = getSpec (operandType (right));
+  letype = getSpec (ptype);
 
-            switch (p_type) {
-                case POINTER:
-                    emitcode ("mov","b,a");
-                    emitcode("mov","a,@%s",rname);
-                    break;
+  aopOp (result, ic, FALSE);
 
-                case FPOINTER:
-                    emitcode ("mov","b,a");
-                    emitcode("movx","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 ("push","b");
-                    emitcode ("push","acc");
-                    emitcode ("lcall","__gptrget");
-                    emitcode ("pop","b");
-                    break;
+  /* 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__);
             }
-
-            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");
+            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;
         }
     }
-
-    switch (p_type) {
-        case POINTER:
-            emitcode("mov","@%s,a",rname);
-            break;
-
-        case FPOINTER:
-            emitcode("movx","@dptr,a");
-            break;
-
-        case GPOINTER:
-            emitcode("lcall","__gptrput");
-            break;
+    else
+    {
+        rname = aopGet (result, 0, FALSE, FALSE);
     }
 
-    /* if we r done */
-    if ( SPEC_BLEN(etype) <= 8 )
-        return ;
+  aopOp (right, ic, FALSE);
 
-    emitcode("inc","%s",rname);
-    rLen = SPEC_BLEN(etype) ;     
+  /* 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;
 
-    /* now generate for lengths greater than one byte */
-    while (1) {
-
-        l = aopGet(AOP(right),offset++,FALSE,TRUE);
-
-        rLen -= 8 ;
-        if (rLen <= 0 )
-            break ;
-
-        switch (p_type) {
-            case POINTER:
-                if (*l == '@') {
-                    MOVA(l);
-                    emitcode("mov","@%s,a",rname);
-                } else
-                    emitcode("mov","@%s,%s",rname,l);
-                break;
-
-            case FPOINTER:
-                MOVA(l);
-                emitcode("movx","@dptr,a");
-                break;
-
-            case GPOINTER:
-                MOVA(l);
-                emitcode("lcall","__gptrput");
-                break;  
-        }   
-        emitcode ("inc","%s",rname);
+      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++;
+        }
     }
 
-    MOVA(l);
-
-    /* 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;
-
-            case FPOINTER:
-                emitcode ("mov","b,a");
-                emitcode("movx","a,@dptr");
-                break;
-
-            case GPOINTER:
-                emitcode ("push","b");
-                emitcode ("push","acc");
-                emitcode ("lcall","__gptrget");
-                emitcode ("pop","b");
-                break;
+  /* 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);
         }
-
-        emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
-        emitcode ("orl","a,b");
     }
 
-    if (p_type == GPOINTER)
-        emitcode("pop","b");
-
-    switch (p_type) {
-
-    case POINTER:
-       emitcode("mov","@%s,a",rname);
-       break;
-       
-    case FPOINTER:
-       emitcode("movx","@dptr,a");
-       break;
-       
-    case GPOINTER:
-       emitcode("lcall","__gptrput");
-       break;                  
-    }
+  /* done */
+  if (pi) pi->generated = 1;
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
 }
+
 /*-----------------------------------------------------------------*/
-/* genDataPointerSet - remat pointer to data space                 */
+/* genPagedPointerSet - emitcode for Paged pointer put             */
 /*-----------------------------------------------------------------*/
-static void genDataPointerSet(operand *right,
-                             operand *result,
-                             iCode *ic)
+static void
+genPagedPointerSet (operand * right,
+                    operand * result,
+                    iCode * ic,
+                    iCode * pi)
 {
-    int size, offset = 0 ;
-    char *l, buffer[256];
+  asmop *aop = NULL;
+  regs *preg = NULL;
+  char *rname, *l;
+  sym_link *retype, *letype;
 
-    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 (";", "genPagedPointerSet"));
 
-    freeAsmop(right,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
-}
+  retype = getSpec (operandType (right));
+  letype = getSpec (operandType (result));
 
-/*-----------------------------------------------------------------*/
-/* 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++;
+  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 (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 */
-        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);
+  /* 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);
         }
     }
 
-    /* done */
-    freeAsmop(right,NULL,ic,TRUE);
-
-
-}
-
-/*-----------------------------------------------------------------*/
-/* 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);
-    
-       
+  /* done */
+  if (pi) pi->generated = 1;
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
 /* genFarPointerSet - set value from far space                     */
 /*-----------------------------------------------------------------*/
-static void genFarPointerSet (operand *right,
-                              operand *result, iCode *ic)
+static void
+genFarPointerSet (operand * right,
+                  operand * result, iCode * ic, iCode * pi)
 {
-    int size, offset ;
-    link *retype = getSpec(operandType(right));
+  int size, offset;
+  sym_link *retype = getSpec (operandType (right));
+  sym_link *letype = getSpec (operandType (result));
 
-    aopOp(result,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(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));
-        }
-    }
-    /* so dptr know contains the address */
-    freeAsmop(result,NULL,ic,TRUE);
-    aopOp(right,ic,FALSE);
+  aopOp (result, ic, FALSE);
+  loadDptrFromOperand (result, FALSE);
 
-    /* if bit then unpack */
-    if (IS_BITVAR(retype)) 
-        genPackBits(retype,right,"dptr",FPOINTER);
-    else {
-        size = AOP_SIZE(right);
-        offset = 0 ;
+  /* so dptr now contains the address */
+  aopOp (right, ic, FALSE);
 
-        while (size--) {
-            char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
-            MOVA(l);
-            emitcode("movx","@dptr,a");
-            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(right,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);
 }
 
 /*-----------------------------------------------------------------*/
 /* genGenPointerSet - set value from generic pointer space         */
 /*-----------------------------------------------------------------*/
-static void genGenPointerSet (operand *right,
-                              operand *result, iCode *ic)
+static void
+genGenPointerSet (operand * right,
+                  operand * result, iCode * ic, iCode * pi)
 {
-    int size, offset ;
-    link *retype = getSpec(operandType(right));
+  int size, offset;
+  sym_link *retype = getSpec (operandType (right));
+  sym_link *letype = getSpec (operandType (result));
 
-    aopOp(result,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(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));
-            emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
-        }
-    }
-    /* so dptr know contains the address */
-    freeAsmop(result,NULL,ic,TRUE);
-    aopOp(right,ic,FALSE);
+  aopOp (result, ic, FALSE);
+  loadDptrFromOperand (result, TRUE);
 
-    /* if bit then unpack */
-    if (IS_BITVAR(retype)) 
-        genPackBits(retype,right,"dptr",GPOINTER);
-    else {
-        size = AOP_SIZE(right);
-        offset = 0 ;
+  /* so dptr now contains the address */
+  aopOp (right, ic, FALSE);
 
-        while (size--) {
-            char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
-            MOVA(l);
-            emitcode("lcall","__gptrput");
-            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(right,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);
 }
 
 /*-----------------------------------------------------------------*/
 /* genPointerSet - stores the value into a pointer location        */
 /*-----------------------------------------------------------------*/
-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 */
-       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 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:
-       genNearPointerSet (right,result,ic);
-       break;
+      genNearPointerSet (right, result, ic, pi);
+      break;
 
     case PPOINTER:
-       genPagedPointerSet (right,result,ic);
-       break;
+      genPagedPointerSet (right, result, ic, pi);
+      break;
 
     case FPOINTER:
-       genFarPointerSet (right,result,ic);
-       break;
+      genFarPointerSet (right, result, ic, pi);
+      break;
 
     case GPOINTER:
-       genGenPointerSet (right,result,ic);
-       break;
-    }
+      genGenPointerSet (right, result, ic, pi);
+      break;
 
+    default:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+              "genPointerSet: illegal pointer type");
+    }
 }
 
 /*-----------------------------------------------------------------*/
 /* genIfx - generate code for Ifx statement                        */
 /*-----------------------------------------------------------------*/
-static void genIfx (iCode *ic, iCode *popIc)
+static void
+genIfx (iCode * ic, iCode * popIc)
 {
-    operand *cond = IC_COND(ic);
-    int isbit =0;
+  operand *cond = IC_COND (ic);
+  int isbit = 0;
+  char *dup = NULL;
 
-    aopOp(cond,ic,FALSE);
+  D (emitcode (";", "genIfx"));
 
-    /* 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");
+  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);
+    }
 
-    ic->generated = 1;
+  /* the result is now in the accumulator or a directly addressable bit */
+  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 && 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);
+
+  ic->generated = 1;
 }
 
 /*-----------------------------------------------------------------*/
 /* genAddrOf - generates code for address of                       */
 /*-----------------------------------------------------------------*/
-static void genAddrOf (iCode *ic)
-{
-    symbol *sym = OP_SYMBOL(IC_LEFT(ic));
-    int size, offset ;
-
-    aopOp(IC_RESULT(ic),ic,FALSE);
-
-    /* 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;
-        offset = 1;
-        while (size--) 
-            aopPut(AOP(IC_RESULT(ic)),zero,offset++);
+static void
+genAddrOf (iCode * ic)
+{
+  symbol *sym = OP_SYMBOL (IC_LEFT (ic));
+  int size, offset;
 
-        goto release;
+  D (emitcode (";", "genAddrOf"));
+
+  aopOp (IC_RESULT (ic), ic, FALSE);
+
+  /* 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;
     }
 
-    /* object not on stack then we need the name */
-    size = AOP_SIZE(IC_RESULT(ic));
-    offset = 0;
+  /* 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++);
+  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++);
     }
 
 release:
-    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
 
 }
 
 /*-----------------------------------------------------------------*/
 /* genFarFarAssign - assignment when both are in far space         */
 /*-----------------------------------------------------------------*/
-static void genFarFarAssign (operand *result, operand *right, iCode *ic)
+static void
+genFarFarAssign (operand * result, operand * right, 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");
+  int size = AOP_SIZE (right);
+  int offset = 0;
+  char *l;
+
+  D (emitcode (";", "genFarFarAssign"));
+
+  /* first push the right side on to the stack */
+  while (size--)
+    {
+      l = aopGet (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 (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);
-       
+  freeAsmop (result, NULL, ic, FALSE);
 }
 
 /*-----------------------------------------------------------------*/
 /* genAssign - generate code for assignment                        */
 /*-----------------------------------------------------------------*/
-static void genAssign (iCode *ic)
+static void
+genAssign (iCode * ic)
 {
-    operand *result, *right;
-    int size, offset ;
-       unsigned long lit = 0L;
+  operand *result, *right;
+  int size, offset;
+  unsigned long lit = 0L;
 
-    result = IC_RESULT(ic);
-    right  = IC_RIGHT(ic) ;
+  D (emitcode (";", "genAssign"));
 
-    /* if they are the same */
-    if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
-        return ;
+  result = IC_RESULT (ic);
+  right = IC_RIGHT (ic);
+
+  /* if they are the same */
+  if (operandsEqu (result, right) &&
+      !isOperandVolatile (result, FALSE) &&
+      !isOperandVolatile (right, FALSE))
+    return;
 
-    aopOp(right,ic,FALSE);
-    
-    /* special case both in far space */
-    if (AOP_TYPE(right) == AOP_DPTR &&
-       IS_TRUE_SYMOP(result)       &&
-       isOperandInFarSpace(result)) {
+  aopOp (right, ic, FALSE);
 
-       genFarFarAssign (result,right,ic);
-        return ;
+  /* special case both in far space */
+  if (AOP_TYPE (right) == AOP_DPTR &&
+      IS_TRUE_SYMOP (result) &&
+      isOperandInFarSpace (result))
+    {
+      genFarFarAssign (result, right, ic);
+      return;
     }
 
-    aopOp(result,ic,TRUE);
+  aopOp (result, ic, TRUE);
 
-    /* if they are the same registers */
-    if (sameRegs(AOP(right),AOP(result)))
-        goto release;
+  /* if they are the same registers */
+  if (sameRegs (AOP (right), AOP (result)) &&
+      !isOperandVolatile (result, FALSE) &&
+      !isOperandVolatile (right, FALSE))
+    goto release;
 
-    /* if the result is a bit */
-    if (AOP_TYPE(result) == AOP_CRY) {
+  /* 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;
+        }
+
+      /* 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;
+    }
+
+  /* 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))
+    {
+      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++;
+        }
+    }
 
-        /* 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 (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
+}
 
 /*-----------------------------------------------------------------*/
-/* genJumpTab - genrates code for jump table                       */
+/* genJumpTab - generates code for jump table                      */
 /*-----------------------------------------------------------------*/
-static void genJumpTab (iCode *ic)
+static void
+genJumpTab (iCode * ic)
 {
-    symbol *jtab;
-    char *l;
+  symbol *jtab,*jtablo,*jtabhi;
+  char *l;
+  unsigned int count;
+
+  D (emitcode (";", "genJumpTab"));
+
+  count = elementsInSet( IC_JTLABELS (ic) );
+
+  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");
+        }
+      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");
+        }
 
-    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);
+      emitcode ("ret", "");
 
-    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);
+      /* 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);
 
+      /* 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);
+    }
 }
 
 /*-----------------------------------------------------------------*/
 /* genCast - gen code for casting                                  */
 /*-----------------------------------------------------------------*/
-static void genCast (iCode *ic)
+static void
+genCast (iCode * ic)
 {
-    operand *result = IC_RESULT(ic);
-    link *ctype = operandType(IC_LEFT(ic));
-    operand *right = IC_RIGHT(ic);
-    int size, offset ;
+  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;
 
-    /* if they are equivalent then do nothing */
-    if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
-        return ;
+  D (emitcode (";", "genCast"));
 
-    aopOp(right,ic,FALSE) ;
-    aopOp(result,ic,FALSE);
+  /* if they are equivalent then do nothing */
+  if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
+    return;
 
-    /* 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);
+  aopOp (right, ic, FALSE);
+  aopOp (result, ic, FALSE);
 
-            goto release;
+  /* 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(AOP(result),"c",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(AOP(result),"a",0);
-        goto release ;
+      /* we need to or */
+      toBoolean (right);
+      aopPut (result, "a", 0);
+      goto release;
     }
 
-    /* if they are the same size : or less */
-    if (AOP_SIZE(result) <= AOP_SIZE(right)) {
+  /* if they are the same size : or less */
+  if (AOP_SIZE (result) <= AOP_SIZE (right))
+    {
 
-        /* if they are in the same place */
-        if (sameRegs(AOP(right),AOP(result)))
-            goto release;
+      /* if they are in the same place */
+      if (sameRegs (AOP (right), AOP (result)))
+        goto release;
 
-        /* if they in different places then copy */
-        size = AOP_SIZE(result);
-        offset = 0 ;
-        while (size--) {
-            aopPut(AOP(result),
-                   aopGet(AOP(right),offset,FALSE,FALSE),
-                   offset);
-            offset++;
+      /* 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;
+      goto release;
     }
 
+  /* if the result is of type pointer */
+  if (IS_PTR (ctype))
+    {
 
-    /* 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 */
-                       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 = 2;
-               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,2);            
-               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 !!!! */
+      int p_type;
+      sym_link *type = operandType (right);
+      sym_link *etype = getSpec (type);
 
-release:
-    freeAsmop(right,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
+      /* 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));
+              }
+            }
+
+          /* the first two bytes are known */
+          size = GPTRSIZE - 1;
+          offset = 0;
+          while (size--)
+            {
+              aopPut (result,
+                      aopGet (right, offset, FALSE, FALSE),
+                      offset);
+              offset++;
+            }
+          /* the last byte depending on type */
+            {
+                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 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++;
+    }
+
+  /* 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++);
+    }
+
+  /* we are done hurray !!!! */
 
+release:
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
 /* 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;
+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 */
+
+  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;
 }
 
 /*-----------------------------------------------------------------*/
 /* 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 =  4 - size;
-       while (size--) {
-           emitcode ("push","%s", (strcmp(fReturn[3 - offset],"a") ?
-                                   fReturn[3 - offset] : "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 {
-       accInUse++;
-       aopOp(IC_RESULT(ic),ic,FALSE);  
-       accInUse--;
-       assignResultValue(IC_RESULT(ic));       
-    }
-
-    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+static void
+genReceive (iCode * ic)
+{
+  int size = getSize (operandType (IC_RESULT (ic)));
+  int offset = 0;
+
+  D (emitcode (";", "genReceive"));
+
+  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;
+
+          for (offset = 0; offset<size; offset++)
+            if (!strcmp (fReturn[offset], "a"))
+              receivingA = 1;
+
+          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;
+                }
+            }
+
+          offset = fReturnSizeMCS51 - size;
+          while (size--)
+            {
+              emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
+                                       fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
+              offset++;
+            }
+          aopOp (IC_RESULT (ic), ic, FALSE);
+          size = AOP_SIZE (IC_RESULT (ic));
+          offset = 0;
+          while (size--)
+            {
+              emitcode ("pop", "acc");
+              aopPut (IC_RESULT (ic), "a", offset++);
+            }
+        }
+      else
+        {
+          _G.accInUse++;
+          aopOp (IC_RESULT (ic), ic, FALSE);
+          _G.accInUse--;
+          assignResultValue (IC_RESULT (ic), NULL);
+        }
+    }
+  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);
+}
+
+/*-----------------------------------------------------------------*/
+/* genDummyRead - generate code for dummy read of volatiles        */
+/*-----------------------------------------------------------------*/
+static void
+genDummyRead (iCode * ic)
+{
+  operand *op;
+  int size, offset;
+
+  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
+        {
+          /* bit variables done */
+          /* general case */
+          size = AOP_SIZE (op);
+          offset = 0;
+          while (size--)
+          {
+            MOVA (aopGet (op, offset, FALSE, FALSE));
+            offset++;
+          }
+        }
+
+      freeAsmop (op, NULL, ic, TRUE);
+    }
+
+  op = IC_LEFT (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
+        {
+          /* bit variables done */
+          /* general case */
+          size = AOP_SIZE (op);
+          offset = 0;
+          while (size--)
+          {
+            MOVA (aopGet (op, offset, FALSE, FALSE));
+            offset++;
+          }
+        }
+
+      freeAsmop (op, NULL, ic, TRUE);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genCritical - generate code for start of a critical sequence    */
+/*-----------------------------------------------------------------*/
+static void
+genCritical (iCode *ic)
+{
+  symbol *tlbl = newiTempLabel (NULL);
+
+  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*/
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genEndCritical - generate code for end of a critical sequence   */
+/*-----------------------------------------------------------------*/
+static void
+genEndCritical (iCode *ic)
+{
+  D(emitcode(";     genEndCritical",""));
+
+  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");
+        }
+      else
+        {
+          if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
+            MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
+          emitcode ("rrc", "a");
+          emitcode ("mov", "ea,c");
+        }
+      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");
+    }
 }
 
 /*-----------------------------------------------------------------*/
 /* gen51Code - generate code for 8051 based controllers            */
 /*-----------------------------------------------------------------*/
-void gen51Code (iCode *lic)
+void
+gen51Code (iCode * lic)
 {
-    iCode *ic;
-    int cln = 0;
+  iCode *ic;
+  int cln = 0;
+  /* int cseq = 0; */
 
-    lineHead = lineCurr = NULL;
+  _G.currentFunc = NULL;
+  lineHead = lineCurr = NULL;
 
-    /* if debug information required */
-/*     if (options.debug && currFunc) { */
-    if (currFunc) {
-       cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
-       debugLine = 1;
-       if (IS_STATIC(currFunc->etype))
-           emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
-       else
-           emitcode("","G$%s$0$0 ==.",currFunc->name);
-       debugLine = 0;
+  /* 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";
-    
-    for (ic = lic ; ic ; ic = ic->next ) {
-       
-       if ( cln != ic->lineno ) {
-           if ( options.debug ) {
-               debugLine = 1;
-               emitcode("","C$%s$%d$%d$%d ==.",
-                        ic->filename,ic->lineno,
-                        ic->level,ic->block);
-               debugLine = 0;
-           }
-           emitcode(";","%s %d",ic->filename,ic->lineno);
-           cln = ic->lineno ;
-       }
-       /* if the result is marked as
-          spilt and rematerializable or code for
-          this has already been generated then
-          do nothing */
-       if (resultRemat(ic) || ic->generated ) 
-           continue ;
-       
-       /* 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(&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;
+  /* stack pointer name */
+  if (options.useXstack)
+    spname = "_spx";
+  else
+    spname = "sp";
+
+
+  for (ic = lic; ic; ic = ic->next)
+    {
+      _G.current_iCode = ic;
+
+      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;
+
+        #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;
+        }
+    }
+
+  _G.current_iCode = NULL;
+
+  /* now we are ready to call the
+     peep hole optimizer */
+  if (!options.nopeep)
+    peepHole (&lineHead);
+
+  /* now do the actual printing */
+  printLine (lineHead, codeOutFile);
+  return;
 }