]> git.sur5r.net Git - cc65/blobdiff - src/cc65/assignment.c
Reverted part of change 4108 that prevented an optimization step to find
[cc65] / src / cc65 / assignment.c
index af414ff50e76e2902c7b4c40e567a462125271c9..662128c84821d3bafacaafe8667f516ad2a0869f 100644 (file)
@@ -34,6 +34,7 @@
 
 
 /* cc65 */
+#include "asmcode.h"
 #include "assignment.h"
 #include "codegen.h"
 #include "datatype.h"
@@ -160,6 +161,9 @@ void Assignment (ExprDesc* Expr)
 
     } else if (ED_IsBitField (Expr)) {
 
+        CodeMark AndPos;
+        CodeMark PushPos;
+
         unsigned Mask;
         unsigned Flags;
 
@@ -182,30 +186,57 @@ void Assignment (ExprDesc* Expr)
 
         /* Mask unwanted bits */
         Mask = (0x0001U << Expr->BitWidth) - 1U;
+        GetCodePos (&AndPos);
         g_and (Flags | CF_CONST, ~(Mask << Expr->BitOffs));
 
         /* Push it on stack */
+        GetCodePos (&PushPos);
         g_push (Flags, 0);
 
        /* Read the expression on the right side of the '=' */
-       hie1 (&Expr2);
+               MarkedExprWithCheck (hie1, &Expr2);
 
-       /* Do type conversion if necessary. Beware: Do not use char type 
+       /* Do type conversion if necessary. Beware: Do not use char type
          * here!
          */
        TypeConversion (&Expr2, ltype);
 
-       /* If necessary, load the value into the primary register */
-       LoadExpr (CF_NONE, &Expr2);
+        /* Special treatment if the value is constant. */
+        /* Beware: Expr2 may contain side effects, so there must not be
+         * code generated for Expr2.
+         */
+        if (ED_IsConstAbsInt (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) {
+
+            /* Get the value and apply the mask */
+            unsigned Val = (unsigned) (Expr2.IVal & Mask);
 
-        /* Apply the mask */
-        g_and (Flags | CF_CONST, Mask);
+            /* Since we will do the OR with a constant, we can remove the push */
+            RemoveCode (&PushPos);
 
-        /* Shift it into the right position */
-        g_asl (Flags | CF_CONST, Expr->BitOffs);
+            /* If the value is equal to the mask now, all bits are one, and we
+             * can remove the mask operation from above.
+             */
+            if (Val == Mask) {
+                RemoveCode (&AndPos);
+            }
 
-        /* Or both values */
-        g_or (Flags, 0);
+            /* Generate the or operation */
+            g_or (Flags | CF_CONST, Val << Expr->BitOffs);
+
+        } else {
+
+            /* If necessary, load the value into the primary register */
+            LoadExpr (CF_NONE, &Expr2);
+
+            /* Apply the mask */
+            g_and (Flags | CF_CONST, Mask);
+
+            /* Shift it into the right position */
+            g_asl (Flags | CF_CONST, Expr->BitOffs);
+
+            /* Or both values */
+            g_or (Flags, 0);
+        }
 
        /* Generate a store instruction */
        Store (Expr, 0);