* configure.in,
[fw/sdcc] / src / mcs51 / gen.c
index be482612447b15e1b03af774379d1c94ab5036f6..e9f0df3c3907375972af4590d50cd15bb25af35b 100644 (file)
@@ -969,7 +969,7 @@ aopOp (operand * op, iCode * ic, bool result)
       if (sym->remat)
         {
           sym->aop = op->aop = aop = aopForRemat (sym);
-          aop->size = getSize (sym->type);
+          aop->size = operandSize (op);
           return;
         }
 
@@ -1492,6 +1492,7 @@ aopPut (operand * result, const char *s, int offset)
   bool bvolatile = isOperandVolatile (result, FALSE);
   bool accuse = FALSE;
   asmop * aop = AOP (result);
+  const char *d = NULL;
 
   if (aop->size && offset > (aop->size - 1))
     {
@@ -1667,28 +1668,40 @@ aopPut (operand * result, const char *s, int offset)
       break;
 
     case AOP_CRY:
-      /* if result no bit variable */
-      if (!aop->aopu.aop_dir)
-        {
-          assert (!strcmp (s, "c"));
-          /* inefficient: move carry into A and use jz/jnz */
-          emitcode ("clr", "a");
-          emitcode ("rlc", "a");
-          accuse = TRUE;
-        }
-      else if (s == zero)
-          emitcode ("clr", "%s", aop->aopu.aop_dir);
-      else if (s == one)
-          emitcode ("setb", "%s", aop->aopu.aop_dir);
-      else if (!strcmp (s, "c"))
-          emitcode ("mov", "%s,c", aop->aopu.aop_dir);
-      else if (strcmp (s, aop->aopu.aop_dir))
+      // destination is carry for return-use-only
+      d = (IS_OP_RUONLY (result)) ? "c" : aop->aopu.aop_dir;
+      // source is no literal and not in carry
+      if ((s != zero) && (s != one) && strcmp (s, "c"))
         {
           MOVA (s);
           /* set C, if a >= 1 */
           emitcode ("add", "a,#0xff");
-          emitcode ("mov", "%s,c", aop->aopu.aop_dir);
+          s = "c";
         }
+      // now source is zero, one or carry
+
+      /* if result no bit variable */
+      if (!d)
+        {
+          if (!strcmp (s, "c"))
+            {
+              /* inefficient: move carry into A and use jz/jnz */
+              emitcode ("clr", "a");
+              emitcode ("rlc", "a");
+              accuse = TRUE;
+            }
+          else
+            {
+              MOVA (s);
+              accuse = TRUE;
+            }
+        }
+      else if (s == zero)
+          emitcode ("clr", "%s", d);
+      else if (s == one)
+          emitcode ("setb", "%s", d);
+      else if (strcmp (s, d))
+          emitcode ("mov", "%s,c", d);
       break;
 
     case AOP_STR:
@@ -1839,7 +1852,7 @@ outBitC (operand * result)
   /* if the result is bit */
   if (AOP_TYPE (result) == AOP_CRY)
     {
-      if (!OP_SYMBOL (result)->ruonly)
+      if (!IS_OP_RUONLY (result))
         aopPut (result, "c", 0);
     }
   else
@@ -1993,7 +2006,7 @@ genNot (iCode * ic)
         }
       else
         {
-          emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
+          toCarry (IC_LEFT (ic));
           emitcode ("cpl", "c");
           outBitC (IC_RESULT (ic));
         }
@@ -4040,7 +4053,7 @@ genRet (iCode * ic)
 
   if (IS_BIT(_G.currentFunc->etype))
     {
-      if (!(IS_SYMOP (IC_LEFT (ic)) && OP_SYMBOL (IC_LEFT (ic))->ruonly))
+      if (!IS_OP_RUONLY (IC_LEFT (ic)))
         toCarry (IC_LEFT (ic));
     }
   else
@@ -6034,8 +6047,9 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
   /* if the left side is a literal or
      if the right is in a pointer register and left
      is not */
