* src/mcs51/gen.c (genPlus): replaced "mov b,acc" by "mov b,a" Fiorenzo D. Ramaglia...
[fw/sdcc] / src / mcs51 / gen.c
index 6ea17c482f7864b701db871d101b18b5d35e52b4..55094e63b6973e051fc05ff657ffb2030695dcab 100644 (file)
@@ -93,6 +93,10 @@ 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;
@@ -101,7 +105,7 @@ static void saveRBank (int, iCode *, bool);
                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
                          IC_RESULT(x)->aop->type == AOP_STK )
 
-#define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
+#define MOVA(x) mova(x)  /* use function to avoid multiple eval */
 #define CLRC    emitcode("clr","c")
 #define SETC    emitcode("setb","c")
 
@@ -155,6 +159,19 @@ emitcode (char *inst, char *fmt,...)
   va_end (ap);
 }
 
+/*-----------------------------------------------------------------*/
+/* mova - moves specified value into accumulator                   */
+/*-----------------------------------------------------------------*/
+static void
+mova (char *x)
+{
+  /* do some early peephole optimization */
+  if (!strcmp(x, "a") || !strcmp(x, "acc"))
+    return;
+
+  emitcode("mov","a,%s", x);
+}
+
 /*-----------------------------------------------------------------*/
 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
 /*-----------------------------------------------------------------*/
@@ -751,6 +768,51 @@ dealloc:
     }
 }
 
+/*-----------------------------------------------------------------*/
+/* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
+/*                 clobber the accumulator                         */
+/*-----------------------------------------------------------------*/
+static bool
+aopGetUsesAcc (asmop *aop, int offset)
+{
+  if (offset > (aop->size - 1))
+    return FALSE;
+
+  switch (aop->type)
+    {
+
+    case AOP_R0:
+    case AOP_R1:
+      if (aop->paged)
+       return TRUE;
+      return FALSE;
+    case AOP_DPTR:
+      return TRUE;
+    case AOP_IMMD:
+      return FALSE;
+    case AOP_DIR:
+      return FALSE;
+    case AOP_REG:
+      wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
+      return FALSE;
+    case AOP_CRY:
+      return TRUE;
+    case AOP_ACC:
+      return TRUE;
+    case AOP_LIT:
+      return FALSE;
+    case AOP_STR:
+      if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
+       return TRUE;
+      return FALSE;
+    default:
+      /* Error case --- will have been caught already */
+      wassert(0);
+      return FALSE;
+    }
+}
+
+
 /*-----------------------------------------------------------------*/
 /* aopGet - for fetching value of the aop                          */
 /*-----------------------------------------------------------------*/
@@ -1042,11 +1104,8 @@ aopPut (asmop * aop, char *s, int offset)
                  MOVA (s);
                }
              {
-               symbol *lbl = newiTempLabel (NULL);
-               emitcode ("clr", "c");
-               emitcode ("jz", "%05d$", lbl->key + 100);
-               emitcode ("cpl", "c");
-               emitcode ("", "%05d$:", lbl->key + 100);
+               /* set C, if a >= 1 */
+                emitcode ("add", "a,#0xff");
                emitcode ("mov", "%s,c", aop->aopu.aop_dir);
              }
            }
@@ -1328,7 +1387,7 @@ genCpl (iCode * ic)
 {
   int offset = 0;
   int size;
-
+  symbol *tlbl;
 
   D(emitcode (";", "genCpl"));
 
@@ -1336,17 +1395,21 @@ genCpl (iCode * ic)
   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--)
@@ -1883,6 +1946,39 @@ saveRBank (int bank, iCode * ic, bool pushPsw)
   }
 }
 
+/*-----------------------------------------------------------------*/
+/* 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);
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* genCall - generates a call statement                            */
 /*-----------------------------------------------------------------*/
@@ -1890,34 +1986,21 @@ static void
 genCall (iCode * ic)
 {
   sym_link *dtype;
-  bool restoreBank = FALSE;
+//  bool restoreBank = FALSE;
   bool swapBanks = FALSE;
 
   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;
     }
 
