* support/regression/tests/bug-460444.c: Added test case.
[fw/sdcc] / src / z80 / gen.c
index 7c15dcaa646585bf0d34ca440730f039d98b0e81..c8c6df5cf302e736d0d4445091db587bf5852b40 100644 (file)
@@ -96,7 +96,7 @@
 #include "SDCCglue.h"
 #include "newalloc.h"
 
-/* this is the down and dirty file with all kinds of kludgy & hacky
+/* This is the down and dirty file with all kinds of kludgy & hacky
    stuff. This is what it is all about CODE GENERATION for a specific MCU.
    Some of the routines may be reusable, will have to see */
 
    PENDING: What if the parameter is a long?
    Everything is caller saves. i.e. the caller must save any registers
    that it wants to preserve over the call.
-   The return value is returned in DEHL.  DE is normally used as a
+   GB: The return value is returned in DEHL.  DE is normally used as a
    working register pair.  Caller saves allows it to be used for a
    return value.
    va args functions do not use register parameters.  All arguments
    area.  ix-0 is the top most local variable.
 */
 
-enum {
+enum 
+{
+  /* Set to enable debugging trace statements in the output assembly code. */
   DISABLE_DEBUG = 0
 };
 
@@ -133,6 +135,8 @@ static char **_fTmp;
 
 extern FILE *codeOutFile;
 
+/** Enum covering all the possible register pairs.
+ */
 typedef enum
   {
     PAIR_INVALID,
@@ -175,8 +179,13 @@ enum
     MSB32
   };
 
+/** Code generator persistent data.
+ */
 static struct 
 {
+  /** Used to optimised setting up of a pair by remebering what it
+      contains and adjusting instead of reloading where possible.
+  */
   struct 
   {
     AOP_TYPE last_type;
@@ -236,23 +245,6 @@ _getTempPairName(void)
   return _pairs[_getTempPairId()].name;
 }
 
-#if 0
-static const char *
-_getTempPairPart(int idx)
-{
-  wassertl (idx == LSB || idx == MSB16, "Invalid pair offset");
-  
-  if (idx == LSB)
-    {
-      return _pairs[_getTempPairId()].l;
-    }
-  else
-    {
-      return _pairs[_getTempPairId()].h;
-    }
-}
-#endif
-
 static void
 _tidyUp (char *buf)
 {
@@ -411,7 +403,7 @@ getPairName (asmop * aop)
          break;
        }
     }
-  wassert (0);
+  wassertl (0, "Tried to get the pair name of something that isn't a pair");
   return NULL;
 }
 
@@ -821,7 +813,7 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a)
            }
          else 
               {
-                  wassert (0);
+                  wassertl (0, "Marked as being allocated into A or HL but is actually in neither");
               }
          return;
        }
@@ -1221,7 +1213,7 @@ aopGet (asmop * aop, int offset, bool bit16)
            tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
            break;
          default:
-           wassert (0);
+           wassertl (0, "Fetching from beyond the limits of an immediate value.");
          }
 
       return gc_strdup(s);
@@ -1273,7 +1265,7 @@ aopGet (asmop * aop, int offset, bool bit16)
       return gc_strdup(s);
 
     case AOP_CRY:
-      wassert (0);
+      wassertl (0, "Tried to fetch from a bit variable");
 
     case AOP_ACC:
       if (!offset)
@@ -1457,7 +1449,7 @@ aopPut (asmop * aop, const char *s, int offset)
       else
        {
          /* In bit space but not in C - cant happen */
-         wassert (0);
+         wassertl (0, "Tried to write into a bit variable");
        }
       break;
 
@@ -1475,8 +1467,7 @@ aopPut (asmop * aop, const char *s, int offset)
        break;
       if (offset > 0)
        {
-
-         emitDebug ("; Error aopPut AOP_ACC");
+          wassertl (0, "Tried to access past the end of A");
        }
       else
        {
@@ -1530,7 +1521,7 @@ getDataSize (operand * op)
   if (size == 3)
     {
       /* pointer */
-      wassert (0);
+      wassertl (0, "Somehow got a three byte data pointer");
     }
   return size;
 }
