]> git.sur5r.net Git - cc65/blobdiff - src/ca65/instr.c
New module strstack
[cc65] / src / ca65 / instr.c
index f5dfff89b79b2672e2affe161736fe7b6ae0477f..b6fc51f01df4459c333ff050b76743ad159e1336 100644 (file)
 #include <ctype.h>
 
 /* common */
+#include "addrsize.h"
 #include "assertdefs.h"
+#include "attrib.h"
 #include "bitops.h"
 #include "check.h"
+#include "mmodel.h"
 
 /* ca65 */
 #include "asserts.h"
@@ -52,6 +55,7 @@
 #include "nexttok.h"
 #include "objcode.h"
 #include "spool.h"
+#include "studyexpr.h"
 #include "symtab.h"
 
 
@@ -69,7 +73,8 @@ static void PutBlockMove (const InsDesc* Ins);
 static void PutBitBranch (const InsDesc* Ins);
 static void PutREP (const InsDesc* Ins);
 static void PutSEP (const InsDesc* Ins);
-static void PutJmp (const InsDesc* Ins);
+static void PutJMP (const InsDesc* Ins);
+static void PutRTS (const InsDesc* Ins);
 static void PutAll (const InsDesc* Ins);
 
 
@@ -109,7 +114,7 @@ static const struct {
                { "INC",  0x000006c, 0x00, 4, PutAll },
                { "INX",  0x0000001, 0xe8, 0, PutAll },
                { "INY",  0x0000001, 0xc8, 0, PutAll },
-               { "JMP",  0x0000808, 0x4c, 6, PutJmp },
+               { "JMP",  0x0000808, 0x4c, 6, PutJMP },
                { "JSR",  0x0000008, 0x20, 7, PutAll },
                { "LDA",  0x080A26C, 0xa0, 0, PutAll },
                { "LDX",  0x080030C, 0xa2, 1, PutAll },
@@ -403,7 +408,7 @@ static const struct {
                { "ROR",  0x000006F, 0x62, 1, PutAll },
                { "RTI",  0x0000001, 0x40, 0, PutAll },
                { "RTL",  0x0000001, 0x6b, 0, PutAll },
-               { "RTS",  0x0000001, 0x60, 0, PutAll },
+               { "RTS",  0x0000001, 0x60, 0, PutRTS },
                { "SBC",  0x0b8f6fc, 0xe0, 0, PutAll },
                { "SEC",  0x0000001, 0x38, 0, PutAll },
                { "SED",  0x0000001, 0xf8, 0, PutAll },
@@ -568,12 +573,41 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A)
      */
     A->AddrModeSet &= Ins->AddrMode;
 
-    /* If we have possible zero page addressing modes, and the expression
-     * involved (if any) is not in byte range, remove the zero page addressing
-     * modes.
+    /* If we have an expression, check it and remove any addressing modes that
+     * are too small for the expression size. Since we have to study the
+     * expression anyway, do also replace it by a simpler one if possible.
      */
-    if (A->Expr && (A->AddrModeSet & AM_ZP) && !IsByteExpr (A->Expr)) {
-               A->AddrModeSet &= ~AM_ZP;
+    if (A->Expr) {
+        ExprDesc ED;
+        ED_Init (&ED);
+
+        /* Study the expression */
+        StudyExpr (A->Expr, &ED);
+
+        /* Simplify it if possible */
+        A->Expr = SimplifyExpr (A->Expr, &ED);
+
+        /* If we don't know how big the expression is, assume the default
+         * address size for data.
+         */
+        if (ED.AddrSize == ADDR_SIZE_DEFAULT) {
+            ED.AddrSize = DataAddrSize;
+        }
+
+        /* Check the size */
+        switch (ED.AddrSize) {
+
+            case ADDR_SIZE_ABS:
+                A->AddrModeSet &= ~AM_SET_ZP;
+                break;
+
+            case ADDR_SIZE_FAR:
+                A->AddrModeSet &= ~(AM_SET_ZP | AM_SET_ABS);
+                break;
+        }
+
+        /* Free any resource associated with the expression desc */
+        ED_Done (&ED);
     }
 
     /* Check if we have any adressing modes left */
@@ -597,8 +631,8 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A)
         /* Found, check the expression */
         ExprNode* Left = A->Expr->Left;
         if ((A->Expr->Op == EXPR_BYTE0 || A->Expr->Op == EXPR_BYTE1) &&
-            Left->Op == EXPR_SYMBOL                                &&
-            !SymIsZP (Left->V.Sym)) {
+            Left->Op == EXPR_SYMBOL                                  &&
+            GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP) {
 
             /* Output a warning */
             Warning (1, "Suspicious address expression");
@@ -641,13 +675,8 @@ static void EmitCode (EffAddr* A)
            break;
 
        case 3:
-           if (A->Bank) {
-               /* Separate bank given */
-               Emit3b (A->Opcode, A->Expr, A->Bank);
-           } else {
-               /* One far argument */
-               Emit3 (A->Opcode, A->Expr);
-           }
+            /* Far argument */
+           Emit3 (A->Opcode, A->Expr);
            break;
 
        default:
@@ -788,7 +817,7 @@ static void PutSEP (const InsDesc* Ins)
 
 
 
-static void PutJmp (const InsDesc* Ins)
+static void PutJMP (const InsDesc* Ins)
 /* Handle the jump instruction for the 6502. Problem is that these chips have
  * a bug: If the address crosses a page, the upper byte gets not corrected and
  * the instruction will fail. The PutJmp function will add a linker assertion
@@ -823,6 +852,20 @@ static void PutJmp (const InsDesc* Ins)
 
 
 
+static void PutRTS (const InsDesc* Ins attribute ((unused)))
+/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
+ * the enclosing scope is FAR.
+ */
+{
+    if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
+        Emit0 (0x6B);       /* RTL */
+    } else {
+        Emit0 (0x60);       /* RTS */
+    }
+}
+
+
+
 static void PutAll (const InsDesc* Ins)
 /* Handle all other instructions */
 {