From 7ecb4c50b1bedcf28f8b4dd936e3d28df238d41a Mon Sep 17 00:00:00 2001 From: uz Date: Wed, 18 Jan 2012 19:50:34 +0000 Subject: [PATCH] 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 --- doc/ca65.sgml | 23 ++++++++++------ src/ca65/expr.c | 63 ++++++++++++++++++++++++++++++++++++++++++++ src/ca65/expr.h | 13 +++++++++ src/ca65/feature.c | 10 ++++--- src/ca65/feature.h | 9 ++++--- src/ca65/global.c | 5 ++-- src/ca65/global.h | 3 ++- src/ca65/instr.c | 12 ++++++++- src/ca65/instr.h | 3 ++- src/ca65/pseudo.c | 28 ++++++++++---------- src/ca65/studyexpr.c | 56 +++++++++++++++++++++++++++++++++++---- 11 files changed, 185 insertions(+), 40 deletions(-) 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; -- 2.39.5