Improved genFarFarAssign
[fw/sdcc] / src / ds390 / gen.c
index f85207e39089982a9250d5021ae581552967e8a6..11e5217fb3265f83b9cdfef8d18e8a23a18f5167 100644 (file)
@@ -48,6 +48,8 @@
 #endif
 #endif
 
+#define BETTER_LITERAL_SHIFT
+
 char *aopLiteral (value * val, int offset);
 
 /* this is the down and dirty file with all kinds of
@@ -98,6 +100,10 @@ static void saverbank (int, iCode *, bool);
 #define CLRC    emitcode("clr","c")
 #define SETC    emitcode("setb","c")
 
+// A scratch register which will be used to hold
+// result bytes from operands in far space via DPTR2.
+#define DP2_RESULT_REG "ap"
+
 static lineNode *lineHead = NULL;
 static lineNode *lineCurr = NULL;
 
@@ -233,7 +239,6 @@ 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");
@@ -307,7 +312,11 @@ _startLazyDPSEvaluation (void)
 {
   _currentDPS = 0;
   _desiredDPS = 0;
+#ifdef BETTER_LITERAL_SHIFT  
+  _lazyDPS++;
+#else
   _lazyDPS = 1;
+#endif  
 }
 
 /*-----------------------------------------------------------------*/
@@ -346,14 +355,21 @@ _flushLazyDPS (void)
 static void
 _endLazyDPSEvaluation (void)
 {
-  if (_currentDPS)
+#ifdef BETTER_LITERAL_SHIFT  
+  _lazyDPS--;
+#else
+  _lazyDPS = 0;
+#endif    
+  if (!_lazyDPS)
+  {
+    if (_currentDPS)
     {
       genSetDPTR (0);
       _flushLazyDPS ();
     }
-  _lazyDPS = 0;
-  _currentDPS = 0;
-  _desiredDPS = 0;
+    _currentDPS = 0;
+    _desiredDPS = 0;
+  }
 }
 
 
