/* */
/* */
/* (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"
#include "nexttok.h"
#include "objcode.h"
#include "spool.h"
+#include "studyexpr.h"
#include "symtab.h"
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);
{ "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 },
{ "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 },
*/
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);
/* 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");
}
}
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:
}
/* 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 */
/* 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 */
/* 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 */
-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
+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 */
{
CPU = NewCPU;
InsTab = InsTabs[CPU];
} else {
- Error (ERR_CPU_NOT_SUPPORTED);
+ Error ("CPU not supported");
}
}
/* 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;
}