* src/SDCCpeeph.c (labelIsReturnOnly): fixed bug 1464657
[fw/sdcc] / src / mcs51 / gen.c
index 82408a9600009aa879fbabef99a1b88631a7ba5f..e8b5afaba5abf93112addd9f882e2f8953a2e29e 100644 (file)
@@ -809,6 +809,24 @@ operandsEqu (operand * op1, operand * op2)
   return FALSE;
 }
 
+/*-----------------------------------------------------------------*/
+/* sameReg - two asmops have the same register at given offsets    */
+/*-----------------------------------------------------------------*/
+static bool
+sameReg (asmop * aop1, int off1, asmop * aop2, int off2)
+{
+  if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
+    return FALSE;
+
+  if (aop1->type != aop2->type)
+    return FALSE;
+
+  if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
+    return FALSE;
+
+  return TRUE;
+}
+
 /*-----------------------------------------------------------------*/
 /* sameRegs - two asmops have the same registers                   */
 /*-----------------------------------------------------------------*/
@@ -830,8 +848,7 @@ sameRegs (asmop * aop1, asmop * aop2)
     return FALSE;
 
   for (i = 0; i < aop1->size; i++)
-    if (aop1->aopu.aop_reg[i] !=
-        aop2->aopu.aop_reg[i])
+    if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
       return FALSE;
 
   return TRUE;
@@ -2593,12 +2610,12 @@ static void genSend(set *sendSet)
   for (sic = setFirstItem (sendSet); sic;
        sic = setNextItem (sendSet))
     {
-      aopOp (IC_LEFT (sic), sic, FALSE);
-
       if (sic->argreg > 12)
         {
           int bit = sic->argreg-13;
 
+          aopOp (IC_LEFT (sic), sic, FALSE);
+
           /* if left is a literal then
              we know what the value is */
           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
@@ -2625,8 +2642,9 @@ static void genSend(set *sendSet)
             }
           bit_count++;
           BitBankUsed = 1;
+
+          freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
         }
-      freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
     }
 
   if (bit_count)
@@ -2639,30 +2657,33 @@ static void genSend(set *sendSet)
   for (sic = setFirstItem (sendSet); sic;
        sic = setNextItem (sendSet))
     {
-      int size, offset = 0;
-      aopOp (IC_LEFT (sic), sic, FALSE);
-      size = AOP_SIZE (IC_LEFT (sic));
-
-      if (sic->argreg == 1)
+      if (sic->argreg <= 12)
         {
-          while (size--)
+          int size, offset = 0;
+          aopOp (IC_LEFT (sic), sic, FALSE);
+          size = AOP_SIZE (IC_LEFT (sic));
+
+          if (sic->argreg == 1)
             {
-              char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
-              if (strcmp (l, fReturn[offset]))
-                  emitcode ("mov", "%s,%s", fReturn[offset], l);
-              offset++;
+              while (size--)
+                {
+                  char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
+                  if (strcmp (l, fReturn[offset]))
+                      emitcode ("mov", "%s,%s", fReturn[offset], l);
+                  offset++;
+                }
             }
-        }
-      else if (sic->argreg <= 12)
-        {
-          while (size--)
+          else
             {
-              emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
-                        aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
-              offset++;
+              while (size--)
+                {
+                  emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
+                            aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
+                  offset++;
+                }
             }
+          freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
         }
-      freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
     }
 }
 
@@ -2698,6 +2719,7 @@ genCall (iCode * ic)
   bool accuse = FALSE;
   bool accPushed = FALSE;
   bool resultInF0 = FALSE;
+  bool assignResultGenerated = FALSE;
 
   D(emitcode(";     genCall",""));
 
@@ -2780,6 +2802,7 @@ genCall (iCode * ic)
       _G.accInUse--;
 
       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
+      assignResultGenerated = TRUE;
 
       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
     }
@@ -2796,7 +2819,8 @@ genCall (iCode * ic)
               accPushed = TRUE;
             }
           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