@@ -440,11 +456,9 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
 
       if (useDP2)
        {
-         /* genSetDPTR(1); */
          emitcode ("mov", "dpx1,#0x40");
          emitcode ("mov", "dph1,#0x00");
          emitcode ("mov", "dpl1, a");
-         /* genSetDPTR(0); */
        }
       else
        {
@@ -900,7 +914,7 @@ dealloc:
 /*------------------------------------------------------------------*/
 /* aopGet - for fetching value of the aop                           */
 /*                    */
-/* Set canClobberACC if you are aure it is OK to clobber the value  */
+/* Set canClobberACC if you are sure it is OK to clobber the value  */
 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
 /* just less efficient.               */
 /*------------------------------------------------------------------*/
@@ -959,7 +973,7 @@ aopGet (asmop * aop,
          genSetDPTR (1);
          if (!canClobberACC)
            {
-             emitcode ("xch", "a, ap");
+             emitcode ("xch", "a, %s", DP2_RESULT_REG);
            }
        }
 
@@ -993,8 +1007,8 @@ aopGet (asmop * aop,
          genSetDPTR (0);
          if (!canClobberACC)
            {
-             emitcode ("xch", "a, ap");
-             return "ap";
+             emitcode ("xch", "a, %s", DP2_RESULT_REG);
+             return DP2_RESULT_REG;
            }
        }
       return (dname ? "acc" : "a");
@@ -1468,8 +1482,9 @@ outBitC (operand * result)
 static void
 toBoolean (operand * oper)
 {
-  int size = AOP_SIZE (oper) - 1;
-  int offset = 1;
+  int  size = AOP_SIZE (oper) - 1;
+  int  offset = 1;
+  bool usedB = FALSE;
 
   /* The generic part of a generic pointer should
    * not participate in it's truth value.
@@ -1484,8 +1499,9 @@ toBoolean (operand * oper)
     }
 
   _startLazyDPSEvaluation ();
-  if (AOP_NEEDSACC (oper))
+  if (AOP_NEEDSACC (oper) && size)
     {
+      usedB = TRUE;
       emitcode ("push", "b");
       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
     }
@@ -1495,7 +1511,7 @@ toBoolean (operand * oper)
     }
   while (size--)
     {
-      if (AOP_NEEDSACC (oper))
+      if (usedB)
        {
          emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
        }
@@ -1506,7 +1522,7 @@ toBoolean (operand * oper)
     }
   _endLazyDPSEvaluation ();
 
-  if (AOP_NEEDSACC (oper))
+  if (usedB)
     {
       emitcode ("mov", "a,b");
       emitcode ("pop", "b");
@@ -2201,8 +2217,6 @@ genCall (iCode * ic)
          int size = getSize (operandType (IC_RESULT (ic)));
 
          /* Special case for 1 or 2 byte return in far space. */
-         emitcode (";", "Kevin function call abuse #1");
-
          MOVA (fReturn[0]);
          if (size > 1)
            {
@@ -2502,7 +2516,7 @@ genFunction (iCode * ic)
              emitcode ("push", "dpl1");
              emitcode ("push", "dph1");
              emitcode ("push", "dpx1");
-             emitcode ("push", "ap");
+             emitcode ("push",  DP2_RESULT_REG);
            }
        }
       /* if this isr has no bank i.e. is going to
@@ -2710,7 +2724,7 @@ genEndFunction (iCode * ic)
        {
          if (options.stack10bit)
            {
-             emitcode ("pop", "ap");
+             emitcode ("pop", DP2_RESULT_REG);
              emitcode ("pop", "dpx1");
              emitcode ("pop", "dph1");
              emitcode ("pop", "dpl1");
@@ -3127,6 +3141,8 @@ adjustArithmeticResult (iCode * ic)
     }
 }
 
+// Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
+// (because all three operands are in far space).
 #define AOP_OP_3(ic) \
     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
@@ -3140,6 +3156,10 @@ adjustArithmeticResult (iCode * ic)
                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
     }
 
+// Macro to aopOp all three operands of an ic. If this cannot be done, 
+// the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
+// will be set TRUE. The caller must then handle the case specially, noting
+// that the IC_RESULT operand is not aopOp'd.
 #define AOP_OP_3_NOFATAL(ic, rc) \
     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
@@ -3163,15 +3183,48 @@ adjustArithmeticResult (iCode * ic)
        } \
     }
 
+// aopOp the left & right operands of an ic.
 #define AOP_OP_2(ic) \
     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
 
+// convienience macro.
 #define AOP_SET_LOCALS(ic) \
     left = IC_LEFT(ic); \
     right = IC_RIGHT(ic); \
     result = IC_RESULT(ic);
 
+
+// Given an integer value of pushedSize bytes on the stack,
+// adjust it to be resultSize bytes, either by discarding
+// the most significant bytes or by zero-padding.
+//
+// On exit from this macro, pushedSize will have been adjusted to
+// equal resultSize, and ACC may be trashed.
+#define ADJUST_PUSHED_RESULT(pushedSize, resultSize)           \
+      /* If the pushed data is bigger than the result,         \
+       * simply discard unused bytes. Icky, but works.         \
+       */                                                      \
+      while (pushedSize > resultSize)                          \
+      {                                                                \
+         D (emitcode (";", "discarding unused result byte."););\
+         emitcode ("pop", "acc");                              \
+         pushedSize--;                                         \
+      }                                                                \
+      if (pushedSize < resultSize)                             \
+      {                                                                \
+         emitcode ("clr", "a");                                \
+         /* Conversly, we haven't pushed enough here.          \
+          * just zero-pad, and all is well.                    \
+          */                                                   \
+         while (pushedSize < resultSize)                       \
+         {                                                     \
+             emitcode("push", "acc");                          \
+             pushedSize++;                                     \
+         }                                                     \
+      }                                                                \
+      assert(pushedSize == resultSize);
+
 /*-----------------------------------------------------------------*/
 /* genPlus - generates code for addition                           */
 /*-----------------------------------------------------------------*/
@@ -3182,16 +3235,14 @@ genPlus (iCode * ic)
   bool pushResult = FALSE;
   int rSize;
 
-  D (emitcode (";", "genPlus ");
-    );
+  D (emitcode (";", "genPlus "););
 
   /* special cases :- */
 
   AOP_OP_3_NOFATAL (ic, pushResult);
   if (pushResult)
     {
-      D (emitcode (";", "genPlus: must push result: 3 ops in far space");
-       );
+      D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
     }
 
   if (!pushResult)
@@ -3298,38 +3349,13 @@ genPlus (iCode * ic)
       size = getDataSize (IC_LEFT (ic));
       rSize = getDataSize (IC_RESULT (ic));
 
-      /* If the pushed data is bigger than the result,
-       * simply discard unused bytes. Icky, but works.
-       *
-       * Should we throw a warning here? We're losing data...
-       */
-      while (size > rSize)
-       {
-         D (emitcode (";", "discarding unused result byte.");
-           );
-         emitcode ("pop", "acc");
-         size--;
-         offset--;
-       }
-      if (size < rSize)
-       {
-         emitcode ("clr", "a");
-         /* Conversly, we haven't pushed enough here.
-          * just zero-pad, and all is well.
-          */
-         while (size < rSize)
-           {
-             emitcode ("push", "acc");
-             size++;
-             offset++;
-           }
-       }
+      ADJUST_PUSHED_RESULT(size, rSize);
 
       _startLazyDPSEvaluation ();
       while (size--)
        {
          emitcode ("pop", "acc");
-         aopPut (AOP (IC_RESULT (ic)), "a", --offset);
+         aopPut (AOP (IC_RESULT (ic)), "a", size);
        }
       _endLazyDPSEvaluation ();
     }
@@ -3481,16 +3507,24 @@ addSign (operand * result, int offset, int sign)
   int size = (getDataSize (result) - offset);
   if (size > 0)
     {
+      _startLazyDPSEvaluation();
       if (sign)
        {
          emitcode ("rlc", "a");
          emitcode ("subb", "a,acc");
          while (size--)
+         {
            aopPut (AOP (result), "a", offset++);
+         }
        }
       else
+      {
        while (size--)
+       {
          aopPut (AOP (result), zero, offset++);
+       }
+      }
+      _endLazyDPSEvaluation();
     }
 }
 
