* sdcc.spec: updated
[fw/sdcc] / src / mcs51 / gen.c
index 34c178c00454d23ecfe80712a442eb4c09829d61..649c643e5ea6f50e6b464777b546b4369137ce52 100644 (file)
@@ -3192,8 +3192,10 @@ static void
 genPlus (iCode * ic)
 {
   int size, offset = 0;
-  char *add;
+  int skip_bytes = 0;
+  char *add = "add";
   asmop *leftOp, *rightOp;
+  operand * op;
 
   /* special cases :- */
 
@@ -3255,33 +3257,92 @@ genPlus (iCode * ic)
     goto release;
 
   size = getDataSize (IC_RESULT (ic));
-
   leftOp = AOP(IC_LEFT(ic));
   rightOp = AOP(IC_RIGHT(ic));
-  add = "add";
+  op=IC_LEFT(ic);
+
+  /* if this is an add for an array access
+     at a 256 byte boundary */
+  if ( 2 == size
+       && AOP_TYPE (op) == AOP_IMMD
+       && IS_SYMOP (op)
+       && IS_SPEC (OP_SYM_ETYPE (op))
+       && SPEC_ABSA (OP_SYM_ETYPE (op))
+       && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
+     )
+    {
+      D(emitcode (";     genPlus aligned array",""));
+      aopPut (AOP (IC_RESULT (ic)),
+             aopGet (rightOp, 0, FALSE, FALSE),
+             0,
+             isOperandVolatile (IC_RESULT (ic), FALSE));
 
-  while (size--)
-    {
-      if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
+      if( 1 == getDataSize (IC_RIGHT (ic)) )
        {
-         emitcode("mov", "b,a");
-         MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
-         emitcode("xch", "a,b");
-         MOVA (aopGet (rightOp, offset, FALSE, TRUE));
-         emitcode (add, "a,b");
+         aopPut (AOP (IC_RESULT (ic)),
+                 aopGet (leftOp, 1, FALSE, FALSE),
+                 1,
+                 isOperandVolatile (IC_RESULT (ic), FALSE));
        }
-      else if (aopGetUsesAcc (leftOp, offset))
-       {
-         MOVA (aopGet (leftOp, offset, FALSE, TRUE));
-         emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
+      else
+        {
+         MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
+         emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
+         aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
        }
+      goto release;
+    }
+
+  /* if the lower bytes of a literal are zero skip the addition */
+  if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
+    {
+       while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
+              (skip_bytes+1 < size))
+         {
+           skip_bytes++;
+        }
+       if (skip_bytes)
+         D(emitcode (";     genPlus shortcut",""));
+    }
+
+  while (size--)
+    {
+      if( offset >= skip_bytes )
+        {
+         if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
+           {
+             emitcode("mov", "b,a");
+             MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
+             emitcode("xch", "a,b");
+             MOVA (aopGet (rightOp, offset, FALSE, TRUE));
+             emitcode (add, "a,b");
+           }
+         else if (aopGetUsesAcc (leftOp, offset))
+           {
+             MOVA (aopGet (leftOp, offset, FALSE, TRUE));
+             emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
+           }
+         else
+           {
+             MOVA (aopGet (rightOp, offset, FALSE, TRUE));
+             emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
+           }
+         aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
+         add = "addc";  /* further adds must propagate carry */
+        }
       else
-       {
-         MOVA (aopGet (rightOp, offset, FALSE, TRUE));
-         emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
+        {
+          if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) || 
+             isOperandVolatile (IC_RESULT (ic), FALSE))
+           {
+             /* just move */
+              aopPut (AOP (IC_RESULT (ic)),
+                     aopGet (leftOp, offset, FALSE, FALSE),
+                     offset,
+                     isOperandVolatile (IC_RESULT (ic), FALSE));
+           }
        }
-      aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
-      add = "addc";  /* further adds must propagate carry */
+      offset++;
     }
 
   adjustArithmeticResult (ic);
@@ -3614,8 +3675,16 @@ genMultOneByte (operand * left,
     // just an unsigned 8*8=8/16 multiply
     //emitcode (";","unsigned");
     // TODO: check for accumulator clash between left & right aops?
-    emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
-    MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+  
+    if( AOP_TYPE(right)==AOP_LIT ){
+      // moving to accumulator first helps peepholes 
+      MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+      emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
+    } else {
+      emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
+      MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+    }
+    
     emitcode ("mul", "ab");
     aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
     if (size==2) {
@@ -4263,12 +4332,14 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
      if the right is in a pointer register and left
      is not */
   if ((AOP_TYPE (left) == AOP_LIT) ||
+      (AOP_TYPE (left) == AOP_IMMD) ||
       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
     {
       operand *t = right;
       right = left;
       left = t;
     }
+  
   if (AOP_TYPE (right) == AOP_LIT)
     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
 
@@ -4292,6 +4363,7 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
   else if (AOP_TYPE (right) == AOP_REG ||
           AOP_TYPE (right) == AOP_DIR ||
           AOP_TYPE (right) == AOP_LIT ||
+           AOP_TYPE (right) == AOP_IMMD ||
           (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
           (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
     {
@@ -4891,6 +4963,8 @@ genAnd (iCode * ic, iCode * ifx)
            {
              if (ifx)
                jmpTrueOrFalse (ifx, tlbl);
+              else
+               emitcode ("", "%05d$:", tlbl->key + 100);
              goto release;
            }
        }
@@ -4981,6 +5055,8 @@ genAnd (iCode * ic, iCode * ifx)
            }
          else if (ifx)
            jmpTrueOrFalse (ifx, tlbl);
+          else
+           emitcode ("", "%05d$:", tlbl->key + 100);
        }
       else
        {
@@ -5267,6 +5343,8 @@ genOr (iCode * ic, iCode * ifx)
            }
          else if (ifx)
            jmpTrueOrFalse (ifx, tlbl);
+         else
+           emitcode ("", "%05d$:", tlbl->key + 100);
        }
       else
        for (; (size--); offset++)
@@ -5748,6 +5826,66 @@ genGetHbit (iCode * ic)
   freeAsmop (result, NULL, ic, TRUE);
 }
 
+/*-----------------------------------------------------------------*/
+/* genSwap - generates code to swap nibbles or bytes               */
+/*-----------------------------------------------------------------*/
+static void
+genSwap (iCode * ic)
+{
+  operand *left, *result;
+
+  D(emitcode (";     genSwap",""));
+
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, FALSE);
+  
+  switch (AOP_SIZE (left))
+    {
+    case 1: /* swap nibbles in byte */
+      MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+      emitcode ("swap", "a");
+      aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
+      break;
+    case 2: /* swap bytes in word */
+      if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
+       {
+         MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+         aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
+                 0, isOperandVolatile (result, FALSE));
+         aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
+       }
+      else if (operandsEqu (left, result))
+       {
+          char * reg = "a";
+         MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+         if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
+           {
+             emitcode ("mov", "b,a");
+              reg = "b";
+            }
+         aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
+                 0, isOperandVolatile (result, FALSE));
+         aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
+       }
+      else
+       {
+         aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
+                 0, isOperandVolatile (result, FALSE));
+         aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
+                 1, isOperandVolatile (result, FALSE));
+       }
+      break;
+    default:
+      wassertl(FALSE, "unsupported SWAP operand size");
+    }
+  
+  freeAsmop (left, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+    
 /*-----------------------------------------------------------------*/
 /* AccRol - rotate left accumulator by known count                 */
 /*-----------------------------------------------------------------*/
@@ -7060,7 +7198,7 @@ static void
 genRightShift (iCode * ic)
 {
   operand *right, *left, *result;
-  sym_link *retype;
+  sym_link *letype;
   int size, offset;
   char *l;
   symbol *tlbl, *tlbl1;
@@ -7069,9 +7207,9 @@ genRightShift (iCode * ic)
 
   /* if signed then we do it the hard way preserve the
      sign bit moving it inwards */
-  retype = getSpec (operandType (IC_RESULT (ic)));
+  letype = getSpec (operandType (IC_LEFT (ic)));
 
-  if (!SPEC_USIGN (retype))
+  if (!SPEC_USIGN (letype))
     {
       genSignedRightShift (ic);
       return;
@@ -8977,34 +9115,58 @@ genReceive (iCode * ic)
 static void
 genDummyRead (iCode * ic)
 {
-  operand *right;
+  operand *op;
   int size, offset;
 
   D(emitcode(";     genDummyRead",""));
 
-  right = IC_RIGHT (ic);
+  op = IC_RIGHT (ic);
+  if (op && IS_SYMOP (op))
+    {
+      aopOp (op, ic, FALSE);
 
-  aopOp (right, ic, FALSE);
+      /* if the result is a bit */
+      if (AOP_TYPE (op) == AOP_CRY)
+        emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
+      else
+       {
+         /* bit variables done */
+         /* general case */
+         size = AOP_SIZE (op);
+         offset = 0;
+         while (size--)
+         {
+           MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
+           offset++;
+         }
+       }
 
-  /* if the result is a bit */
-  if (AOP_TYPE (right) == AOP_CRY)
-    {
-      emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
-      goto release;
+      freeAsmop (op, NULL, ic, TRUE);
     }
 
-  /* bit variables done */
-  /* general case */
-  size = AOP_SIZE (right);
-  offset = 0;
-  while (size--)
+  op = IC_LEFT (ic);
+  if (op && IS_SYMOP (op))
     {
-      MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
-      offset++;
-    }
+      aopOp (op, ic, FALSE);
 
-release:
-  freeAsmop (right, NULL, ic, TRUE);
+      /* if the result is a bit */
+      if (AOP_TYPE (op) == AOP_CRY)
+        emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
+      else
+       {
+         /* bit variables done */
+         /* general case */
+         size = AOP_SIZE (op);
+         offset = 0;
+         while (size--)
+         {
+           MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
+           offset++;
+         }
+       }
+
+      freeAsmop (op, NULL, ic, TRUE);
+    }
 }
 
 /*-----------------------------------------------------------------*/
@@ -9332,6 +9494,10 @@ gen51Code (iCode * lic)
          genEndCritical (ic);
          break;
 
+       case SWAP:
+         genSwap (ic);
+         break;
+
        default:
          ic = ic;
        }