Improved genFarFarAssign
[fw/sdcc] / src / ds390 / gen.c
index c1a456725bbdc05064ffb00e389dc1a134860775..11e5217fb3265f83b9cdfef8d18e8a23a18f5167 100644 (file)
@@ -1,5 +1,5 @@
 /*-------------------------------------------------------------------------
-  gen.c - source file for code generation for 8051
+  gen.c - source file for code generation for DS80C390
 
   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
   In other words, you are welcome to use, share and improve this program.
   You are forbidden to forbid anyone else to use, share and improve
   what you give them.   Help stamp out software-hoarding!
-
-  Notes:
-  000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
-      Made everything static
 -------------------------------------------------------------------------*/
 
 #include <stdio.h>
 #endif
 #endif
 
+#define BETTER_LITERAL_SHIFT
+
 char *aopLiteral (value * val, int offset);
-#if 0
-//REMOVE ME!!!
-extern int allocInfo;
-#endif
 
 /* this is the down and dirty file with all kinds of
    kludgy & hacky stuff. This is what it is all about
@@ -106,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;
 
@@ -241,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");
@@ -315,7 +312,11 @@ _startLazyDPSEvaluation (void)
 {
   _currentDPS = 0;
   _desiredDPS = 0;
+#ifdef BETTER_LITERAL_SHIFT  
+  _lazyDPS++;
+#else
   _lazyDPS = 1;
+#endif  
 }
 
 /*-----------------------------------------------------------------*/
@@ -354,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;
+  }
 }
 
 
@@ -448,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
        {
@@ -908,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.               */
 /*------------------------------------------------------------------*/
@@ -967,7 +973,7 @@ aopGet (asmop * aop,
          genSetDPTR (1);
          if (!canClobberACC)
            {
-             emitcode ("xch", "a, ap");
+             emitcode ("xch", "a, %s", DP2_RESULT_REG);
            }
        }
 
@@ -1001,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");
@@ -1073,7 +1079,6 @@ static void
 aopPut (asmop * aop, char *s, int offset)
 {
   char *d = buffer;
-  symbol *lbl;
 
   if (aop->size && offset > (aop->size - 1))
     {
@@ -1229,17 +1234,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;
@@ -1268,23 +1274,21 @@ aopPut (asmop * aop, char *s, int offset)
 }
 
 
-/*-----------------------------------------------------------------*/
-/* reAdjustPreg - points a register back to where it should        */
-/*-----------------------------------------------------------------*/
+/*--------------------------------------------------------------------*/
+/* reAdjustPreg - points a register back to where it should (coff==0) */
+/*--------------------------------------------------------------------*/
 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:
@@ -1294,7 +1298,7 @@ reAdjustPreg (asmop * aop)
          genSetDPTR (1);
          _flushLazyDPS ();
        }
-      while (size--)
+      while (aop->coff--)
        {
          emitcode ("lcall", "__decdptr");
        }
@@ -1306,7 +1310,7 @@ reAdjustPreg (asmop * aop)
       break;
 
     }
-
+  aop->coff=0;
 }
 
 #define AOP(op) op->aop
@@ -1380,7 +1384,6 @@ genNotFloat (operand * op, operand * res)
                        offset++, FALSE, FALSE, FALSE));
     }
   _endLazyDPSEvaluation ();
-  tlbl = newiTempLabel (NULL);
 
   tlbl = newiTempLabel (NULL);
   aopPut (res->aop, one, 1);
@@ -1479,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.
@@ -1495,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));
     }
@@ -1506,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));
        }
@@ -1517,7 +1522,7 @@ toBoolean (operand * oper)
     }
   _endLazyDPSEvaluation ();
 
-  if (AOP_NEEDSACC (oper))
+  if (usedB)
     {
       emitcode ("mov", "a,b");
       emitcode ("pop", "b");
@@ -2212,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)
            {
@@ -2513,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
@@ -2721,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");
@@ -3138,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)); \
@@ -3151,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)); \
@@ -3174,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                           */
 /*-----------------------------------------------------------------*/
@@ -3193,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)
@@ -3309,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 ();
     }
@@ -3492,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();
     }
 }
 
