Added support for --parms-in-bank1
[fw/sdcc] / src / mcs51 / gen.c
index a305f416540e9a2bc6072ad6e6a4e6cb2da2a737..09e259908d88ac44133cd9c0b21cd639db0a4b91 100644 (file)
@@ -28,6 +28,9 @@
       Made everything static
 -------------------------------------------------------------------------*/
 
+//#define D(x)
+#define D(x) x
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #ifdef HAVE_SYS_ISA_DEFS_H
 #include <sys/isa_defs.h>
 #else
+#ifdef HAVE_MACHINE_ENDIAN_H
+#include <machine/endian.h>
+#else
 #ifdef HAVE_ENDIAN_H
 #include <endian.h>
 #else
-#if !defined(__BORLANDC__) && !defined(_MSC_VER)
+#if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
 #endif
 #endif
 #endif
+#endif
 
 #include "common.h"
 #include "SDCCpeeph.h"
@@ -86,10 +93,14 @@ static struct
   }
 _G;
 
+static char *rb1regs[] = {
+    "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
+};
+
 extern int mcs51_ptrRegReq;
 extern int mcs51_nRegs;
 extern FILE *codeOutFile;
-static void saverbank (int, iCode *, bool);
+static void saveRBank (int, iCode *, bool);
 #define RESULTONSTACK(x) \
                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
                          IC_RESULT(x)->aop->type == AOP_STK )
@@ -120,7 +131,7 @@ static void
 emitcode (char *inst, char *fmt,...)
 {
   va_list ap;
-  char lb[MAX_INLINEASM];
+  char lb[INITIAL_INLINEASM];
   char *lbp = lb;
 
   va_start (ap, fmt);
@@ -162,9 +173,9 @@ getFreePtr (iCode * ic, asmop ** aopp, bool result)
 
   /* 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)))
-    {
+  r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
+  r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
+  if (r0iu && r1iu) {
       goto endOfWorld;
     }
 
@@ -233,11 +244,10 @@ endOfWorld:
       return NULL;
     }
 
-  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);
+  exit (1);
 }
 
 /*-----------------------------------------------------------------*/
@@ -253,21 +263,6 @@ newAsmop (short type)
   return aop;
 }
 
-static void
-genSetDPTR (int n)
-{
-  if (!n)
-    {
-      emitcode (";", "Select standard DPTR");
-      emitcode ("mov", "dps, #0x00");
-    }
-  else
-    {
-      emitcode (";", "Select alternate DPTR");
-      emitcode ("mov", "dps, #0x01");
-    }
-}
-
 /*-----------------------------------------------------------------*/
 /* pointerCode - returns the code for a pointer type               */
 /*-----------------------------------------------------------------*/
@@ -286,7 +281,12 @@ static asmop *
 aopForSym (iCode * ic, symbol * sym, bool result)
 {
   asmop *aop;
-  memmap *space = SPEC_OCLS (sym->etype);
+  memmap *space;
+
+  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)
@@ -354,8 +354,8 @@ aopForSym (iCode * ic, symbol * sym, bool result)
   if (IS_FUNC (sym->type))
     {
       sym->aop = aop = newAsmop (AOP_IMMD);
-      aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
-      strcpy (aop->aopu.aop_immd, sym->rname);
+      aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
+      strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
       aop->size = FPTRSIZE;
       return aop;
     }
@@ -381,16 +381,26 @@ aopForRemat (symbol * sym)
 {
   iCode *ic = sym->rematiCode;
   asmop *aop = newAsmop (AOP_IMMD);
+  int ptr_type=0;
   int val = 0;
 
   for (;;)
     {
       if (ic->op == '+')
-       val += operandLitValue (IC_RIGHT (ic));
+       val += (int) operandLitValue (IC_RIGHT (ic));
       else if (ic->op == '-')
-       val -= operandLitValue (IC_RIGHT (ic));
-      else
-       break;
+       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 = DCL_TYPE(from_type);
+             if (ptr_type == IPOINTER) {
+               // bug #481053
+               ptr_type = POINTER;
+             }
+             continue ;
+      } else break;
 
       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
     }
@@ -403,8 +413,15 @@ aopForRemat (symbol * sym)
   else
     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
 
-  aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
-  strcpy (aop->aopu.aop_immd, buffer);
+  aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
+  strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
+  /* set immd2 field if required */
+  if (aop->aopu.aop_immd.from_cast_remat) {
+         sprintf(buffer,"#0x%02x",ptr_type);
+         aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
+         strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
+  }
+
   return aop;
 }
 
@@ -541,7 +558,7 @@ aopOp (operand * op, iCode * ic, bool result)
     }
 
   /* if already has a asmop then continue */
-  if (op->aop)
+  if (op->aop )
     return;
 
   /* if the underlying symbol has a aop */
@@ -568,7 +585,6 @@ aopOp (operand * op, iCode * ic, bool result)
 
   sym = OP_SYMBOL (op);
 
-
   /* if the type is a conditional */
   if (sym->regType == REG_CND)
     {
@@ -604,7 +620,8 @@ aopOp (operand * op, iCode * ic, bool result)
 
       if (sym->ruonly)
        {
-         int i;
+         unsigned i;
+
          aop = op->aop = sym->aop = newAsmop (AOP_STR);
          aop->size = getSize (sym->type);
          for (i = 0; i < fReturnSizeMCS51; i++)
@@ -613,6 +630,10 @@ aopOp (operand * op, iCode * ic, bool result)
        }
 
       /* else spill location  */
+      if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
+         /* force a new aop if sizes differ */
+         sym->usl.spillLoc->aop = NULL;
+      }
       sym->aop = op->aop = aop =
        aopForSym (ic, sym->usl.spillLoc, result);
       aop->size = getSize (sym->type);
@@ -780,13 +801,6 @@ aopGet (asmop * aop, int offset, bool bit16, bool dname)
       return rs;
 
     case AOP_DPTR:
-    case AOP_DPTR2:
-
-      if (aop->type == AOP_DPTR2)
-       {
-         genSetDPTR (1);
-       }
-
       while (offset > aop->coff)
        {
          emitcode ("inc", "dptr");
@@ -809,25 +823,21 @@ aopGet (asmop * aop, int offset, bool bit16, bool dname)
        {
          emitcode ("movx", "a,@dptr");
        }
-
-      if (aop->type == AOP_DPTR2)
-       {
-         genSetDPTR (0);
-       }
-
       return (dname ? "acc" : "a");
 
 
     case AOP_IMMD:
-      if (bit16)
-       sprintf (s, "#%s", aop->aopu.aop_immd);
+      if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
+             sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
+      } else if (bit16)
+       sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
       else if (offset)
        sprintf (s, "#(%s >> %d)",
-                aop->aopu.aop_immd,
+                aop->aopu.aop_immd.aop_immd1,
                 offset * 8);
       else
        sprintf (s, "#%s",
-                aop->aopu.aop_immd);
+                aop->aopu.aop_immd.aop_immd1);
       rs = Safe_calloc (1, strlen (s) + 1);
       strcpy (rs, s);
       return rs;
@@ -875,7 +885,7 @@ aopGet (asmop * aop, int offset, bool bit16, bool dname)
 
   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
          "aopget got unsupported aop->type");
-  exit (0);
+  exit (1);
 }
 /*-----------------------------------------------------------------*/
 /* aopPut - puts a string for a aop                                */
@@ -884,13 +894,12 @@ static void
 aopPut (asmop * aop, char *s, int offset)
 {
   char *d = buffer;
-  symbol *lbl;
 
   if (aop->size && offset > (aop->size - 1))
     {
       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
              "aopPut got offset > aop->size");
-      exit (0);
+      exit (1);
     }
 
   /* will assign value to value */
@@ -931,18 +940,11 @@ aopPut (asmop * aop, char *s, int offset)
       break;
 
     case AOP_DPTR:
-    case AOP_DPTR2:
-
-      if (aop->type == AOP_DPTR2)
-       {
-         genSetDPTR (1);
-       }
-
       if (aop->code)
        {
          werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
                  "aopPut writting to code space");
-         exit (0);
+         exit (1);
        }
 
       while (offset > aop->coff)
@@ -963,11 +965,6 @@ aopPut (asmop * aop, char *s, int offset)
       MOVA (s);
 
       emitcode ("movx", "@dptr,a");
-
-      if (aop->type == AOP_DPTR2)
-       {
-         genSetDPTR (0);
-       }
       break;
 
     case AOP_R0:
@@ -1018,7 +1015,12 @@ aopPut (asmop * aop, char *s, int offset)
       if (strcmp (s, "a") == 0)
        emitcode ("push", "acc");
       else
-       emitcode ("push", "%s", s);
+       if (*s=='@') {
+         MOVA(s);
+         emitcode ("push", "acc");
+       } else {
+         emitcode ("push", s);
+       }
 
       break;
 
@@ -1039,17 +1041,18 @@ aopPut (asmop * aop, char *s, int offset)
            emitcode ("mov", "%s,c", aop->aopu.aop_dir);
          else
            {
-             lbl = newiTempLabel (NULL);
-
              if (strcmp (s, "a"))
                {
                  MOVA (s);
                }
-             emitcode ("clr", "c");
-             emitcode ("jz", "%05d$", lbl->key + 100);
-             emitcode ("cpl", "c");
-             emitcode ("", "%05d$:", lbl->key + 100);
-             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
+             {
+               symbol *lbl = newiTempLabel (NULL);
+               emitcode ("clr", "c");
+               emitcode ("jz", "%05d$", lbl->key + 100);
+               emitcode ("cpl", "c");
+               emitcode ("", "%05d$:", lbl->key + 100);
+               emitcode ("mov", "%s,c", aop->aopu.aop_dir);
+             }
            }
        }
       break;
@@ -1072,7 +1075,7 @@ aopPut (asmop * aop, char *s, int offset)
     default:
       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
              "aopPut got unsupported aop->type");
-      exit (0);
+      exit (1);
     }
 
 }
