Fixed several address size issues
git-svn-id: svn://svn.cc65.org/cc65/trunk@2729 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -43,6 +43,7 @@
|
|||||||
#include "attrib.h"
|
#include "attrib.h"
|
||||||
#include "bitops.h"
|
#include "bitops.h"
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
#include "mmodel.h"
|
||||||
|
|
||||||
/* ca65 */
|
/* ca65 */
|
||||||
#include "asserts.h"
|
#include "asserts.h"
|
||||||
@@ -586,16 +587,21 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A)
|
|||||||
/* Simplify it if possible */
|
/* Simplify it if possible */
|
||||||
A->Expr = SimplifyExpr (A->Expr, &ED);
|
A->Expr = SimplifyExpr (A->Expr, &ED);
|
||||||
|
|
||||||
|
/* If we don't know how big the expression is, assume the default
|
||||||
|
* address size for data.
|
||||||
|
*/
|
||||||
|
if (ED.AddrSize == ADDR_SIZE_DEFAULT) {
|
||||||
|
ED.AddrSize = DataAddrSize;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check the size */
|
/* Check the size */
|
||||||
switch (ED.AddrSize) {
|
switch (ED.AddrSize) {
|
||||||
|
|
||||||
case ADDR_SIZE_ABS:
|
case ADDR_SIZE_ABS:
|
||||||
printf ("abs\n");
|
|
||||||
A->AddrModeSet &= ~AM_SET_ZP;
|
A->AddrModeSet &= ~AM_SET_ZP;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ADDR_SIZE_FAR:
|
case ADDR_SIZE_FAR:
|
||||||
printf ("far\n");
|
|
||||||
A->AddrModeSet &= ~(AM_SET_ZP | AM_SET_ABS);
|
A->AddrModeSet &= ~(AM_SET_ZP | AM_SET_ABS);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -355,6 +355,11 @@ void SegCheck (void)
|
|||||||
if ((F->Len == 1 && ED.AddrSize > ADDR_SIZE_ZP) ||
|
if ((F->Len == 1 && ED.AddrSize > ADDR_SIZE_ZP) ||
|
||||||
(F->Len == 2 && ED.AddrSize > ADDR_SIZE_ABS) ||
|
(F->Len == 2 && ED.AddrSize > ADDR_SIZE_ABS) ||
|
||||||
(F->Len == 3 && ED.AddrSize > ADDR_SIZE_FAR)) {
|
(F->Len == 3 && ED.AddrSize > ADDR_SIZE_FAR)) {
|
||||||
|
printf ("Range error\n");
|
||||||
|
printf ("F->Len = %u, ED.AddrSize = %s\n",
|
||||||
|
F->Len, AddrSizeToStr (ED.AddrSize));
|
||||||
|
DumpExpr (F->V.Expr, SymResolve);
|
||||||
|
printf ("-------------------------------------------\n");
|
||||||
PError (&F->Pos, "Range error");
|
PError (&F->Pos, "Range error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,8 +126,47 @@ static void ED_Invalidate (ExprDesc* D)
|
|||||||
static void ED_UpdateAddrSize (ExprDesc* ED, unsigned char AddrSize)
|
static void ED_UpdateAddrSize (ExprDesc* ED, unsigned char AddrSize)
|
||||||
/* Update the address size of the expression */
|
/* Update the address size of the expression */
|
||||||
{
|
{
|
||||||
if (ED->AddrSize == ADDR_SIZE_DEFAULT || AddrSize > ED->AddrSize) {
|
if (ED_IsValid (ED)) {
|
||||||
ED->AddrSize = AddrSize;
|
/* ADDR_SIZE_DEFAULT may get overridden */
|
||||||
|
if (ED->AddrSize == ADDR_SIZE_DEFAULT || AddrSize > ED->AddrSize) {
|
||||||
|
ED->AddrSize = AddrSize;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* ADDR_SIZE_DEFAULT takes precedence */
|
||||||
|
if (ED->AddrSize != ADDR_SIZE_DEFAULT) {
|
||||||
|
if (AddrSize == ADDR_SIZE_DEFAULT || AddrSize > ED->AddrSize) {
|
||||||
|
ED->AddrSize = AddrSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void ED_MergeAddrSize (ExprDesc* ED, const ExprDesc* Right)
|
||||||
|
/* Merge the address sizes of two expressions into ED */
|
||||||
|
{
|
||||||
|
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 larger of
|
||||||
|
* the two.
|
||||||
|
*/
|
||||||
|
if (Right->AddrSize > ED->AddrSize) {
|
||||||
|
ED->AddrSize = Right->AddrSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +340,7 @@ static void ED_Add (ExprDesc* ED, const ExprDesc* Right)
|
|||||||
{
|
{
|
||||||
ED->Val += Right->Val;
|
ED->Val += Right->Val;
|
||||||
ED_MergeRefs (ED, Right);
|
ED_MergeRefs (ED, Right);
|
||||||
ED_UpdateAddrSize (ED, Right->AddrSize);
|
ED_MergeAddrSize (ED, Right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -318,7 +357,7 @@ static void ED_Mul (ExprDesc* ED, const ExprDesc* Right)
|
|||||||
for (I = 0; I < ED->SecCount; ++I) {
|
for (I = 0; I < ED->SecCount; ++I) {
|
||||||
ED->SecRef[I].Count *= Right->Val;
|
ED->SecRef[I].Count *= Right->Val;
|
||||||
}
|
}
|
||||||
ED_UpdateAddrSize (ED, Right->AddrSize);
|
ED_MergeAddrSize (ED, Right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -398,7 +437,7 @@ 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);
|
||||||
ED_UpdateAddrSize (D, Right.AddrSize);
|
ED_MergeAddrSize (D, &Right);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,6 +450,7 @@ static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
|
|||||||
static void StudyLiteral (ExprNode* Expr, ExprDesc* D)
|
static void StudyLiteral (ExprNode* Expr, ExprDesc* D)
|
||||||
/* Study a literal expression node */
|
/* Study a literal expression node */
|
||||||
{
|
{
|
||||||
|
|
||||||
/* This one is easy */
|
/* This one is easy */
|
||||||
D->Val = Expr->V.Val;
|
D->Val = Expr->V.Val;
|
||||||
}
|
}
|
||||||
@@ -429,6 +469,7 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D)
|
|||||||
* a circular reference.
|
* a circular reference.
|
||||||
*/
|
*/
|
||||||
if (SymHasExpr (Sym)) {
|
if (SymHasExpr (Sym)) {
|
||||||
|
|
||||||
if (SymHasUserMark (Sym)) {
|
if (SymHasUserMark (Sym)) {
|
||||||
if (Verbosity > 0) {
|
if (Verbosity > 0) {
|
||||||
DumpExpr (Expr, SymResolve);
|
DumpExpr (Expr, SymResolve);
|
||||||
@@ -448,26 +489,52 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D)
|
|||||||
|
|
||||||
/* If the symbol has an explicit address size, use it. This may
|
/* If the symbol has an explicit address size, use it. This may
|
||||||
* lead to range errors later (maybe even in the linker stage), if
|
* lead to range errors later (maybe even in the linker stage), if
|
||||||
* the user lied about the address size, but for now we trust the
|
* the user lied about the address size, but for now we trust him.
|
||||||
* user.
|
|
||||||
*/
|
*/
|
||||||
AddrSize = GetSymAddrSize (Sym);
|
AddrSize = GetSymAddrSize (Sym);
|
||||||
if (AddrSize != ADDR_SIZE_DEFAULT) {
|
if (AddrSize != ADDR_SIZE_DEFAULT) {
|
||||||
D->AddrSize = AddrSize;
|
D->AddrSize = AddrSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
/* The symbol is either undefined or an import. In both cases, track
|
} else if (SymIsImport (Sym)) {
|
||||||
* the symbols used and update the address size, but in case of an
|
|
||||||
* undefined symbol also set the "too complex" flag, since we cannot
|
/* The symbol is an import. Track the symbols used and update the
|
||||||
* evaluate the final result.
|
* address size.
|
||||||
*/
|
*/
|
||||||
ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
|
ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
|
||||||
++SymRef->Count;
|
++SymRef->Count;
|
||||||
ED_UpdateAddrSize (D, GetSymAddrSize (Sym));
|
ED_UpdateAddrSize (D, GetSymAddrSize (Sym));
|
||||||
if (!SymIsImport (Sym)) {
|
|
||||||
/* Cannot handle */
|
} else {
|
||||||
ED_Invalidate (D);
|
|
||||||
|
unsigned char AddrSize;
|
||||||
|
SymTable* Parent;
|
||||||
|
|
||||||
|
/* The symbol is undefined. Track symbol usage but set the "too
|
||||||
|
* complex" flag, since we cannot evaluate the final result.
|
||||||
|
*/
|
||||||
|
ED_SymRef* SymRef = ED_GetSymRef (D, Sym);
|
||||||
|
++SymRef->Count;
|
||||||
|
ED_Invalidate (D);
|
||||||
|
|
||||||
|
/* Since the symbol may be a forward, and we may need a statement
|
||||||
|
* about the address size, check higher lexical levels for a symbol
|
||||||
|
* with the same name and use its address size if we find such a
|
||||||
|
* symbol which is defined.
|
||||||
|
*/
|
||||||
|
AddrSize = GetSymAddrSize (Sym);
|
||||||
|
Parent = GetSymParentScope (Sym);
|
||||||
|
if (AddrSize == ADDR_SIZE_DEFAULT && Parent != 0) {
|
||||||
|
SymEntry* H = SymFindAny (Parent, GetSymName (Sym));
|
||||||
|
if (H) {
|
||||||
|
AddrSize = GetSymAddrSize (H);
|
||||||
|
if (AddrSize != ADDR_SIZE_DEFAULT) {
|
||||||
|
D->AddrSize = AddrSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
D->AddrSize = AddrSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -528,7 +595,7 @@ static void StudyPlus (ExprNode* Expr, ExprDesc* D)
|
|||||||
|
|
||||||
/* Merge references and update address size */
|
/* Merge references and update address size */
|
||||||
ED_MergeRefs (D, &Right);
|
ED_MergeRefs (D, &Right);
|
||||||
ED_UpdateAddrSize (D, Right.AddrSize);
|
ED_MergeAddrSize (D, &Right);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -564,7 +631,7 @@ static void StudyMinus (ExprNode* Expr, ExprDesc* D)
|
|||||||
|
|
||||||
/* Merge references and update address size */
|
/* Merge references and update address size */
|
||||||
ED_MergeRefs (D, &Right);
|
ED_MergeRefs (D, &Right);
|
||||||
ED_UpdateAddrSize (D, Right.AddrSize);
|
ED_MergeAddrSize (D, &Right);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,7 +679,7 @@ static void StudyMul (ExprNode* Expr, ExprDesc* D)
|
|||||||
/* If we could not handle the op, merge references and update address size */
|
/* If we could not handle the op, merge references and update address size */
|
||||||
if (!ED_IsValid (D)) {
|
if (!ED_IsValid (D)) {
|
||||||
ED_MergeRefs (D, &Right);
|
ED_MergeRefs (D, &Right);
|
||||||
ED_UpdateAddrSize (D, Right.AddrSize);
|
ED_MergeAddrSize (D, &Right);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Done */
|
/* Done */
|
||||||
|
|||||||
@@ -485,6 +485,16 @@ int SymIsConst (SymEntry* S, long* Val)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SymTable* GetSymParentScope (SymEntry* S)
|
||||||
|
/* Get the parent scope of the symbol (not the one it is defined in). Return
|
||||||
|
* NULL if the symbol is a cheap local, or defined on global level.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
return (S->SymTab && S->SymTab->Parent)? S->SymTab->Parent : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct ExprNode* GetSymExpr (SymEntry* S)
|
struct ExprNode* GetSymExpr (SymEntry* S)
|
||||||
/* Get the expression for a non-const symbol */
|
/* Get the expression for a non-const symbol */
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -247,6 +247,11 @@ INLINE int SymHasUserMark (SymEntry* S)
|
|||||||
#else
|
#else
|
||||||
# define SymHasUserMark(S) (((S)->Flags & SF_USER) != 0)
|
# define SymHasUserMark(S) (((S)->Flags & SF_USER) != 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct SymTable* GetSymParentScope (SymEntry* S);
|
||||||
|
/* Get the parent scope of the symbol (not the one it is defined in). Return
|
||||||
|
* NULL if the symbol is a cheap local, or defined on global level.
|
||||||
|
*/
|
||||||
|
|
||||||
struct ExprNode* GetSymExpr (SymEntry* Sym);
|
struct ExprNode* GetSymExpr (SymEntry* Sym);
|
||||||
/* Get the expression for a non-const symbol */
|
/* Get the expression for a non-const symbol */
|
||||||
|
|||||||
Reference in New Issue
Block a user