@@ -1925,18 +2008,10 @@ genCall (iCode * ic)
      the same register bank then we need to save the
      destination registers on the stack */
   dtype = operandType (IC_LEFT (ic));
-  if (dtype && !IFFUNC_ISNAKED(dtype) &&
+  if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
-      IFFUNC_ISISR (currFunc->type))
+       !IFFUNC_ISISR (dtype))
   {
-      if (!ic->bankSaved) 
-      {
-           /* This is unexpected; the bank should have been saved in
-            * genFunction.
-            */
-          saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
-          restoreBank = TRUE;
-      }
       swapBanks = TRUE;  
   } 
     
@@ -1998,20 +2073,21 @@ genCall (iCode * ic)
   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
     unsaveRegisters (ic);
 
-  /* if register bank was saved then pop them */
-  if (restoreBank)
-    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
+//  /* 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 *dtype;
   symbol *rlbl = newiTempLabel (NULL);
-  bool restoreBank=FALSE;
+//  bool restoreBank=FALSE;
+  bool swapBanks = FALSE;
 
   D(emitcode(";", "genPCall"));
 
@@ -2019,15 +2095,18 @@ genPcall (iCode * ic)
   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 */
-  dtype = operandType (IC_LEFT (ic));
-  if (dtype && !FUNC_ISNAKED(dtype) &&
-      IFFUNC_ISISR (currFunc->type) &&
-      (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
-    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
-    restoreBank=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 */
@@ -2046,33 +2125,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 ||
@@ -2106,9 +2179,9 @@ genPcall (iCode * ic)
 
     }
 
-  /* if register bank was saved then unsave them */
-  if (restoreBank)
-    unsaveRBank (FUNC_REGBANK (dtype), 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 */
@@ -2171,6 +2244,7 @@ genFunction (iCode * ic)
   symbol *sym;
   sym_link *ftype;
   bool   switchedPSW = FALSE;
+  int calleesaves_saved_register = -1;
 
   _G.nRegsSaved = 0;
   /* create the function header */
@@ -2253,10 +2327,17 @@ genFunction (iCode * ic)
            }
          else
            {
+               
              /* this function has  a function call cannot
                 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
@@ -2367,6 +2448,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++;
                    }
@@ -2376,7 +2460,7 @@ genFunction (iCode * ic)
     }
 
   /* set the register bank to the desired value */
-  if ((FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
+  if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
    && !switchedPSW)
     {
       emitcode ("push", "psw");
@@ -2417,6 +2501,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");
@@ -2478,9 +2590,9 @@ genEndFunction (iCode * ic)
     }
 
   /* restore the register bank  */
-  if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
+  if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
   {
-    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
@@ -2521,6 +2633,12 @@ 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 to pop the
                 entire bank */
@@ -2568,7 +2686,6 @@ genEndFunction (iCode * ic)
        emitcode ("setb", "ea");
 
       /* if debug then send end of function */
-      /*  if (options.debug && currFunc)  */
       if (options.debug && currFunc)
        {
          _G.debugLine = 1;
@@ -2727,9 +2844,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;
        }
     }
@@ -2760,7 +2883,8 @@ genPlusIncr (iCode * ic)
   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))
     {
@@ -2788,15 +2912,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));
@@ -2804,13 +2928,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));
        }
@@ -2818,14 +2942,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));
        }