@@ -1112,38 +1115,24 @@ pointToEnd (asmop * aop)
 static void
 reAdjustPreg (asmop * aop)
 {
-  int size;
-
-  aop->coff = 0;
-  if ((size = aop->size) <= 1)
+  if ((aop->coff==0) || aop->size <= 1)
     return;
-  size--;
+
   switch (aop->type)
     {
     case AOP_R0:
     case AOP_R1:
-      while (size--)
+      while (aop->coff--)
        emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
       break;
     case AOP_DPTR:
-    case AOP_DPTR2:
-      if (aop->type == AOP_DPTR2)
-       {
-         genSetDPTR (1);
-       }
-      while (size--)
+      while (aop->coff--)
        {
          emitcode ("lcall", "__decdptr");
        }
-
-      if (aop->type == AOP_DPTR2)
-       {
-         genSetDPTR (0);
-       }
       break;
-
     }
-
+  aop->coff = 0;
 }
 
 #define AOP(op) op->aop
@@ -1153,8 +1142,7 @@ reAdjustPreg (asmop * aop)
                        AOP_TYPE(x) == AOP_R0))
 
 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
-                        AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
-                         AOP(x)->paged))
+                        AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
 
 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
                       (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
@@ -1170,6 +1158,8 @@ genNotFloat (operand * op, operand * res)
   char *l;
   symbol *tlbl;
 
+  D(emitcode (";", "genNotFloat"));
+
   /* we will put 127 in the first byte of
      the result */
   aopPut (AOP (res), "#127", 0);
@@ -1185,7 +1175,6 @@ genNotFloat (operand * op, operand * res)
                aopGet (op->aop,
                        offset++, FALSE, FALSE));
     }
-  tlbl = newiTempLabel (NULL);
 
   tlbl = newiTempLabel (NULL);
   aopPut (res->aop, one, 1);
@@ -1299,6 +1288,8 @@ genNot (iCode * ic)
   symbol *tlbl;
   sym_link *optype = operandType (IC_LEFT (ic));
 
+  D(emitcode (";", "genNot"));
+
   /* assign asmOps to operand & result */
   aopOp (IC_LEFT (ic), ic, FALSE);
   aopOp (IC_RESULT (ic), ic, TRUE);
@@ -1341,23 +1332,29 @@ genCpl (iCode * ic)
 {
   int offset = 0;
   int size;
+  symbol *tlbl;
 
+  D(emitcode (";", "genCpl"));
 
   /* assign asmOps to operand & result */
   aopOp (IC_LEFT (ic), ic, FALSE);
   aopOp (IC_RESULT (ic), ic, TRUE);
 
-  /* if both are in bit space then
-     a special case */
-  if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
-      AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
-    {
-
+  /* special case if in bit space */
+  if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
+    if (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;
     }
+    tlbl=newiTempLabel(NULL);
+    emitcode ("cjne", "%s,#0x01,%05d$", 
+             aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
+    emitcode ("", "%05d$:", tlbl->key+100);
+    outBitC (IC_RESULT(ic));
+    goto release;
+  }
 
   size = AOP_SIZE (IC_RESULT (ic));
   while (size--)
@@ -1383,6 +1380,9 @@ genUminusFloat (operand * op, operand * result)
 {
   int size, offset = 0;
   char *l;
+
+  D(emitcode (";", "genUminusFloat"));
+
   /* for this we just need to flip the
      first it then copy the rest in place */
   size = AOP_SIZE (op) - 1;
@@ -1412,6 +1412,8 @@ genUminus (iCode * ic)
   sym_link *optype, *rtype;
 
 
+  D(emitcode (";", "genUminus"));
+
   /* assign asmops */
   aopOp (IC_LEFT (ic), ic, FALSE);
   aopOp (IC_RESULT (ic), ic, TRUE);
@@ -1487,7 +1489,6 @@ saveRegisters (iCode * lic)
   int i;
   iCode *ic;
   bitVect *rsave;
-  sym_link *detype;
 
   /* look for call */
   for (ic = lic; ic; ic = ic->next)
@@ -1500,15 +1501,16 @@ saveRegisters (iCode * lic)
       return;
     }
 
-  /* if the registers have been saved already then
+  /* if the registers have been saved already or don't need to be then
      do nothing */
-  if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
+  if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
+      IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
     return;
 
-  /* find the registers in use at this time
-     and push them away to safety */
-  rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
-                        ic->rUsed);
+  /* safe 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)
@@ -1538,16 +1540,8 @@ saveRegisters (iCode * lic)
        if (bitVectBitValue (rsave, i))
          emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
       }
-
-  detype = getSpec (operandType (IC_LEFT (ic)));
-  if (detype &&
-      (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
-      IS_ISR (currFunc->etype) &&
-      !ic->bankSaved)
-
-    saverbank (SPEC_BANK (detype), ic, TRUE);
-
 }
+
 /*-----------------------------------------------------------------*/
 /* unsaveRegisters - pop the pushed registers                      */
 /*-----------------------------------------------------------------*/
@@ -1556,10 +1550,11 @@ 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);
+
+  /* restore the registers in use at this time but skip the
+     ones for the result */
+  rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
+                        mcs51_rUmaskForOp (IC_RESULT(ic)));
 
   if (options.useXstack)
     {
@@ -1639,6 +1634,8 @@ genXpush (iCode * ic)
   regs *r;
   int size, offset = 0;
 
+  D(emitcode (";", "genXpush"));
+
   aopOp (IC_LEFT (ic), ic, FALSE);
   r = getFreePtr (ic, &aop, FALSE);
 
@@ -1673,6 +1670,7 @@ genIpush (iCode * ic)
   int size, offset = 0;
   char *l;
 
+  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 */
@@ -1744,6 +1742,7 @@ genIpop (iCode * ic)
 {
   int size, offset;
 
+  D(emitcode (";", "genIpop"));
 
   /* if the temp was not pushed then */
   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
@@ -1760,31 +1759,42 @@ genIpop (iCode * ic)
 }
 
 /*-----------------------------------------------------------------*/
-/* unsaverbank - restores the resgister bank from stack            */
+/* unsaveRBank - restores the resgister bank from stack            */
 /*-----------------------------------------------------------------*/
 static void
-unsaverbank (int bank, iCode * ic, bool popPsw)
+unsaveRBank (int bank, iCode * ic, bool popPsw)
 {
   int i;
-  asmop *aop;
+  asmop *aop = NULL;
   regs *r = NULL;
 
+  if (options.useXstack)
+  {
+      if (!ic)
+      {
+         /* Assume r0 is available for use. */
+         r = mcs51_regWithIdx (R0_IDX);;          
+      }        
+      else
+      {
+         aop = newAsmop (0);
+         r = getFreePtr (ic, &aop, FALSE);
+      }
+      emitcode ("mov", "%s,_spx", r->name);      
+  }
+  
   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");
+      }
     }
 
   for (i = (mcs51_nRegs - 1); i >= 0; i--)
@@ -1804,30 +1814,38 @@ unsaverbank (int bank, iCode * ic, bool popPsw)
 
   if (options.useXstack)
     {
-
       emitcode ("mov", "_spx,%s", r->name);
-      freeAsmop (NULL, aop, ic, TRUE);
-
     }
+    
+  if (aop)
+  {
+      freeAsmop (NULL, aop, ic, TRUE);  
+  }    
 }
 
 /*-----------------------------------------------------------------*/
-/* saverbank - saves an entire register bank on the stack          */
+/* saveRBank - saves an entire register bank on the stack          */
 /*-----------------------------------------------------------------*/
 static void
