* src/mcs51/peeph.def: renamed rule 257 to 257.a, added 257.b
[fw/sdcc] / src / mcs51 / gen.c
index 64d48eb4543d26033d628a86be321e3eef70dde4..732c97a31d767e74deb56328d901c5b4fbf14dcc 100644 (file)
@@ -624,9 +624,9 @@ aopForSym (iCode * ic, symbol * sym, bool result)
         {
           if (sym->onStack)
             {
-              char offset = ((sym->stack < 0) ?
-                         ((char) (sym->stack - _G.nRegsSaved)) :
-                         ((char) sym->stack)) & 0xff;
+              signed char offset = ((sym->stack < 0) ?
+                         ((signed char) (sym->stack - _G.nRegsSaved)) :
+                         ((signed char) sym->stack)) & 0xff;
 
               if ((abs(offset) <= 3) ||
                   (accuse && (abs(offset) <= 7)))
@@ -849,11 +849,14 @@ operandsEqu (operand * op1, operand * op2)
 }
 
 /*-----------------------------------------------------------------*/
-/* sameReg - two asmops have the same register at given offsets    */
+/* sameByte - two asmops have the same address at given offsets    */
 /*-----------------------------------------------------------------*/
 static bool
-sameReg (asmop * aop1, int off1, asmop * aop2, int off2)
+sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
 {
+  if (aop1 == aop2 && off1 == off2)
+    return TRUE;
+
   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
     return FALSE;
 
@@ -1874,6 +1877,32 @@ toBoolean (operand * oper)
 }
 
 
+/*-------------------------------------------------------------------*/
+/* xch_a_aopGet - for exchanging acc with value of the aop           */
+/*-------------------------------------------------------------------*/
+static char *
+xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
+{
+  char * l;
+
+  if (aopGetUsesAcc (oper, offset))
+    {
+      emitcode("mov", "b,a");
+      MOVA (aopGet (oper, offset, bit16, dname));
+      emitcode("xch", "a,b");
+      aopPut (oper, "a", offset);
+      emitcode("xch", "a,b");
+      l = "b";
+    }
+  else
+    {
+      l = aopGet (oper, offset, bit16, dname);
+      emitcode("xch", "a,%s", l);
+    }
+  return l;
+}
+
+
 /*-----------------------------------------------------------------*/
 /* genNot - generate code for ! operation                          */
 /*-----------------------------------------------------------------*/
@@ -3439,7 +3468,6 @@ genFunction (iCode * ic)
         }
     }
 
-
   if (fReentrant)
     {
       if (options.useXstack)
@@ -6641,7 +6669,7 @@ genAnd (iCode * ic, iCode * ifx)
                 }
               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
                 {
-                  emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+                  MOVB (aopGet (left, offset, FALSE, FALSE));
                   MOVA (aopGet (right, offset, FALSE, FALSE));
                   emitcode ("anl", "a,b");
                   aopPut (result, "a", offset);
@@ -6661,8 +6689,7 @@ genAnd (iCode * ic, iCode * ifx)
                       aopPut (result, "a", offset);
                     }
                   else
-                    emitcode ("anl", "%s,a",
-                              aopGet (left, offset, FALSE, TRUE));
+                    emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
                 }
             }
         }