@@ -2996,6 +3120,8 @@ static void
 genPlus (iCode * ic)
 {
   int size, offset = 0;
+  char *add;
+  asmop *leftOp, *rightOp;
 
   /* special cases :- */
 
@@ -3058,29 +3184,32 @@ genPlus (iCode * ic)
 
   size = getDataSize (IC_RESULT (ic));
 
+  leftOp = AOP(IC_LEFT(ic));
+  rightOp = AOP(IC_RIGHT(ic));
+  add = "add";
+
   while (size--)
     {
-      if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
+      if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
        {
-         MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
-         if (offset == 0)
-           emitcode ("add", "a,%s",
-                     aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
-         else
-           emitcode ("addc", "a,%s",
-                     aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
+         emitcode("mov", "b,a");
+         MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
+         emitcode("xch", "a,b");
+         MOVA (aopGet (rightOp, offset, FALSE, TRUE));
+         emitcode (add, "a,b");
+       }
+      else if (aopGetUsesAcc (leftOp, offset))
+       {
+         MOVA (aopGet (leftOp, offset, FALSE, TRUE));
+         emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
        }
       else
        {
-         MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
-         if (offset == 0)
-           emitcode ("add", "a,%s",
-                     aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
-         else
-           emitcode ("addc", "a,%s",
-                     aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
+         MOVA (aopGet (rightOp, offset, FALSE, TRUE));
+         emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
        }
       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+      add = "addc";  /* further adds must propagate carry */
     }
 
   adjustArithmeticResult (ic);
@@ -3114,7 +3243,8 @@ genMinusDec (iCode * ic)
   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))
     {
@@ -3270,7 +3400,6 @@ static void
 genMinus (iCode * ic)
 {
   int size, offset = 0;
-  unsigned long lit = 0L;
 
   D(emitcode (";", "genMinus"));
 
@@ -3294,25 +3423,17 @@ genMinus (iCode * ic)
 
   size = getDataSize (IC_RESULT (ic));
 
-  if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
-    {
-      CLRC;
-    }
-  else
+  /* if literal, add a,#-lit, else normal subb */
+  if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
     {
+      unsigned long lit = 0L;
+
       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
       lit = -(long) lit;
-    }
 
-  /* if literal, add a,#-lit, else normal subb */
-  while (size--)
-    {
-      MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
-      if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
-       emitcode ("subb", "a,%s",
-                 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
-      else
+      while (size--)
        {
+         MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
          /* first add without previous c */
          if (!offset) {
            if (!size && lit==-1) {
@@ -3325,10 +3446,41 @@ genMinus (iCode * ic)
            emitcode ("addc", "a,#0x%02x",
                      (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
          }
+         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
        }
-      aopPut (AOP (IC_RESULT (ic)), "a", offset++);
     }
+  else
+    {
+      asmop *leftOp, *rightOp;
+
+      leftOp = AOP(IC_LEFT(ic));
+      rightOp = AOP(IC_RIGHT(ic));
 
+      while (size--)
+       {
+         if (aopGetUsesAcc(rightOp, offset)) {
+           wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
+           MOVA (aopGet(rightOp, offset, FALSE, TRUE));
+           if (offset > 0) {
+             emitcode( "cpl", "c");
+           } else {
+             emitcode( "setb", "c");
+           }
+           emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
+           emitcode("cpl", "a");
+         } else {
+           MOVA (aopGet (leftOp, offset, FALSE, FALSE));
+           if (offset == 0)
+             CLRC;
+           emitcode ("subb", "a,%s",
+                     aopGet(rightOp, offset, FALSE, TRUE));
+         }
+
+         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+       }
+    }
+  
+  
   adjustArithmeticResult (ic);
 
 release:
@@ -3391,6 +3543,7 @@ genMultOneByte (operand * left,
          SPEC_USIGN(operandType(right)))) {
     // just an unsigned 8*8=8/16 multiply
     //emitcode (";","unsigned");
+    // TODO: check for accumulator clash between left & right aops?
     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
     MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
     emitcode ("mul", "ab");
@@ -4297,7 +4450,7 @@ ifxForOp (operand * op, iCode * ic)
 /* hasInc - operand is incremented before any other use            */
 /*-----------------------------------------------------------------*/
 static iCode *
-hasInc (operand *op, iCode *ic)
+hasInc (operand *op, iCode *ic,int osize)
 {
   sym_link *type = operandType(op);
   sym_link *retype = getSpec (type);
@@ -4308,7 +4461,9 @@ hasInc (operand *op, iCode *ic)
   if (!IS_SYMOP(op)) return NULL;
 
   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
-  isize = getSize(type->next);
+  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) &&
@@ -4322,7 +4477,7 @@ hasInc (operand *op, iCode *ic)
       return NULL;
     }
     /* if GOTO or IFX */
-    if (lic->op == IFX || lic->op == GOTO) break;
+    if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
     lic = lic->next;
   }
   return NULL;
@@ -4845,7 +5000,7 @@ genOr (iCode * ic, iCode * ifx)
     {
       if (AOP_TYPE (right) == AOP_LIT)
        {
-         // c = bit & literal;
+         // c = bit | literal;
          if (lit)
            {
              // lit != 0 => result = 1
@@ -6336,7 +6491,8 @@ genLeftShiftLiteral (operand * left,
          genlshFour (result, left, shCount);
          break;
        default:
-         fprintf(stderr, "*** ack! mystery literal shift!\n");
+         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
+                 "*** ack! mystery literal shift!\n");
          break;
        }
     }
@@ -7485,7 +7641,7 @@ genPointerGet (iCode * ic, iCode *pi)
   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);
+         type = operandType (left);
          p_type = DCL_TYPE (type);
   }
   /* now that we have the pointer type we assign
@@ -8096,7 +8252,7 @@ genPointerSet (iCode * ic, iCode *pi)
   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);
+         type = operandType (result);
          p_type = DCL_TYPE (type);
   }
   /* now that we have the pointer type we assign
@@ -8120,6 +8276,10 @@ genPointerSet (iCode * ic, iCode *pi)
     case GPOINTER:
       genGenPointerSet (right, result, ic, pi);
       break;
+
+    default:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
+             "genPointerSet: illegal pointer type");
     }
 
 }
@@ -8418,7 +8578,6 @@ genCast (iCode * ic)
   aopOp (result, ic, FALSE);
 
   /* if the result is a bit */
-  // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
   if (IS_BITVAR(OP_SYMBOL(result)->type))
     {
       /* if the right size is a literal then
@@ -8480,8 +8639,6 @@ genCast (iCode * ic)
       /* pointer to generic pointer */
       if (IS_GENPTR (ctype))
        {
-         char *l = zero;
-
          if (IS_PTR (type))
            p_type = DCL_TYPE (type);
          else
@@ -8506,32 +8663,19 @@ genCast (iCode * ic)
              offset++;
            }
          /* the last byte depending on type */
-         switch (p_type)
            {
-           case IPOINTER:
-           case POINTER:
-             l = zero;
-             break;
-           case FPOINTER:
-             l = one;
-             break;
-           case CPOINTER:
-             l = "#0x02";
-             break;
-           case GPOINTER:
-             l = "0x03";
-             break;
-           case PPOINTER: // what the fck is this?
-             l = "#0x03";
-             break;
-
-           default:
-             /* this should never happen */
-             werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-                     "got unknown pointer type");
-             exit (1);
-           }
-         aopPut (AOP (result), l, GPTRSIZE - 1);
+               int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
+               char gpValStr[10];
+           
+               if (gpVal == -1)
+               {
+                   // pointerTypeToGPByte will have bitched.
+                   exit(1);
+               }
+           
+               sprintf(gpValStr, "#0x%d", gpVal);
+               aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
+           }       
          goto release;
        }
 
@@ -8564,7 +8708,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) || AOP_TYPE(right)==AOP_CRY)
+  if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
     {
       while (size--)
        aopPut (AOP (result), zero, offset++);
@@ -8677,100 +8821,44 @@ genDjnz (iCode * ic, iCode * ifx)
 static void
 genReceive (iCode * ic)
 {
+    int size = getSize (operandType (IC_RESULT (ic)));
+    int offset = 0;
   D(emitcode (";", "genReceive"));
 
-  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++;
+  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));
-    }
-
-  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
-}
-
-/*-----------------------------------------------------------------*/
-/* gen51AggregateAssign - copy complete array's or structures            */
-/*-----------------------------------------------------------------*/
-void gen51AggregateAssign(iCode *ic) {
-  operand *left=IC_LEFT(ic);
-  operand *right=IC_RIGHT(ic);
-  char *fromName=OP_SYMBOL(right)->rname;
-  char *toName=OP_SYMBOL(left)->rname;
-  int fromSize=getSize(OP_SYMBOL(right)->type);
-  int toSize=getSize(OP_SYMBOL(left)->type);
-  int count=toSize;
-
-  D(emitcode (";", "gen51AggregateAssign"));
-
-  if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
-      SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
-    // well, this code isn't used yet from anywhere else as for initialising
-    fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
-    exit (457);
-  }
-
-  if (fromSize!=toSize) {
-    fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
-            ic->filename, ic->lineno);
-    exit (821);
+      rb1off = ic->argreg;
+      while (size--) {
+         aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
+      }
   }