-saverbank (int bank, iCode * ic, bool pushPsw)
+saveRBank (int bank, iCode * ic, bool pushPsw)
 {
   int i;
-  asmop *aop;
+  asmop *aop = NULL;
   regs *r = NULL;
 
   if (options.useXstack)
     {
-
-      aop = newAsmop (0);
-      r = getFreePtr (ic, &aop, FALSE);
+      if (!ic)
+      {
+         /* Assume r0 is available for use. */
+         r = mcs51_regWithIdx (R0_IDX);;
+      }
+      else
+      {
+         aop = newAsmop (0);
+         r = getFreePtr (ic, &aop, FALSE);
+      }
       emitcode ("mov", "%s,_spx", r->name);
-
     }
 
   for (i = 0; i < mcs51_nRegs; i++)
@@ -1852,16 +1870,58 @@ saverbank (int bank, iCode * ic, bool pushPsw)
          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;
 
+    if (aop)
+    {
+        freeAsmop (NULL, aop, ic, TRUE);
+    }
+
+  if (ic)
+  {  
+      ic->bankSaved = 1;
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* genSend - gen code for SEND                                    */
+/*-----------------------------------------------------------------*/
+static void genSend(set *sendSet)
+{
+    iCode *sic;
+    int rb1_count = 0 ;
+
+    for (sic = setFirstItem (_G.sendSet); sic;
+        sic = setNextItem (_G.sendSet)) {
+         int size, offset = 0;
+         aopOp (IC_LEFT (sic), sic, FALSE);
+         size = AOP_SIZE (IC_LEFT (sic));
+
+         if (sic->argreg == 1) {
+             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++;
+             }
+             rb1_count = 0;
+         } else {
+             while (size--) {
+                 emitcode ("mov","b1_%d,%s",rb1_count++,
+                           aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
+             }
+         }       
+         freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
+    }
 }
 
 /*-----------------------------------------------------------------*/
@@ -1870,56 +1930,61 @@ saverbank (int bank, iCode * ic, bool pushPsw)
 static void
 genCall (iCode * ic)
 {
-  sym_link *detype;
-
-  /* if caller saves & we have not saved then */
-  if (!ic->regsSaved)
-    saveRegisters (ic);
+  sym_link *dtype;
+//  bool restoreBank = FALSE;
+  bool swapBanks = FALSE;
 
-  /* 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);
+  D(emitcode(";", "genCall"));
 
+  dtype = operandType (IC_LEFT (ic));
   /* if send set is not empty the assign */
   if (_G.sendSet)
     {
-      iCode *sic;
-
-      for (sic = setFirstItem (_G.sendSet); sic;
-          sic = setNextItem (_G.sendSet))
-       {
-         int size, offset = 0;
-         aopOp (IC_LEFT (sic), sic, FALSE);
-         size = AOP_SIZE (IC_LEFT (sic));
-         while (size--)
-           {
-             char *l = aopGet (AOP (IC_LEFT (sic)), offset,
-                               FALSE, FALSE);
-             if (strcmp (l, fReturn[offset]))
-               emitcode ("mov", "%s,%s",
-                         fReturn[offset],
-                         l);
-             offset++;
-           }
-         freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
+       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 */
+  dtype = operandType (IC_LEFT (ic));
+  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 */
   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
                            OP_SYMBOL (IC_LEFT (ic))->rname :
                            OP_SYMBOL (IC_LEFT (ic))->name));
 
+  if (swapBanks)
+  {
+       emitcode ("mov", "psw,#0x%02x", 
+          ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
+  }
+
   /* if we need assign a result value */
   if ((IS_ITEMP (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)))
     {
@@ -1947,43 +2012,47 @@ genCall (iCode * ic)
       else
        for (i = 0; i < 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))
+  if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
     unsaveRegisters (ic);
 
-
+//  /* if register bank was saved then pop them */
+//  if (restoreBank)
+//    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genPcall - generates a call by pointer statement                */
+/* -10l - generates a call by pointer statement                */
 /*-----------------------------------------------------------------*/
 static void
 genPcall (iCode * ic)
 {
-  sym_link *detype;
+  sym_link *dtype;
   symbol *rlbl = newiTempLabel (NULL);
+//  bool restoreBank=FALSE;
+  bool swapBanks = FALSE;
 
+  D(emitcode(";", "genPCall"));
 
   /* if caller saves & we have not saved then */
   if (!ic->regsSaved)
     saveRegisters (ic);
 
-  /* if we are calling a function that is not using
+  /* 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 */
-  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);
-
+  dtype = operandType (IC_LEFT (ic))->next;
+  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
+  }
 
   /* push the return address on to the stack */
   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
@@ -2001,33 +2070,27 @@ genPcall (iCode * ic)
   /* if send set is not empty the assign */
   if (_G.sendSet)
     {
-      iCode *sic;
-
-      for (sic = setFirstItem (_G.sendSet); sic;
-          sic = setNextItem (_G.sendSet))
-       {
-         int size, offset = 0;
-         aopOp (IC_LEFT (sic), sic, FALSE);
-         size = AOP_SIZE (IC_LEFT (sic));
-         while (size--)
-           {
-             char *l = aopGet (AOP (IC_LEFT (sic)), offset,
-                               FALSE, FALSE);
-             if (strcmp (l, fReturn[offset]))
-               emitcode ("mov", "%s,%s",
-                         fReturn[offset],
-                         l);
-             offset++;
-           }
-         freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
-       }
-      _G.sendSet = NULL;
+       genSend(reverseSet(_G.sendSet));
+       _G.sendSet = NULL;
     }
 
+  if (swapBanks)
+  {
+        emitcode ("mov", "psw,#0x%02x", 
+           ((FUNC_REGBANK(dtype)) << 3) & 0xff);
+  }
+
+  /* make the call */
   emitcode ("ret", "");
   emitcode ("", "%05d$:", (rlbl->key + 100));
 
 
+  if (swapBanks)
+  {
+       emitcode ("mov", "psw,#0x%02x", 
+          ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
+  }
+
   /* if we need assign a result value */
   if ((IS_ITEMP (IC_RESULT (ic)) &&
        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
@@ -2061,17 +2124,14 @@ genPcall (iCode * ic)
 
     }
 
-  /* if register bank was saved then unsave them */
-  if (detype &&
-      (SPEC_BANK (currFunc->etype) !=
-       SPEC_BANK (detype)))
-    unsaverbank (SPEC_BANK (detype), ic, TRUE);
+//  /* if register bank was saved then unsave them */
+//  if (restoreBank)
+//    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
 
   /* if we hade saved some registers then
      unsave them */
-  if (ic->regsSaved)
+  if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
     unsaveRegisters (ic);
-
 }
 
 /*-----------------------------------------------------------------*/
@@ -2127,7 +2187,9 @@ static void
 genFunction (iCode * ic)
 {
   symbol *sym;
-  sym_link *fetype;
+  sym_link *ftype;
+  bool   switchedPSW = FALSE;
+  int calleesaves_saved_register = -1;
 
   _G.nRegsSaved = 0;
   /* create the function header */
@@ -2136,19 +2198,25 @@ genFunction (iCode * ic)
   emitcode (";", "-----------------------------------------");
 
   emitcode ("", "%s:", sym->rname);
-  fetype = getSpec (operandType (IC_LEFT (ic)));
+  ftype = operandType (IC_LEFT (ic));
+
+  if (IFFUNC_ISNAKED(ftype))
+  {
+      emitcode(";", "naked function: no prologue.");
+      return;
+  }
 
   /* if critical function then turn interrupts off */
-  if (SPEC_CRTCL (fetype))
+  if (IFFUNC_ISCRITICAL (ftype))
     emitcode ("clr", "ea");
 
   /* here we need to generate the equates for the
      register bank if required */
-  if (SPEC_BANK (fetype) != rbank)
+  if (FUNC_REGBANK (ftype) != rbank)
     {
       int i;
 
-      rbank = SPEC_BANK (fetype);
+      rbank = FUNC_REGBANK (ftype);
       for (i = 0; i < mcs51_nRegs; i++)
        {
          if (strcmp (regs8051[i].base, "0") == 0)
@@ -2165,7 +2233,7 @@ genFunction (iCode * ic)
 
   /* if this is an interrupt service routine then
      save acc, b, dpl, dph  */
-  if (IS_ISR (sym->etype))
+  if (IFFUNC_ISISR (sym->type))
     {
 
       if (!inExcludeList ("acc"))
@@ -2179,13 +2247,13 @@ genFunction (iCode * ic)
       /* 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 (!FUNC_REGBANK (sym->type))
        {
 
          /* 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)
+         if (!IFFUNC_HASFCALL(sym->type))
            {
              int i;
 
@@ -2204,18 +2272,115 @@ genFunction (iCode * ic)
            }
          else
            {
+               
              /* this function has  a function call cannot
-                determines register usage so we will have the
+                determines register usage so we will have to push the
                 entire bank */
-             saverbank (0, ic, FALSE);
+               saveRBank (0, ic, FALSE);
+               if (options.parms_in_bank1) {
+                   int i;
+                   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);
+                    }
+               }
+           }
+           // jwk: this needs a closer look
+           SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
+       }
     }
   else
     {
       /* if callee-save to be used for this function
          then save the registers being used in this function */
-      if (sym->calleeSave)
+      if (IFFUNC_CALLEESAVES(sym->type))
        {
          int i;
 
@@ -2228,6 +2393,9 @@ genFunction (iCode * ic)
                  if (bitVectBitValue (sym->regsUsed, i) ||
                      (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
                    {
+                     /* remember one saved register for later usage */
+                     if (calleesaves_saved_register < 0)
+                       calleesaves_saved_register = i;
                      emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
                      _G.nRegsSaved++;
                    }
@@ -2237,13 +2405,14 @@ genFunction (iCode * ic)
     }
 
   /* set the register bank to the desired value */
-  if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
+  if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
+   && !switchedPSW)
     {
       emitcode ("push", "psw");
-      emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
+      emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
     }
 
-  if (IS_RENT (sym->etype) || options.stackAuto)
+  if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
     {
 
       if (options.useXstack)
@@ -2277,6 +2446,34 @@ genFunction (iCode * ic)
          emitcode ("mov", "sp,a");
 
        }
+      else if (i > 5)
+        {
+         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", mcs51_regWithIdx (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", mcs51_regWithIdx (calleesaves_saved_register)->dname);
+               }
+             else
+               /* do it the hard way */
+               while (i--)
+                 emitcode ("inc", "sp");
+           }
+         else
+           {
+             /* not callee-saves, we can clobber ar0 */
+             emitcode ("mov", "ar0,a");
+             emitcode ("mov", "a,sp");
+             emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
+             emitcode ("mov", "sp,a");
+             emitcode ("mov", "a,ar0");
+           }
+       }
       else
        while (i--)
          emitcode ("inc", "sp");
@@ -2300,7 +2497,13 @@ genEndFunction (iCode * ic)
 {
   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
 
-  if (IS_RENT (sym->etype) || options.stackAuto)
+  if (IFFUNC_ISNAKED(sym->type))
+  {
+      emitcode(";", "naked function: no epilogue.");
+      return;
+  }
+
+  if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
     {
       emitcode ("mov", "%s,_bp", spname);
     }
@@ -2316,7 +2519,7 @@ genEndFunction (iCode * ic)
     }
 
 
-  if ((IS_RENT (sym->etype) || options.stackAuto))
+  if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
     {
       if (options.useXstack)
        {
@@ -2332,23 +2535,31 @@ genEndFunction (iCode * ic)
     }
 
   /* restore the register bank  */
-  if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
-    emitcode ("pop", "psw");
+  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 (IS_ISR (sym->etype))
+  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 (!SPEC_BANK (sym->etype))
+      if (!FUNC_REGBANK (sym->type))
        {
-
          /* 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)
+         if (!IFFUNC_HASFCALL(sym->type))
            {
              int i;
 
@@ -2367,10 +2578,43 @@ genEndFunction (iCode * ic)
            }
          else
            {
+             if (options.parms_in_bank1) {
+                 int i;
+                 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 the
+                determines register usage so we will have to pop the
                 entire bank */
-             unsaverbank (0, ic, FALSE);
+             unsaveRBank (0, ic, FALSE);
+           }
+       }
+       else
+       {
+           /* This ISR uses a non-zero bank.
+            *
+            * Restore any register banks saved by genFunction
+            * in reverse order.
+            */
+         // jwk: this needs a closer look
+           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");
            }
        }
 
@@ -2383,12 +2627,11 @@ genEndFunction (iCode * ic)
       if (!inExcludeList ("acc"))
        emitcode ("pop", "acc");
 
-      if (SPEC_CRTCL (sym->etype))
+      if (IFFUNC_ISCRITICAL (sym->type))
        emitcode ("setb", "ea");
 
       /* if debug then send end of function */
-/*  if (options.debug && currFunc) { */
-      if (currFunc)
+      if (options.debug && currFunc)
        {
          _G.debugLine = 1;
          emitcode ("", "C$%s$%d$%d$%d ==.",
@@ -2405,10 +2648,10 @@ genEndFunction (iCode * ic)
     }
   else
     {
-      if (SPEC_CRTCL (sym->etype))
+      if (IFFUNC_ISCRITICAL (sym->type))
        emitcode ("setb", "ea");
 
-      if (sym->calleeSave)
+      if (IFFUNC_CALLEESAVES(sym->type))
        {
          int i;
 
@@ -2427,7 +2670,7 @@ genEndFunction (iCode * ic)
        }
 
       /* if debug then send end of function */
-      if (currFunc)
+      if (options.debug && currFunc)
        {
          _G.debugLine = 1;
          emitcode ("", "C$%s$%d$%d$%d ==.",
@@ -2453,6 +2696,8 @@ 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))
@@ -2544,9 +2789,15 @@ findLabelBackwards (iCode * ic, int key)
       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)
        {
-         /* printf("findLabelBackwards = %d\n", count); */
          return count;
        }
     }
@@ -2571,11 +2822,14 @@ genPlusIncr (iCode * ic)
 
   /* 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)
+  if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
     return FALSE;
 
+  D(emitcode (";", "genPlusIncr"));
+
   /* if increment 16 bits in register */
-  if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
+  if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
+      sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) && 
       (size > 1) &&
       (icount == 1))
     {
@@ -2603,15 +2857,15 @@ genPlusIncr (iCode * ic)
       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);