@@ -3513,8 +3536,7 @@ genMinusBits (iCode * ic)
 {
   symbol *lbl = newiTempLabel (NULL);
 
-  D (emitcode (";", "genMinusBits ");
-    );
+  D (emitcode (";", "genMinusBits "););
 
   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
     {
@@ -3547,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);
@@ -3628,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);
@@ -3685,12 +3684,8 @@ genMultbits (operand * left,
 
 
 /*-----------------------------------------------------------------*/
-/* genMultOneByte : 8*8=16 bit multiplication                      */
+/* genMultOneByte : 8*8=8/16 bit multiplication                    */
 /*-----------------------------------------------------------------*/
-void catchMe() {
-  emitcode(";catch","me");
-}
-
 static void
 genMultOneByte (operand * left,
                operand * right,
@@ -3698,80 +3693,98 @@ genMultOneByte (operand * left,
 {
   sym_link *opetype = operandType (result);
   symbol *lbl;
+  int size=AOP_SIZE(result);
 
-  if (AOP_SIZE (result)!=2) {
+  emitcode (";",__FUNCTION__);
+  if (size<1 || size>2) {
     // this should never happen
-      fprintf (stderr, "size!=2 in geniCodeMultOneByte\n");
+      fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
+              AOP_SIZE(result), __FUNCTION__, lineno);
+      exit (1);
   }
 
-  if (SPEC_USIGN(opetype) || 
+  /* (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=16 multiply
+      || (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, TRUE));
     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
     emitcode ("mul", "ab");
     aopPut (AOP (result), "a", 0);
-    aopPut (AOP (result), "b", 1);
+    if (size==2) {
+      aopPut (AOP (result), "b", 1);
+    }
     return;
   }
 
   // we have to do a signed multiply
 
-#if 0
-  // literals ignored for now
-
-  /* (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;
-    }
-#endif
+  emitcode (";", "signed");
+  emitcode ("clr", "F0"); // reset sign flag
+  emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
+  MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
 
-  emitcode ("mov", "ap,#0"); // can't we use some flag bit here?
-  MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
   lbl=newiTempLabel(NULL);
   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
-  // right side is negative, should test for litteral too
-  emitcode ("inc", "ap"); // opRight is negative
-  emitcode ("cpl", "a"); // 8-bit two's complement, this fails for -128
+  // 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");
-  emitcode ("", "%05d$:", lbl->key+100);
-  emitcode ("mov", "b,a");
 
-  MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
-  lbl=newiTempLabel(NULL);
-  emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
-  // left side is negative
-  emitcode ("inc", "ap"); // opLeft is negative
-  emitcode ("cpl", "a"); // 8-bit two's complement, this fails for -128
-  emitcode ("inc", "a");
   emitcode ("", "%05d$:", lbl->key+100);
+  emitcode ("xch", "a,b");
+
+  /* if literal */
+  if (AOP_TYPE(right)==AOP_LIT) {
+    /* AND literal negative */
+    if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
+      // two's complement for literal<0
+      emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
+      emitcode ("cpl", "a");
+      emitcode ("inc", "a");
+    }
+  } else {
+    lbl=newiTempLabel(NULL);
+    emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
+    // right side is negative, 8-bit two's complement
+    emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
+    emitcode ("cpl", "a");
+    emitcode ("inc", "a");
+    emitcode ("", "%05d$:", lbl->key+100);
+  }
   emitcode ("mul", "ab");
     
   lbl=newiTempLabel(NULL);
-  emitcode ("xch", "a,ap");
-  emitcode ("rrc", "a");
-  emitcode ("xch", "a,ap");
-  emitcode ("jnc", "%05d$", lbl->key+100);
-  // only ONE op was negative, we have to do a 16-bit two's complement
-  emitcode ("setb", "c");
-  emitcode ("cpl", "a");
-  emitcode ("addc", "a,#0");
-  emitcode ("push", "acc"); // lsb
-  emitcode ("mov", "a,b");
-  emitcode ("cpl", "a");
-  emitcode ("addc", "a,#0");
-  emitcode ("mov", "b,a"); // msb
-  emitcode ("pop", "acc"); // lsb
+  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");
+  }
 
   emitcode ("", "%05d$:", lbl->key+100);
   aopPut (AOP (result), "a", 0);
-  aopPut (AOP (result), "b", 1);
+  if (size==2) {
+    aopPut (AOP (result), "b", 1);
+  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -3784,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);
@@ -4339,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);
@@ -4675,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 */
@@ -4690,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
@@ -4699,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);
 }
 
 