@@ -3502,8 +3536,7 @@ genMinusBits (iCode * ic)
 {
   symbol *lbl = newiTempLabel (NULL);
 
-  D (emitcode (";", "genMinusBits ");
-    );
+  D (emitcode (";", "genMinusBits "););
 
   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
     {
@@ -3536,8 +3569,7 @@ genMinus (iCode * ic)
   unsigned long lit = 0L;
   bool pushResult = FALSE;
 
-  D (emitcode (";", "genMinus ");
-    );
+  D (emitcode (";", "genMinus "););
 
   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
@@ -3617,37 +3649,15 @@ genMinus (iCode * ic)
       size = getDataSize (IC_LEFT (ic));
       rSize = getDataSize (IC_RESULT (ic));
 
-      /* If the pushed data is bigger than the result,
-       * simply discard unused bytes. Icky, but works.
-       *
-       * Should we throw a warning here? We're losing data...
-       */
-      while (size > getDataSize (IC_RESULT (ic)))
-       {
-         emitcode (";", "discarding unused result byte.");
-         emitcode ("pop", "acc");
-         size--;
-         offset--;
-       }
-      if (size < rSize)
-       {
-         emitcode ("clr", "a");
-         /* Conversly, we haven't pushed enough here.
-          * just zero-pad, and all is well.
-          */
-         while (size < rSize)
-           {
-             emitcode ("push", "acc");
-             size++;
-             offset++;
-           }
-       }
+      ADJUST_PUSHED_RESULT(size, rSize);
 
+      _startLazyDPSEvaluation ();
       while (size--)
        {
          emitcode ("pop", "acc");
-         aopPut (AOP (IC_RESULT (ic)), "a", --offset);
+         aopPut (AOP (IC_RESULT (ic)), "a", size);
        }
+      _endLazyDPSEvaluation ();
     }
 
   adjustArithmeticResult (ic);
@@ -3787,8 +3797,7 @@ genMult (iCode * ic)
   operand *right = IC_RIGHT (ic);
   operand *result = IC_RESULT (ic);
 
-  D (emitcode (";", "genMult ");
-    );
+  D (emitcode (";", "genMult "););
 
   /* assign the amsops */
   AOP_OP_3 (ic);
@@ -4342,8 +4351,7 @@ genCmpLt (iCode * ic, iCode * ifx)
   sym_link *letype, *retype;
   int sign;
 
-  D (emitcode (";", "genCmpLt ");
-    );
+  D (emitcode (";", "genCmpLt "););
 
   left = IC_LEFT (ic);
   right = IC_RIGHT (ic);
@@ -4678,13 +4686,12 @@ genAndOp (iCode * ic)
   operand *left, *right, *result;
   symbol *tlbl;
 
-  D (emitcode (";", "genAndOp ");
-    );
+  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 */
-  AOP_OP_3 (ic);
+  AOP_OP_2 (ic);
   AOP_SET_LOCALS (ic);
 
   /* if both are bit variables */
@@ -4693,6 +4700,10 @@ genAndOp (iCode * ic)
     {
       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
+      freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+      freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  
+      aopOp (result,ic,FALSE, FALSE);
       outBitC (result);
     }
   else
@@ -4702,12 +4713,13 @@ genAndOp (iCode * ic)
       emitcode ("jz", "%05d$", tlbl->key + 100);
       toBoolean (right);
       emitcode ("", "%05d$:", tlbl->key + 100);
+      freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+      freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  
+      aopOp (result,ic,FALSE, FALSE);
       outBitAcc (result);
     }
-
-  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
-  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
-  freeAsmop (result, NULL, ic, TRUE);
+    freeAsmop (result, NULL, ic, TRUE);
 }
 
 
@@ -4720,13 +4732,12 @@ genOrOp (iCode * ic)
   operand *left, *right, *result;
   symbol *tlbl;
 
-  D (emitcode (";", "genOrOp ");
-    );
+  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 */
-  AOP_OP_3 (ic);
+  AOP_OP_2 (ic);
   AOP_SET_LOCALS (ic);
 
   /* if both are bit variables */
@@ -4735,6 +4746,11 @@ genOrOp (iCode * ic)
     {
       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
+      freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+      freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  
+      aopOp (result,ic,FALSE, FALSE);
+      
       outBitC (result);
     }
   else
@@ -4744,11 +4760,14 @@ genOrOp (iCode * ic)
       emitcode ("jnz", "%05d$", tlbl->key + 100);
       toBoolean (right);
       emitcode ("", "%05d$:", tlbl->key + 100);
+      freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+      freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  
+      aopOp (result,ic,FALSE, FALSE);
+      
       outBitAcc (result);
     }
 
-  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
-  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
   freeAsmop (result, NULL, ic, TRUE);
 }
 
@@ -4819,6 +4838,52 @@ jmpTrueOrFalse (iCode * ic, symbol * tlbl)
   ic->generated = 1;
 }
 
+// Generate code to perform a bit-wise logic operation
+// on two operands in far space (assumed to already have been 
+// aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
+// in far space. This requires pushing the result on the stack
+// then popping it into the result.
+static void
+genFarFarLogicOp(iCode *ic, char *logicOp)
+{
+      int size, resultSize, compSize;
+      int offset = 0;
+      
+      D(emitcode(";", "%s special case for 3 far operands.", logicOp););
+      compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
+                 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
+      
+      _startLazyDPSEvaluation();
+      for (size = compSize; (size--); offset++)
+      {
+         MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
+         emitcode ("mov", "%s, acc", DP2_RESULT_REG);
+         MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
+         
+         emitcode (logicOp, "a,%s", DP2_RESULT_REG);
+         emitcode ("push", "acc");
+      }
+      _endLazyDPSEvaluation();
+     
+      freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
+      freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
+      aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
+     
+      resultSize = AOP_SIZE(IC_RESULT(ic));
+
+      ADJUST_PUSHED_RESULT(compSize, resultSize);
+
+      _startLazyDPSEvaluation();
+      while (compSize--)
+      {
+         emitcode ("pop", "acc");
+         aopPut (AOP (IC_RESULT (ic)), "a", compSize);
+      }
+      _endLazyDPSEvaluation();
+      freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
+}
+
+
 /*-----------------------------------------------------------------*/
 /* genAnd  - code for and                                          */
 /*-----------------------------------------------------------------*/
@@ -4830,13 +4895,19 @@ genAnd (iCode * ic, iCode * ifx)
   unsigned long lit = 0L;
   int bytelit = 0;
   char buffer[10];
+  bool pushResult;
 