+       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 ("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));
@@ -2619,13 +2873,13 @@ genPlusIncr (iCode * ic)
        {
          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);
+           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 ("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));
        }
@@ -2633,14 +2887,14 @@ genPlusIncr (iCode * ic)
        {
          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);
+           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 ("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));
        }
@@ -2709,6 +2963,8 @@ outBitAcc (operand * result)
 static void
 genPlusBits (iCode * ic)
 {
+  D(emitcode (";", "genPlusBits"));
+
   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
     {
       symbol *lbl = newiTempLabel (NULL);
@@ -2812,6 +3068,8 @@ genPlus (iCode * ic)
 
   /* special cases :- */
 
+  D(emitcode (";", "genPlus"));
+
   aopOp (IC_LEFT (ic), ic, FALSE);
   aopOp (IC_RIGHT (ic), ic, FALSE);
   aopOp (IC_RESULT (ic), ic, TRUE);
@@ -2922,8 +3180,11 @@ genMinusDec (iCode * ic)
   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
     return FALSE;
 
+  D(emitcode (";", "genMinusDec"));
+
   /* if decrement 16 bits in register */
-  if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
+  if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
+      sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
       (size > 1) &&
       (icount == 1))
     {
@@ -3049,6 +3310,9 @@ static void
 genMinusBits (iCode * ic)
 {
   symbol *lbl = newiTempLabel (NULL);
+
+  D(emitcode (";", "genMinusBits"));
+
   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
     {
       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
@@ -3078,6 +3342,8 @@ genMinus (iCode * ic)
   int size, offset = 0;
   unsigned long lit = 0L;
 
+  D(emitcode (";", "genMinus"));
+
   aopOp (IC_LEFT (ic), ic, FALSE);
   aopOp (IC_RIGHT (ic), ic, FALSE);
   aopOp (IC_RESULT (ic), ic, TRUE);
@@ -3118,12 +3384,17 @@ genMinus (iCode * ic)
       else
        {
          /* first add without previous c */
-         if (!offset)
-           emitcode ("add", "a,#0x%02x",
-                     (unsigned int) (lit & 0x0FFL));
-         else
+         if (!offset) {
+           if (!size && lit==-1) {
+             emitcode ("dec", "a");
+           } else {
+             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++);
     }
@@ -3145,6 +3416,8 @@ 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);
@@ -3152,7 +3425,7 @@ genMultbits (operand * left,
 
 
 /*-----------------------------------------------------------------*/
-/* genMultOneByte : 8 bit multiplication & division                */
+/* genMultOneByte : 8*8=8/16 bit multiplication                    */
 /*-----------------------------------------------------------------*/
 static void
 genMultOneByte (operand * left,
@@ -3160,89 +3433,101 @@ genMultOneByte (operand * left,
                operand * result)
 {
   sym_link *opetype = operandType (result);
-  char *l;
   symbol *lbl;
-  int size, offset;
+  int size=AOP_SIZE(result);
+
+  D(emitcode (";", "genMultOneByte"));
 
-  /* (if two literals, the value is computed before) */
+  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 (SPEC_USIGN(opetype)
+      // ignore the sign of left and right, what else can we do?
+      || (SPEC_USIGN(operandType(left)) && 
+         SPEC_USIGN(operandType(right)))) {
+    // just an unsigned 8*8=8/16 multiply
+    //emitcode (";","unsigned");
+    emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
+    MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+    emitcode ("mul", "ab");
+    aopPut (AOP (result), "a", 0);
+    if (size==2) {
+      aopPut (AOP (result), "b", 1);
     }
+    return;
+  }
 
-  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");
+  // we have to do a signed multiply
 
-         /* adjust the MSB if left or right neg */
+  //emitcode (";", "signed");
+  emitcode ("clr", "F0"); // reset sign flag
+  MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
 
-         /* 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 ("jnb", "acc.7,%05d$",  lbl->key+100);
+  // left side is negative, 8-bit two's complement, this fails for -128
+  emitcode ("setb", "F0"); // set sign flag
+  emitcode ("cpl", "a");
+  emitcode ("inc", "a");
 
-         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));
+  emitcode ("", "%05d$:", lbl->key+100);
+
+  /* if literal */
+  if (AOP_TYPE(right)==AOP_LIT) {
+    signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
+    /* AND literal negative */
+    if (val < 0) {
+      emitcode ("cpl", "F0"); // complement sign flag
+      emitcode ("mov", "b,#0x%02x", -val);
+    } else {
+      emitcode ("mov", "b,#0x%02x", val);
+    }
+  } else {
+    lbl=newiTempLabel(NULL);
+    emitcode ("mov", "b,a");
+    emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
+    emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
+    // right side is negative, 8-bit two's complement
+    emitcode ("cpl", "F0"); // complement sign flag
+    emitcode ("cpl", "a");
+    emitcode ("inc", "a");
+    emitcode ("", "%05d$:", lbl->key+100);
+  }
+  emitcode ("mul", "ab");
+    
+  lbl=newiTempLabel(NULL);
+  emitcode ("jnb", "F0,%05d$", lbl->key+100);
+  // only ONE op was negative, we have to do a 8/16-bit two's complement
+  emitcode ("cpl", "a"); // lsb
+  if (size==1) {
+    emitcode ("inc", "a");
+  } else {
+    emitcode ("add", "a,#1");
+    emitcode ("xch", "a,b");
+    emitcode ("cpl", "a"); // msb
+    emitcode ("addc", "a,#0");
+    emitcode ("xch", "a,b");
+  }
 
-         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++);
-    }
+  emitcode ("", "%05d$:", lbl->key+100);
+  aopPut (AOP (result), "a", 0);
+  if (size==2) {
+    aopPut (AOP (result), "b", 1);
+  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -3255,6 +3540,8 @@ genMult (iCode * ic)
   operand *right = IC_RIGHT (ic);
   operand *result = IC_RESULT (ic);
 
+  D(emitcode (";", "genMult"));
+
   /* assign the amsops */
   aopOp (left, ic, FALSE);
   aopOp (right, ic, FALSE);
@@ -3270,15 +3557,21 @@ genMult (iCode * ic)
     }
 
   /* if both are of size == 1 */
-  if (AOP_SIZE (left) == 1 &&
-      AOP_SIZE (right) == 1)
+#if 0 // one of them can be a sloc shared with the result
+    if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
+#else
+  if (getSize(operandType(left)) == 1 && 
+      getSize(operandType(right)) == 1)
+#endif
     {
       genMultOneByte (left, right, result);
       goto release;
     }
 
   /* should have been converted to function call */
-  assert (1);
+    fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
+            getSize(OP_SYMBOL(right)->type));
+  assert (0);
 
 release:
   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
@@ -3297,6 +3590,8 @@ genDivbits (operand * left,
 
   char *l;
 
+  D(emitcode (";", "genDivbits"));
+
   /* the result must be bit */
   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
   l = aopGet (AOP (left), 0, FALSE, FALSE);
@@ -3321,6 +3616,8 @@ genDivOneByte (operand * left,
   symbol *lbl;
   int size, offset;
 
+  D(emitcode (";", "genDivOneByte"));
+
   size = AOP_SIZE (result) - 1;
   offset = 1;
   /* signed or unsigned */
@@ -3404,6 +3701,8 @@ genDiv (iCode * ic)
   operand *right = IC_RIGHT (ic);
   operand *result = IC_RESULT (ic);
 
+  D(emitcode (";", "genDiv"));
+
   /* assign the amsops */
   aopOp (left, ic, FALSE);
   aopOp (right, ic, FALSE);
@@ -3427,7 +3726,7 @@ genDiv (iCode * ic)
     }
 
   /* should have been converted to function call */
-  assert (1);
+  assert (0);
 release:
   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
@@ -3445,6 +3744,8 @@ genModbits (operand * left,
 
   char *l;
 
+  D(emitcode (";", "genModbits"));
+
   /* the result must be bit */
   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
   l = aopGet (AOP (left), 0, FALSE, FALSE);
@@ -3469,6 +3770,8 @@ genModOneByte (operand * left,
   char *l;
   symbol *lbl;
 
+  D(emitcode (";", "genModOneByte"));
+
   /* signed or unsigned */
   if (SPEC_USIGN (opetype))
     {
@@ -3542,6 +3845,8 @@ genMod (iCode * ic)
   operand *right = IC_RIGHT (ic);
   operand *result = IC_RESULT (ic);
 
+  D(emitcode (";", "genMod"));
+
   /* assign the amsops */
   aopOp (left, ic, FALSE);
   aopOp (right, ic, FALSE);
@@ -3565,7 +3870,7 @@ genMod (iCode * ic)
     }
 
   /* should have been converted to function call */
-  assert (1);
+  assert (0);
 
 release:
   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
@@ -3583,6 +3888,8 @@ genIfxJump (iCode * ic, char *jval)
   symbol *tlbl = newiTempLabel (NULL);
   char *inst;
 
+  D(emitcode (";", "genIfxJump"));
+
   /* if true label then we jump if condition
      supplied is true */
   if (IC_TRUE (ic))
@@ -3614,11 +3921,13 @@ genIfxJump (iCode * ic, char *jval)
 /*-----------------------------------------------------------------*/
 static void
 genCmp (operand * left, operand * right,
-       operand * result, iCode * ifx, int sign)
+       operand * result, iCode * ifx, int sign, iCode *ic)
 {
   int size, offset = 0;
   unsigned long lit = 0L;
 
+  D(emitcode (";", "genCmp"));
+
   /* if left & right are bit variables */
   if (AOP_TYPE (left) == AOP_CRY &&
       AOP_TYPE (right) == AOP_CRY)
@@ -3698,6 +4007,8 @@ genCmp (operand * left, operand * right,
     }
 
 release:
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
     {
       outBitC (result);
@@ -3725,6 +4036,8 @@ genCmpGt (iCode * ic, iCode * ifx)
   sym_link *letype, *retype;
   int sign;
 
+  D(emitcode (";", "genCmpGt"));
+
   left = IC_LEFT (ic);
   right = IC_RIGHT (ic);
   result = IC_RESULT (ic);
@@ -3737,10 +4050,8 @@ genCmpGt (iCode * ic, iCode * ifx)
   aopOp (right, ic, FALSE);
   aopOp (result, ic, TRUE);
 
-  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);
 }
 
@@ -3754,6 +4065,8 @@ genCmpLt (iCode * ic, iCode * ifx)
   sym_link *letype, *retype;
   int sign;
 
+  D(emitcode (";", "genCmpLt"));
+
   left = IC_LEFT (ic);
   right = IC_RIGHT (ic);
   result = IC_RESULT (ic);
@@ -3767,10 +4080,8 @@ genCmpLt (iCode * ic, iCode * ifx)
   aopOp (right, ic, FALSE);
   aopOp (result, ic, TRUE);
 
-  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);
 }
 
@@ -3871,6 +4182,8 @@ genCmpEq (iCode * ic, iCode * ifx)
 {
   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);
@@ -4049,6 +4362,44 @@ ifxForOp (operand * op, iCode * ic)
 
   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) || (unsigned) 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                                     */
 /*-----------------------------------------------------------------*/
@@ -4058,6 +4409,8 @@ genAndOp (iCode * ic)
   operand *left, *right, *result;
   symbol *tlbl;
 
+  D(emitcode (";", "genAndOp"));
+
   /* note here that && operations that are in an
      if statement are taken away by backPatchLabels
      only those used in arthmetic operations remain */
@@ -4098,6 +4451,8 @@ genOrOp (iCode * ic)
   operand *left, *right, *result;
   symbol *tlbl;
 
+  D(emitcode (";", "genOrOp"));
+
   /* note here that || operations that are in an
      if statement are taken away by backPatchLabels
      only those used in arthmetic operations remain */
@@ -4207,6 +4562,8 @@ genAnd (iCode * ic, iCode * ifx)
   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);
@@ -4431,9 +4788,20 @@ genAnd (iCode * ic, iCode * ifx)
            emitcode ("setb", "c");
          while (sizer--)
            {
-             MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
-             emitcode ("anl", "a,%s",
-                       aopGet (AOP (left), offset, FALSE, FALSE));
+             if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
+               emitcode ("anl", "a,%s",
+                         aopGet (AOP (right), offset, FALSE, FALSE));
+             } else {
+               if (AOP_TYPE(left)==AOP_ACC) {
+                 emitcode("mov", "b,a");
+                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
+                 emitcode("anl", "a,b");
+               }else {
+                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
+                 emitcode ("anl", "a,%s",
+                           aopGet (AOP (left), offset, FALSE, FALSE));
+               }
+             }
              emitcode ("jnz", "%05d$", tlbl->key + 100);
              offset++;
            }
@@ -4498,6 +4866,8 @@ genOr (iCode * ic, iCode * ifx)
   int size, offset = 0;
   unsigned long lit = 0L;
 
+  D(emitcode (";", "genOr"));
+
   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
@@ -4547,7 +4917,7 @@ genOr (iCode * ic, iCode * ifx)
     {
       if (AOP_TYPE (right) == AOP_LIT)
        {
-         // c = bit & literal;
+         // c = bit | literal;
          if (lit)
            {
              // lit != 0 => result = 1
@@ -4700,9 +5070,14 @@ genOr (iCode * ic, iCode * ifx)
            emitcode ("setb", "c");
          while (sizer--)
            {
-             MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
-             emitcode ("orl", "a,%s",
-                       aopGet (AOP (left), offset, FALSE, FALSE));
+             if (AOP_TYPE(right)==AOP_REG && 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));
+             }
              emitcode ("jnz", "%05d$", tlbl->key + 100);
              offset++;
            }
@@ -4760,6 +5135,8 @@ genXor (iCode * ic, iCode * ifx)
   int size, offset = 0;
   unsigned long lit = 0L;
 
+  D(emitcode (";", "genXor"));
+
   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
@@ -4952,9 +5329,14 @@ genXor (iCode * ic, iCode * ifx)
                }
              else
                {
-                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
-                 emitcode ("xrl", "a,%s",
-                           aopGet (AOP (left), offset, FALSE, FALSE));
+                 if (AOP_TYPE(right)==AOP_REG && 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, FALSE));
+                 }
                }
              emitcode ("jnz", "%05d$", tlbl->key + 100);
              offset++;
