diff --git a/doc/ca65.sgml b/doc/ca65.sgml
index 6db459ee1..9bcbfa41c 100644
--- a/doc/ca65.sgml
+++ b/doc/ca65.sgml
@@ -2597,7 +2597,7 @@ Here's a list of all control commands and a description, what they do:
at character is not allowed to start an identifier, even with this
feature enabled.
- c_comments
+ c_comments
Allow C like comments using /* and */ as left and right
comment terminators. Note that C comments may not be nested. There's also a
@@ -2616,13 +2616,20 @@ Here's a list of all control commands and a description, what they do:
dollar character is not allowed to start an identifier, even with this
feature enabled.
- dollar_is_pc
+ dollar_is_pc
The dollar sign may be used as an alias for the star (`*'), which
gives the value of the current PC in expressions.
Note: Assignment to the pseudo variable is not allowed.
- labels_without_colons
+ force_range
+
+ Force expressions into their valid range for immediate addressing and
+ storage operators like and
+ . Be very careful with this one,
+ since it will completely disable error checks.
+
+ labels_without_colons
Allow labels without a trailing colon. These labels are only accepted,
if they start at the beginning of a line (no leading white space).
@@ -2636,17 +2643,17 @@ Here's a list of all control commands and a description, what they do:
overridden. When using this feature, you may also get into trouble if
later versions of the assembler define new keywords starting with a dot.
- loose_char_term
+ loose_char_term
Accept single quotes as well as double quotes as terminators for char
constants.
- loose_string_term
+ loose_string_term
Accept single quotes as well as double quotes as terminators for string
constants.
- missing_char_term
+ missing_char_term
Accept single quoted character constants where the terminating quote is
missing.
@@ -2663,7 +2670,7 @@ Here's a list of all control commands and a description, what they do:
effect will only enable absolute mode for the current segment. Dito for
.
- pc_assignment
+ pc_assignment
Allow assignments to the PC symbol (`*' or `$' if ubiquitous_idents
+ ubiquitous_idents
Allow the use of instructions names as names for macros and symbols. This
makes it possible to "overload" instructions by defining a macro with the
diff --git a/src/ca65/expr.c b/src/ca65/expr.c
index b5af9dc4d..740db2aae 100644
--- a/src/ca65/expr.c
+++ b/src/ca65/expr.c
@@ -1705,6 +1705,44 @@ ExprNode* GenWordExpr (ExprNode* Expr)
+ExprNode* GenFarAddrExpr (ExprNode* Expr)
+/* Force the given expression into a far address and return the result. */
+{
+ long Val;
+
+ /* Special handling for const expressions */
+ if (IsEasyConst (Expr, &Val)) {
+ FreeExpr (Expr);
+ Expr = GenLiteralExpr (Val & 0xFFFFFF);
+ } else {
+ ExprNode* Operand = Expr;
+ Expr = NewExprNode (EXPR_FARADDR);
+ Expr->Left = Operand;
+ }
+ return Expr;
+}
+
+
+
+ExprNode* GenDWordExpr (ExprNode* Expr)
+/* Force the given expression into a dword and return the result. */
+{
+ long Val;
+
+ /* Special handling for const expressions */
+ if (IsEasyConst (Expr, &Val)) {
+ FreeExpr (Expr);
+ Expr = GenLiteralExpr (Val & 0xFFFFFFFF);
+ } else {
+ ExprNode* Operand = Expr;
+ Expr = NewExprNode (EXPR_DWORD);
+ Expr->Left = Operand;
+ }
+ return Expr;
+}
+
+
+
ExprNode* GenNE (ExprNode* Expr, long Val)
/* Generate an expression that compares Expr and Val for inequality */
{
@@ -1957,3 +1995,28 @@ void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize)
+ExprNode* MakeBoundedExpr (ExprNode* Expr, unsigned Size)
+/* Force the given expression into a specific size of ForceRange is true */
+{
+ if (ForceRange) {
+ switch (Size) {
+ case 1: Expr = GenByteExpr (Expr); break;
+ case 2: Expr = GenWordExpr (Expr); break;
+ case 3: Expr = GenFarAddrExpr (Expr); break;
+ case 4: Expr = GenDWordExpr (Expr); break;
+ default: Internal ("Invalid size in BoundedExpr: %u", Size);
+ }
+ }
+ return Expr;
+}
+
+
+
+ExprNode* BoundedExpr (ExprNode* (*ExprFunc) (void), unsigned Size)
+/* Parse an expression and force it within a given size if ForceRange is true */
+{
+ return MakeBoundedExpr (ExprFunc (), Size);
+}
+
+
+
diff --git a/src/ca65/expr.h b/src/ca65/expr.h
index 989a322bb..1bcaba3a0 100644
--- a/src/ca65/expr.h
+++ b/src/ca65/expr.h
@@ -109,6 +109,12 @@ ExprNode* GenByteExpr (ExprNode* Expr);
ExprNode* GenWordExpr (ExprNode* Expr);
/* Force the given expression into a word and return the result. */
+ExprNode* GenFarAddrExpr (ExprNode* Expr);
+/* Force the given expression into a far address and return the result. */
+
+ExprNode* GenDWordExpr (ExprNode* Expr);
+/* Force the given expression into a dword and return the result. */
+
ExprNode* GenNE (ExprNode* Expr, long Val);
/* Generate an expression that compares Expr and Val for inequality */
@@ -170,6 +176,13 @@ ExprNode* FuncLoByte (void);
ExprNode* FuncHiByte (void);
/* Handle the .HIBYTE builtin function */
+ExprNode* MakeBoundedExpr (ExprNode* Expr, unsigned Size);
+/* Force the given expression into a specific size of ForceRange is true */
+
+ExprNode* BoundedExpr (ExprNode* (*ExprFunc) (void), unsigned Size);
+/* Parse an expression and force it within a given size if ForceRange is true */
+
+
/* End of expr.h */
diff --git a/src/ca65/feature.c b/src/ca65/feature.c
index e138bfe74..f0ba4c578 100644
--- a/src/ca65/feature.c
+++ b/src/ca65/feature.c
@@ -6,10 +6,10 @@
/* */
/* */
/* */
-/* (C) 2000-2008 Ullrich von Bassewitz */
-/* Roemerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 2000-2012, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@@ -61,6 +61,7 @@ static const char* FeatureKeys[FEAT_COUNT] = {
"missing_char_term",
"ubiquitous_idents",
"c_comments",
+ "force_range",
};
@@ -115,6 +116,7 @@ feature_t SetFeature (const StrBuf* Key)
case FEAT_MISSING_CHAR_TERM: MissingCharTerm = 1; break;
case FEAT_UBIQUITOUS_IDENTS: UbiquitousIdents = 1; break;
case FEAT_C_COMMENTS: CComments = 1; break;
+ case FEAT_FORCE_RANGE: ForceRange = 1; break;
default: /* Keep gcc silent */ break;
}
diff --git a/src/ca65/feature.h b/src/ca65/feature.h
index 31ebae223..cf2f3ade8 100644
--- a/src/ca65/feature.h
+++ b/src/ca65/feature.h
@@ -6,10 +6,10 @@
/* */
/* */
/* */
-/* (C) 2000-2008 Ullrich von Bassewitz */
-/* Roemerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 2000-2012, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@@ -63,6 +63,7 @@ typedef enum {
FEAT_MISSING_CHAR_TERM,
FEAT_UBIQUITOUS_IDENTS,
FEAT_C_COMMENTS,
+ FEAT_FORCE_RANGE,
/* Special value: Number of features available */
FEAT_COUNT
diff --git a/src/ca65/global.c b/src/ca65/global.c
index ced950d6b..faecfc26c 100644
--- a/src/ca65/global.c
+++ b/src/ca65/global.c
@@ -6,7 +6,7 @@
/* */
/* */
/* */
-/* (C) 1998-2011, Ullrich von Bassewitz */
+/* (C) 1998-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@@ -79,7 +79,8 @@ unsigned char MissingCharTerm = 0; /* Allow lda #'a (no closing term) */
unsigned char UbiquitousIdents = 0; /* Allow ubiquitous identifiers */
unsigned char OrgPerSeg = 0; /* Make .org local to current seg */
unsigned char CComments = 0; /* Allow C like comments */
-
+unsigned char ForceRange = 0; /* Force values into expected range */
+
/* Misc stuff */
const char Copyright[] = "(C) Copyright 1998-2011 Ullrich von Bassewitz";
diff --git a/src/ca65/global.h b/src/ca65/global.h
index 51b31725b..3bd302bda 100644
--- a/src/ca65/global.h
+++ b/src/ca65/global.h
@@ -6,7 +6,7 @@
/* */
/* */
/* */
-/* (C) 1998-2011, Ullrich von Bassewitz */
+/* (C) 1998-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@@ -81,6 +81,7 @@ extern unsigned char MissingCharTerm; /* Allow lda #'a (no closing term) *
extern unsigned char UbiquitousIdents; /* Allow ubiquitous identifiers */
extern unsigned char OrgPerSeg; /* Make .org local to current seg */
extern unsigned char CComments; /* Allow C like comments */
+extern unsigned char ForceRange; /* Force values into expected range */
/* Misc stuff */
extern const char Copyright[]; /* Copyright string */
diff --git a/src/ca65/instr.c b/src/ca65/instr.c
index 198a3d39c..c4513b92a 100644
--- a/src/ca65/instr.c
+++ b/src/ca65/instr.c
@@ -6,7 +6,7 @@
/* */
/* */
/* */
-/* (C) 1998-2011, Ullrich von Bassewitz */
+/* (C) 1998-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@@ -1007,6 +1007,16 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A)
/* Build the opcode */
A->Opcode = Ins->BaseCode | EATab[Ins->ExtCode][A->AddrMode];
+ /* If feature force_range is active, and we have immediate addressing mode,
+ * limit the expression to the maximum possible value.
+ */
+ if (A->AddrMode == AM65I_IMM_ACCU || A->AddrMode == AM65I_IMM_INDEX ||
+ A->AddrMode == AM65I_IMM_IMPLICIT) {
+ if (ForceRange && A->Expr) {
+ A->Expr = MakeBoundedExpr (A->Expr, ExtBytes[A->AddrMode]);
+ }
+ }
+
/* Success */
return 1;
}
diff --git a/src/ca65/instr.h b/src/ca65/instr.h
index 7b36cfffb..aa0a43236 100644
--- a/src/ca65/instr.h
+++ b/src/ca65/instr.h
@@ -6,7 +6,7 @@
/* */
/* */
/* */
-/* (C) 1998-2008, Ullrich von Bassewitz */
+/* (C) 1998-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
@@ -95,6 +95,7 @@
/* Bit numbers and count */
#define AM65I_IMM_ACCU 21
#define AM65I_IMM_INDEX 22
+#define AM65I_IMM_IMPLICIT 23
#define AM65I_COUNT 26
diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c
index 480fc6186..3bd853081 100644
--- a/src/ca65/pseudo.c
+++ b/src/ca65/pseudo.c
@@ -370,12 +370,12 @@ static void DoAddr (void)
/* Parse arguments */
while (1) {
- if (GetCPU() == CPU_65816) {
- EmitWord (GenWordExpr (Expression ()));
- } else {
+ ExprNode* Expr = Expression ();
+ if (GetCPU () == CPU_65816 || ForceRange) {
/* Do a range check */
- EmitWord (Expression ());
- }
+ Expr = GenWordExpr (Expr);
+ }
+ EmitWord (Expr);
if (CurTok.Tok != TOK_COMMA) {
break;
} else {
@@ -586,7 +586,7 @@ static void DoByte (void)
EmitStrBuf (&CurTok.SVal);
NextTok ();
} else {
- EmitByte (Expression ());
+ EmitByte (BoundedExpr (Expression, 1));
}
if (CurTok.Tok != TOK_COMMA) {
break;
@@ -595,7 +595,7 @@ static void DoByte (void)
/* Do smart handling of dangling comma */
if (CurTok.Tok == TOK_SEP) {
Error ("Unexpected end of line");
- break;
+ break;
}
}
}
@@ -791,7 +791,7 @@ static void DoDByt (void)
/* Parse arguments */
while (1) {
- EmitWord (GenSwapExpr (Expression ()));
+ EmitWord (GenSwapExpr (BoundedExpr (Expression, 2)));
if (CurTok.Tok != TOK_COMMA) {
break;
} else {
@@ -865,7 +865,7 @@ static void DoDWord (void)
/* Define dwords */
{
while (1) {
- EmitDWord (Expression ());
+ EmitDWord (BoundedExpr (Expression, 4));
if (CurTok.Tok != TOK_COMMA) {
break;
} else {
@@ -965,7 +965,7 @@ static void DoFarAddr (void)
/* Parse arguments */
while (1) {
- EmitFarAddr (Expression ());
+ EmitFarAddr (BoundedExpr (Expression, 3));
if (CurTok.Tok != TOK_COMMA) {
break;
} else {
@@ -1936,7 +1936,7 @@ static void DoWord (void)
/* Parse arguments */
while (1) {
- EmitWord (Expression ());
+ EmitWord (BoundedExpr (Expression, 2));
if (CurTok.Tok != TOK_COMMA) {
break;
} else {
@@ -1970,14 +1970,14 @@ static void DoZeropage (void)
/* Control commands flags */
enum {
- ccNone = 0x0000, /* No special flags */
- ccKeepToken = 0x0001 /* Do not skip the current token */
+ ccNone = 0x0000, /* No special flags */
+ ccKeepToken = 0x0001 /* Do not skip the current token */
};
/* Control command table */
typedef struct CtrlDesc CtrlDesc;
struct CtrlDesc {
- unsigned Flags; /* Flags for this directive */
+ unsigned Flags; /* Flags for this directive */
void (*Handler) (void); /* Command handler */
};
diff --git a/src/ca65/studyexpr.c b/src/ca65/studyexpr.c
index b9f8d1946..0a2986f2a 100644
--- a/src/ca65/studyexpr.c
+++ b/src/ca65/studyexpr.c
@@ -6,10 +6,10 @@
/* */
/* */
/* */
-/* (C) 2003-2007 Ullrich von Bassewitz */
-/* Roemerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 2003-2012, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@@ -1206,7 +1206,7 @@ static void StudyWord0 (ExprNode* Expr, ExprDesc* D)
/* We can handle only const expressions */
if (ED_IsConst (D)) {
- D->Val = (D->Val & 0xFFFFL);
+ D->Val &= 0xFFFFL;
} else {
ED_Invalidate (D);
}
@@ -1236,6 +1236,44 @@ static void StudyWord1 (ExprNode* Expr, ExprDesc* D)
+static void StudyFarAddr (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_FARADDR expression node */
+{
+ /* Study the expression */
+ StudyExprInternal (Expr->Left, D);
+
+ /* We can handle only const expressions */
+ if (ED_IsConst (D)) {
+ D->Val &= 0xFFFFFFL;
+ } else {
+ ED_Invalidate (D);
+ }
+
+ /* In any case, the result is a far address */
+ D->AddrSize = ADDR_SIZE_FAR;
+}
+
+
+
+static void StudyDWord (ExprNode* Expr, ExprDesc* D)
+/* Study an EXPR_DWORD expression node */
+{
+ /* Study the expression */
+ StudyExprInternal (Expr->Left, D);
+
+ /* We can handle only const expressions */
+ if (ED_IsConst (D)) {
+ D->Val &= 0xFFFFFFFFL;
+ } else {
+ ED_Invalidate (D);
+ }
+
+ /* In any case, the result is a long expression */
+ D->AddrSize = ADDR_SIZE_LONG;
+}
+
+
+
static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
/* Study an expression tree and place the contents into D */
{
@@ -1390,6 +1428,14 @@ static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
StudyWord1 (Expr, D);
break;
+ case EXPR_FARADDR:
+ StudyFarAddr (Expr, D);
+ break;
+
+ case EXPR_DWORD:
+ StudyDWord (Expr, D);
+ break;
+
default:
Internal ("Unknown Op type: %u", Expr->Op);
break;