-  if ((AOP_TYPE (left) == AOP_LIT) ||
+  if ((AOP_TYPE (left) == AOP_LIT)  ||
       (AOP_TYPE (left) == AOP_IMMD) ||
+      (AOP_TYPE (left) == AOP_DIR)  ||
       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
     {
       operand *t = right;
@@ -6102,7 +6116,7 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
 /* gencjne - compare and jump if not equal                         */
 /*-----------------------------------------------------------------*/
 static void
-gencjne (operand * left, operand * right, symbol * lbl)
+gencjne (operand * left, operand * right, symbol * lbl, bool useCarry)
 {
   symbol *tlbl = newiTempLabel (NULL);
 
@@ -6110,10 +6124,16 @@ gencjne (operand * left, operand * right, symbol * lbl)
 
   gencjneshort (left, right, lbl);
 
-  emitcode ("mov", "a,%s", one);
+  if (useCarry)
+      SETC;
+  else
+      MOVA (one);
   emitcode ("sjmp", "%05d$", tlbl->key + 100);
   emitLabel (lbl);
-  emitcode ("clr", "a");
+  if (useCarry)
+      CLRC;
+  else
+      MOVA (zero);
   emitLabel (tlbl);
 }
 
@@ -6274,12 +6294,13 @@ genCmpEq (iCode * ic, iCode * ifx)
     }
   else
     {
-      gencjne (left, right, newiTempLabel (NULL));
       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
         {
-          aopPut (result, "a", 0);
+          gencjne (left, right, newiTempLabel (NULL), TRUE);
+          aopPut (result, "c", 0);
           goto release;
         }
+      gencjne (left, right, newiTempLabel (NULL), FALSE);
       if (ifx)
         {
           genIfxJump (ifx, "a", left, right, result);
@@ -6613,8 +6634,15 @@ genAnd (iCode * ic, iCode * ifx)
           if (AOP_TYPE (right) == AOP_CRY)
             {
               // c = bit & bit;
-              emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
-              emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
+              if (IS_OP_ACCUSE (left))
+                {
+                  emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
+                }
+                         else
+                {
+                  emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
+                  emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
+                }
             }
           else
             {
@@ -7035,8 +7063,15 @@ genOr (iCode * ic, iCode * ifx)
           if (AOP_TYPE (right) == AOP_CRY)
             {
               // c = bit | bit;
-              emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
-              emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
+              if (IS_OP_ACCUSE (left))
+                {
+                  emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
+                }
+                         else
+                {
+                  emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
+                  emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
+                }
             }
           else
             {
@@ -7434,25 +7469,21 @@ genXor (iCode * ic, iCode * ifx)
           if (AOP_TYPE (right) == AOP_CRY)
             {
               // c = bit ^ bit;
-              emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
+              if (IS_OP_ACCUSE (left))
+                {// left already is in the carry
+                  operand *tmp = right;
+                  right = left;
+                  left = tmp;
+                }
+              else
+                {
+                  toCarry (right);
+                }
             }
           else
             {
-              int sizer = AOP_SIZE (right);
               // c = bit ^ val
-              // if val>>1 != 0, result = 1
-              emitcode ("setb", "c");
-              while (sizer)
-                {
-                  MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
-                  if (sizer == 1)
-                    // test the msb of the lsb
-                    emitcode ("anl", "a,#0xfe");
-                  emitcode ("jnz", "%05d$", tlbl->key + 100);
-                  sizer--;
-                }
-              // val = (0,1)
-              emitcode ("rrc", "a");
+              toCarry (right);
             }
           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
           emitcode ("cpl", "c");
@@ -7680,40 +7711,51 @@ static void
 genInline (iCode * ic)
 {
   char *buffer, *bp, *bp1;
+  bool inComment = FALSE;
 
   D (emitcode (";", "genInline"));
 
   _G.inLine += (!options.asmpeep);
 
-  buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
+  buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
 
   /* emit each line as a code */
   while (*bp)
     {
-      if (*bp == '\n')
+      switch (*bp)
         {
+        case ';':
+          inComment = TRUE;
+          ++bp;
+          break;
+
+        case '\n':
+          inComment = FALSE;
           *bp++ = '\0';
           emitcode (bp1, "");
           bp1 = bp;
-        }
-      else
-        {
+          break;
+
+        default:
           /* Add \n for labels, not dirs such as c:\mydir */
-          if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
+          if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
             {
-              bp++;
+              ++bp;
               *bp = '\0';
-              bp++;
+              ++bp;
               emitcode (bp1, "");
               bp1 = bp;
             }
           else
-            bp++;
+            ++bp;
+          break;
         }
     }
   if (bp1 != bp)
     emitcode (bp1, "");
-  /*     emitcode("",buffer); */
+
+  Safe_free (buffer);
+
   _G.inLine -= (!options.asmpeep);
 }
 
@@ -10507,7 +10549,7 @@ genDataPointerSet (operand * right,
 
   l = aopGet (result, 0, FALSE, TRUE);
   l++; //remove #
-  size = AOP_SIZE (right);
+  size = max (AOP_SIZE (right), AOP_SIZE (result));
   while (size--)
     {
       if (offset)
@@ -10518,12 +10560,12 @@ genDataPointerSet (operand * right,
                 aopGet (right, offset++, FALSE, FALSE));
     }
 
-  freeAsmop (result, NULL, ic, TRUE);
   freeAsmop (right, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genNearPointerSet - emitcode for near pointer put                */
+/* genNearPointerSet - emitcode for near pointer put               */
 /*-----------------------------------------------------------------*/
 static void
 genNearPointerSet (operand * right,
@@ -10648,9 +10690,10 @@ genNearPointerSet (operand * right,
     }
 
   /* done */
-  if (pi) pi->generated = 1;
-  freeAsmop (result, NULL, ic, TRUE);
+  if (pi)
+    pi->generated = 1;
   freeAsmop (right, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/