@@ -5009,11 +5391,13 @@ release:
 static void
 genInline (iCode * ic)
 {
-  char buffer[MAX_INLINEASM];
-  char *bp = buffer;
-  char *bp1 = buffer;
+  char *buffer, *bp, *bp1;
+
+  D(emitcode (";", "genInline"));
 
   _G.inLine += (!options.asmpeep);
+
+  buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
   strcpy (buffer, IC_INLINE (ic));
 
   /* emit each line as a code */
@@ -5055,6 +5439,8 @@ genRRC (iCode * ic)
   int size, offset = 0;
   char *l;
 
+  D(emitcode (";", "genRRC"));
+
   /* rotate right with carry */
   left = IC_LEFT (ic);
   result = IC_RESULT (ic);
@@ -5064,6 +5450,12 @@ genRRC (iCode * ic)
   /* move it to the result */
   size = AOP_SIZE (result);
   offset = size - 1;
+  if (size == 1) { /* special case for 1 byte */
+      l = aopGet (AOP (left), offset, FALSE, FALSE);
+      MOVA (l);
+      emitcode ("rr", "a");
+      goto release;
+  }
   CLRC;
   while (size--)
     {
@@ -5081,6 +5473,7 @@ genRRC (iCode * ic)
       MOVA (l);
     }
   emitcode ("mov", "acc.7,c");
+ release:
   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
   freeAsmop (left, NULL, ic, TRUE);
   freeAsmop (result, NULL, ic, TRUE);
@@ -5096,6 +5489,8 @@ genRLC (iCode * ic)
   int size, offset = 0;
   char *l;
 
+  D(emitcode (";", "genRLC"));
+
   /* rotate right with carry */
   left = IC_LEFT (ic);
   result = IC_RESULT (ic);
@@ -5109,6 +5504,10 @@ genRLC (iCode * ic)
     {
       l = aopGet (AOP (left), offset, FALSE, FALSE);
       MOVA (l);
+      if (size == 0) { /* special case for 1 byte */
+             emitcode("rl","a");
+             goto release;
+      }
       emitcode ("add", "a,acc");
       if (AOP_SIZE (result) > 1)
        aopPut (AOP (result), "a", offset++);
@@ -5129,6 +5528,7 @@ genRLC (iCode * ic)
       MOVA (l);
     }
   emitcode ("mov", "acc.0,c");
+ release:
   aopPut (AOP (result), "a", 0);
   freeAsmop (left, NULL, ic, TRUE);
   freeAsmop (result, NULL, ic, TRUE);
@@ -5141,6 +5541,9 @@ static void
 genGetHbit (iCode * ic)
 {
   operand *left, *result;
+
+  D(emitcode (";", "genGetHbit"));
+
   left = IC_LEFT (ic);
   result = IC_RESULT (ic);
   aopOp (left, ic, FALSE);
@@ -5440,7 +5843,7 @@ AccAXLsh (char *x, int shCount)
                SRMask[shCount]);       // 000000BB:CCCCCCDD
       emitcode ("mov", "c,acc.0");     // c = B
       emitcode ("xch", "a,%s", x);     // CCCCCCDD:000000BB
-#if 0
+#if 0 // REMOVE ME
       AccAXRrl1 (x);           // BCCCCCCD:D000000B
       AccAXRrl1 (x);           // BBCCCCCC:DD000000
 #else
@@ -5745,6 +6148,8 @@ shiftRLeftOrResult (operand * left, int offl,
 static void
 genlshOne (operand * result, operand * left, int shCount)
 {
+  D(emitcode (";", "genlshOne"));
+
   shiftL1Left2Result (left, LSB, result, LSB, shCount);
 }
 
@@ -5756,6 +6161,8 @@ genlshTwo (operand * result, operand * left, int shCount)
 {
   int size;
 
+  D(emitcode (";", "genlshTwo"));
+
   size = getDataSize (result);
 
   /* if shCount >= 8 */
@@ -5860,6 +6267,8 @@ genlshFour (operand * result, operand * left, int shCount)
 {
   int size;
 
+  D(emitcode (";", "genlshFour"));
+
   size = AOP_SIZE (result);
 
   /* if shifting more that 3 bytes */
@@ -5874,7 +6283,7 @@ genlshFour (operand * result, operand * left, int shCount)
        movLeft2Result (left, LSB, result, MSB32, 0);
       aopPut (AOP (result), zero, LSB);
       aopPut (AOP (result), zero, MSB16);
-      aopPut (AOP (result), zero, MSB32);
+      aopPut (AOP (result), zero, MSB24);
       return;
     }
 
@@ -5957,6 +6366,8 @@ genLeftShiftLiteral (operand * left,
   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
   int size;
 
+  D(emitcode (";", "genLeftShiftLiteral"));
+
   freeAsmop (right, NULL, ic, TRUE);
 
   aopOp (left, ic, FALSE);
@@ -5990,13 +6401,15 @@ genLeftShiftLiteral (operand * left,
          break;
 
        case 2:
-       case 3:
          genlshTwo (result, left, shCount);
          break;
 
        case 4:
          genlshFour (result, left, shCount);
          break;
+       default:
+         fprintf(stderr, "*** ack! mystery literal shift!\n");
+         break;
        }
     }
   freeAsmop (left, NULL, ic, TRUE);
@@ -6014,6 +6427,8 @@ genLeftShift (iCode * ic)
   char *l;
   symbol *tlbl, *tlbl1;
 
+  D(emitcode (";", "genLeftShift"));
+
   right = IC_RIGHT (ic);
   left = IC_LEFT (ic);
   result = IC_RESULT (ic);
@@ -6115,6 +6530,8 @@ static void
 genrshOne (operand * result, operand * left,
           int shCount, int sign)
 {
+  D(emitcode (";", "genrshOne"));
+
   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
 }
 
@@ -6125,6 +6542,8 @@ static void
 genrshTwo (operand * result, operand * left,
           int shCount, int sign)
 {
+  D(emitcode (";", "genrshTwo"));
+
   /* if shCount >= 8 */
   if (shCount >= 8)
     {
@@ -6150,22 +6569,48 @@ static void
 shiftRLong (operand * left, int offl,
            operand * result, int sign)
 {
-  if (!sign)
-    emitcode ("clr", "c");
+  int isSameRegs=sameRegs(AOP(left),AOP(result));
+
+  if (isSameRegs && offl>1) {
+    // we are in big trouble, but this shouldn't happen
+    werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
+  }
+
   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
-  if (sign)
+  
+  if (offl==MSB16) {
+    // shift is > 8
+    if (sign) {
+      emitcode ("rlc", "a");
+      emitcode ("subb", "a,acc");
+      emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
+    } else {
+      aopPut (AOP(result), zero, MSB32);
+    }
+  }
+
+  if (!sign) {
+    emitcode ("clr", "c");
+  } else {
     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);
+  }
 
-  MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
   emitcode ("rrc", "a");
-  aopPut (AOP (result), "a", MSB24 - offl);
 
-  MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
+  if (isSameRegs && offl==MSB16) {
+    emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
+  } else {
+    aopPut (AOP (result), "a", MSB32);
+    MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
+  }
+
+  emitcode ("rrc", "a");
+  if (isSameRegs && offl==1) {
+    emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
+  } else {
+    aopPut (AOP (result), "a", MSB24);
+    MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
+  }
   emitcode ("rrc", "a");
   aopPut (AOP (result), "a", MSB16 - offl);
 
@@ -6184,6 +6629,8 @@ static void
 genrshFour (operand * result, operand * left,
            int shCount, int sign)
 {
+  D(emitcode (";", "genrshFour"));
+
   /* if shifting more that 3 bytes */
   if (shCount >= 24)
     {
@@ -6257,6 +6704,8 @@ genRightShiftLiteral (operand * left,
   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
   int size;
 
+  D(emitcode (";", "genRightShiftLiteral"));
+
   freeAsmop (right, NULL, ic, TRUE);
 
   aopOp (left, ic, FALSE);
@@ -6320,6 +6769,8 @@ genSignedRightShift (iCode * ic)
   char *l;
   symbol *tlbl, *tlbl1;
 
+  D(emitcode (";", "genSignedRightShift"));
+
   /* we do it the hard way put the shift count in b
      and loop thru preserving the sign */
 
@@ -6426,6 +6877,8 @@ genRightShift (iCode * ic)
   char *l;
   symbol *tlbl, *tlbl1;
 
+  D(emitcode (";", "genRightShift"));
+
   /* if signed then we do it the hard way preserve the
      sign bit moving it inwards */
   retype = getSpec (operandType (IC_RESULT (ic)));
@@ -6545,6 +6998,8 @@ genUnpackBits (operand * result, char *rname, int ptype)
   int offset = 0;
   int rsize;
 
+  D(emitcode (";", "genUnpackBits"));
+
   etype = getSpec (operandType (result));
   rsize = getSize (operandType (result));
   /* read the first byte  */
@@ -6566,7 +7021,7 @@ genUnpackBits (operand * result, char *rname, int ptype)
 
     case CPOINTER:
       emitcode ("clr", "a");
-      emitcode ("movc", "a,%s", "@a+dptr");
+      emitcode ("movc", "a,@a+dptr");
       break;
 
     case GPOINTER:
@@ -6619,7 +7074,7 @@ genUnpackBits (operand * result, char *rname, int ptype)
        case CPOINTER:
          emitcode ("clr", "a");
          emitcode ("inc", "dptr");
-         emitcode ("movc", "a", "@a+dptr");
+         emitcode ("movc", "a,@a+dptr");
          break;
 
        case GPOINTER:
@@ -6666,6 +7121,9 @@ genDataPointerGet (operand * left,
   char *l;
   char buffer[256];
   int size, offset = 0;
+
+  D(emitcode (";", "genDataPointerGet"));
+
   aopOp (result, ic, TRUE);
 
   /* get the string representation of the name */
@@ -6690,7 +7148,8 @@ genDataPointerGet (operand * left,
 static void
 genNearPointerGet (operand * left,
                   operand * result,
-                  iCode * ic)
+                  iCode * ic,
+                  iCode * pi)
 {
   asmop *aop = NULL;
   regs *preg = NULL;
@@ -6699,6 +7158,8 @@ genNearPointerGet (operand * left,
   sym_link *ltype = operandType (left);
   char buffer[80];
 
+  D(emitcode (";", "genNearPointerGet"));
+
   rtype = operandType (result);
   retype = getSpec (rtype);
 
@@ -6730,9 +7191,9 @@ genNearPointerGet (operand * left,
     }
   else
     rname = aopGet (AOP (left), 0, FALSE, FALSE);
-
-  freeAsmop (left, NULL, ic, TRUE);
-  aopOp (result, ic, FALSE);
+  
+  //aopOp (result, ic, FALSE);
+  aopOp (result, ic, result?TRUE:FALSE);
 
   /* if bitfield then unpack the bits */
   if (IS_BITVAR (retype))
@@ -6757,15 +7218,17 @@ genNearPointerGet (operand * left,
              aopPut (AOP (result), buffer, offset);
            }
          offset++;
-         if (size)
+         if (size || pi)
            emitcode ("inc", "%s", rname);
        }
     }
 
   /* now some housekeeping stuff */
-  if (aop)
+  if (aop)       /* we had to allocate for this iCode */
     {
-      /* we had to allocate for this iCode */
+      if (pi) { /* post increment present */
+       aopPut(AOP ( left ),rname,0);
+      }
       freeAsmop (NULL, aop, ic, TRUE);
     }
   else
@@ -6775,10 +7238,11 @@ genNearPointerGet (operand * left,
          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))
+      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--)
@@ -6787,8 +7251,9 @@ genNearPointerGet (operand * left,
     }
 
   /* done */
+  freeAsmop (left, NULL, ic, TRUE);
   freeAsmop (result, NULL, ic, TRUE);
-
+  if (pi) pi->generated = 1;
 }
 
 /*-----------------------------------------------------------------*/
@@ -6797,13 +7262,16 @@ genNearPointerGet (operand * left,
 static void
 genPagedPointerGet (operand * left,
                    operand * result,
-                   iCode * ic)
+                   iCode * ic,
+                   iCode *pi)
 {
   asmop *aop = NULL;
   regs *preg = NULL;
   char *rname;
   sym_link *rtype, *retype;
 
+  D(emitcode (";", "genPagedPointerGet"));
+
   rtype = operandType (result);
   retype = getSpec (rtype);
 
@@ -6824,7 +7292,6 @@ genPagedPointerGet (operand * left,
   else
     rname = aopGet (AOP (left), 0, FALSE, FALSE);
 
-  freeAsmop (left, NULL, ic, TRUE);
   aopOp (result, ic, FALSE);
 
   /* if bitfield then unpack the bits */
@@ -6844,15 +7311,15 @@ genPagedPointerGet (operand * left,
 
          offset++;
 
-         if (size)
+         if (size || pi)
            emitcode ("inc", "%s", rname);
        }
     }
 
   /* now some housekeeping stuff */
-  if (aop)
+  if (aop) /* we had to allocate for this iCode */
     {
-      /* we had to allocate for this iCode */
+      if (pi) aopPut ( AOP (left), rname, 0);
       freeAsmop (NULL, aop, ic, TRUE);
     }
   else
@@ -6862,10 +7329,11 @@ genPagedPointerGet (operand * left,
          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))
+      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--)
@@ -6874,8 +7342,9 @@ genPagedPointerGet (operand * left,
     }
 
   /* done */
+  freeAsmop (left, NULL, ic, TRUE);
   freeAsmop (result, NULL, ic, TRUE);
-
+  if (pi) pi->generated = 1;
 
 }
 
@@ -6884,11 +7353,13 @@ genPagedPointerGet (operand * left,
 /*-----------------------------------------------------------------*/
 static void
 genFarPointerGet (operand * left,
-                 operand * result, iCode * ic)
+                 operand * result, iCode * ic, iCode * pi)
 {
   int size, offset;
   sym_link *retype = getSpec (operandType (result));
 
+  D(emitcode (";", "genFarPointerGet"));
+
   aopOp (left, ic, FALSE);
 
   /* if the operand is already in dptr
@@ -6905,7 +7376,6 @@ genFarPointerGet (operand * left,
        }
     }
   /* so dptr know contains the address */
-  freeAsmop (left, NULL, ic, TRUE);
   aopOp (result, ic, FALSE);
 
   /* if bit then unpack */
@@ -6920,24 +7390,32 @@ genFarPointerGet (operand * left,
        {
          emitcode ("movx", "a,@dptr");
          aopPut (AOP (result), "a", offset++);
-         if (size)
+         if (size || pi)
            emitcode ("inc", "dptr");
        }
     }
-
+  
+  if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
+    aopPut ( AOP (left), "dpl", 0);
+    aopPut ( AOP (left), "dph", 1);
+    pi->generated = 1;
+  }
+  freeAsmop (left, NULL, ic, TRUE);
   freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* emitcodePointerGet - gget value from code space                  */
+/* genCodePointerGet - gget value from code space                  */
 /*-----------------------------------------------------------------*/
 static void
-emitcodePointerGet (operand * left,
-                   operand * result, iCode * ic)
+genCodePointerGet (operand * left,
+                   operand * result, iCode * ic, iCode *pi)
 {
   int size, offset;
   sym_link *retype = getSpec (operandType (result));
 
+  D(emitcode (";", "genCodePointerGet"));
+
   aopOp (left, ic, FALSE);
 
   /* if the operand is already in dptr
@@ -6954,7 +7432,6 @@ emitcodePointerGet (operand * left,
        }
     }
   /* so dptr know contains the address */
-  freeAsmop (left, NULL, ic, TRUE);
   aopOp (result, ic, FALSE);
 
   /* if bit then unpack */
@@ -6970,11 +7447,17 @@ emitcodePointerGet (operand * left,
          emitcode ("clr", "a");
          emitcode ("movc", "a,@a+dptr");
          aopPut (AOP (result), "a", offset++);
-         if (size)
+         if (size || pi)
            emitcode ("inc", "dptr");
        }
     }
 
+  if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
+    aopPut ( AOP (left), "dpl", 0);
+    aopPut ( AOP (left), "dph", 1);
+    pi->generated = 1;
+  }
+  freeAsmop (left, NULL, ic, TRUE);
   freeAsmop (result, NULL, ic, TRUE);
 }
 
@@ -6983,11 +7466,13 @@ emitcodePointerGet (operand * left,
 /*-----------------------------------------------------------------*/
 static void
 genGenPointerGet (operand * left,
-                 operand * result, iCode * ic)
+                 operand * result, iCode * ic, iCode *pi)
 {
   int size, offset;
   sym_link *retype = getSpec (operandType (result));
 
+  D(emitcode (";", "genGenPointerGet"));
+
   aopOp (left, ic, FALSE);
 
   /* if the operand is already in dptr
@@ -6998,7 +7483,10 @@ genGenPointerGet (operand * left,
       if (AOP_TYPE (left) == AOP_IMMD)
        {
          emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
-         emitcode ("mov", "b,#%d", pointerCode (retype));
+         if (AOP(left)->aopu.aop_immd.from_cast_remat) 
+                 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
+         else
+                 emitcode ("mov", "b,#%d", pointerCode (retype));
        }
       else
        {                       /* we need to get it byte by byte */
@@ -7008,7 +7496,6 @@ genGenPointerGet (operand * left,
        }
     }
   /* so dptr know contains the address */
-  freeAsmop (left, NULL, ic, TRUE);
   aopOp (result, ic, FALSE);
 
   /* if bit then unpack */
@@ -7023,11 +7510,18 @@ genGenPointerGet (operand * left,
        {
          emitcode ("lcall", "__gptrget");
          aopPut (AOP (result), "a", offset++);
-         if (size)
+         if (size || pi)
            emitcode ("inc", "dptr");
        }
     }
 
+  if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
+    aopPut ( AOP (left), "dpl", 0);
+    aopPut ( AOP (left), "dph", 1);
+    aopPut ( AOP (left), "b", 2);
+    pi->generated = 1;
+  }
+  freeAsmop (left, NULL, ic, TRUE);
   freeAsmop (result, NULL, ic, TRUE);
 }
 