@@ -6686,30 +6713,41 @@ genAnd (iCode * ic, iCode * ifx)
                 {
                   if (offset)
                     emitcode("mov", "a,b");
-                  emitcode ("anl", "a,%s",
-                            aopGet (right, offset, FALSE, FALSE));
-                } else {
-                  if (AOP_TYPE(left)==AOP_ACC)
+                  emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                }
+              else if (AOP_TYPE(left)==AOP_ACC)
+                {
+                  if (!offset)
                     {
-                      if (!offset)
-                        {
-                          bool pushedB = pushB ();
-                          emitcode("mov", "b,a");
-                          MOVA (aopGet (right, offset, FALSE, FALSE));
-                          emitcode("anl", "a,b");
-                          popB (pushedB);
-                        }
-                      else
-                        {
-                          MOVA (aopGet (right, offset, FALSE, FALSE));
-                          emitcode("anl", "a,b");
-                        }
-                    } else {
+                      bool pushedB = pushB ();
+                      emitcode("mov", "b,a");
                       MOVA (aopGet (right, offset, FALSE, FALSE));
-                      emitcode ("anl", "a,%s",
-                                aopGet (left, offset, FALSE, FALSE));
+                      emitcode("anl", "a,b");
+                      popB (pushedB);
+                    }
+                  else
+                    {
+                      MOVA (aopGet (right, offset, FALSE, FALSE));
+                      emitcode("anl", "a,b");
                     }
                 }
+              else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
+                {
+                  MOVB (aopGet (left, offset, FALSE, FALSE));
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  emitcode ("anl", "a,b");
+                }
+              else if (aopGetUsesAcc (left, offset))
+                {
+                  MOVA (aopGet (left, offset, FALSE, FALSE));
+                  emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                    }
+              else
+                {
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
+                }
+
               emitcode ("jnz", "%05d$", tlbl->key + 100);
               offset++;
             }
@@ -6766,15 +6804,32 @@ genAnd (iCode * ic, iCode * ifx)
                 }
               // faster than result <- left, anl result,right
               // and better if result is SFR
-              if (AOP_TYPE (left) == AOP_ACC)
+              if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
+                  && AOP_TYPE(left)==AOP_ACC)
                 {
                   if (offset)
                     emitcode("mov", "a,b");
                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
                 }
+              else if (AOP_TYPE(left)==AOP_ACC)
+                {
+                  if (!offset)
+                    {
+                      bool pushedB = pushB ();
+                      emitcode("mov", "b,a");
+                      MOVA (aopGet (right, offset, FALSE, FALSE));
+                      emitcode("anl", "a,b");
+                      popB (pushedB);
+                    }
+                  else
+                    {
+                      MOVA (aopGet (right, offset, FALSE, FALSE));
+                      emitcode("anl", "a,b");
+                    }
+                }
               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
                 {
-                  emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+                  MOVB (aopGet (left, offset, FALSE, FALSE));
                   MOVA (aopGet (right, offset, FALSE, FALSE));
                   emitcode ("anl", "a,b");
                 }
@@ -7004,7 +7059,7 @@ genOr (iCode * ic, iCode * ifx)
                 }
               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
                 {
-                  emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+                  MOVB (aopGet (left, offset, FALSE, FALSE));
                   MOVA (aopGet (right, offset, FALSE, FALSE));
                   emitcode ("orl", "a,b");
                   aopPut (result, "a", offset);
@@ -7025,8 +7080,7 @@ genOr (iCode * ic, iCode * ifx)
                     }
                   else
                     {
-                      emitcode ("orl", "%s,a",
-                                aopGet (left, offset, FALSE, TRUE));
+                      emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
                     }
                 }
             }
@@ -7046,16 +7100,46 @@ genOr (iCode * ic, iCode * ifx)
             emitcode ("setb", "c");
           while (sizer--)
             {
-              if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
-                if (offset)
-                  emitcode("mov", "a,b");
-                emitcode ("orl", "a,%s",
-                          aopGet (right, offset, FALSE, FALSE));
-              } else {
-                MOVA (aopGet (right, offset, FALSE, FALSE));
-                emitcode ("orl", "a,%s",
-                          aopGet (left, offset, FALSE, FALSE));
+              if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
+                  && AOP_TYPE(left)==AOP_ACC)
+                {
+                  if (offset)
+                    emitcode("mov", "a,b");
+                  emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                }
+              else if (AOP_TYPE(left)==AOP_ACC)
+                {
+                  if (!offset)
+                    {
+                      bool pushedB = pushB ();
+                      emitcode("mov", "b,a");
+                      MOVA (aopGet (right, offset, FALSE, FALSE));
+                      emitcode("orl", "a,b");
+                      popB (pushedB);
+                    }
+                  else
+                    {
+                      MOVA (aopGet (right, offset, FALSE, FALSE));
+                      emitcode("orl", "a,b");
+                    }
+                }
+              else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
+                {
+                  MOVB (aopGet (left, offset, FALSE, FALSE));
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  emitcode ("orl", "a,b");
+                }
+              else if (aopGetUsesAcc (left, offset))
+                {
+                  MOVA (aopGet (left, offset, FALSE, FALSE));
+                  emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                }
+              else
+                {
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
               }
