* src/ds390/gen.c (genCall): fixed a double use of acc and b after
[fw/sdcc] / src / ds390 / gen.c
index 99dba5b475767aa9516308518a7a4564bd8d78f1..979d993e9373525f442027e43f4c535d761dc278 100644 (file)
@@ -516,7 +516,13 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
 
   /* if already has one */
   if (sym->aop)
-    return sym->aop;
+    {
+      if ((sym->aop->type == AOP_DPTR && useDP2)
+          || (sym->aop->type == AOP_DPTR2 && !useDP2))
+       sym->aop = NULL;
+      else
+        return sym->aop;
+    }
 
   /* assign depending on the storage class */
   /* if it is on the stack or indirectly addressable */
@@ -862,6 +868,14 @@ operandsEqu (operand * op1, operand * op2)
       (sym2->usl.spillLoc == sym1))
     return TRUE;
 
+  /* are they spilt to the same location */
+  if (IS_ITEMP (op2) &&
+      IS_ITEMP (op1) &&
+      sym2->isspilt &&
+      sym1->isspilt &&
+      (sym1->usl.spillLoc == sym2->usl.spillLoc))
+    return TRUE;
+    
   return FALSE;
 }
 
@@ -921,13 +935,23 @@ aopOp (operand * op, iCode * ic, bool result, bool useDP2)
 
   /* if already has a asmop then continue */
   if (op->aop)
-    return;
+    {
+      if ((op->aop->type == AOP_DPTR && useDP2)
+          || (op->aop->type == AOP_DPTR2 && !useDP2))
+       op->aop = NULL;
+      else
+        return;
+    }
 
   /* if the underlying symbol has a aop */
   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
     {
       op->aop = OP_SYMBOL (op)->aop;
-      return;
+      if ((op->aop->type == AOP_DPTR && useDP2)
+          || (op->aop->type == AOP_DPTR2 && !useDP2))
+       op->aop = NULL;
+      else
+        return;
     }
 
   /* if this is a true symbol */
@@ -1961,7 +1985,7 @@ genUminus (iCode * ic)
 
   /* assign asmops */
   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
-  aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
+  aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
 
   /* if both in bit space then special
      case */
@@ -2651,9 +2675,16 @@ genCall (iCode * ic)
          if (size > 1)
            {
              emitcode ("mov", "b,%s", fReturn[1]);
+             _G.bInUse++;
            }
 
+         _G.accInUse++;
          aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
+         _G.accInUse--;
+         
+         if (size > 1)
+           _G.bInUse--;
+
          aopPut (AOP (IC_RESULT (ic)), "a", 0);
 
          if (size > 1)
@@ -2664,9 +2695,9 @@ genCall (iCode * ic)
        }
       else
        {
-         _G.accInUse++;
+         _G.bInUse++;
          aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
-         _G.accInUse--;
+         _G.bInUse--;
 
          assignResultValue (IC_RESULT (ic));
 
@@ -3194,9 +3225,12 @@ genFunction (iCode * ic)
   /* if critical function then turn interrupts off */
   if (IFFUNC_ISCRITICAL (ftype))
     {
-      emitcode ("mov", "c,ea");
+      symbol *tlbl = newiTempLabel (NULL);
+      emitcode ("setb", "c");
+      emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
+      emitcode ("clr", "c");
+      emitcode ("", "%05d$:", (tlbl->key + 100));
       emitcode ("push", "psw"); /* save old ea via c in psw */
-      emitcode ("clr", "ea");
     }
 
 }
@@ -3916,7 +3950,8 @@ bool aopOp3(iCode * ic)
     }
 
     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
-    
+
+        
     // We've op'd the left & right. So, if left or right are the same operand as result, 
     // we know aopOp will succeed, and we can just do it & bail.
     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
@@ -3927,6 +3962,19 @@ bool aopOp3(iCode * ic)
        return TRUE;
     }
     
+    // Operands may be equivalent (but not equal) if they share a spill location. If
+    // so, use the same DPTR or DPTR2.
+    if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
+      {
+        aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
+       return TRUE;
+      }
+    if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
+      {
+        aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
+       return TRUE;
+      }
+    
     // Note which dptrs are currently in use.
     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
@@ -5657,6 +5705,7 @@ 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;
@@ -5695,6 +5744,8 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
      if the left is a pointer register & right is not */
   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)))
     {
@@ -6381,6 +6432,8 @@ genAnd (iCode * ic, iCode * ifx)
            {
              if (ifx)
                jmpTrueOrFalse (ifx, tlbl);
+              else
+               emitcode ("", "!tlabeldef", tlbl->key + 100);
              goto release;
            }
        }
@@ -6471,6 +6524,8 @@ genAnd (iCode * ic, iCode * ifx)
            }
          else if (ifx)
            jmpTrueOrFalse (ifx, tlbl);
