]> git.sur5r.net Git - cc65/blobdiff - src/ca65/instr.c
New module strstack
[cc65] / src / ca65 / instr.c
index dd1729ec3578a9fef482f60dab0af8cf0b63732d..b6fc51f01df4459c333ff050b76743ad159e1336 100644 (file)
@@ -7,7 +7,7 @@
 /*                                                                           */
 /*                                                                           */
 /* (C) 1998-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
+/*               Römerstraße 52                                              */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 #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,17 +573,46 @@ 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 */
     if (A->AddrModeSet == 0) {
-               Error (ERR_ILLEGAL_ADDR_MODE);
+               Error ("Illegal addressing mode");
                return 0;
     }
     A->AddrMode    = BitFind (A->AddrModeSet);
@@ -597,11 +631,11 @@ 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 (WARN_SUSPICIOUS_ADDREXPR);
+            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:
@@ -673,8 +702,8 @@ static long PutImmed8 (const InsDesc* Ins)
     }
 
     /* If we have an expression and it's const, get it's value */
-    if (A.Expr && IsConstExpr (A.Expr)) {
-       Val = GetExprVal (A.Expr);
+    if (A.Expr) {
+        (void) IsConstExpr (A.Expr, &Val);
     }
 
     /* Check how many extension bytes are needed and output the instruction */
@@ -744,7 +773,7 @@ static void PutREP (const InsDesc* Ins)
        /* Check the range for Val. */
        if (Val < 0) {
            /* We had an error */
-           Warning (WARN_CANNOT_TRACK_STATUS);
+           Warning (1, "Cannot track processor status byte");
        } else {
            if (Val & 0x10) {
                /* Index registers to 16 bit */
@@ -772,7 +801,7 @@ static void PutSEP (const InsDesc* Ins)
        /* Check the range for Val. */
        if (Val < 0) {
            /* We had an error */
-           Warning (WARN_CANNOT_TRACK_STATUS);
+           Warning (1, "Cannot track processor status byte");
        } else {
            if (Val & 0x10) {
                /* Index registers to 8 bit */
@@ -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 */
 {
@@ -862,7 +905,7 @@ void SetCPU (cpu_t NewCPU)
        CPU = NewCPU;
        InsTab = InsTabs[CPU];
     } else {
-       Error (ERR_CPU_NOT_SUPPORTED);
+       Error ("CPU not supported");
     }
 }
 
@@ -887,7 +930,14 @@ int FindInstruction (const char* Ident)
 
     /* Make a copy, and uppercase that copy */
     I = 0;
-    while (Ident[I]) {
+    while (Ident[I] != '\0') {
+        /* If the identifier is longer than the longest mnemonic, it cannot
+         * be one.
+         */
+        if (I >= sizeof (Key) - 1) {
+            /* Not found, no need for further action */
+            return -1;
+        }
         Key[I] = toupper ((unsigned char)Ident[I]);
         ++I;
     }