mirror of
https://github.com/cc65/cc65.git
synced 2024-12-30 20:29:25 +00:00
First implementation of bit fields.
git-svn-id: svn://svn.cc65.org/cc65/trunk@4079 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
7c6ee79ea9
commit
6b4fe90928
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
@ -57,17 +57,29 @@
|
||||
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;
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user