]> git.sur5r.net Git - cc65/commitdiff
Add bounded expressions for immediate addressing and list the new feature in
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Wed, 18 Jan 2012 19:50:34 +0000 (19:50 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Wed, 18 Jan 2012 19:50:34 +0000 (19:50 +0000)
the docs.

git-svn-id: svn://svn.cc65.org/cc65/trunk@5406 b7a2c559-68d2-44c3-8de9-860c34a00d81

doc/ca65.sgml
src/ca65/expr.c
src/ca65/expr.h
src/ca65/feature.c
src/ca65/feature.h
src/ca65/global.c
src/ca65/global.h
src/ca65/instr.c
src/ca65/instr.h
src/ca65/pseudo.c
src/ca65/studyexpr.c

index 6db459ee11f3a49eb2bd09344a8c14b5c8de9669..9bcbfa41c38bb35c27432c4ea52b61fcf58f7f61 100644 (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
index b5af9dc4daececa903d7d7c96b26906f7686da26..740db2aae3342871721916ede1b624e3a5f759b3 100644 (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);
+}
+
+
+
index 989a322bbdba9acfaeae8237fcb822f09e720cc4..1bcaba3a06443eb25469722f437b47c888546f65 100644 (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 */
 
index e138bfe74a83e65bae7acfd4239c7793eb365911..f0ba4c57853eebfd4f62ef4e07f790f00880985d 100644 (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;
     }
 
index 31ebae223e112feb8ebecd3f3adedff61e910f27..cf2f3ade8ed3dd1105bba425525c268f764fb1e1 100644 (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
index ced950d6b52de17bf69c57dca79ed5858ceda1f4..faecfc26c55fa049b15647630c1bd1f24c87c9dc 100644 (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";
 
index 51b31725b5673d9b4652fa1dfa559db019da87c8..3bd302bda8c05f582fdcc858f0a745f1992888ca 100644 (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 */
index 198a3d39cc2d9d17bd77a78a2fdb18bd9a3c4eff..c4513b92ab8fe2bf02b0e8a171a287d87ab71f53 100644 (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;
 }
index 7b36cfffbab6e5c87ff698fba87adaa71c683a8d..aa0a432362d154a2aef59ccd20b2758f98f97df1 100644 (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
 
 
index 480fc61865d5cdb7d5d1ce89582ca5c1547a1ecf..3bd8530819ff56b4944ee1c96cdc01f996e64623 100644 (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 */
 };
 
index b9f8d194651a7cb996450d1bbe5623fa9ef8743f..0a2986f2a2cb1eccbd6f5a52e133225d2358961a 100644 (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;