1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-07 07:29:33 +00:00

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
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
@ -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.
<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).
@ -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.
<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.
@ -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
<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/
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
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

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)
/* 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);
/* 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 */

View File

@ -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;
}

View File

@ -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

View File

@ -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";

View File

@ -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 */

View File

@ -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;
}

View File

@ -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

View File

@ -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 */
};

View File

@ -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;