@@ -4717,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 */
@@ -4732,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
@@ -4741,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);
 }
 
@@ -4816,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                                          */
 /*-----------------------------------------------------------------*/
@@ -4827,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),
@@ -5123,6 +5197,7 @@ release:
   freeAsmop (result, NULL, ic, TRUE);
 }
 
+
 /*-----------------------------------------------------------------*/
 /* genOr  - code for or                                            */
 /*-----------------------------------------------------------------*/
@@ -5132,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),
@@ -5421,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),
@@ -5949,8 +6037,7 @@ AccRsh (int shCount)
     }
 }
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* AccSRsh - signed right shift accumulator by known count                 */
 /*-----------------------------------------------------------------*/
@@ -5988,8 +6075,7 @@ AccSRsh (int shCount)
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* shiftR1Left2Result - shift right one byte from left to result   */
 /*-----------------------------------------------------------------*/
@@ -6008,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    */
 /*-----------------------------------------------------------------*/
@@ -6017,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                  */
 /*-----------------------------------------------------------------*/
@@ -6037,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 ! */
@@ -6058,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                         */
 /*-----------------------------------------------------------------*/
@@ -6078,7 +6161,7 @@ AccAXRrl1 (char *x)
 }
 #endif
 
-#if 0
+#ifdef BETTER_LITERAL_SHIFT
 //REMOVE ME!!!
 /*-----------------------------------------------------------------*/
 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
@@ -6093,8 +6176,7 @@ AccAXLrl1 (char *x)
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
+#ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
 /*-----------------------------------------------------------------*/
@@ -6108,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)                 */
 /*-----------------------------------------------------------------*/
@@ -6155,18 +6236,25 @@ AccAXLsh (char *x, int shCount)
 
       break;
     case 6:                    // AAAAAABB:CCCCCCDD
-
       emitcode ("anl", "a,#0x%02x",
                SRMask[shCount]);       // 000000BB:CCCCCCDD
-
       emitcode ("mov", "c,acc.0");     // c = B
-
       emitcode ("xch", "a,%s", x);     // CCCCCCDD:000000BB
-
+#if 0
       AccAXRrl1 (x);           // BCCCCCCD:D000000B
-
       AccAXRrl1 (x);           // BBCCCCCC:DD000000
-
+#else
+      emitcode("rrc","a"); 
+      emitcode("xch","a,%s", x); 
+      emitcode("rrc","a"); 
+      emitcode("mov","c,acc.0"); //<< get correct bit 
+      emitcode("xch","a,%s", x); 
+
+      emitcode("rrc","a"); 
+      emitcode("xch","a,%s", x); 
+      emitcode("rrc","a"); 
+      emitcode("xch","a,%s", x); 
+#endif
       break;
     case 7:                    // a:x <<= 7
 
@@ -6186,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)                   */
@@ -6269,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)           */
@@ -6372,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   */
 /*-----------------------------------------------------------------*/
@@ -6381,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  */
 /*-----------------------------------------------------------------*/
@@ -6409,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
 
@@ -6469,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           */
 /*-----------------------------------------------------------------*/
@@ -6493,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
@@ -6623,7 +6797,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;
     }
 
@@ -6695,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,
@@ -6709,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));
@@ -6726,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:
@@ -6745,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
 
@@ -6770,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);
@@ -6779,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
 
@@ -6795,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);
@@ -6873,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      */
 /*-----------------------------------------------------------------*/
@@ -6882,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          */
 /*-----------------------------------------------------------------*/
@@ -6897,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
 
@@ -7029,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,
@@ -7044,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);
 
@@ -7057,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
@@ -7086,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;
        }
@@ -7097,6 +7342,7 @@ genRightShiftLiteral (operand * left,
       freeAsmop (left, NULL, ic, TRUE);
       freeAsmop (result, NULL, ic, TRUE);
     }
+    return TRUE;
 }
 #endif
 
@@ -7111,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 */
@@ -7123,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
@@ -7136,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);
@@ -7225,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 */
@@ -7251,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
 
@@ -7266,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);
@@ -8564,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);
 
@@ -8681,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),
@@ -8703,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 ();
-    }
+  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -8815,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))
        {
@@ -9152,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));
@@ -9166,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);
@@ -9466,8 +9779,6 @@ gen390Code (iCode * lic)
 
        default:
          ic = ic;
-         /*      piCode(ic,stdout); */
-
        }
     }