@@ -7035,12 +7529,14 @@ genGenPointerGet (operand * left,
 /* genPointerGet - generate code for pointer get                   */
 /*-----------------------------------------------------------------*/
 static void
-genPointerGet (iCode * ic)
+genPointerGet (iCode * ic, iCode *pi)
 {
   operand *left, *result;
   sym_link *type, *etype;
   int p_type;
 
+  D(emitcode (";", "genPointerGet"));
+
   left = IC_LEFT (ic);
   result = IC_RESULT (ic);
 
@@ -7055,23 +7551,15 @@ genPointerGet (iCode * ic)
     {
       /* we have to go by the storage class */
       p_type = PTR_TYPE (SPEC_OCLS (etype));
-
-/*  if (SPEC_OCLS(etype)->codesp ) { */
-/*      p_type = CPOINTER ;  */
-/*  } */
-/*  else */
-/*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
-/*    p_type = FPOINTER ; */
-/*      else */
-/*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
-/*        p_type = PPOINTER; */
-/*    else */
-/*        if (SPEC_OCLS(etype) == idata ) */
-/*      p_type = IPOINTER; */
-/*        else */
-/*      p_type = POINTER ; */
     }
 
+  /* 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 =   type = operandType (left);
+         p_type = DCL_TYPE (type);
+  }
   /* now that we have the pointer type we assign
      the pointer values */
   switch (p_type)
@@ -7079,23 +7567,23 @@ genPointerGet (iCode * ic)
 
     case POINTER:
     case IPOINTER:
-      genNearPointerGet (left, result, ic);
+      genNearPointerGet (left, result, ic, pi);
       break;
 
     case PPOINTER:
-      genPagedPointerGet (left, result, ic);
+      genPagedPointerGet (left, result, ic, pi);
       break;
 
     case FPOINTER:
-      genFarPointerGet (left, result, ic);
+      genFarPointerGet (left, result, ic, pi);
       break;
 
     case CPOINTER:
-      emitcodePointerGet (left, result, ic);
+      genCodePointerGet (left, result, ic, pi);
       break;
 
     case GPOINTER:
-      genGenPointerGet (left, result, ic);
+      genGenPointerGet (left, result, ic, pi);
       break;
     }
 
@@ -7115,6 +7603,8 @@ genPackBits (sym_link * etype,
   int blen, bstr;
   char *l;
 
+  D(emitcode (";", "genPackBits"));
+
   blen = SPEC_BLEN (etype);
   bstr = SPEC_BSTR (etype);
 
@@ -7280,6 +7770,8 @@ genDataPointerSet (operand * right,
   int size, offset = 0;
   char *l, buffer[256];
 
+  D(emitcode (";", "genDataPointerSet"));
+
   aopOp (right, ic, FALSE);
 
   l = aopGet (AOP (result), 0, FALSE, TRUE);
@@ -7304,7 +7796,8 @@ genDataPointerSet (operand * right,
 static void
 genNearPointerSet (operand * right,
                   operand * result,
-                  iCode * ic)
+                  iCode * ic,
+                  iCode * pi)
 {
   asmop *aop = NULL;
   regs *preg = NULL;
@@ -7312,6 +7805,8 @@ genNearPointerSet (operand * right,
   sym_link *retype, *letype;
   sym_link *ptype = operandType (result);
 
+  D(emitcode (";", "genNearPointerSet"));
+
   retype = getSpec (operandType (right));
   letype = getSpec (ptype);
   aopOp (result, ic, FALSE);
@@ -7326,25 +7821,47 @@ genNearPointerSet (operand * right,
       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;
+       if (
+           //AOP_TYPE (result) == AOP_STK
+           IS_AOP_PREG(result)
+           )
+       {
+           // Aha, it is a pointer, just in disguise.
+           rname = aopGet (AOP (result), 0, FALSE, FALSE);
+           if (*rname != '@')
+           {
+               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
+                       __FILE__, __LINE__);
+           }
+           else
+           {
+               // Expected case.
+               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 (AOP (result), 0, FALSE, TRUE));
+           rname = preg->name;
+       }
+    }
+    else
+    {
+       rname = aopGet (AOP (result), 0, FALSE, FALSE);
     }
-  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) || IS_BITVAR (letype))
     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
@@ -7364,16 +7881,16 @@ genNearPointerSet (operand * right,
            }
          else
            emitcode ("mov", "@%s,%s", rname, l);
-         if (size)
+         if (size || pi)
            emitcode ("inc", "%s", rname);
          offset++;
        }
     }
 
   /* now some housekeeping stuff */