@@ -1542,7 +1533,7 @@ static void
 movLeft2Result (operand * left, int offl,
                operand * result, int offr, int sign)
 {
-    const char *l;
+  const char *l;
   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
     {
       l = aopGet (AOP (left), offl, FALSE);
@@ -1553,7 +1544,11 @@ movLeft2Result (operand * left, int offl,
        }
       else
        {
-         wassert (0);
+          if (getDataSize (left) == offl + 1)
+            {
+              emit2 ("ld a,%s", l);
+              aopPut (AOP (result), "a", offr);
+            }
        }
     }
 }
@@ -1587,8 +1582,7 @@ outBitCLong (operand * result, bool swap_sense)
   /* if the result is bit */
   if (AOP_TYPE (result) == AOP_CRY)
     {
-      emitDebug ("; Note: outBitC form 1");
-      aopPut (AOP (result), "blah", 0);
+      wassertl (0, "Tried to write carry to a bit");
     }
   else
     {
@@ -1646,13 +1640,13 @@ genNot (iCode * ic)
   /* if in bit space then a special case */
   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to negate a bit");
     }
 
   /* if type float then do float */
   if (IS_FLOAT (optype))
     {
-      wassert (0);
+      wassertl (0, "Tried to negate a float");
     }
 
   _toBoolean (IC_LEFT (ic));
@@ -1688,7 +1682,7 @@ genCpl (iCode * ic)
   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Left and the result are in bit space");
     }
 
   size = AOP_SIZE (IC_RESULT (ic));
@@ -1776,7 +1770,7 @@ genUminus (iCode * ic)
   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Left and right are in bit space");
       goto release;
     }
 
@@ -1786,10 +1780,13 @@ genUminus (iCode * ic)
   /* if float then do float stuff */
   if (IS_FLOAT (optype))
     {
-      wassert (0);
+      wassertl (0, "Tried to do a unary minus on a float");
       goto release;
     }
 
+  /* otherwise subtract from zero */
+  size = AOP_SIZE (IC_LEFT (ic));
+
   if (AOP_SIZE (IC_RESULT (ic)) == 4 && IS_GB)
     {
       /* Create a new asmop with value zero */
@@ -1800,8 +1797,6 @@ genUminus (iCode * ic)
       goto release;
     }
 
-  /* otherwise subtract from zero */
-  size = AOP_SIZE (IC_LEFT (ic));
   offset = 0;
   _clearCarry();
   while (size--)
@@ -1837,13 +1832,9 @@ assignResultValue (operand * oper)
   int size = AOP_SIZE (oper);
   bool topInA = 0;
 
-  wassert (size <= 4);
+  wassertl (size <= 4, "Got a result that is bigger than four bytes");
   topInA = requiresHL (AOP (oper));
 
-#if 0
-  if (!IS_GB)
-    wassert (size <= 2);
-#endif
   if (IS_GB && size == 4 && requiresHL (AOP (oper)))
     {
       /* We do it the hard way here. */
@@ -1893,19 +1884,7 @@ _saveRegsForCall(iCode *ic, int sendSetSize)
     bool bcInRet = FALSE, deInRet = FALSE;
     bitVect *rInUse;
 
-#if 1
     rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
-#else
-    if (IC_RESULT(ic))
-      {
-        rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), z80_rUmaskForOp (IC_RESULT(ic)));
-      }
-    else 
-      {
-        /* Has no result, so in use is all of in use */
-        rInUse = ic->rMask;
-      }
-#endif
 
     deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
     bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