-
-#if 1
-  // use the generic memcpy() for now
-  emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
-  emitcode ("mov", "dptr,#_memcpy_PARM_2");
-  emitcode ("mov", "a,#%s", fromName);
-  emitcode ("movx", "@dptr,a");
-  emitcode ("inc", "dptr");
-  emitcode ("mov", "a,#(%s>>8)", fromName);
-  emitcode ("movx", "@dptr,a");
-  emitcode ("inc", "dptr");
-  emitcode ("mov", "a,#%02x;   only from cseg for now", 2);
-  emitcode ("movx", "@dptr,a");
-  emitcode ("mov", "dptr,#_memcpy_PARM_3");
-  emitcode ("mov", "a,#(%d>>0);        number of bytes", count);
-  emitcode ("movx", "@dptr,a");
-  emitcode ("inc", "dptr");
-  emitcode ("mov", "a,#(%d>>8)", count);
-  emitcode ("movx", "@dptr,a");
-  emitcode ("mov", "dptr,#%s", toName);
-  emitcode ("mov", "b,#%02x;   only to xseg for now", 1);
-  emitcode ("lcall", "_memcpy");
-#else
-  // more efficient, but will require the native_memcpy_cs2xs
-  emitcode ("mov", "r0,#%s", fromName);
-  emitcode ("mov", "r1,#(%s>>8)", fromName);
-  emitcode ("mov", "r2,#%s", toName);
-  emitcode ("mov", "r3,#(%s>>8)", toName);
-  emitcode ("mov", "r4,#%d", count);
-  emitcode ("mov", "r5,#(%d>>8)", count);
-  emitcode ("lcall", "_native_memcpy_cs2xs");
-#endif
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
@@ -8788,7 +8876,6 @@ gen51Code (iCode * lic)
   if (allocInfo)
     printAllocInfo (currFunc, codeOutFile);
   /* if debug information required */
-  /*     if (options.debug && currFunc) { */
   if (options.debug && currFunc)
     {
       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
@@ -8809,7 +8896,7 @@ gen51Code (iCode * lic)
   for (ic = lic; ic; ic = ic->next)
     {
 
-      if (cln != ic->lineno)
+      if (ic->lineno && cln != ic->lineno)
        {
          if (options.debug)
            {
@@ -8819,7 +8906,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
@@ -8979,12 +9067,12 @@ gen51Code (iCode * lic)
          break;
 
        case GET_VALUE_AT_ADDRESS:
-         genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
+         genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
          break;
 
        case '=':
          if (POINTER_SET (ic))
-           genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
+           genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
          else
            genAssign (ic);
          break;
@@ -9013,10 +9101,6 @@ gen51Code (iCode * lic)
          addSet (&_G.sendSet, ic);
          break;
 
-       case ARRAYINIT:
-         gen51AggregateAssign(ic);
-         break;
-
        default:
          ic = ic;
        }