-  if (aop)
+  if (aop) /* we had to allocate for this iCode */
     {
-      /* we had to allocate for this iCode */
+      if (pi) aopPut (AOP (result),rname,0);
       freeAsmop (NULL, aop, ic, TRUE);
     }
   else
@@ -7383,10 +7900,11 @@ genNearPointerSet (operand * right,
          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))
+      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--)
@@ -7395,9 +7913,9 @@ genNearPointerSet (operand * right,
     }
 
   /* done */
+  if (pi) pi->generated = 1;
+  freeAsmop (result, NULL, ic, TRUE);
   freeAsmop (right, NULL, ic, TRUE);
-
-
 }
 
 /*-----------------------------------------------------------------*/
@@ -7406,13 +7924,16 @@ genNearPointerSet (operand * right,
 static void
 genPagedPointerSet (operand * right,
                    operand * result,
-                   iCode * ic)
+                   iCode * ic,
+                   iCode * pi)
 {
   asmop *aop = NULL;
   regs *preg = NULL;
   char *rname, *l;
   sym_link *retype, *letype;
 
+  D(emitcode (";", "genPagedPointerSet"));
+
   retype = getSpec (operandType (right));
   letype = getSpec (operandType (result));
 
@@ -7433,7 +7954,6 @@ genPagedPointerSet (operand * right,
   else
     rname = aopGet (AOP (result), 0, FALSE, FALSE);
 
-  freeAsmop (result, NULL, ic, TRUE);
   aopOp (right, ic, FALSE);
 
   /* if bitfield then unpack the bits */
@@ -7452,7 +7972,7 @@ genPagedPointerSet (operand * right,
          MOVA (l);
          emitcode ("movx", "@%s,a", rname);
 
-         if (size)
+         if (size || pi)
            emitcode ("inc", "%s", rname);
 
          offset++;
@@ -7460,9 +7980,9 @@ genPagedPointerSet (operand * right,
     }
 
   /* now some housekeeping stuff */
-  if (aop)
+  if (aop) /* we had to allocate for this iCode */
     {
-      /* we had to allocate for this iCode */
+      if (pi) aopPut (AOP (result),rname,0);
       freeAsmop (NULL, aop, ic, TRUE);
     }
   else
@@ -7484,6 +8004,8 @@ genPagedPointerSet (operand * right,
     }
 
   /* done */
+  if (pi) pi->generated = 1;
+  freeAsmop (result, NULL, ic, TRUE);
   freeAsmop (right, NULL, ic, TRUE);
 
 
@@ -7494,11 +8016,14 @@ genPagedPointerSet (operand * right,
 /*-----------------------------------------------------------------*/
 static void
 genFarPointerSet (operand * right,
-                 operand * result, iCode * ic)
+                 operand * result, iCode * ic, iCode * pi)
 {
   int size, offset;
   sym_link *retype = getSpec (operandType (right));
   sym_link *letype = getSpec (operandType (result));
+
+  D(emitcode (";", "genFarPointerSet"));
+
   aopOp (result, ic, FALSE);
 
   /* if the operand is already in dptr
@@ -7515,7 +8040,6 @@ genFarPointerSet (operand * right,
        }
     }
   /* so dptr know contains the address */
-  freeAsmop (result, NULL, ic, TRUE);
   aopOp (right, ic, FALSE);
 
   /* if bit then unpack */
@@ -7531,11 +8055,16 @@ genFarPointerSet (operand * right,
          char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
          MOVA (l);
          emitcode ("movx", "@dptr,a");
-         if (size)
+         if (size || pi)
            emitcode ("inc", "dptr");
        }
     }
-
+  if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
+    aopPut (AOP(result),"dpl",0);
+    aopPut (AOP(result),"dph",1);
+    pi->generated=1;
+  }
+  freeAsmop (result, NULL, ic, TRUE);
   freeAsmop (right, NULL, ic, TRUE);
 }
 
@@ -7544,12 +8073,14 @@ genFarPointerSet (operand * right,
 /*-----------------------------------------------------------------*/
 static void
 genGenPointerSet (operand * right,
-                 operand * result, iCode * ic)
+                 operand * result, iCode * ic, iCode * pi)
 {
   int size, offset;
   sym_link *retype = getSpec (operandType (right));
   sym_link *letype = getSpec (operandType (result));
 
+  D(emitcode (";", "genGenPointerSet"));
+
   aopOp (result, ic, FALSE);
 
   /* if the operand is already in dptr
@@ -7560,7 +8091,10 @@ genGenPointerSet (operand * right,
       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));
+         if (AOP(result)->aopu.aop_immd.from_cast_remat) 
+                 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
+         else 
+                 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
        }
       else
        {                       /* we need to get it byte by byte */
@@ -7570,7 +8104,6 @@ genGenPointerSet (operand * right,
        }
     }
   /* so dptr know contains the address */
-  freeAsmop (result, NULL, ic, TRUE);
   aopOp (right, ic, FALSE);
 
   /* if bit then unpack */
@@ -7586,11 +8119,18 @@ genGenPointerSet (operand * right,
          char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
          MOVA (l);
          emitcode ("lcall", "__gptrput");
-         if (size)
+         if (size || pi)
            emitcode ("inc", "dptr");
        }
     }
 