@@ -2222,7 +2201,6 @@ emitCall (iCode * ic, bool ispcall)
 
       if (isLitWord (AOP (IC_LEFT (ic))))
        {
-         emitDebug ("; Special case where the pCall is to a constant");
          emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
        }
       else
@@ -2424,14 +2402,6 @@ genFunction (iCode * ic)
   */
   _G.receiveOffset = 0;
 
-#if 0
-  /* PENDING: hack */
-  if (!IS_STATIC (sym->etype))
-    {
-      addSetIfnotP (&publics, sym);
-    }
-#endif
-
   /* Record the last function name for debugging. */
   _G.lastFunctionName = sym->rname;
   
@@ -2528,7 +2498,7 @@ genEndFunction (iCode * ic)
 
   if (IS_ISR (sym->etype))
     {
-      wassert (0);
+      wassertl (0, "Tried to close an interrupt support function");
     }
   else
     {
@@ -2767,7 +2737,7 @@ outBitAcc (operand * result)
   /* if the result is a bit */
   if (AOP_TYPE (result) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to write A into a bit");
     }
   else
     {
@@ -2813,7 +2783,7 @@ genPlus (iCode * ic)
       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
     {
       /* Cant happen */
-      wassert (0);
+      wassertl (0, "Tried to add two bits");
     }
 
   /* if left in bit space & right literal */
@@ -2821,7 +2791,7 @@ genPlus (iCode * ic)
       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
     {
       /* Can happen I guess */
-      wassert (0);
+      wassertl (0, "Tried to add a bit to a literal");
     }
 
   /* if I can do an increment instead
@@ -3056,7 +3026,7 @@ genMinus (iCode * ic)
   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to subtract two bits");
       goto release;
     }
 
@@ -3152,7 +3122,9 @@ genMinus (iCode * ic)
   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
       AOP_SIZE (IC_LEFT (ic)) == 3 &&
       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
-    wassert (0);
+    {
+      wassertl (0, "Tried to subtract on a long pointer");
+    }
 
 release:
   freeAsmop (IC_LEFT (ic), NULL, ic);
@@ -3167,7 +3139,7 @@ static void
 genMult (iCode * ic)
 {
   /* Shouldn't occur - all done through function calls */
-  wassert (0);
+  wassertl (0, "Multiplication is handled through support function calls");
 }
 
 /*-----------------------------------------------------------------*/
@@ -3177,7 +3149,7 @@ static void
 genDiv (iCode * ic)
 {
   /* Shouldn't occur - all done through function calls */
-  wassert (0);
+  wassertl (0, "Division is handled through support function calls");
 }
 
 /*-----------------------------------------------------------------*/
@@ -3288,7 +3260,7 @@ genCmp (operand * left, operand * right,
       AOP_TYPE (right) == AOP_CRY)
     {
       /* Cant happen on the Z80 */
-      wassert (0);
+      wassertl (0, "Tried to compare two bits");
     }
   else
     {
@@ -3353,49 +3325,6 @@ genCmp (operand * left, operand * right,
         }
       else
        {
-#if 0
-          // PENDING: Doesn't work around zero
-
-         /* Special cases:
-            On the GB:
-            If the left or the right is a lit:
-            Load -lit into HL, add to right via, check sense.
-          */
-         if (IS_GB && size == 2 && (AOP_TYPE (right) == AOP_LIT || AOP_TYPE (left) == AOP_LIT))
-           {
-             PAIR_ID id = PAIR_DE;
-             asmop *lit = AOP (right);
-             asmop *op = AOP (left);
-             swap_sense = TRUE;
-
-             if (AOP_TYPE (left) == AOP_LIT)
-               {
-                 swap_sense = FALSE;
-                 lit = AOP (left);
-                 op = AOP (right);
-               }
-             if (sign)
-               {
-                 emit2 ("ld e,%s", aopGet (op, 0, 0));
-                 emit2 ("ld a,%s", aopGet (op, 1, 0));
-                 emit2 ("xor a,!immedbyte", 0x80);
-                 emit2 ("ld d,a");
-               }
-             else
-               {
-                 id = getPairId (op);
-                 if (id == PAIR_INVALID)
-                   {
-                     fetchPair (PAIR_DE, op);
-                     id = PAIR_DE;
-                   }
-               }
-             spillPair (PAIR_HL);
-             emit2 ("ld hl,%s", fetchLitSpecial (lit, TRUE, sign));
-             emit2 ("add hl,%s", _getPairIdName (id));
-             goto release;
-           }
-#endif
          if (AOP_TYPE (right) == AOP_LIT)
            {
              lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
@@ -3694,7 +3623,7 @@ genCmpEq (iCode * ic, iCode * ifx)
       if (AOP_TYPE (left) == AOP_CRY &&
          ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
        {
-         wassert (0);
+         wassertl (0, "Tried to compare two bits");
        }
       else
        {
@@ -3724,7 +3653,7 @@ genCmpEq (iCode * ic, iCode * ifx)
   if (AOP_TYPE (left) == AOP_CRY &&
       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
     {
-      wassert (0);
+      wassertl (0, "Tried to compare a bit to either a literal or another bit");
     }
   else
     {
@@ -3795,7 +3724,7 @@ genAndOp (iCode * ic)
   if (AOP_TYPE (left) == AOP_CRY &&
       AOP_TYPE (right) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to and two bits");
     }
   else
     {
@@ -3832,7 +3761,7 @@ genOrOp (iCode * ic)
   if (AOP_TYPE (left) == AOP_CRY &&
       AOP_TYPE (right) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to OR two bits");
     }
   else
     {
@@ -3909,15 +3838,6 @@ genAnd (iCode * ic, iCode * ifx)
   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
 
-#ifdef DEBUG_TYPE
-  emitDebug ("; Type res[%d] = l[%d]&r[%d]",
-           AOP_TYPE (result),
-           AOP_TYPE (left), AOP_TYPE (right));
-  emitDebug ("; Size res[%d] = l[%d]&r[%d]",
-           AOP_SIZE (result),
-           AOP_SIZE (left), AOP_SIZE (right));
-#endif
-
   /* if left is a literal & right is not then exchange them */
   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
       AOP_NEEDSACC (left))
@@ -3950,7 +3870,7 @@ genAnd (iCode * ic, iCode * ifx)
 
   if (AOP_TYPE (left) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to perform an AND with a bit as an operand");
       goto release;
     }
 
@@ -3960,80 +3880,46 @@ genAnd (iCode * ic, iCode * ifx)
       (AOP_TYPE (result) == AOP_CRY) &&
       (AOP_TYPE (left) != AOP_CRY))
     {
-      int posbit = isLiteralBit (lit);
-      /* left &  2^n */
-      if (posbit)
-       {
-         posbit--;
-         _moveA (aopGet (AOP (left), posbit >> 3, FALSE));
-         // bit = left & 2^n
-         if (size)
-           {
-             wassert (0);
-             emit2 ("mov c,acc.%d", posbit & 0x07);
-           }
-         // if(left &  2^n)
-         else
-           {
-             if (ifx)
-               {
-                 sprintf (buffer, "%d", posbit & 0x07);
-                 genIfxJump (ifx, buffer);
-               }
-             else
-               {
-                 wassert (0);
-               }
-             goto release;
-           }
-       }
-      else
-       {
-         symbol *tlbl = newiTempLabel (NULL);
-         int sizel = AOP_SIZE (left);
-         if (size)
-           {
-             wassert (0);
-             emit2 ("setb c");
-           }
-         while (sizel--)
-           {
-             if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
-               {
-                 _moveA (aopGet (AOP (left), offset, FALSE));
-                 // byte ==  2^n ?
-                 if ((posbit = isLiteralBit (bytelit)) != 0)
-                   {
-                     wassert (0);
-                     emit2 ("jb acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
-                   }
-                 else
-                   {
-                     if (bytelit != 0x0FFL)
-                       emit2 ("and a,%s",
-                                 aopGet (AOP (right), offset, FALSE));
-                     else
-                       /* For the flags */
-                       emit2 ("or a,a");
-                     emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
-                   }
-               }
+      symbol *tlbl = newiTempLabel (NULL);
+      int sizel = AOP_SIZE (left);
+      if (size)
+        {
+          /* PENDING: Test case for this. */
+          emit2 ("scf");
+        }
+      while (sizel--)
+        {
+          if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
+            {
+              _moveA (aopGet (AOP (left), offset, FALSE));
+              if (bytelit != 0x0FFL)
+                {
+                  emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
+                }
+              else
+                {
+                  /* For the flags */
+                  emit2 ("or a,a");
+                }
+              emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+            }
              offset++;
-           }
-         // bit = left & literal
-         if (size)
-           {
-             emit2 ("clr c");
-             emit2 ("!tlabeldef", tlbl->key + 100);
-           }
-         // if(left & literal)
-         else
-           {
-             if (ifx)
-               jmpTrueOrFalse (ifx, tlbl);
-             goto release;
-           }
-       }
+        }
+      // bit = left & literal
+      if (size)
+        {
+          emit2 ("clr c");
+          emit2 ("!tlabeldef", tlbl->key + 100);
+        }
+      // if(left & literal)
+      else
+        {
+          if (ifx)
+            {
+              jmpTrueOrFalse (ifx, tlbl);
+            }
+          goto release;
+        }
       outBitC (result);
       goto release;
     }
@@ -4065,7 +3951,7 @@ genAnd (iCode * ic, iCode * ifx)
            {
              if (AOP_TYPE (left) == AOP_ACC)
                {
-                 wassert (0);
+                 wassertl (0, "Tried to perform an AND where the left operand is allocated into A");
                }
              else
                {
@@ -4082,7 +3968,7 @@ genAnd (iCode * ic, iCode * ifx)
       // left & result in different registers
       if (AOP_TYPE (result) == AOP_CRY)
        {
-         wassert (0);
+         wassertl (0, "Tried to AND where the result is in carry");
        }
       else
        {
@@ -4136,20 +4022,12 @@ genOr (iCode * ic, iCode * ifx)
   operand *left, *right, *result;
   int size, offset = 0;
   unsigned long lit = 0L;
+  int bytelit = 0;
 
   aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
   aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
   aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
 
-#if 1
-  emitDebug ("; Type res[%d] = l[%d]&r[%d]",
-           AOP_TYPE (result),
-           AOP_TYPE (left), AOP_TYPE (right));
-  emitDebug ("; Size res[%d] = l[%d]&r[%d]",
-           AOP_SIZE (result),
-           AOP_SIZE (left), AOP_SIZE (right));
-#endif
-
   /* if left is a literal & right is not then exchange them */
   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
       AOP_NEEDSACC (left))
@@ -4182,15 +4060,39 @@ genOr (iCode * ic, iCode * ifx)
 
   if (AOP_TYPE (left) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to OR where left is a bit");
       goto release;
     }
 
+  // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
+  // bit = val | 0xZZ     - size = 1, ifx = FALSE -
   if ((AOP_TYPE (right) == AOP_LIT) &&
       (AOP_TYPE (result) == AOP_CRY) &&
       (AOP_TYPE (left) != AOP_CRY))
     {
-      wassert (0);
+      symbol *tlbl = newiTempLabel (NULL);
+      int sizel = AOP_SIZE (left);
+
+      if (size)
+        {
+          wassertl (0, "Result is assigned to a bit");
+        }
+      /* PENDING: Modeled after the AND code which is inefficent. */
+      while (sizel--)
+        {
+          bytelit = (lit >> (offset * 8)) & 0x0FFL;
+
+          _moveA (aopGet (AOP (left), offset, FALSE));
+          /* OR with any literal is the same as OR with itself. */
+          emit2 ("or a,a");
+          emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+
+          offset++;
+        }
+      if (ifx)
+        {
+          jmpTrueOrFalse (ifx, tlbl);
+        }
       goto release;
     }
 
@@ -4230,7 +4132,7 @@ genOr (iCode * ic, iCode * ifx)
       // left & result in different registers
       if (AOP_TYPE (result) == AOP_CRY)
        {
-         wassert (0);
+         wassertl (0, "Result of OR is in a bit");
        }
       else
        for (; (size--); offset++)
@@ -4316,15 +4218,39 @@ genXor (iCode * ic, iCode * ifx)
 
   if (AOP_TYPE (left) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to XOR a bit");
       goto release;
     }
 
+  // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
+  // bit = val & 0xZZ     - size = 1, ifx = FALSE -
   if ((AOP_TYPE (right) == AOP_LIT) &&
       (AOP_TYPE (result) == AOP_CRY) &&
       (AOP_TYPE (left) != AOP_CRY))
     {
-      wassert (0);
+      symbol *tlbl = newiTempLabel (NULL);
+      int sizel = AOP_SIZE (left);
+
+      if (size)
+        {
+          /* PENDING: Test case for this. */
+          wassertl (0, "Tried to XOR left against a literal with the result going into a bit");
+        }
+      while (sizel--)
+        {
+          _moveA (aopGet (AOP (left), offset, FALSE));
+          emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
+          emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+          offset++;
+        }
+      if (ifx)
+        {
+          jmpTrueOrFalse (ifx, tlbl);
+        }
+      else
+        {
+          wassertl (0, "Result of XOR was destined for a bit");
+        }
       goto release;
     }
 
@@ -4366,7 +4292,7 @@ genXor (iCode * ic, iCode * ifx)
       // left & result in different registers
       if (AOP_TYPE (result) == AOP_CRY)
        {
-         wassert (0);
+         wassertl (0, "Result of XOR is in a bit");
        }
       else
        for (; (size--); offset++)
@@ -4538,7 +4464,7 @@ shiftR2Left2Result (operand * left, int offl,
   tlbl1 = newiTempLabel (NULL);
 
   /* Left is already in result - so now do the shift */
-  if (shCount <= 2)
+  if (shCount <= 4)
     {
       while (shCount--)
         {
@@ -4733,7 +4659,7 @@ genlshTwo (operand * result, operand * left, int shCount)
            {
              movLeft2Result (left, LSB, result, MSB16, 0);
              aopPut (AOP (result), "!zero", 0);
-             shiftL1Left2Result (left, MSB16, result, MSB16, shCount);
+             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
            }
          else
            {
@@ -4788,11 +4714,6 @@ genLeftShiftLiteral (operand * left,
 
   size = getSize (operandType (result));
 
-#if VIEW_SIZE
-  emitDebug ("; shift left  result %d, left %d", size,
-           AOP_SIZE (left));
-#endif
-
   /* I suppose that the left size >= result size */
   if (shCount == 0)
     {
@@ -4864,7 +4785,7 @@ genLeftShift (iCode * ic)
 
   /* now move the left to the result if they are not the
      same */
-#if 1
+
   if (!sameRegs (AOP (left), AOP (result)))
     {
 
@@ -4877,17 +4798,6 @@ genLeftShift (iCode * ic)
          offset++;
        }
     }
-#else
-  size = AOP_SIZE (result);
-  offset = 0;
-  while (size--)
-    {
-      l = aopGet (AOP (left), offset, FALSE);
-      aopPut (AOP (result), l, offset);
-      offset++;
-    }
-#endif
-
 
   tlbl = newiTempLabel (NULL);
   size = AOP_SIZE (result);
@@ -4935,8 +4845,6 @@ genrshOne (operand * result, operand * left, int shCount, int is_signed)
 
   l = aopGet (AOP (left), 0, FALSE);
 
-  emit2 ("or a,a");
-
   if (AOP (result)->type == AOP_REG)
     {
       aopPut (AOP (result), l, 0);
@@ -4988,7 +4896,10 @@ shiftR1Left2Result (operand * left, int offl,
   _moveA (aopGet (AOP (left), offl, FALSE));
   if (sign)
     {
-      wassert (0);
+      while (shCount--)
+       {
+         emit2 ("%s a", sign ? "sra" : "srl");
+       }
     }
   else
     {
@@ -5017,7 +4928,19 @@ genrshTwo (operand * result, operand * left,
        {
          movLeft2Result (left, MSB16, result, LSB, sign);
        }
-      aopPut (AOP (result), "!zero", 1);
+      if (sign)
+        {
+          /* Sign extend the result */
+          _moveA(aopGet (AOP (result), 0, FALSE));
+          emit2 ("rlc a");
+          emit2 ("sbc a,a");
+
+          aopPut (AOP (result), ACC_NAME, MSB16);
+        }
+      else
+        {
+          aopPut (AOP (result), "!zero", 1);
+        }
     }
   /*  1 <= shCount <= 7 */
   else
@@ -5046,9 +4969,6 @@ genRightShiftLiteral (operand * left,
 
   size = getSize (operandType (result));
 
-  emitDebug ("; shift right  result %d, left %d", size,
-           AOP_SIZE (left));
-
   /* I suppose that the left size >= result size */
   if (shCount == 0)
     {
@@ -5066,7 +4986,6 @@ genRightShiftLiteral (operand * left,
          genrshOne (result, left, shCount, sign);
          break;
        case 2:
-         /* PENDING: sign support */
          genrshTwo (result, left, shCount, sign);
          break;
        case 4:
@@ -5479,14 +5398,12 @@ genAssign (iCode * ic)
   result = IC_RESULT (ic);
   right = IC_RIGHT (ic);
 
-#if 1
   /* Dont bother assigning if they are the same */
   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
     {
       emitDebug ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
       return;
     }
-#endif
 
   aopOp (right, ic, FALSE, FALSE);
   aopOp (result, ic, TRUE, FALSE);
@@ -5501,7 +5418,7 @@ genAssign (iCode * ic)
   /* if the result is a bit */
   if (AOP_TYPE (result) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to assign to a bit");
     }
 
   /* general case */
@@ -5657,7 +5574,7 @@ genCast (iCode * ic)
   /* if the result is a bit */
   if (AOP_TYPE (result) == AOP_CRY)
     {
-      wassert (0);
+      wassertl (0, "Tried to cast to a bit");
     }
 
   /* if they are the same size : or less */
@@ -5681,16 +5598,7 @@ genCast (iCode * ic)
       goto release;
     }
 
-  /* PENDING: should be OK. */
-#if 0
-  /* if the result is of type pointer */
-  if (IS_PTR (ctype))
-    {
-      wassert (0);
-    }
-#endif
-
-  /* so we now know that the size of destination is greater
+  /* So we now know that the size of destination is greater
      than the size of the source */
   /* we move to result for the size of source */
   size = AOP_SIZE (right);
@@ -5717,7 +5625,6 @@ genCast (iCode * ic)
         const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
                        FALSE);
       _moveA (l);
-      emitDebug ("; genCast: sign extend untested.");
       emit2 ("rla ");
       emit2 ("sbc a,a");
       while (size--)
@@ -6270,13 +6177,11 @@ genZ80Code (iCode * lic)
          break;
 
        case ARRAYINIT:
-           genArrayInit(ic);
-           break;
+          genArrayInit(ic);
+          break;
            
        default:
          ic = ic;
-         /*      piCode(ic,stdout); */
-
        }
     }