]> git.sur5r.net Git - cc65/commitdiff
First implementation of bit fields.
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 29 Aug 2009 21:20:13 +0000 (21:20 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 29 Aug 2009 21:20:13 +0000 (21:20 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@4079 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/assignment.c
src/cc65/expr.c
src/cc65/exprdesc.c
src/cc65/exprdesc.h
src/cc65/loadexpr.c

index d4e9d61fdc3f74c1ae1d42fbab6105b2d79a2037..24fccfaa34d1387d136b750c6137f992ac669dd1 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2002-2006 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2002-2009, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -96,7 +96,7 @@ void Assignment (ExprDesc* Expr)
         }
         if (UseReg) {
             PushAddr (Expr);
-        } else {  
+        } else {
             ED_MakeRVal (Expr);
            LoadExpr (CF_NONE, Expr);
             g_push (CF_PTR | CF_UNSIGNED, 0);
@@ -158,6 +158,46 @@ void Assignment (ExprDesc* Expr)
 
         }
 
+    } else if (ED_IsBitField (Expr)) {
+
+        unsigned Mask;
+        unsigned Flags = TypeOf (Expr->Type);
+
+        /* Assignment to a bit field. Get the address on stack for the store. */
+        PushAddr (Expr);
+
+        /* Load the value from the location as an unsigned */
+        Expr->Flags &= ~E_BITFIELD;
+        LoadExpr (CF_NONE, Expr);
+
+        /* Mask unwanted bits */
+        Mask = (0x0001U << Expr->BitWidth) - 1U;
+        g_and (Flags | CF_CONST, ~(Mask << Expr->BitOffs));
+
+        /* Push it on stack */
+        g_push (Flags, 0);
+
+       /* Read the expression on the right side of the '=' */
+       hie1 (&Expr2);
+
+       /* Do type conversion if necessary */
+       TypeConversion (&Expr2, ltype);
+
+       /* 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);
+
     } else {
 
        /* Get the address on stack if needed */
index 1d5dd9ccdc7eb84c74b141a168f8fa01a4154607..d1413bb818a205a216b554a202574f10fdd7ba96 100644 (file)
@@ -779,7 +779,7 @@ static void ArrayRef (ExprDesc* Expr)
 /* Handle an array reference. This function needs a rewrite. */
 {
     int         ConstBaseAddr;
-    ExprDesc    SubScript;
+    ExprDesc    Subscript;
     CodeMark    Mark1;
     CodeMark    Mark2;
     Type*       ElementType;
@@ -814,7 +814,7 @@ static void ArrayRef (ExprDesc* Expr)
     }
 
     /* TOS now contains ptr to array elements. Get the subscript. */
-    ExprWithCheck (hie0, &SubScript);
+    ExprWithCheck (hie0, &Subscript);
 
     /* Check the types of array and subscript. We can either have a
      * pointer/array to the left, in which case the subscript must be of an
@@ -824,33 +824,39 @@ static void ArrayRef (ExprDesc* Expr)
      * correct types.
      */
     if (IsClassPtr (Expr->Type)) {
-        if (!IsClassInt (SubScript.Type))  {
+        if (!IsClassInt (Subscript.Type))  {
             Error ("Array subscript is not an integer");
             /* To avoid any compiler errors, make the expression a valid int */
-            ED_MakeConstAbsInt (&SubScript, 0);
+            ED_MakeConstAbsInt (&Subscript, 0);
         }
         ElementType = Indirect (Expr->Type);
     } else if (IsClassInt (Expr->Type)) {
-        if (!IsClassPtr (SubScript.Type)) {
+        if (!IsClassPtr (Subscript.Type)) {
             Error ("Subscripted value is neither array nor pointer");
             /* To avoid compiler errors, make the subscript a char[] at
              * address 0.
              */
-            ED_MakeConstAbs (&SubScript, 0, GetCharArrayType (1));
+            ED_MakeConstAbs (&Subscript, 0, GetCharArrayType (1));
         }
-        ElementType = Indirect (SubScript.Type);
+        ElementType = Indirect (Subscript.Type);
     } else {
         Error ("Cannot subscript");
         /* To avoid compiler errors, fake both the array and the subscript, so
          * we can just proceed.
          */
         ED_MakeConstAbs (Expr, 0, GetCharArrayType (1));
-        ED_MakeConstAbsInt (&SubScript, 0);
+        ED_MakeConstAbsInt (&Subscript, 0);
         ElementType = Indirect (Expr->Type);
     }
 
+    /* If the subscript is a bit-field, load it and make it an rvalue */
+    if (ED_IsBitField (&Subscript)) {
+        LoadExpr (CF_NONE, &Subscript);
+        ED_MakeRValExpr (&Subscript);
+    }
+
     /* Check if the subscript is constant absolute value */
-    if (ED_IsConstAbs (&SubScript)) {
+    if (ED_IsConstAbs (&Subscript)) {
 
                /* The array subscript is a numeric constant. If we had pushed the
          * array base address onto the stack before, we can remove this value,
@@ -868,7 +874,7 @@ static void ArrayRef (ExprDesc* Expr)
                    /* Lhs is pointer/array. Scale the subscript value according to
              * the element size.
              */
-           SubScript.IVal *= CheckedSizeOf (ElementType);
+           Subscript.IVal *= CheckedSizeOf (ElementType);
 
             /* Remove the address load code */
             RemoveCode (&Mark1);
@@ -880,7 +886,7 @@ static void ArrayRef (ExprDesc* Expr)
             if (IsTypeArray (Expr->Type)) {
 
                 /* Adjust the offset */
-                Expr->IVal += SubScript.IVal;
+                Expr->IVal += Subscript.IVal;
 
             } else {
 
@@ -893,7 +899,7 @@ static void ArrayRef (ExprDesc* Expr)
                 }
 
                 /* Use the offset */
-                Expr->IVal = SubScript.IVal;
+                Expr->IVal = Subscript.IVal;
             }
 
                } else {
@@ -905,7 +911,7 @@ static void ArrayRef (ExprDesc* Expr)
              * we will ignore the true type of the subscript here and
              * use always an int. #### Use offset but beware of LoadExpr!
              */
-            g_inc (CF_INT | CF_CONST, SubScript.IVal);
+            g_inc (CF_INT | CF_CONST, Subscript.IVal);
 
        }
 
@@ -913,7 +919,7 @@ static void ArrayRef (ExprDesc* Expr)
 
        /* Array subscript is not constant. Load it into the primary */
        GetCodePos (&Mark2);
-        LoadExpr (CF_NONE, &SubScript);
+        LoadExpr (CF_NONE, &Subscript);
 
         /* Do scaling */
        if (IsClassPtr (Expr->Type)) {
@@ -968,13 +974,13 @@ static void ArrayRef (ExprDesc* Expr)
             * subscript was not scaled, that is, if this was a byte array
             * or pointer.
             */
-            if ((ED_IsLocConst (&SubScript) || ED_IsLocStack (&SubScript)) &&
+            if ((ED_IsLocConst (&Subscript) || ED_IsLocStack (&Subscript)) &&
                 CheckedSizeOf (ElementType) == SIZEOF_CHAR) {
 
                 unsigned Flags;
 
                /* Reverse the order of evaluation */
-                if (CheckedSizeOf (SubScript.Type) == SIZEOF_CHAR) {
+                if (CheckedSizeOf (Subscript.Type) == SIZEOF_CHAR) {
                     Flags = CF_CHAR;
                 } else {
                     Flags = CF_INT;
@@ -985,11 +991,11 @@ static void ArrayRef (ExprDesc* Expr)
                LoadExpr (CF_NONE, Expr);
 
                /* Add the variable */
-               if (ED_IsLocStack (&SubScript)) {
-                   g_addlocal (Flags, SubScript.IVal);
+               if (ED_IsLocStack (&Subscript)) {
+                   g_addlocal (Flags, Subscript.IVal);
                } else {
-                   Flags |= GlobalModeFlags (&SubScript);
-                   g_addstatic (Flags, SubScript.Name, SubScript.IVal);
+                   Flags |= GlobalModeFlags (&Subscript);
+                   g_addstatic (Flags, Subscript.Name, Subscript.IVal);
                }
            } else {
 
@@ -1066,11 +1072,6 @@ static void StructRef (ExprDesc* Expr)
        Error ("Struct/union has no field named `%s'", Ident);
                Expr->Type = type_int;
        return;
-    }       
-    if ((Field->Flags & SC_BITFIELD) == SC_BITFIELD) {
-        Error ("Bit-fields are currently unsupported - sorry");
-        Expr->Type = type_int;
-        return;
     }
 
     /* If we have a struct pointer that is an lvalue and not already in the
@@ -1101,6 +1102,11 @@ static void StructRef (ExprDesc* Expr)
     } else {
         ED_MakeLVal (Expr);
     }
+
+    /* Make the expression a bit field if necessary */
+    if ((Field->Flags & SC_BITFIELD) == SC_BITFIELD) {
+        ED_MakeBitField (Expr, Field->V.B.BitOffs, Field->V.B.BitWidth);
+    }
 }
 
 
@@ -1595,7 +1601,12 @@ void hie10 (ExprDesc* Expr)
             */
            if (ED_IsRVal (Expr) && !IsTypeFunc (Expr->Type) && !IsTypeArray (Expr->Type)) {
                 Error ("Illegal address");
-           } else {
+            } else {
+                if (ED_IsBitField (Expr)) {
+                    Error ("Cannot take address of bit-field");
+                    /* Do it anyway, just to avoid further warnings */
+                    Expr->Flags &= ~E_BITFIELD;
+                }
                 Expr->Type = PointerTo (Expr->Type);
                 /* The & operator yields an rvalue */
                 ED_MakeRVal (Expr);
index 0d282c94a46b68d88511eaddf1d60e73ce98ecaf..6726a2cf1cb92c58299c327e88f1042540099d15 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2002-2008 Ullrich von Bassewitz                                       */
-/*               Roemerstrasse 52                                            */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2002-2009, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 ExprDesc* ED_Init (ExprDesc* Expr)
 /* Initialize an ExprDesc */
 {
-    Expr->Sym   = 0;
-    Expr->Type  = 0;
-    Expr->Flags = 0;
-    Expr->Name  = 0;
-    Expr->IVal  = 0;
-    Expr->FVal  = FP_D_Make (0.0);
+    Expr->Sym       = 0;
+    Expr->Type      = 0;
+    Expr->Flags     = 0;
+    Expr->Name      = 0;
+    Expr->IVal      = 0;
+    Expr->FVal      = FP_D_Make (0.0);
+    Expr->BitOffs   = 0;
+    Expr->BitWidth  = 0;
     return Expr;
 }
 
 
 
+void ED_MakeBitField (ExprDesc* Expr, unsigned BitOffs, unsigned BitWidth)
+/* Make this expression a bit field expression */
+{
+    Expr->Flags   |= E_BITFIELD;
+    Expr->BitOffs  = BitOffs;
+    Expr->BitWidth = BitWidth;
+}
+
+
+
 const char* ED_GetLabelName (const ExprDesc* Expr, long Offs)
 /* Return the assembler label name of the given expression. Beware: This
  * function may use a static buffer, so the name may get "lost" on the second
@@ -168,7 +180,7 @@ ExprDesc* ED_MakeRValExpr (ExprDesc* Expr)
  */
 {
     Expr->Sym   = 0;
-    Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_NEED_TEST | E_CC_SET);
+    Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_BITFIELD | E_NEED_TEST | E_CC_SET);
     Expr->Flags |= (E_LOC_EXPR | E_RTYPE_RVAL);
     Expr->Name  = 0;
     Expr->IVal  = 0;    /* No offset */
@@ -184,7 +196,7 @@ ExprDesc* ED_MakeLValExpr (ExprDesc* Expr)
  */
 {
     Expr->Sym   = 0;
-    Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_NEED_TEST | E_CC_SET);
+    Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_BITFIELD | E_NEED_TEST | E_CC_SET);
     Expr->Flags |= (E_LOC_EXPR | E_RTYPE_LVAL);
     Expr->Name  = 0;
     Expr->IVal  = 0;    /* No offset */
@@ -217,8 +229,9 @@ int ED_IsConstAbsInt (const ExprDesc* Expr)
 int ED_IsNullPtr (const ExprDesc* Expr)
 /* Return true if the given expression is a NULL pointer constant */
 {
-    return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL) &&
-           Expr->IVal == 0                                                        &&
+    return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE|E_BITFIELD)) == 
+                                (E_LOC_ABS|E_RTYPE_RVAL) &&
+           Expr->IVal == 0                               &&
            IsClassInt (Expr->Type);
 }
 
@@ -304,6 +317,11 @@ void PrintExprDesc (FILE* F, ExprDesc* E)
         Flags &= ~E_RTYPE_LVAL;
         Sep = ',';
     }
+    if (Flags & E_BITFIELD) {
+        fprintf (F, "%cE_BITFIELD", Sep);
+        Flags &= ~E_BITFIELD;
+        Sep = ',';
+    }
     if (Flags & E_NEED_TEST) {
         fprintf (F, "%cE_NEED_TEST", Sep);
         Flags &= ~E_NEED_TEST;
index 6876bfd079234053b092afdb87660a1f3bbff0f1..6091f159791a1b0ba0f20e7e5b985cfca1f73184 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2002-2008 Ullrich von Bassewitz                                       */
-/*               Roemerstrasse 52                                            */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2002-2009, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -77,26 +77,32 @@ enum {
     E_RTYPE_RVAL        = 0x0000,
     E_RTYPE_LVAL        = 0x0100,
 
+    /* Bit-field? */
+    E_BITFIELD          = 0x0200,
+
     /* Test */
-    E_NEED_TEST         = 0x0200,       /* Expression needs a test to set cc */
-    E_CC_SET            = 0x0400        /* Condition codes are set */
+    E_NEED_TEST         = 0x0400,       /* Expression needs a test to set cc */
+    E_CC_SET            = 0x0800        /* Condition codes are set */
 };
 
 /* Describe the result of an expression */
 typedef struct ExprDesc ExprDesc;
 struct ExprDesc {
-    struct SymEntry*   Sym;    /* Symbol table entry if known */
-    Type*              Type;   /* Type array of expression */
+    struct SymEntry*   Sym;            /* Symbol table entry if known */
+    Type*              Type;           /* Type array of expression */
     unsigned            Flags;
-    unsigned long      Name;   /* Name or label number */
-    long                       IVal;   /* Integer value if expression constant */
-    Double              FVal;   /* Floating point value */
+    unsigned long      Name;           /* Name or label number */
+    long                       IVal;           /* Integer value if expression constant */
+    Double              FVal;           /* Floating point value */
+
+    unsigned            BitOffs;        /* Bit offset for bit fields */
+    unsigned            BitWidth;       /* Bit width for bit fields */
 };
 
 
 
 /*****************************************************************************/
-/*                                  Code                                    */
+/*                                  Code                                    */
 /*****************************************************************************/
 
 
@@ -224,6 +230,19 @@ INLINE void ED_MakeRVal (ExprDesc* Expr)
 #  define ED_MakeRVal(Expr)     do { (Expr)->Flags &= ~E_RTYPE_LVAL; } while (0)
 #endif
 
+#if defined(HAVE_INLINE)
+INLINE int ED_IsBitField (const ExprDesc* Expr)
+/* Return true if the expression is a bit field */
+{
+    return (Expr->Flags & E_BITFIELD) != 0;
+}
+#else
+#  define ED_IsBitField(Expr)   (((Expr)->Flags & E_BITFIELD) != 0)
+#endif
+
+void ED_MakeBitField (ExprDesc* Expr, unsigned BitOffs, unsigned BitWidth);
+/* Make this expression a bit field expression */
+
 #if defined(HAVE_INLINE)
 INLINE void ED_MarkForTest (ExprDesc* Expr)
 /* Mark the expression for a test. */
index faeec06ba72b8ffb58b5edd07ddd46ffb2e303b7..8e7f83b76177dc87a55d25750d945d96fb4750b6 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2004      Ullrich von Bassewitz                                       */
-/*               Römerstraße 52                                              */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2004-2009, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -145,6 +145,18 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
                 Internal ("Invalid location in LoadExpr: 0x%04X", ED_GetLoc (Expr));
         }
 
+        /* Handle bit fields. The actual type may have been casted or
+         * converted, so be sure to always use unsigned ints for the
+         * operations.
+         */
+        if (ED_IsBitField (Expr)) {
+            unsigned F = CF_INT | CF_UNSIGNED | CF_CONST | (Flags & CF_TEST);
+            /* Shift right by the bit offset */
+            g_asr (F, Expr->BitOffs);
+            /* And by the width */
+            g_and (F, (0x0001U << Expr->BitWidth) - 1U);
+        }
+
         /* Expression was tested */
         ED_TestDone (Expr);