-  D (emitcode (";", "genAnd ");
-    );
+  D (emitcode (";", "genAnd "););
 
-  AOP_OP_3 (ic);
+  AOP_OP_3_NOFATAL (ic, pushResult);
   AOP_SET_LOCALS (ic);
 
+  if (pushResult)
+  {
+      genFarFarLogicOp(ic, "anl");
+      return;
+  }  
+
 #ifdef DEBUG_TYPE
   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
            AOP_TYPE (result),
@@ -5126,6 +5197,7 @@ release:
   freeAsmop (result, NULL, ic, TRUE);
 }
 
+
 /*-----------------------------------------------------------------*/
 /* genOr  - code for or                                            */
 /*-----------------------------------------------------------------*/
@@ -5135,13 +5207,20 @@ genOr (iCode * ic, iCode * ifx)
   operand *left, *right, *result;
   int size, offset = 0;
   unsigned long lit = 0L;
+  bool            pushResult;
 
-  D (emitcode (";", "genOr ");
-    );
+  D (emitcode (";", "genOr "););
 
-  AOP_OP_3 (ic);
+  AOP_OP_3_NOFATAL (ic, pushResult);
   AOP_SET_LOCALS (ic);
 
+  if (pushResult)
+  {
+      genFarFarLogicOp(ic, "orl");
+      return;
+  }
+
+
 #ifdef DEBUG_TYPE
   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
            AOP_TYPE (result),
@@ -5424,13 +5503,19 @@ genXor (iCode * ic, iCode * ifx)
   operand *left, *right, *result;
   int size, offset = 0;
   unsigned long lit = 0L;
+  bool pushResult;
 
-  D (emitcode (";", "genXor ");
-    );
+  D (emitcode (";", "genXor "););
 
-  AOP_OP_3 (ic);
+  AOP_OP_3_NOFATAL (ic, pushResult);
   AOP_SET_LOCALS (ic);
 
+  if (pushResult)
+  {
+      genFarFarLogicOp(ic, "xrl");
+      return;
+  }  
+
 #ifdef DEBUG_TYPE
   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
            AOP_TYPE (result),
@@ -5952,8 +6037,7 @@ AccRsh (int shCount)
     }
 }
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* AccSRsh - signed right shift accumulator by known count                 */
 /*-----------------------------------------------------------------*/
@@ -5991,8 +6075,7 @@ AccSRsh (int shCount)
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* shiftR1Left2Result - shift right one byte from left to result   */
 /*-----------------------------------------------------------------*/
