at character is not allowed to start an identifier, even with this
feature enabled.
- <tag><tt>c_comments</tt></tag>
+ <tag><tt>c_comments</tt><label id="c_comments"></tag>
Allow C like comments using <tt>/*</tt> and <tt>*/</tt> as left and right
comment terminators. Note that C comments may not be nested. There's also a
dollar character is not allowed to start an identifier, even with this
feature enabled.
- <tag><tt>dollar_is_pc</tt></tag>
+ <tag><tt>dollar_is_pc</tt><label id="dollar_is_pc"></tag>
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.
- <tag><tt>labels_without_colons</tt></tag>
+ <tag><tt>force_range</tt><label id="force_range"></tag>
+
+ Force expressions into their valid range for immediate addressing and
+ storage operators like <tt><ref id=".BYTE" name=".BYTE"></tt> and
+ <tt><ref id=".WORD" name=".WORD"></tt>. Be very careful with this one,
+ since it will completely disable error checks.
+
+ <tag><tt>labels_without_colons</tt><label id="labels_without_colons"></tag>
Allow labels without a trailing colon. These labels are only accepted,
if they start at the beginning of a line (no leading white space).
overridden. When using this feature, you may also get into trouble if
later versions of the assembler define new keywords starting with a dot.
- <tag><tt>loose_char_term</tt></tag>
+ <tag><tt>loose_char_term</tt><label id="loose_char_term"></tag>
Accept single quotes as well as double quotes as terminators for char
constants.
- <tag><tt>loose_string_term</tt></tag>
+ <tag><tt>loose_string_term</tt><label id="loose_string_term"></tag>
Accept single quotes as well as double quotes as terminators for string
constants.
- <tag><tt>missing_char_term</tt></tag>
+ <tag><tt>missing_char_term</tt><label id="missing_char_term"></tag>
Accept single quoted character constants where the terminating quote is
missing.
effect will only enable absolute mode for the current segment. Dito for
<tt><ref id=".RELOC" name=".RELOC"></tt>.
- <tag><tt>pc_assignment</tt></tag>
+ <tag><tt>pc_assignment</tt><label id="pc_assignment"></tag>
Allow assignments to the PC symbol (`*' or `$' if <tt/dollar_is_pc/
is enabled). Such an assignment is handled identical to the <tt><ref
removing the lines with the assignments may also be an option when porting
code written for older assemblers).
- <tag><tt>ubiquitous_idents</tt></tag>
+ <tag><tt>ubiquitous_idents</tt><label id="ubiquitous_idents"></tag>
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
+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 */
{
+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);
+}
+
+
+
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 */
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 */
/* */
/* */
/* */
-/* (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 */
"missing_char_term",
"ubiquitous_idents",
"c_comments",
+ "force_range",
};
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;
}
/* */
/* */
/* */
-/* (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 */
FEAT_MISSING_CHAR_TERM,
FEAT_UBIQUITOUS_IDENTS,
FEAT_C_COMMENTS,
+ FEAT_FORCE_RANGE,
/* Special value: Number of features available */
FEAT_COUNT
/* */
/* */
/* */
-/* (C) 1998-2011, Ullrich von Bassewitz */
+/* (C) 1998-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
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";
/* */
/* */
/* */
-/* (C) 1998-2011, Ullrich von Bassewitz */
+/* (C) 1998-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
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 */
/* */
/* */
/* */
-/* (C) 1998-2011, Ullrich von Bassewitz */
+/* (C) 1998-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* 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;
}
/* */
/* */
/* */
-/* (C) 1998-2008, Ullrich von Bassewitz */
+/* (C) 1998-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* Bit numbers and count */
#define AM65I_IMM_ACCU 21
#define AM65I_IMM_INDEX 22
+#define AM65I_IMM_IMPLICIT 23
#define AM65I_COUNT 26
/* 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 {
EmitStrBuf (&CurTok.SVal);
NextTok ();
} else {
- EmitByte (Expression ());
+ EmitByte (BoundedExpr (Expression, 1));
}
if (CurTok.Tok != TOK_COMMA) {
break;
/* Do smart handling of dangling comma */
if (CurTok.Tok == TOK_SEP) {
Error ("Unexpected end of line");
- break;
+ break;
}
}
}
/* Parse arguments */
while (1) {
- EmitWord (GenSwapExpr (Expression ()));
+ EmitWord (GenSwapExpr (BoundedExpr (Expression, 2)));
if (CurTok.Tok != TOK_COMMA) {
break;
} else {
/* Define dwords */
{
while (1) {
- EmitDWord (Expression ());
+ EmitDWord (BoundedExpr (Expression, 4));
if (CurTok.Tok != TOK_COMMA) {
break;
} else {
/* Parse arguments */
while (1) {
- EmitFarAddr (Expression ());
+ EmitFarAddr (BoundedExpr (Expression, 3));
if (CurTok.Tok != TOK_COMMA) {
break;
} else {
/* Parse arguments */
while (1) {
- EmitWord (Expression ());
+ EmitWord (BoundedExpr (Expression, 2));
if (CurTok.Tok != TOK_COMMA) {
break;
} else {
/* 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 */
};
/* */
/* */
/* */
-/* (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 */
/* We can handle only const expressions */
if (ED_IsConst (D)) {
- D->Val = (D->Val & 0xFFFFL);
+ D->Val &= 0xFFFFL;
} else {
ED_Invalidate (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 */
{
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;