-              IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
+              IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
+              !assignResultGenerated)
             {
               emitcode ("mov", "F0,c");
               resultInF0 = TRUE;
@@ -2835,7 +2859,7 @@ genCall (iCode * ic)
 //  if (restoreBank)
 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
 
-  if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
+  if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
     {
       if (resultInF0)
           emitcode ("mov", "c,F0");
@@ -8771,59 +8795,89 @@ static void
 shiftRLong (operand * left, int offl,
             operand * result, int sign)
 {
-  int isSameRegs = sameRegs (AOP (left), AOP (result));
+  bool useSameRegs = regsInCommon (left, result);
 
-  if (isSameRegs && offl>1) {
-    // we are in big trouble, but this shouldn't happen
-    werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
-  }
+  if (useSameRegs && offl>1)
+    {
+      // we are in big trouble, but this shouldn't happen
+      werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
+    }
 
   MOVA (aopGet (left, MSB32, FALSE, FALSE));
 
-  if (offl==MSB16) {
-    // shift is > 8
-    if (sign) {
-      emitcode ("rlc", "a");
-      emitcode ("subb", "a,acc");
-      if (isSameRegs)
-        emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
-      else {
-        aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
-        MOVA (aopGet (left, MSB32, FALSE, FALSE));
-      }
-    } else {
-      aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
+  if (offl==MSB16)
+    {
+      // shift is > 8
+      if (sign)
+           {
+          emitcode ("rlc", "a");
+          emitcode ("subb", "a,acc");
+          if (useSameRegs && sameReg (AOP (left), MSB32, AOP (result), MSB32))
+                   {
+              emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
+                   }
+          else
+                   {
+              aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
+              MOVA (aopGet (left, MSB32, FALSE, FALSE));
+                   }
+           }
+         else
+           {
+          aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
+           }
     }
-  }
 
-  if (!sign) {
-    emitcode ("clr", "c");
-  } else {
-    emitcode ("mov", "c,acc.7");
-  }
+  if (!sign)
+    {
+      emitcode ("clr", "c");
+    }
+  else
+    {
+      emitcode ("mov", "c,acc.7");
+    }
 
   emitcode ("rrc", "a");
 
-  if (isSameRegs && offl==MSB16) {
-    emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
-  } else {
-    aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
-    MOVA (aopGet (left, MSB24, FALSE, FALSE));
-  }
+  if (useSameRegs && offl==MSB16 &&
+      sameReg (AOP (left), MSB24, AOP (result), MSB32-offl))
+    {
+      emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
+    }
+  else
+    {
+      aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
+      MOVA (aopGet (left, MSB24, FALSE, FALSE));
+    }
 
   emitcode ("rrc", "a");
-  if (isSameRegs && offl==1) {
-    emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
-  } else {
-    aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
-    MOVA (aopGet (left, MSB16, FALSE, FALSE));
-  }
+  if (useSameRegs && offl==1 &&
+      sameReg (AOP (left), MSB16, AOP (result), MSB24-offl))
+    {
+      emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
+    }
+  else
+    {
+      aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
+      MOVA (aopGet (left, MSB16, FALSE, FALSE));
+    }
   emitcode ("rrc", "a");
-  aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
-
-  if (offl == LSB)
+  if (offl != LSB)
     {
-      MOVA (aopGet (left, LSB, FALSE, FALSE));
+      aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
+    }
+  else
+    {
+      if (useSameRegs &&
+          sameReg (AOP (left), LSB, AOP (result), MSB16-offl))
+        {
+          emitcode ("xch", "a,%s",aopGet (left, LSB, FALSE, FALSE));
+        }
+      else
+        {
+          aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
+          MOVA (aopGet (left, LSB, FALSE, FALSE));
+           }
       emitcode ("rrc", "a");
       aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
     }
@@ -10782,15 +10836,24 @@ genJumpTab (iCode * ic)
       /* this algorithm needs 9 cycles and 7 + 3*n bytes
          if the switch argument is in a register.
          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
-      /* (MB) What if peephole converts ljmp to sjmp or ret ???
-         How will multiply by three be updated ???*/
+      /* Peephole may not convert ljmp to sjmp or ret
+         labelIsReturnOnly & labelInRange must check
+         currPl->ic->op != JUMPTABLE */
       aopOp (IC_JTCOND (ic), ic, FALSE);
       /* get the condition into accumulator */
       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
       MOVA (l);
       /* multiply by three */
-      emitcode ("add", "a,acc");
-      emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
+      if (aopGetUsesAcc (IC_JTCOND (ic), 0))
+        {
+          emitcode ("mov", "b,#3");
+          emitcode ("mul", "ab");
+        }
+      else
+        {
+          emitcode ("add", "a,acc");
+          emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
+        }
       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
 
       jtab = newiTempLabel (NULL);