fix several 'three operand in far space' problems
[fw/sdcc] / src / ds390 / gen.c
index ce33ecc5d570060fe5afc9b659bc92a47fc79b8b..b1acf729b984dcb9eff3a90de5f3d36e4d532eed 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
 
 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
@@ -69,7 +61,7 @@ static char *spname;
 
 #define D(x) x
 
-unsigned fReturnSize_390 = 5;  /* shared with ralloc.c */
+unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
 static char *fReturn[] =
 {"dpl", "dph", "dpx", "b", "a"};
 static char *accUse[] =
@@ -106,6 +98,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 +237,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");
@@ -769,7 +764,7 @@ aopOp (operand * op, iCode * ic, bool result, bool useDP2)
 
          aop = op->aop = sym->aop = newAsmop (AOP_STR);
          aop->size = getSize (sym->type);
-         for (i = 0; i < (int) fReturnSize_390; i++)
+         for (i = 0; i < (int) fReturnSizeDS390; i++)
            aop->aopu.aop_str[i] = fReturn[i];
          return;
        }
@@ -908,7 +903,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.               */
 /*------------------------------------------------------------------*/
@@ -965,10 +960,9 @@ aopGet (asmop * aop,
       if (aop->type == AOP_DPTR2)
        {
          genSetDPTR (1);
-
          if (!canClobberACC)
            {
-             emitcode ("xch", "a, ap");
+             emitcode ("xch", "a, %s", DP2_RESULT_REG);
            }
        }
 
@@ -1000,14 +994,12 @@ aopGet (asmop * aop,
       if (aop->type == AOP_DPTR2)
        {
          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");
 
     case AOP_IMMD:
@@ -1076,7 +1068,6 @@ static void
 aopPut (asmop * aop, char *s, int offset)
 {
   char *d = buffer;
-  symbol *lbl;
 
   if (aop->size && offset > (aop->size - 1))
     {
@@ -1232,17 +1223,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;
@@ -1271,23 +1263,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:
@@ -1297,7 +1287,7 @@ reAdjustPreg (asmop * aop)
          genSetDPTR (1);
          _flushLazyDPS ();
        }
-      while (size--)
+      while (aop->coff--)
        {
          emitcode ("lcall", "__decdptr");
        }
@@ -1309,7 +1299,7 @@ reAdjustPreg (asmop * aop)
       break;
 
     }
-
+  aop->coff=0;
 }
 
 #define AOP(op) op->aop
@@ -1383,7 +1373,6 @@ genNotFloat (operand * op, operand * res)
                        offset++, FALSE, FALSE, FALSE));
     }
   _endLazyDPSEvaluation ();
-  tlbl = newiTempLabel (NULL);
 
   tlbl = newiTempLabel (NULL);
   aopPut (res->aop, one, 1);
@@ -1790,7 +1779,7 @@ saveRegisters (iCode * lic)
     for (i = 0; i < ds390_nRegs; i++)
       {
        if (bitVectBitValue (rsave, i))
-         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
+         emitcode ("push", "%s ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
       }
 
   detype = getSpec (operandType (IC_LEFT (ic)));
@@ -1839,7 +1828,7 @@ unsaveRegisters (iCode * ic)
     for (i = ds390_nRegs; i >= 0; i--)
       {
        if (bitVectBitValue (rsave, i))
-         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
+         emitcode ("pop", "%s ;jwk unsaveRegisters", ds390_regWithIdx (i)->dname);
       }
 
 }
@@ -1940,7 +1929,6 @@ genIpush (iCode * ic)
   D (emitcode (";", "genIpush ");
     );
 
-
   /* if this is not a parm push : ie. it is spill push
      and spill push is always done on the local stack */
   if (!ic->parmPush)
@@ -1962,7 +1950,7 @@ genIpush (iCode * ic)
              MOVA (l);
              l = "acc";
            }
-         emitcode ("push", "%s", l);
+         emitcode ("push", "%s ;jwk genIpush: !parm", l);
        }
       _endLazyDPSEvaluation ();
       return;
@@ -1999,7 +1987,7 @@ genIpush (iCode * ic)
          emitcode ("push", "acc");
        }
       else
-       emitcode ("push", "%s", l);
+       emitcode ("push", "%s ;jwk genIpush", l);
     }
   _endLazyDPSEvaluation ();
 
@@ -2028,7 +2016,7 @@ genIpop (iCode * ic)
   _startLazyDPSEvaluation ();
   while (size--)
     {
-      emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
+      emitcode ("pop", "%s ;jwk genIpop", aopGet (AOP (IC_LEFT (ic)), offset--,
                                     FALSE, TRUE, TRUE));
     }
   _endLazyDPSEvaluation ();