@@ -6011,8 +6094,7 @@ shiftR1Left2Result (operand * left, int offl,
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* shiftL1Left2Result - shift left one byte from left to result    */
 /*-----------------------------------------------------------------*/
@@ -6020,17 +6102,14 @@ static void
 shiftL1Left2Result (operand * left, int offl,
                    operand * result, int offr, int shCount)
 {
-  char *l;
-  l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
-  MOVA (l);
+  MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
   /* shift left accumulator */
   AccLsh (shCount);
   aopPut (AOP (result), "a", offr);
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* movLeft2Result - move byte from left to result                  */
 /*-----------------------------------------------------------------*/
@@ -6040,18 +6119,20 @@ movLeft2Result (operand * left, int offl,
 {
   char *l;
   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
-    {
-      l = aopGet (AOP (left), offl, FALSE, FALSE, FALSE);
+  {
+      l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
 
       if (*l == '@' && (IS_AOP_PREG (result)))
-       {
+      {
          emitcode ("mov", "a,%s", l);
          aopPut (AOP (result), "a", offr);
-       }
+      }
       else
-       {
+      {
          if (!sign)
+         {
            aopPut (AOP (result), l, offr);
+         }
          else
            {
              /* MSB sign in acc.7 ! */
@@ -6061,13 +6142,12 @@ movLeft2Result (operand * left, int offl,
                  aopPut (AOP (result), "a", offr);
                }
            }
-       }
-    }
+      }
+  }
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
 /*-----------------------------------------------------------------*/
@@ -6081,7 +6161,7 @@ AccAXRrl1 (char *x)
 }
 #endif
 
-#if 0
+#ifdef BETTER_LITERAL_SHIFT
 //REMOVE ME!!!
 /*-----------------------------------------------------------------*/
 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
@@ -6096,8 +6176,7 @@ AccAXLrl1 (char *x)
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
 /*-----------------------------------------------------------------*/
@@ -6111,8 +6190,7 @@ AccAXLsh1 (char *x)
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* AccAXLsh - left shift a:x by known count (0..7)                 */
 /*-----------------------------------------------------------------*/
@@ -6196,7 +6274,7 @@ AccAXLsh (char *x, int shCount)
 }
 #endif
 
-#if 0
+#ifdef BETTER_LITERAL_SHIFT
 //REMOVE ME!!!
 /*-----------------------------------------------------------------*/
 /* AccAXRsh - right shift a:x known count (0..7)                   */
@@ -6279,7 +6357,7 @@ AccAXRsh (char *x, int shCount)
 }
 #endif
 
-#if 0
+#ifdef BETTER_LITERAL_SHIFT
 //REMOVE ME!!!
 /*-----------------------------------------------------------------*/
 /* AccAXRshS - right shift signed a:x known count (0..7)           */
@@ -6382,8 +6460,93 @@ AccAXRshS (char *x, int shCount)
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
+static void
+_loadLeftIntoAx(char   **lsb, 
+               operand *left, 
+               operand *result,
+               int     offl,
+               int     offr)
+{
+  // Get the initial value from left into a pair of registers.
+  // MSB must be in A, LSB can be any register.
+  //
+  // If the result is held in registers, it is an optimization
+  // if the LSB can be held in the register which will hold the,
+  // result LSB since this saves us from having to copy it into
+  // the result following AccAXLsh.
+  //
+  // If the result is addressed indirectly, this is not a gain.
+  if (AOP_NEEDSACC(result))
+  {
+       char *leftByte;
+       
+       _startLazyDPSEvaluation();
+       if (AOP_TYPE(left) == AOP_DPTR2)
+       {
+           // Get MSB in A.
+                  MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
+                  // get LSB in DP2_RESULT_REG.
+                  leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
+                  assert(!strcmp(leftByte, DP2_RESULT_REG));
+       }
+       else
+       {
+           // get LSB into DP2_RESULT_REG
+                  leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
+           if (strcmp(leftByte, DP2_RESULT_REG))
+           {
+               emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
+                  }
+                  // And MSB in A.
+                  leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
+                  assert(strcmp(leftByte, DP2_RESULT_REG));
+                  MOVA(leftByte);
+       }
+       _endLazyDPSEvaluation();
+       *lsb = DP2_RESULT_REG;
+  }
+  else
+  {
+      if (sameRegs (AOP (result), AOP (left)) &&
+       ((offl + MSB16) == offr))
+      {
+         /* don't crash result[offr] */
+         MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
+         emitcode ("xch", "a,%s", 
+                   aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
+      }
+      else
+      {
+         movLeft2Result (left, offl, result, offr, 0);
+         MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
+      }
+      *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
+      assert(strcmp(*lsb,"a"));      
+  }
+}
+
+static void
+_storeAxResults(char   *lsb,
+               operand *result,
+               int     offr)
+{
+  _startLazyDPSEvaluation();
+  if (AOP_NEEDSACC(result))
+  {
+      /* We have to explicitly update the result LSB.
+       */
+      emitcode("xch","a,%s", lsb);
+      aopPut(AOP(result), "a", offr);
+      emitcode("mov","a,%s", lsb);
+  }
+  if (getDataSize (result) > 1)
+  {
+      aopPut (AOP (result), "a", offr + MSB16);
+  }
+  _endLazyDPSEvaluation();
+}
+
 /*-----------------------------------------------------------------*/
 /* shiftL2Left2Result - shift left two bytes from left to result   */
 /*-----------------------------------------------------------------*/
@@ -6391,26 +6554,17 @@ static void
 shiftL2Left2Result (operand * left, int offl,
                    operand * result, int offr, int shCount)
 {
-  if (sameRegs (AOP (result), AOP (left)) &&
-      ((offl + MSB16) == offr))
-    {
-      /* don't crash result[offr] */
-      MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
-      emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
-    }
-  else
-    {
-      movLeft2Result (left, offl, result, offr, 0);
-      MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
-    }
-  /* ax << shCount (x = lsb(result)) */
-  AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
-  aopPut (AOP (result), "a", offr + MSB16);
+  char *lsb;
+
+  _loadLeftIntoAx(&lsb, left, result, offl, offr);
+  
+  AccAXLsh (lsb, shCount);
+  
+  _storeAxResults(lsb, result, offr);
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* shiftR2Left2Result - shift right two bytes from left to result  */
 /*-----------------------------------------------------------------*/
@@ -6419,25 +6573,21 @@ shiftR2Left2Result (operand * left, int offl,
                    operand * result, int offr,
                    int shCount, int sign)
 {
-  if (sameRegs (AOP (result), AOP (left)) &&
-      ((offl + MSB16) == offr))
-    {
-      /* don't crash result[offr] */
-      MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
-      emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE, FALSE));
-    }
-  else
-    {
-      movLeft2Result (left, offl, result, offr, 0);
-      MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
-    }
+  char *lsb;
+  
+  _loadLeftIntoAx(&lsb, left, result, offl, offr);
+  
   /* a:x >> shCount (x = lsb(result)) */
   if (sign)
-    AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
+  {
+    AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
+  }
   else
-    AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE, FALSE), shCount);
-  if (getDataSize (result) > 1)
-    aopPut (AOP (result), "a", offr + MSB16);
+  {
+    AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
+  }
+  
+  _storeAxResults(lsb, result, offr);
 }
 #endif
 
