mirror of
https://github.com/cc65/cc65.git
synced 2024-12-25 02:29:52 +00:00
65816 now generate EXPR_NEARADDR instead of EXPR_WORD0 for default assumed address mode, which will be validated by the linker's range check rather than blindly truncated. Assuming the assembler correctly validated this, the linker is allowed to truncate.
This commit is contained in:
parent
a01c4231f2
commit
ac2ecb0b2c
@ -1865,6 +1865,28 @@ ExprNode* GenWordExpr (ExprNode* Expr)
|
||||
|
||||
|
||||
|
||||
ExprNode* GenNearAddrExpr (ExprNode* Expr)
|
||||
/* A word sized expression that will error if given a far expression at assemble time. */
|
||||
{
|
||||
long Val;
|
||||
/* Special handling for const expressions */
|
||||
if (IsEasyConst (Expr, &Val)) {
|
||||
FreeExpr (Expr);
|
||||
Expr = GenLiteralExpr (Val & 0xFFFF);
|
||||
if (Val > 0xFFFF)
|
||||
{
|
||||
Error("Range error: constant too large for assumed near address.");
|
||||
}
|
||||
} else {
|
||||
ExprNode* Operand = Expr;
|
||||
Expr = NewExprNode (EXPR_NEARADDR);
|
||||
Expr->Left = Operand;
|
||||
}
|
||||
return Expr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ExprNode* GenFarAddrExpr (ExprNode* Expr)
|
||||
/* Force the given expression into a far address and return the result. */
|
||||
{
|
||||
|
@ -109,6 +109,9 @@ ExprNode* GenByteExpr (ExprNode* Expr);
|
||||
ExprNode* GenWordExpr (ExprNode* Expr);
|
||||
/* Force the given expression into a word and return the result. */
|
||||
|
||||
ExprNode* GenNearAddrExpr (ExprNode* Expr);
|
||||
/* A word sized expression that will error if given a far expression at assemble time. */
|
||||
|
||||
ExprNode* GenFarAddrExpr (ExprNode* Expr);
|
||||
/* Force the given expression into a far address and return the result. */
|
||||
|
||||
|
@ -1217,7 +1217,7 @@ static void EmitCode (EffAddr* A)
|
||||
** mode, force this address into 16 bit range to allow
|
||||
** addressing inside a 64K segment.
|
||||
*/
|
||||
Emit2 (A->Opcode, GenWordExpr (A->Expr));
|
||||
Emit2 (A->Opcode, GenNearAddrExpr (A->Expr));
|
||||
} else {
|
||||
Emit2 (A->Opcode, A->Expr);
|
||||
}
|
||||
|
@ -1277,6 +1277,26 @@ static void StudyDWord (ExprNode* Expr, ExprDesc* D)
|
||||
|
||||
|
||||
|
||||
static void StudyNearAddr (ExprNode* Expr, ExprDesc* D)
|
||||
/* Study an EXPR_NearAddr expression node */
|
||||
{
|
||||
/* Study the expression */
|
||||
StudyExprInternal (Expr->Left, D);
|
||||
|
||||
/* We can handle only const expressions */
|
||||
if (!ED_IsConst (D)) {
|
||||
ED_Invalidate (D);
|
||||
}
|
||||
|
||||
/* Promote to absolute if smaller. */
|
||||
if (D->AddrSize < ADDR_SIZE_ABS)
|
||||
{
|
||||
D->AddrSize = ADDR_SIZE_ABS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
|
||||
/* Study an expression tree and place the contents into D */
|
||||
{
|
||||
@ -1427,6 +1447,10 @@ static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
|
||||
StudyWord1 (Expr, D);
|
||||
break;
|
||||
|
||||
case EXPR_NEARADDR:
|
||||
StudyNearAddr (Expr, D);
|
||||
break;
|
||||
|
||||
case EXPR_FARADDR:
|
||||
StudyFarAddr (Expr, D);
|
||||
break;
|
||||
|
@ -210,6 +210,10 @@ static void InternalDumpExpr (const ExprNode* Expr, const ExprNode* (*ResolveSym
|
||||
printf (" WORD1");
|
||||
break;
|
||||
|
||||
case EXPR_NEARADDR:
|
||||
printf (" NEARADDR");
|
||||
break;
|
||||
|
||||
case EXPR_FARADDR:
|
||||
printf (" FARADDR");
|
||||
break;
|
||||
|
@ -97,8 +97,9 @@
|
||||
#define EXPR_BYTE3 (EXPR_UNARYNODE | 0x0B)
|
||||
#define EXPR_WORD0 (EXPR_UNARYNODE | 0x0C)
|
||||
#define EXPR_WORD1 (EXPR_UNARYNODE | 0x0D)
|
||||
#define EXPR_FARADDR (EXPR_UNARYNODE | 0x0E)
|
||||
#define EXPR_DWORD (EXPR_UNARYNODE | 0x0F)
|
||||
#define EXPR_NEARADDR (EXPR_UNARYNODE | 0x0E)
|
||||
#define EXPR_FARADDR (EXPR_UNARYNODE | 0x0F)
|
||||
#define EXPR_DWORD (EXPR_UNARYNODE | 0x10)
|
||||
|
||||
|
||||
|
||||
|
@ -436,6 +436,10 @@ long GetExprVal (ExprNode* Expr)
|
||||
case EXPR_WORD1:
|
||||
return (GetExprVal (Expr->Left) >> 16) & 0xFFFF;
|
||||
|
||||
case EXPR_NEARADDR:
|
||||
/* Assembler was expected to validate this truncation. */
|
||||
return GetExprVal (Expr->Left) & 0xFFFF;
|
||||
|
||||
case EXPR_FARADDR:
|
||||
return GetExprVal (Expr->Left) & 0xFFFFFF;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user