@@ -2247,17 +2235,17 @@ genCall (iCode * ic)
 
   /* adjust the stack for parameters if
      required */
-  if (IC_LEFT (ic)->parmBytes)
+  if (ic->parmBytes)
     {
       int i;
-      if (IC_LEFT (ic)->parmBytes > 3)
+      if (ic->parmBytes > 3)
        {
          emitcode ("mov", "a,%s", spname);
-         emitcode ("add", "a,#0x%02x", (-IC_LEFT (ic)->parmBytes) & 0xff);
+         emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
          emitcode ("mov", "%s,a", spname);
        }
       else
-       for (i = 0; i < IC_LEFT (ic)->parmBytes; i++)
+       for (i = 0; i < ic->parmBytes; i++)
          emitcode ("dec", "%s", spname);
 
     }
@@ -2372,17 +2360,17 @@ genPcall (iCode * ic)
 
   /* adjust the stack for parameters if
      required */
-  if (IC_LEFT (ic)->parmBytes)
+  if (ic->parmBytes)
     {
       int i;
-      if (IC_LEFT (ic)->parmBytes > 3)
+      if (ic->parmBytes > 3)
        {
          emitcode ("mov", "a,%s", spname);
-         emitcode ("add", "a,#0x%02x", (-IC_LEFT (ic)->parmBytes) & 0xff);
+         emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
          emitcode ("mov", "%s,a", spname);
        }
       else
-       for (i = 0; i < IC_LEFT (ic)->parmBytes; i++)
+       for (i = 0; i < ic->parmBytes; i++)
          emitcode ("dec", "%s", spname);
 
     }
@@ -2517,7 +2505,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
@@ -2725,7 +2713,7 @@ genEndFunction (iCode * ic)
        {
          if (options.stack10bit)
            {
-             emitcode ("pop", "ap");
+             emitcode ("pop", DP2_RESULT_REG);
              emitcode ("pop", "dpx1");
              emitcode ("pop", "dph1");
              emitcode ("pop", "dpl1");
@@ -3142,6 +3130,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)); \
@@ -3155,6 +3145,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)); \
@@ -3178,15 +3172,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                           */
 /*-----------------------------------------------------------------*/
@@ -3197,16 +3224,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)
@@ -3313,38 +3338,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 ();
     }
@@ -3551,8 +3551,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);
@@ -3632,37 +3631,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);
@@ -3689,7 +3666,7 @@ genMultbits (operand * left,
 
 
 /*-----------------------------------------------------------------*/
-/* genMultOneByte : 8 bit multiplication & division                */
+/* genMultOneByte : 8*8=8/16 bit multiplication                    */
 /*-----------------------------------------------------------------*/
 static void
 genMultOneByte (operand * left,
@@ -3697,89 +3674,99 @@ genMultOneByte (operand * left,
                operand * result)
 {
   sym_link *opetype = operandType (result);
-  char *l;
   symbol *lbl;
-  int size, offset;
+  int size=AOP_SIZE(result);
+
+  emitcode (";",__FUNCTION__);
+  if (size<1 || size>2) {
+    // this should never happen
+      fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
+              AOP_SIZE(result), __FUNCTION__, lineno);
+      exit (1);
+  }
 
-  /* (if two literals, the value is computed before) */
+  /* (if two literals: the value is computed before) */
   /* if one literal, literal on the right */
   if (AOP_TYPE (left) == AOP_LIT)
     {
       operand *t = right;
       right = left;
       left = t;
+      emitcode (";", "swapped left and right");
+    }
+
+  if (SPEC_USIGN(opetype)
+      // ignore the sign of left and right, what else can we do?
+      || (SPEC_USIGN(operandType(left)) && 
+         SPEC_USIGN(operandType(right)))) {
+    // just an unsigned 8*8=8/16 multiply
+    //emitcode (";","unsigned");
+    emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
+    MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
+    emitcode ("mul", "ab");
+    aopPut (AOP (result), "a", 0);
+    if (size==2) {
+      aopPut (AOP (result), "b", 1);
     }
+    return;
+  }
 
-  size = AOP_SIZE (result);
-  /* signed or unsigned */
-  emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
-  l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
-  MOVA (l);
-  emitcode ("mul", "ab");
-  /* if result size = 1, mul signed = mul unsigned */
-  aopPut (AOP (result), "a", 0);
-  if (size > 1)
-    {
-      if (SPEC_USIGN (opetype))
-       {
-         aopPut (AOP (result), "b", 1);
-         if (size > 2)
-           /* for filling the MSBs */
-           emitcode ("clr", "a");
-       }
-      else
-       {
-         emitcode ("mov", "a,b");
+  // we have to do a signed multiply
 
-         /* adjust the MSB if left or right neg */
+  emitcode (";", "signed");
+  emitcode ("clr", "F0"); // reset sign flag
+  emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
+  MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
 
-         /* if one literal */
-         if (AOP_TYPE (right) == AOP_LIT)
-           {
-             /* AND literal negative */
-             if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0)
-               {
-                 /* adjust MSB (c==0 after mul) */
-                 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, FALSE));
-               }
-           }
-         else
-           {
-             lbl = newiTempLabel (NULL);
-             emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
-             emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
-             emitcode ("", "%05d$:", (lbl->key + 100));
-             emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
-             lbl = newiTempLabel (NULL);
-             emitcode ("jc", "%05d$", (lbl->key + 100));
-             emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, FALSE));
-             emitcode ("", "%05d$:", (lbl->key + 100));
-           }
+  lbl=newiTempLabel(NULL);
+  emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
+  // left side is negative, 8-bit two's complement, this fails for -128
+  emitcode ("setb", "F0"); // set sign flag
+  emitcode ("cpl", "a");
+  emitcode ("inc", "a");
 
