mirror of
https://github.com/cc65/cc65.git
synced 2024-12-28 22:30:12 +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:
parent
0e4f581f71
commit
7ecb4c50b1
@ -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 `$' 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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user