Add bounded expressions for immediate addressing and list the new feature in

the docs.


git-svn-id: svn://svn.cc65.org/cc65/trunk@5406 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz
2012-01-18 19:50:34 +00:00
parent 0e4f581f71
commit 7ecb4c50b1
11 changed files with 185 additions and 40 deletions

View File

@@ -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 at character is not allowed to start an identifier, even with this
feature enabled. 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 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 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 dollar character is not allowed to start an identifier, even with this
feature enabled. 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 The dollar sign may be used as an alias for the star (`*'), which
gives the value of the current PC in expressions. gives the value of the current PC in expressions.
Note: Assignment to the pseudo variable is not allowed. 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, Allow labels without a trailing colon. These labels are only accepted,
if they start at the beginning of a line (no leading white space). 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 overridden. When using this feature, you may also get into trouble if
later versions of the assembler define new keywords starting with a dot. 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 Accept single quotes as well as double quotes as terminators for char
constants. 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 Accept single quotes as well as double quotes as terminators for string
constants. 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 Accept single quoted character constants where the terminating quote is
missing. 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 effect will only enable absolute mode for the current segment. Dito for
<tt><ref id=".RELOC" name=".RELOC"></tt>. <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 `&dollar;' if <tt/dollar_is_pc/ Allow assignments to the PC symbol (`*' or `&dollar;' if <tt/dollar_is_pc/
is enabled). Such an assignment is handled identical to the <tt><ref is enabled). Such an assignment is handled identical to the <tt><ref
@@ -2671,7 +2678,7 @@ Here's a list of all control commands and a description, what they do:
removing the lines with the assignments may also be an option when porting removing the lines with the assignments may also be an option when porting
code written for older assemblers). 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 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 makes it possible to "overload" instructions by defining a macro with the

View File

@@ -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) ExprNode* GenNE (ExprNode* Expr, long Val)
/* Generate an expression that compares Expr and Val for inequality */ /* 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);
}

View File

@@ -109,6 +109,12 @@ ExprNode* GenByteExpr (ExprNode* Expr);
ExprNode* GenWordExpr (ExprNode* Expr); ExprNode* GenWordExpr (ExprNode* Expr);
/* Force the given expression into a word and return the result. */ /* 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); ExprNode* GenNE (ExprNode* Expr, long Val);
/* Generate an expression that compares Expr and Val for inequality */ /* Generate an expression that compares Expr and Val for inequality */
@@ -170,6 +176,13 @@ ExprNode* FuncLoByte (void);
ExprNode* FuncHiByte (void); ExprNode* FuncHiByte (void);
/* Handle the .HIBYTE builtin function */ /* 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 */ /* End of expr.h */

View File

@@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2008 Ullrich von Bassewitz */ /* (C) 2000-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@@ -61,6 +61,7 @@ static const char* FeatureKeys[FEAT_COUNT] = {
"missing_char_term", "missing_char_term",
"ubiquitous_idents", "ubiquitous_idents",
"c_comments", "c_comments",
"force_range",
}; };
@@ -115,6 +116,7 @@ feature_t SetFeature (const StrBuf* Key)
case FEAT_MISSING_CHAR_TERM: MissingCharTerm = 1; break; case FEAT_MISSING_CHAR_TERM: MissingCharTerm = 1; break;
case FEAT_UBIQUITOUS_IDENTS: UbiquitousIdents = 1; break; case FEAT_UBIQUITOUS_IDENTS: UbiquitousIdents = 1; break;
case FEAT_C_COMMENTS: CComments = 1; break; case FEAT_C_COMMENTS: CComments = 1; break;
case FEAT_FORCE_RANGE: ForceRange = 1; break;
default: /* Keep gcc silent */ break; default: /* Keep gcc silent */ break;
} }

View File

@@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2008 Ullrich von Bassewitz */ /* (C) 2000-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@@ -63,6 +63,7 @@ typedef enum {
FEAT_MISSING_CHAR_TERM, FEAT_MISSING_CHAR_TERM,
FEAT_UBIQUITOUS_IDENTS, FEAT_UBIQUITOUS_IDENTS,
FEAT_C_COMMENTS, FEAT_C_COMMENTS,
FEAT_FORCE_RANGE,
/* Special value: Number of features available */ /* Special value: Number of features available */
FEAT_COUNT FEAT_COUNT

View File

@@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998-2011, Ullrich von Bassewitz */ /* (C) 1998-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
@@ -79,6 +79,7 @@ unsigned char MissingCharTerm = 0; /* Allow lda #'a (no closing term) */
unsigned char UbiquitousIdents = 0; /* Allow ubiquitous identifiers */ unsigned char UbiquitousIdents = 0; /* Allow ubiquitous identifiers */
unsigned char OrgPerSeg = 0; /* Make .org local to current seg */ unsigned char OrgPerSeg = 0; /* Make .org local to current seg */
unsigned char CComments = 0; /* Allow C like comments */ unsigned char CComments = 0; /* Allow C like comments */
unsigned char ForceRange = 0; /* Force values into expected range */
/* Misc stuff */ /* Misc stuff */
const char Copyright[] = "(C) Copyright 1998-2011 Ullrich von Bassewitz"; const char Copyright[] = "(C) Copyright 1998-2011 Ullrich von Bassewitz";

View File

@@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998-2011, Ullrich von Bassewitz */ /* (C) 1998-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* 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 UbiquitousIdents; /* Allow ubiquitous identifiers */
extern unsigned char OrgPerSeg; /* Make .org local to current seg */ extern unsigned char OrgPerSeg; /* Make .org local to current seg */
extern unsigned char CComments; /* Allow C like comments */ extern unsigned char CComments; /* Allow C like comments */
extern unsigned char ForceRange; /* Force values into expected range */
/* Misc stuff */ /* Misc stuff */
extern const char Copyright[]; /* Copyright string */ extern const char Copyright[]; /* Copyright string */

View File

@@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998-2011, Ullrich von Bassewitz */ /* (C) 1998-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
@@ -1007,6 +1007,16 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A)
/* Build the opcode */ /* Build the opcode */
A->Opcode = Ins->BaseCode | EATab[Ins->ExtCode][A->AddrMode]; 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 */ /* Success */
return 1; return 1;
} }

View File

@@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998-2008, Ullrich von Bassewitz */ /* (C) 1998-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
@@ -95,6 +95,7 @@
/* Bit numbers and count */ /* Bit numbers and count */
#define AM65I_IMM_ACCU 21 #define AM65I_IMM_ACCU 21
#define AM65I_IMM_INDEX 22 #define AM65I_IMM_INDEX 22
#define AM65I_IMM_IMPLICIT 23
#define AM65I_COUNT 26 #define AM65I_COUNT 26

View File

@@ -370,12 +370,12 @@ static void DoAddr (void)
/* Parse arguments */ /* Parse arguments */
while (1) { while (1) {
if (GetCPU() == CPU_65816) { ExprNode* Expr = Expression ();
EmitWord (GenWordExpr (Expression ())); if (GetCPU () == CPU_65816 || ForceRange) {
} else {
/* Do a range check */ /* Do a range check */
EmitWord (Expression ()); Expr = GenWordExpr (Expr);
} }
EmitWord (Expr);
if (CurTok.Tok != TOK_COMMA) { if (CurTok.Tok != TOK_COMMA) {
break; break;
} else { } else {
@@ -586,7 +586,7 @@ static void DoByte (void)
EmitStrBuf (&CurTok.SVal); EmitStrBuf (&CurTok.SVal);
NextTok (); NextTok ();
} else { } else {
EmitByte (Expression ()); EmitByte (BoundedExpr (Expression, 1));
} }
if (CurTok.Tok != TOK_COMMA) { if (CurTok.Tok != TOK_COMMA) {
break; break;
@@ -595,7 +595,7 @@ static void DoByte (void)
/* Do smart handling of dangling comma */ /* Do smart handling of dangling comma */
if (CurTok.Tok == TOK_SEP) { if (CurTok.Tok == TOK_SEP) {
Error ("Unexpected end of line"); Error ("Unexpected end of line");
break; break;
} }
} }
} }
@@ -791,7 +791,7 @@ static void DoDByt (void)
/* Parse arguments */ /* Parse arguments */
while (1) { while (1) {
EmitWord (GenSwapExpr (Expression ())); EmitWord (GenSwapExpr (BoundedExpr (Expression, 2)));
if (CurTok.Tok != TOK_COMMA) { if (CurTok.Tok != TOK_COMMA) {
break; break;
} else { } else {
@@ -865,7 +865,7 @@ static void DoDWord (void)
/* Define dwords */ /* Define dwords */
{ {
while (1) { while (1) {
EmitDWord (Expression ()); EmitDWord (BoundedExpr (Expression, 4));
if (CurTok.Tok != TOK_COMMA) { if (CurTok.Tok != TOK_COMMA) {
break; break;
} else { } else {
@@ -965,7 +965,7 @@ static void DoFarAddr (void)
/* Parse arguments */ /* Parse arguments */
while (1) { while (1) {
EmitFarAddr (Expression ()); EmitFarAddr (BoundedExpr (Expression, 3));
if (CurTok.Tok != TOK_COMMA) { if (CurTok.Tok != TOK_COMMA) {
break; break;
} else { } else {
@@ -1936,7 +1936,7 @@ static void DoWord (void)
/* Parse arguments */ /* Parse arguments */
while (1) { while (1) {
EmitWord (Expression ()); EmitWord (BoundedExpr (Expression, 2));
if (CurTok.Tok != TOK_COMMA) { if (CurTok.Tok != TOK_COMMA) {
break; break;
} else { } else {
@@ -1970,14 +1970,14 @@ static void DoZeropage (void)
/* Control commands flags */ /* Control commands flags */
enum { enum {
ccNone = 0x0000, /* No special flags */ ccNone = 0x0000, /* No special flags */
ccKeepToken = 0x0001 /* Do not skip the current token */ ccKeepToken = 0x0001 /* Do not skip the current token */
}; };
/* Control command table */ /* Control command table */
typedef struct CtrlDesc CtrlDesc; typedef struct CtrlDesc CtrlDesc;
struct CtrlDesc { struct CtrlDesc {
unsigned Flags; /* Flags for this directive */ unsigned Flags; /* Flags for this directive */
void (*Handler) (void); /* Command handler */ void (*Handler) (void); /* Command handler */
}; };

View File

@@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2003-2007 Ullrich von Bassewitz */ /* (C) 2003-2012, Ullrich von Bassewitz */
/* Roemerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* 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 */ /* We can handle only const expressions */
if (ED_IsConst (D)) { if (ED_IsConst (D)) {
D->Val = (D->Val & 0xFFFFL); D->Val &= 0xFFFFL;
} else { } else {
ED_Invalidate (D); 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) static void StudyExprInternal (ExprNode* Expr, ExprDesc* D)
/* Study an expression tree and place the contents into 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); StudyWord1 (Expr, D);
break; break;
case EXPR_FARADDR:
StudyFarAddr (Expr, D);
break;
case EXPR_DWORD:
StudyDWord (Expr, D);
break;
default: default:
Internal ("Unknown Op type: %u", Expr->Op); Internal ("Unknown Op type: %u", Expr->Op);
break; break;