-         lbl = newiTempLabel (NULL);
-         emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, FALSE));
-         emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
-         emitcode ("", "%05d$:", (lbl->key + 100));
-         emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, FALSE));
-         lbl = newiTempLabel (NULL);
-         emitcode ("jc", "%05d$", (lbl->key + 100));
-         emitcode ("subb", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
-         emitcode ("", "%05d$:", (lbl->key + 100));
+  emitcode ("", "%05d$:", lbl->key+100);
+  emitcode ("xch", "a,b");
 
-         aopPut (AOP (result), "a", 1);
-         if (size > 2)
-           {
-             /* get the sign */
-             emitcode ("rlc", "a");
-             emitcode ("subb", "a,acc");
-           }
-       }
-      size -= 2;
-      offset = 2;
-      if (size > 0)
-       while (size--)
-         aopPut (AOP (result), "a", offset++);
+  /* 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 ("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);
+  if (size==2) {
+    aopPut (AOP (result), "b", 1);
+  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -3792,8 +3779,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);
@@ -4683,13 +4669,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 */
@@ -4698,6 +4683,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
@@ -4707,12 +4696,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);
 }
 
 
@@ -4725,13 +4715,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 */
@@ -4740,6 +4729,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
@@ -4749,11 +4743,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);
 }
 
@@ -4824,6 +4821,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                                          */
 /*-----------------------------------------------------------------*/
@@ -4835,13 +4878,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),
@@ -5131,6 +5180,7 @@ release:
   freeAsmop (result, NULL, ic, TRUE);
 }
 
+
 /*-----------------------------------------------------------------*/
 /* genOr  - code for or                                            */
 /*-----------------------------------------------------------------*/
@@ -5140,13 +5190,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),
@@ -5429,13 +5486,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),
@@ -6163,18 +6226,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
 
@@ -6631,7 +6701,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;
     }
 
@@ -7878,15 +7948,15 @@ genGenPointerGet (operand * left,
            l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
            genSetDPTR(0);
            _flushLazyDPS();
-           emitcode ("mov", "dpl,%s", l);
+           emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
            l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
            genSetDPTR(0);
            _flushLazyDPS();
-           emitcode ("mov", "dph,%s", l);
+           emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
            l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
            genSetDPTR(0);
            _flushLazyDPS();
-           emitcode ("mov", "dpx,%s", l);
+           emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
            emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
          } else {
            emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
@@ -9174,7 +9244,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);
@@ -9202,11 +9272,11 @@ genReceive (iCode * ic)
        IS_TRUE_SYMOP (IC_RESULT (ic))))
     {
       int size = getSize (operandType (IC_RESULT (ic)));
-      int offset = fReturnSize_390 - size;
+      int offset = fReturnSizeDS390 - size;
       while (size--)
        {
-         emitcode ("push", "%s", (strcmp (fReturn[fReturnSize_390 - offset - 1], "a") ?
-                           fReturn[fReturnSize_390 - offset - 1] : "acc"));
+         emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
+                           fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
          offset++;
        }
       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
@@ -9474,8 +9544,6 @@ gen390Code (iCode * lic)
 
        default:
          ic = ic;
-         /*      piCode(ic,stdout); */
-
        }
     }