/* */
/* */
/* */
-/* (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 */
}
if (UseReg) {
PushAddr (Expr);
- } else {
+ } else {
ED_MakeRVal (Expr);
LoadExpr (CF_NONE, Expr);
g_push (CF_PTR | CF_UNSIGNED, 0);
}
+ } 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 */
/* Handle an array reference. This function needs a rewrite. */
{
int ConstBaseAddr;
- ExprDesc SubScript;
+ ExprDesc Subscript;
CodeMark Mark1;
CodeMark Mark2;
Type* ElementType;
}
/* 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
* 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,
/* 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);
if (IsTypeArray (Expr->Type)) {
/* Adjust the offset */
- Expr->IVal += SubScript.IVal;
+ Expr->IVal += Subscript.IVal;
} else {
}
/* Use the offset */
- Expr->IVal = SubScript.IVal;
+ Expr->IVal = Subscript.IVal;
}
} else {
* 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);
}
/* 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)) {
* 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;
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 {
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
} 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);
+ }
}
*/
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);
/* */
/* */
/* */
-/* (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
*/
{
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 */
*/
{
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 */
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);
}
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;
/* */
/* */
/* */
-/* (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 */
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 */
/*****************************************************************************/
# 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. */
/* */
/* */
/* */
-/* (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 */
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);