+  if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
+    aopPut (AOP(result),"dpl",0);
+    aopPut (AOP(result),"dph",1);
+    aopPut (AOP(result),"b",2);
+    pi->generated=1;
+  }
+  freeAsmop (result, NULL, ic, TRUE);
   freeAsmop (right, NULL, ic, TRUE);
 }
 
@@ -7598,12 +8138,14 @@ genGenPointerSet (operand * right,
 /* genPointerSet - stores the value into a pointer location        */
 /*-----------------------------------------------------------------*/
 static void
-genPointerSet (iCode * ic)
+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);
 
@@ -7622,6 +8164,13 @@ genPointerSet (iCode * ic)
       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 =   type = operandType (result);
+         p_type = DCL_TYPE (type);
+  }
   /* now that we have the pointer type we assign
      the pointer values */
   switch (p_type)
@@ -7629,19 +8178,19 @@ genPointerSet (iCode * ic)
 
     case POINTER:
     case IPOINTER:
-      genNearPointerSet (right, result, ic);
+      genNearPointerSet (right, result, ic, pi);
       break;
 
     case PPOINTER:
-      genPagedPointerSet (right, result, ic);
+      genPagedPointerSet (right, result, ic, pi);
       break;
 
     case FPOINTER:
-      genFarPointerSet (right, result, ic);
+      genFarPointerSet (right, result, ic, pi);
       break;
 
     case GPOINTER:
-      genGenPointerSet (right, result, ic);
+      genGenPointerSet (right, result, ic, pi);
       break;
     }
 
@@ -7656,6 +8205,8 @@ genIfx (iCode * ic, iCode * popIc)
   operand *cond = IC_COND (ic);
   int isbit = 0;
 
+  D(emitcode (";", "genIfx"));
+
   aopOp (cond, ic, FALSE);
 
   /* get the value into acc */
@@ -7691,6 +8242,8 @@ genAddrOf (iCode * ic)
   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
   int size, offset;
 
+  D(emitcode (";", "genAddrOf"));
+
   aopOp (IC_RESULT (ic), ic, FALSE);
 
   /* if the operand is on the stack then we
@@ -7703,7 +8256,9 @@ genAddrOf (iCode * ic)
       if (sym->stack)
        {
          emitcode ("mov", "a,_bp");
-         emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
+         emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
+                                        ((char) (sym->stack - _G.nRegsSaved)) :
+                                        ((char) sym->stack)) & 0xff);
          aopPut (AOP (IC_RESULT (ic)), "a", 0);
        }
       else
@@ -7753,6 +8308,9 @@ genFarFarAssign (operand * result, operand * right, iCode * ic)
   int size = AOP_SIZE (right);
   int offset = 0;
   char *l;
+
+  D(emitcode (";", "genFarFarAssign"));
+
   /* first push the right side on to the stack */
   while (size--)
     {
@@ -7784,6 +8342,8 @@ genAssign (iCode * ic)
   int size, offset;
   unsigned long lit = 0L;
 
+  D(emitcode(";","genAssign"));
+
   result = IC_RESULT (ic);
   right = IC_RIGHT (ic);
 
@@ -7794,8 +8354,7 @@ genAssign (iCode * ic)
   aopOp (right, ic, FALSE);
 
   /* special case both in far space */
-  if ((AOP_TYPE (right) == AOP_DPTR ||
-       AOP_TYPE (right) == AOP_DPTR2) &&
+  if (AOP_TYPE (right) == AOP_DPTR &&
       IS_TRUE_SYMOP (result) &&
       isOperandInFarSpace (result))
     {
@@ -7887,6 +8446,8 @@ genJumpTab (iCode * ic)
   symbol *jtab;
   char *l;
 
+  D(emitcode (";", "genJumpTab"));
+
   aopOp (IC_JTCOND (ic), ic, FALSE);
   /* get the condition into accumulator */
   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
@@ -7919,6 +8480,8 @@ genCast (iCode * ic)
   operand *right = IC_RIGHT (ic);
   int size, offset;
 
+  D(emitcode(";", "genCast"));
+
   /* if they are equivalent then do nothing */
   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
     return;
@@ -7927,7 +8490,7 @@ genCast (iCode * ic)
   aopOp (result, ic, FALSE);
 
   /* if the result is a bit */
-  if (AOP_TYPE (result) == AOP_CRY)
+  if (IS_BITVAR(OP_SYMBOL(result)->type))
     {
       /* if the right size is a literal then
          we know what the value is */
@@ -7994,8 +8557,13 @@ genCast (iCode * ic)
            p_type = DCL_TYPE (type);
          else
            {
-             /* we have to go by the storage class */
-             p_type = PTR_TYPE (SPEC_OCLS (etype));
+             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 */
@@ -8021,7 +8589,10 @@ genCast (iCode * ic)
            case CPOINTER:
              l = "#0x02";
              break;
-           case PPOINTER:
+           case GPOINTER:
+             l = "0x03";
+             break;
+           case PPOINTER: // what the fck is this?
              l = "#0x03";
              break;
 
@@ -8064,7 +8635,7 @@ genCast (iCode * ic)
   /* now depending on the sign of the source && destination */
   size = AOP_SIZE (result) - AOP_SIZE (right);
   /* if unsigned or not an integral type */
-  if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
+  if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
     {
       while (size--)
        aopPut (AOP (result), zero, offset++);
@@ -8099,6 +8670,8 @@ genDjnz (iCode * ic, iCode * ifx)
   if (!ifx)
     return 0;
 
+  D(emitcode (";", "genDjnz"));
+
   /* if the if condition has a false label
      then we cannot save */
   if (IC_FALSE (ifx))
@@ -8124,7 +8697,30 @@ genDjnz (iCode * ic, iCode * ifx)
 
   aopOp (IC_RESULT (ic), ic, FALSE);
 
-  if (IS_AOP_PREG (IC_RESULT (ic)))
+  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(AOP(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(AOP(IC_RESULT(ic)), rByte, 0);
+      emitcode ("jnz", "%05d$", lbl->key + 100);
+  }
+  else if (IS_AOP_PREG (IC_RESULT (ic)))
     {
       emitcode ("dec", "%s",
                aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
@@ -8152,37 +8748,43 @@ genDjnz (iCode * ic, iCode * ifx)
 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 = 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 (AOP (IC_RESULT (ic)), "a", offset++);
-       }
-
-    }
-  else
-    {
-      _G.accInUse++;
+    int size = getSize (operandType (IC_RESULT (ic)));
+    int offset = 0;
+  D(emitcode (";", "genReceive"));
+
+  if (ic->argreg == 1) { /* first parameter */
+      if (isOperandInFarSpace (IC_RESULT (ic)) &&
+         (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
+          IS_TRUE_SYMOP (IC_RESULT (ic)))) {
+         
+         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 (AOP (IC_RESULT (ic)), "a", offset++);
+         }
+         
+      } else {
+         _G.accInUse++;
+         aopOp (IC_RESULT (ic), ic, FALSE);
+         _G.accInUse--;
+         assignResultValue (IC_RESULT (ic));
+      }
+  } else { /* second receive onwards */
+      int rb1off ;
       aopOp (IC_RESULT (ic), ic, FALSE);
-      _G.accInUse--;
-      assignResultValue (IC_RESULT (ic));
-    }
-
+      rb1off = ic->argreg;
+      while (size--) {
+         aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
+      }
+  }
   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
 }
 
@@ -8201,8 +8803,7 @@ gen51Code (iCode * lic)
   if (allocInfo)
     printAllocInfo (currFunc, codeOutFile);
   /* if debug information required */
-/*     if (options.debug && currFunc) { */
-  if (currFunc)
+  if (options.debug && currFunc)
     {
       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
       _G.debugLine = 1;
@@ -8222,7 +8823,7 @@ gen51Code (iCode * lic)
   for (ic = lic; ic; ic = ic->next)
     {
 
-      if (cln != ic->lineno)
+      if (ic->lineno && cln != ic->lineno)
        {
          if (options.debug)
            {
@@ -8232,7 +8833,8 @@ gen51Code (iCode * lic)
                        ic->level, ic->block);
              _G.debugLine = 0;
            }
-         emitcode (";", "%s %d", ic->filename, ic->lineno);
+         emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
+                   printCLine(ic->filename, ic->lineno));
          cln = ic->lineno;
        }
       /* if the result is marked as
@@ -8392,12 +8994,12 @@ gen51Code (iCode * lic)
          break;
 
        case GET_VALUE_AT_ADDRESS:
-         genPointerGet (ic);
+         genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
          break;
 
        case '=':
          if (POINTER_SET (ic))
-           genPointerSet (ic);
+           genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
          else
            genAssign (ic);
          break;
@@ -8428,8 +9030,6 @@ gen51Code (iCode * lic)
 
        default:
          ic = ic;
-         /*      piCode(ic,stdout); */
-
        }
     }