+
               emitcode ("jnz", "%05d$", tlbl->key + 100);
               offset++;
             }
@@ -7095,17 +7179,34 @@ genOr (iCode * ic, iCode * ifx)
                       continue;
                     }
                 }
-              // faster than result <- left, anl result,right
+              // faster than result <- left, orl result,right
               // and better if result is SFR
-              if (AOP_TYPE (left) == AOP_ACC)
+              if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
+                  && AOP_TYPE(left)==AOP_ACC)
                 {
                   if (offset)
                     emitcode("mov", "a,b");
                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
                 }
+              else if (AOP_TYPE(left)==AOP_ACC)
+                {
+                  if (!offset)
+                    {
+                      bool pushedB = pushB ();
+                      emitcode("mov", "b,a");
+                      MOVA (aopGet (right, offset, FALSE, FALSE));
+                      emitcode("orl", "a,b");
+                      popB (pushedB);
+                    }
+                  else
+                    {
+                      MOVA (aopGet (right, offset, FALSE, FALSE));
+                      emitcode("orl", "a,b");
+                    }
+                }
               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
                 {
-                  emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+                  MOVB (aopGet (left, offset, FALSE, FALSE));
                   MOVA (aopGet (right, offset, FALSE, FALSE));
                   emitcode ("orl", "a,b");
                 }
@@ -7232,7 +7333,6 @@ genXor (iCode * ic, iCode * ifx)
                     }
                 }
             }
-
         }
       else
         {
@@ -7314,7 +7414,7 @@ genXor (iCode * ic, iCode * ifx)
                 }
               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
                 {
-                  emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+                  MOVB (aopGet (left, offset, FALSE, FALSE));
                   MOVA (aopGet (right, offset, FALSE, FALSE));
                   emitcode ("xrl", "a,b");
                   aopPut (result, "a", offset);
@@ -7334,8 +7434,7 @@ genXor (iCode * ic, iCode * ifx)
                       aopPut (result, "a", offset);
                     }
                   else
-                    emitcode ("xrl", "%s,a",
-                              aopGet (left, offset, FALSE, TRUE));
+                    emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
                 }
             }
         }
@@ -7360,19 +7459,46 @@ genXor (iCode * ic, iCode * ifx)
                 {
                   MOVA (aopGet (left, offset, FALSE, FALSE));
                 }
+              else if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
+                  && AOP_TYPE(left)==AOP_ACC)
+                {
+                  if (offset)
+                    emitcode("mov", "a,b");
+                  emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                }
+              else if (AOP_TYPE(left)==AOP_ACC)
+                {
+                  if (!offset)
+                    {
+                      bool pushedB = pushB ();
+                      emitcode("mov", "b,a");
+                      MOVA (aopGet (right, offset, FALSE, FALSE));
+                      emitcode("xrl", "a,b");
+                      popB (pushedB);
+                    }
+                  else
+                    {
+                      MOVA (aopGet (right, offset, FALSE, FALSE));
+                      emitcode("xrl", "a,b");
+                    }
+                }
+              else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
+                {
+                  MOVB (aopGet (left, offset, FALSE, FALSE));
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  emitcode ("xrl", "a,b");
+                }
+              else if (aopGetUsesAcc (left, offset))
+                {
+                  MOVA (aopGet (left, offset, FALSE, FALSE));
+                  emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
+                }
               else
                 {
-                  if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
-                    if (offset)
-                      emitcode("mov", "a,b");
-                    emitcode ("xrl", "a,%s",
-                              aopGet (right, offset, FALSE, FALSE));
-                  } else {
-                    MOVA (aopGet (right, offset, FALSE, FALSE));
-                    emitcode ("xrl", "a,%s",
-                              aopGet (left, offset, FALSE, FALSE));
-                  }
+                  MOVA (aopGet (right, offset, FALSE, FALSE));
+                  emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
                 }