+          else
+           emitcode ("", "!tlabeldef", tlbl->key + 100);
        }
       else
        {
@@ -6789,6 +6844,8 @@ genOr (iCode * ic, iCode * ifx)
            }
          else if (ifx)
            jmpTrueOrFalse (ifx, tlbl);
+          else
+           emitcode ("", "!tlabeldef", tlbl->key + 100);
        }
       else
        {
@@ -7325,6 +7382,65 @@ 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, FALSE);
+  aopOp (result, ic, FALSE, AOP_USESDPTR(left));
+  
+  _startLazyDPSEvaluation ();
+  switch (AOP_SIZE (left))
+    {
+    case 1: /* swap nibbles in byte */
+      MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+      emitcode ("swap", "a");
+      aopPut (AOP (result), "a", 0);
+      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, NULL));
+         aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
+         aopPut (AOP (result), "a", 1);
+       }
+      else if (operandsEqu (left, result))
+       {
+          char * reg = "a";
+         MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+         if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
+           {
+             emitcode ("mov", "b,a");
+              reg = "b";
+              _G.bInUse=1;
+            }
+         aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
+         aopPut (AOP (result), reg, 1);
+          _G.bInUse=0;
+       }
+      else
+       {
+         aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
+         aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
+       }
+      break;
+    default:
+      wassertl(FALSE, "unsupported SWAP operand size");
+    }
+  _endLazyDPSEvaluation ();
+  
+  freeAsmop (left, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
 /*-----------------------------------------------------------------*/
 /* AccRol - rotate left accumulator by known count                 */
 /*-----------------------------------------------------------------*/
@@ -8684,7 +8800,7 @@ genRightShiftLiteral (operand * left,
    && (size != 2)
    && (size != 4))
   {
-      D(emitcode (";", "genRightShiftLiteral wimping out"););  
+      D(emitcode (";", "genRightShiftLiteral wimping out"););
       return FALSE;
   }
 
@@ -8878,7 +8994,7 @@ static void
 genRightShift (iCode * ic)
 {
   operand *right, *left, *result;
-  sym_link *retype;
+  sym_link *letype;
   int size, offset;
   char *l;
   symbol *tlbl, *tlbl1;
@@ -8887,9 +9003,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;
@@ -11047,7 +11163,7 @@ genCast (iCode * ic)
     return;
 
   aopOp (right, ic, FALSE, FALSE);
-  aopOp (result, ic, FALSE, AOP_USESDPTR(right));
+  aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
 
   /* if the result is a bit */
   if (IS_BITVAR (OP_SYMBOL (result)->type)
@@ -12643,36 +12759,121 @@ static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *na
 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, FALSE);
 
-  aopOp (right, ic, FALSE, 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, 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, FALSE));
-      offset++;
+      aopOp (op, ic, FALSE, 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, FALSE));
+           offset++;
+         }
+       }
+
+      freeAsmop (op, NULL, ic, TRUE);
     }
+    
+}
 
-release:
-  freeAsmop (right, NULL, ic, TRUE);
+/*-----------------------------------------------------------------*/
+/* genCritical - generate code for start of a critical sequence    */
+/*-----------------------------------------------------------------*/
+static void
+genCritical (iCode *ic)
+{
+  symbol *tlbl = newiTempLabel (NULL);
+
+  D(emitcode(";     genCritical",""));
+  
+  if (IC_RESULT (ic))
+    aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
+
+  emitcode ("setb", "c");
+  emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
+  emitcode ("clr", "c");
+  emitcode ("", "%05d$:", (tlbl->key + 100));
+
+  if (IC_RESULT (ic))
+    outBitC (IC_RESULT (ic)); /* save old ea in an operand */
+  else
+    emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
+
+  if (IC_RESULT (ic))
+    freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
 }
 
+/*-----------------------------------------------------------------*/
+/* genEndCritical - generate code for end of a critical sequence   */
+/*-----------------------------------------------------------------*/
+static void
+genEndCritical (iCode *ic)
+{
+  D(emitcode(";     genEndCritical",""));
+  
+  if (IC_RIGHT (ic))
+    {
+      aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
+      if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
+        {
+         emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
+          emitcode ("mov", "ea,c");
+        }
+      else
+        {
+          MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
+          emitcode ("rrc", "a");
+          emitcode ("mov", "ea,c");
+        }
+      freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
+    }
+  else
+    {
+      emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
+      emitcode ("mov", "ea,c");
+    }
+}
+
+
+
 /*-----------------------------------------------------------------*/
 /* genBuiltIn - calls the appropriate function to  generating code */
 /* for a built in function                                        */
@@ -13046,6 +13247,18 @@ gen390Code (iCode * lic)
          genDummyRead (ic);
          break;
 
+       case CRITICAL:
+         genCritical (ic);
+         break;
+
+       case ENDCRITICAL:
+         genEndCritical (ic);
+         break;
+       
+        case SWAP:
+         genSwap (ic);
+         break;
+          
 #if 0 // obsolete, and buggy for != xdata
        case ARRAYINIT:
            genArrayInit(ic);