special case for evaluating the AND operator, this should fix the problems
described in issue #1538
This commit is contained in:
@@ -43,6 +43,7 @@
|
|||||||
|
|
||||||
/* ca65 */
|
/* ca65 */
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "expr.h"
|
||||||
#include "segment.h"
|
#include "segment.h"
|
||||||
#include "studyexpr.h"
|
#include "studyexpr.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
@@ -187,6 +188,57 @@ static void ED_MergeAddrSize (ExprDesc* ED, const ExprDesc* Right)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ED_MergeAddrSizeAND (ExprNode* Expr, ExprDesc* ED, const ExprDesc* Right)
|
||||||
|
/* Merge the address sizes of two expressions into ED, special case for AND operator */
|
||||||
|
{
|
||||||
|
int ConstL, ConstR;
|
||||||
|
long Val, ValR;
|
||||||
|
|
||||||
|
if (ED->AddrSize == ADDR_SIZE_DEFAULT) {
|
||||||
|
/* If ED is valid, ADDR_SIZE_DEFAULT gets always overridden, otherwise
|
||||||
|
** it takes precedence over anything else.
|
||||||
|
*/
|
||||||
|
if (ED_IsValid (ED)) {
|
||||||
|
ED->AddrSize = Right->AddrSize;
|
||||||
|
}
|
||||||
|
} else if (Right->AddrSize == ADDR_SIZE_DEFAULT) {
|
||||||
|
/* If Right is valid, ADDR_SIZE_DEFAULT gets always overridden,
|
||||||
|
** otherwise it takes precedence over anything else.
|
||||||
|
*/
|
||||||
|
if (!ED_IsValid (Right)) {
|
||||||
|
ED->AddrSize = Right->AddrSize;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Neither ED nor Right has a default address size, use the smaller of
|
||||||
|
** the two.
|
||||||
|
*/
|
||||||
|
if (Right->AddrSize < ED->AddrSize) {
|
||||||
|
ED->AddrSize = Right->AddrSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Check if either side of the expression is constant */
|
||||||
|
ConstL = IsConstExpr (Expr->Left, &Val);
|
||||||
|
ConstR = IsConstExpr (Expr->Right, &ValR);
|
||||||
|
if (!ConstL && !ConstR) {
|
||||||
|
/* If neither part of the expression is constant, the above is all we can do */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Use the constant side of the expression */
|
||||||
|
if (ConstR) {
|
||||||
|
Val = ValR;
|
||||||
|
}
|
||||||
|
/* Figure out the size of the constant value and use that as expression size */
|
||||||
|
if (IsByteRange (Val)) {
|
||||||
|
ED->AddrSize = ADDR_SIZE_ZP;
|
||||||
|
} else if (IsWordRange (Val)) {
|
||||||
|
ED->AddrSize = ADDR_SIZE_ABS;
|
||||||
|
} else if (IsFarRange (Val)) {
|
||||||
|
ED->AddrSize = ADDR_SIZE_FAR;
|
||||||
|
} else {
|
||||||
|
ED->AddrSize = ADDR_SIZE_DEFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ED_SymRef* ED_FindSymRef (ExprDesc* ED, SymEntry* Sym)
|
static ED_SymRef* ED_FindSymRef (ExprDesc* ED, SymEntry* Sym)
|
||||||
/* Find a symbol reference and return it. Return NULL if the reference does
|
/* Find a symbol reference and return it. Return NULL if the reference does
|
||||||
@@ -489,7 +541,11 @@ static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
|
|||||||
|
|
||||||
/* Merge references and update address size */
|
/* Merge references and update address size */
|
||||||
ED_MergeRefs (D, &Right);
|
ED_MergeRefs (D, &Right);
|
||||||
|
if (Expr->Op == EXPR_AND) {
|
||||||
|
ED_MergeAddrSizeAND (Expr, D, &Right);
|
||||||
|
} else {
|
||||||
ED_MergeAddrSize (D, &Right);
|
ED_MergeAddrSize (D, &Right);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user