+              
               emitcode ("jnz", "%05d$", tlbl->key + 100);
               offset++;
             }
@@ -7402,17 +7528,34 @@ genXor (iCode * ic, iCode * ifx)
                       continue;
                     }
                 }
-              // faster than result <- left, anl result,right
+              // faster than result <- left, xrl result,right
               // and better if result is SFR
-              if (AOP_TYPE (left) == AOP_ACC)
+              if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
+                  && AOP_TYPE(left)==AOP_ACC)
                 {
                   if (offset)
                     emitcode("mov", "a,b");
                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
                 }
+              else if (AOP_TYPE(left)==AOP_ACC)
+                {
+                  if (!offset)
+                    {
+                      bool pushedB = pushB ();
+                      emitcode("mov", "b,a");
+                      MOVA (aopGet (right, offset, FALSE, FALSE));
+                      emitcode("xrl", "a,b");
+                      popB (pushedB);
+                    }
+                  else
+                    {
+                      MOVA (aopGet (right, offset, FALSE, FALSE));
+                      emitcode("xrl", "a,b");
+                    }
+                }
               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
                 {
-                  emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
+                  MOVB (aopGet (left, offset, FALSE, FALSE));
                   MOVA (aopGet (right, offset, FALSE, FALSE));
                   emitcode ("xrl", "a,b");
                 }