@@ -6479,22 +6629,19 @@ shiftRLeftOrResult (operand * left, int offl,
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* genlshOne - left shift a one byte quantity by known count       */
 /*-----------------------------------------------------------------*/
 static void
 genlshOne (operand * result, operand * left, int shCount)
 {
-  D (emitcode (";", "genlshOne ");
-    );
+  D (emitcode (";", "genlshOne "););
   shiftL1Left2Result (left, LSB, result, LSB, shCount);
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* genlshTwo - left shift two bytes by known amount != 0           */
 /*-----------------------------------------------------------------*/
@@ -6503,33 +6650,50 @@ genlshTwo (operand * result, operand * left, int shCount)
 {
   int size;
 
-  D (emitcode (";", "genlshTwo ");
-    );
+  D (emitcode (";", "genlshTwo "););
 
   size = getDataSize (result);
 
   /* if shCount >= 8 */
   if (shCount >= 8)
-    {
+  {
       shCount -= 8;
 
+      _startLazyDPSEvaluation();
+
       if (size > 1)
        {
          if (shCount)
+         {
+           _endLazyDPSEvaluation();
            shiftL1Left2Result (left, LSB, result, MSB16, shCount);
+           aopPut (AOP (result), zero, LSB);       
+         }
          else
+         {
            movLeft2Result (left, LSB, result, MSB16, 0);
+           aopPut (AOP (result), zero, LSB);
+           _endLazyDPSEvaluation();
+         }
        }
-      aopPut (AOP (result), zero, LSB);
-    }
+       else
+       {
+         aopPut (AOP (result), zero, LSB);
+         _endLazyDPSEvaluation();
+       }
+  }
 
   /*  1 <= shCount <= 7 */
   else
     {
       if (size == 1)
+      {
        shiftL1Left2Result (left, LSB, result, LSB, shCount);
+      }
       else
+      {
        shiftL2Left2Result (left, LSB, result, LSB, shCount);
+      }
     }
 }
 #endif
@@ -6705,12 +6869,11 @@ genlshFour (operand * result, operand * left, int shCount)
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* genLeftShiftLiteral - left shifting by known count              */
 /*-----------------------------------------------------------------*/
-static void
+static bool
 genLeftShiftLiteral (operand * left,
                     operand * right,
                     operand * result,
@@ -6719,16 +6882,44 @@ genLeftShiftLiteral (operand * left,
   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
   int size;
 
-  D (emitcode (";", "genLeftShiftLiteral (%d)", shCount);
-    );
+  size = getSize (operandType (result));
 
-  freeAsmop (right, NULL, ic, TRUE);
+  D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
 
-  aopOp (left, ic, FALSE, FALSE);
-  aopOp (result, ic, FALSE, TRUE);
+  /* We only handle certain easy cases so far. */
+  if ((shCount != 0)
+   && (shCount < (size * 8))
+   && (size != 1)
+   && (size != 2))
+  {
+      D(emitcode (";", "genLeftShiftLiteral wimping out"););   
+      return FALSE;
+  }
 
-  size = getSize (operandType (result));
+  freeAsmop (right, NULL, ic, TRUE);
+
+  aopOp(left, ic, FALSE, FALSE);
+  aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
 
+#if 1 // debug spew
+  if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
+  {
+       emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
+       if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
+       {
+          emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
+       }
+  }
+  if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
+  {
+       emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
+       if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
+       {
+          emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
+       }       
+  }  
+#endif
+  
 #if VIEW_SIZE
   emitcode ("; shift left ", "result %d, left %d", size,
            AOP_SIZE (left));
@@ -6736,18 +6927,25 @@ genLeftShiftLiteral (operand * left,
 
   /* I suppose that the left size >= result size */
   if (shCount == 0)
-    {
-      while (size--)
+  {
+       _startLazyDPSEvaluation();
+       while (size--)
        {
          movLeft2Result (left, size, result, size, 0);
        }
-    }
-
+       _endLazyDPSEvaluation();
+  }
   else if (shCount >= (size * 8))
+  {
+    _startLazyDPSEvaluation();
     while (size--)
+    {
       aopPut (AOP (result), zero, size);
+    }
+    _endLazyDPSEvaluation();
+  }
   else
-    {
+  {
       switch (size)
        {
        case 1:
@@ -6755,17 +6953,21 @@ genLeftShiftLiteral (operand * left,
          break;
 
        case 2:
-       case 3:         /* bug: this is for generic pointers, I bet. */
          genlshTwo (result, left, shCount);
          break;
-
+#if 0
        case 4:
          genlshFour (result, left, shCount);
          break;
+#endif
+       default:
+         fprintf(stderr, "*** ack! mystery literal shift!\n");   
+         break;
        }
     }
   freeAsmop (left, NULL, ic, TRUE);
   freeAsmop (result, NULL, ic, TRUE);
+  return TRUE;
 }
 #endif
 
@@ -6780,8 +6982,7 @@ genLeftShift (iCode * ic)
   char *l;
   symbol *tlbl, *tlbl1;
 
-  D (emitcode (";", "genLeftShift ");
-    );
+  D (emitcode (";", "genLeftShift "););
 
   right = IC_RIGHT (ic);
   left = IC_LEFT (ic);
@@ -6789,13 +6990,16 @@ genLeftShift (iCode * ic)
 
   aopOp (right, ic, FALSE, FALSE);
 
-#if 0
+
+#ifdef BETTER_LITERAL_SHIFT
   /* if the shift count is known then do it
      as efficiently as possible */
   if (AOP_TYPE (right) == AOP_LIT)
     {
-      genLeftShiftLiteral (left, right, result, ic);
-      return;
+      if (genLeftShiftLiteral (left, right, result, ic))
+      {
+       return;
+      }
     }
 #endif
 
@@ -6805,8 +7009,20 @@ genLeftShift (iCode * ic)
      more that 32 bits make no sense anyway, ( the
      largest size of an object can be only 32 bits ) */
 
-  emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
-  emitcode ("inc", "b");
+  if (AOP_TYPE (right) == AOP_LIT)
+  {
+      /* Really should be handled by genLeftShiftLiteral,
+       * but since I'm too lazy to fix that today, at least we can make
+       * some small improvement.
+       */
+       emitcode("mov", "b,#0x%02x",
+                       ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
+  }
+  else
+  {
+       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
+       emitcode ("inc", "b");
+  }
   freeAsmop (right, NULL, ic, TRUE);
   aopOp (left, ic, FALSE, FALSE);
   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
@@ -6883,8 +7099,7 @@ release:
   freeAsmop (result, NULL, ic, TRUE);
 }
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* genrshOne - right shift a one byte quantity by known count      */
 /*-----------------------------------------------------------------*/
@@ -6892,14 +7107,12 @@ static void
 genrshOne (operand * result, operand * left,
           int shCount, int sign)
 {
-  D (emitcode (";", "genrshOne");
-    );
+  D (emitcode (";", "genrshOne"););
   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* genrshTwo - right shift two bytes by known amount != 0          */
 /*-----------------------------------------------------------------*/
@@ -6907,24 +7120,31 @@ static void
 genrshTwo (operand * result, operand * left,
           int shCount, int sign)
 {
-  D (emitcode (";", "genrshTwo");
-    );
+  D (emitcode (";", "genrshTwo"););
 
   /* if shCount >= 8 */
   if (shCount >= 8)
     {
       shCount -= 8;
+      _startLazyDPSEvaluation();
       if (shCount)
+      {
        shiftR1Left2Result (left, MSB16, result, LSB,
                            shCount, sign);
+      }                            
       else
+      {
        movLeft2Result (left, MSB16, result, LSB, sign);
+      }
       addSign (result, MSB16, sign);
+      _endLazyDPSEvaluation();
     }
 
   /*  1 <= shCount <= 7 */
   else
+  {
     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
+  }
 }
 #endif
 
@@ -7039,12 +7259,11 @@ genrshFour (operand * result, operand * left,
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* genRightShiftLiteral - right shifting by known count            */
 /*-----------------------------------------------------------------*/
-static void
+static bool
 genRightShiftLiteral (operand * left,
                      operand * right,
                      operand * result,
@@ -7054,8 +7273,19 @@ genRightShiftLiteral (operand * left,
   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
   int size;
 
-  D (emitcode (";", "genRightShiftLiteral");
-    );
+  size = getSize (operandType (result));
+
+  D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
+
+  /* We only handle certain easy cases so far. */
+  if ((shCount != 0)
+   && (shCount < (size * 8))
+   && (size != 1)
+   && (size != 2))
+  {
+      D(emitcode (";", "genRightShiftLiteral wimping out"););  
+      return FALSE;
+  }
 
   freeAsmop (right, NULL, ic, TRUE);
 
@@ -7067,22 +7297,26 @@ genRightShiftLiteral (operand * left,
            AOP_SIZE (left));
 #endif
 
-  size = getDataSize (left);
   /* test the LEFT size !!! */
 
   /* I suppose that the left size >= result size */
   if (shCount == 0)
-    {
+  {
       size = getDataSize (result);
+      _startLazyDPSEvaluation();
       while (size--)
+      {
        movLeft2Result (left, size, result, size, 0);
-    }
-
+      }
+      _endLazyDPSEvaluation();
+  }
   else if (shCount >= (size * 8))
     {
       if (sign)
+      {
        /* get sign in acc.7 */
        MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
+      }
       addSign (result, LSB, sign);
     }
   else
@@ -7096,10 +7330,11 @@ genRightShiftLiteral (operand * left,
        case 2:
          genrshTwo (result, left, shCount, sign);
          break;
-
+#if 0
        case 4:
          genrshFour (result, left, shCount, sign);
          break;
+#endif   
        default:
          break;
        }
@@ -7107,6 +7342,7 @@ genRightShiftLiteral (operand * left,
       freeAsmop (left, NULL, ic, TRUE);
       freeAsmop (result, NULL, ic, TRUE);
     }
+    return TRUE;
 }
 #endif
 
@@ -7121,8 +7357,7 @@ genSignedRightShift (iCode * ic)
   char *l;
   symbol *tlbl, *tlbl1;
 
-  D (emitcode (";", "genSignedRightShift ");
-    );
+  D (emitcode (";", "genSignedRightShift "););
 
   /* we do it the hard way put the shift count in b
      and loop thru preserving the sign */
@@ -7133,11 +7368,13 @@ genSignedRightShift (iCode * ic)
 
   aopOp (right, ic, FALSE, FALSE);
 
-#if 0
+#ifdef BETTER_LITERAL_SHIFT
   if (AOP_TYPE (right) == AOP_LIT)
     {
-      genRightShiftLiteral (left, right, result, ic, 1);
-      return;
+      if (genRightShiftLiteral (left, right, result, ic, 1))
+      {
+       return;
+      }
     }
 #endif
   /* shift count is unknown then we have to form
@@ -7146,8 +7383,20 @@ genSignedRightShift (iCode * ic)
      more that 32 bits make no sense anyway, ( the
      largest size of an object can be only 32 bits ) */
 
-  emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
-  emitcode ("inc", "b");
+  if (AOP_TYPE (right) == AOP_LIT)
+  {
+      /* Really should be handled by genRightShiftLiteral,
+       * but since I'm too lazy to fix that today, at least we can make
+       * some small improvement.
+       */
+       emitcode("mov", "b,#0x%02x",
+                       ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
+  }
+  else
+  {
+       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
+       emitcode ("inc", "b");
+  }
   freeAsmop (right, NULL, ic, TRUE);
   aopOp (left, ic, FALSE, FALSE);
   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
@@ -7235,8 +7484,7 @@ genRightShift (iCode * ic)
   char *l;
   symbol *tlbl, *tlbl1;
 
-  D (emitcode (";", "genRightShift ");
-    );
+  D (emitcode (";", "genRightShift "););
 
   /* if signed then we do it the hard way preserve the
      sign bit moving it inwards */
@@ -7261,13 +7509,15 @@ genRightShift (iCode * ic)
 
   aopOp (right, ic, FALSE, FALSE);
 
-#if 0
+#ifdef BETTER_LITERAL_SHIFT
   /* if the shift count is known then do it
      as efficiently as possible */
   if (AOP_TYPE (right) == AOP_LIT)
     {
-      genRightShiftLiteral (left, right, result, ic, 0);
-      return;
+      if (genRightShiftLiteral (left, right, result, ic, 0))
+      {
+       return;
+      }
     }
 #endif
 
@@ -7276,9 +7526,21 @@ genRightShift (iCode * ic)
      only the lower order byte since shifting
      more that 32 bits make no sense anyway, ( the
      largest size of an object can be only 32 bits ) */
-
-  emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
-  emitcode ("inc", "b");
+  
+  if (AOP_TYPE (right) == AOP_LIT)
+  {
+      /* Really should be handled by genRightShiftLiteral,
+       * but since I'm too lazy to fix that today, at least we can make
+       * some small improvement.
+       */
+       emitcode("mov", "b,#0x%02x",
+                       ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
+  }
+  else
+  {
+       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
+       emitcode ("inc", "b");
+  }
   freeAsmop (right, NULL, ic, TRUE);
   aopOp (left, ic, FALSE, FALSE);
   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
@@ -8574,8 +8836,7 @@ genIfx (iCode * ic, iCode * popIc)
   operand *cond = IC_COND (ic);
   int isbit = 0;
 
-  D (emitcode (";", "genIfx ");
-    );
+  D (emitcode (";", "genIfx "););
 
   aopOp (cond, ic, FALSE, FALSE);
 
@@ -8691,19 +8952,64 @@ genFarFarAssign (operand * result, operand * right, iCode * ic)
 {
   int size = AOP_SIZE (right);
   int offset = 0;
-  char *l;
-
-  if (size > 1)
-    {
-      /* This is a net loss for size == 1, but a big gain
-       * otherwise.
-       */
-      D (emitcode (";", "genFarFarAssign (improved)");
-       );
+  symbol *rSym = NULL;
 
+  if (size == 1)
+  {
+      /* quick & easy case. */
+      D(emitcode(";","genFarFarAssign (1 byte case)"););      
+      MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
+      freeAsmop (right, NULL, ic, FALSE);
+      /* now assign DPTR to result */
+      _G.accInUse++;
+      aopOp(result, ic, FALSE, FALSE);
+      _G.accInUse--;
+      aopPut(AOP(result), "a", 0);
+      freeAsmop(result, NULL, ic, FALSE);
+      return;
+  }
+  
+  /* See if we've got an underlying symbol to abuse. */
+  if (IS_SYMOP(result) && OP_SYMBOL(result))
+  {
+      if (IS_TRUE_SYMOP(result))
+      {
+         rSym = OP_SYMBOL(result);
+      }
+      else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
+      {
+         rSym = OP_SYMBOL(result)->usl.spillLoc;
+      }
+  }
+            
+  if (size > 1 && rSym && rSym->rname && !rSym->onStack)
+  {
+      /* We can use the '390 auto-toggle feature to good effect here. */
+      
+      D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
+      emitcode("mov", "dps, #0x21");   /* Select DPTR2 & auto-toggle. */
+      emitcode ("mov", "dptr,#%s", rSym->rname); 
+      /* DP2 = result, DP1 = right, DP1 is current. */
+      while (size)
+      {
+          emitcode("movx", "a,@dptr");
+          emitcode("movx", "@dptr,a");
+          if (--size)
+          {
+               emitcode("inc", "dptr");
+               emitcode("inc", "dptr");
+          }
+      }
+      emitcode("mov", "dps, #0");
+      freeAsmop (right, NULL, ic, FALSE);
+  }
+  else
+  {
+      D (emitcode (";", "genFarFarAssign"););
       aopOp (result, ic, TRUE, TRUE);
 
       _startLazyDPSEvaluation ();
+      
       while (size--)
        {
          aopPut (AOP (result),
@@ -8713,33 +9019,7 @@ genFarFarAssign (operand * result, operand * right, iCode * ic)
       _endLazyDPSEvaluation ();
       freeAsmop (result, NULL, ic, FALSE);
       freeAsmop (right, NULL, ic, FALSE);
-    }
-  else
-    {
-      D (emitcode (";", "genFarFarAssign ");
-       );
-
-      /* first push the right side on to the stack */
-      _startLazyDPSEvaluation ();
-      while (size--)
-       {
-         l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
-         MOVA (l);
-         emitcode ("push", "acc");
-       }
-
-      freeAsmop (right, NULL, ic, FALSE);
-      /* now assign DPTR to result */
-      aopOp (result, ic, FALSE, FALSE);
-      size = AOP_SIZE (result);
-      while (size--)
-       {
-         emitcode ("pop", "acc");
-         aopPut (AOP (result), "a", --offset);
-       }
-      freeAsmop (result, NULL, ic, FALSE);
-      _endLazyDPSEvaluation ();
-    }
+  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -8825,8 +9105,6 @@ genAssign (iCode * ic)
       (AOP_TYPE (right) == AOP_LIT) &&
       !IS_FLOAT (operandType (right)))
     {
-      D (emitcode (";", "Kevin's better literal load code");
-       );
       _startLazyDPSEvaluation ();
       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
        {
@@ -9162,12 +9440,37 @@ genDjnz (iCode * ic, iCode * ifx)
     return 0;
 
   /* otherwise we can save BIG */
+  D(emitcode(";", "genDjnz"););
+
   lbl = newiTempLabel (NULL);
   lbl1 = newiTempLabel (NULL);
 
   aopOp (IC_RESULT (ic), ic, FALSE, 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, TRUE);
+      
+      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, FALSE));
@@ -9176,7 +9479,7 @@ genDjnz (iCode * ic, iCode * ifx)
     }
   else
     {
-      emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE),
+      emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
                lbl->key + 100);
     }
   emitcode ("sjmp", "%05d$", lbl1->key + 100);
@@ -9476,8 +9779,6 @@ gen390Code (iCode * lic)
 
        default:
          ic = ic;
-         /*      piCode(ic,stdout); */
-
        }
     }