@@ -8323,8 +8466,8 @@ shiftL2Left2Result (operand * left, int offl,
     {
       /* don't crash result[offr] */
       MOVA (aopGet (left, offl, FALSE, FALSE));
-      emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
-      x = aopGet (result, offr, FALSE, FALSE);
+      x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
+      usedB = !strncmp(x, "b", 1);
     }
   else if (aopGetUsesAcc (result, offr))
     {
@@ -8375,8 +8518,8 @@ shiftR2Left2Result (operand * left, int offl,
     {
       /* don't crash result[offr] */
       MOVA (aopGet (left, offl, FALSE, FALSE));
-      emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
-      x = aopGet (result, offr, FALSE, FALSE);
+      x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
+      usedB = !strncmp(x, "b", 1);
     }
   else if (aopGetUsesAcc (result, offr))
     {
@@ -8445,7 +8588,16 @@ shiftRLeftOrResult (operand * left, int offl,
   /* shift right accumulator */
   AccRsh (shCount);
   /* or with result */
-  emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
+  if (aopGetUsesAcc(result, offr))
+    {
+      emitcode ("xch", "a,b");
+      MOVA (aopGet (result, offr, FALSE, FALSE));
+      emitcode ("orl", "a,b");
+    }
+  else
+    {
+      emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
+    }
   /* back to result */
   aopPut (result, "a", offr);
 }
@@ -8515,8 +8667,7 @@ shiftLLong (operand * left, operand * result, int offr)
       emitcode ("add", "a,acc");
       if (sameRegs (AOP (left), AOP (result)) &&
           size >= MSB16 + offr && offr != LSB)
-        emitcode ("xch", "a,%s",
-                  aopGet (left, LSB + offr, FALSE, FALSE));
+        xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
       else
         aopPut (result, "a", LSB + offr);
     }
@@ -8531,8 +8682,7 @@ shiftLLong (operand * left, operand * result, int offr)
       emitcode ("rlc", "a");
       if (sameRegs (AOP (left), AOP (result)) &&
           size >= MSB24 + offr && offr != LSB)
-        emitcode ("xch", "a,%s",
-                  aopGet (left, MSB16 + offr, FALSE, FALSE));
+        xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
       else
         aopPut (result, "a", MSB16 + offr);
     }
@@ -8547,8 +8697,7 @@ shiftLLong (operand * left, operand * result, int offr)
       emitcode ("rlc", "a");
       if (sameRegs (AOP (left), AOP (result)) &&
           size >= MSB32 + offr && offr != LSB)
-        emitcode ("xch", "a,%s",
-                  aopGet (left, MSB24 + offr, FALSE, FALSE));
+        xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
       else
         aopPut (result, "a", MSB24 + offr);
     }
@@ -8883,9 +9032,9 @@ static void
 shiftRLong (operand * left, int offl,
             operand * result, int sign)
 {
-  bool useSameRegs = regsInCommon (left, result);
+  bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
 
-  if (useSameRegs && offl>1)
+  if (overlapping && offl>1)
     {
       // we are in big trouble, but this shouldn't happen
       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
@@ -8900,9 +9049,9 @@ shiftRLong (operand * left, int offl,
         {
           emitcode ("rlc", "a");
           emitcode ("subb", "a,acc");
-          if (useSameRegs && sameReg (AOP (left), MSB32, AOP (result), MSB32))
+          if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
             {
-              emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
+              xch_a_aopGet (left, MSB32, FALSE, FALSE);
             }
           else
             {
@@ -8912,7 +9061,16 @@ shiftRLong (operand * left, int offl,
         }
       else
         {
-          aopPut (result, zero, MSB32);
+          if (aopPutUsesAcc (result, zero, MSB32))
+            {
+              emitcode("xch", "a,b");
+              aopPut (result, zero, MSB32);
+              emitcode("xch", "a,b");
+            }
+          else
+            {
+              aopPut (result, zero, MSB32);
+            }
         }
     }
 
@@ -8927,28 +9085,29 @@ shiftRLong (operand * left, int offl,
 
   emitcode ("rrc", "a");
 
-  if (useSameRegs && offl==MSB16 &&
-      sameReg (AOP (left), MSB24, AOP (result), MSB32-offl))
+  if (overlapping && offl==MSB16 &&
+      sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
     {
-      emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
+      xch_a_aopGet (left, MSB24, FALSE, FALSE);
     }
   else
     {
-      aopPut (result, "a", MSB32-offl);
+      aopPut (result, "a", MSB32 - offl);
       MOVA (aopGet (left, MSB24, FALSE, FALSE));
     }
 
   emitcode ("rrc", "a");
-  if (useSameRegs && offl==1 &&
-      sameReg (AOP (left), MSB16, AOP (result), MSB24-offl))
+  if (overlapping && offl==MSB16 &&
+      sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
     {
-      emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
+      xch_a_aopGet (left, MSB16, FALSE, FALSE);
     }
   else
     {
-      aopPut (result, "a", MSB24-offl);
+      aopPut (result, "a", MSB24 - offl);
       MOVA (aopGet (left, MSB16, FALSE, FALSE));
     }
+
   emitcode ("rrc", "a");
   if (offl != LSB)
     {
@@ -8956,10 +9115,10 @@ shiftRLong (operand * left, int offl,
     }
   else
     {
-      if (useSameRegs &&
-          sameReg (AOP (left), LSB, AOP (result), MSB16-offl))
+      if (overlapping &&
+          sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
         {
-          emitcode ("xch", "a,%s",aopGet (left, LSB, FALSE, FALSE));
+          xch_a_aopGet (left, LSB, FALSE, FALSE);
         }
       else
         {