diff --git a/src/ca65/error.c b/src/ca65/error.c index fc984268b..162080d7b 100644 --- a/src/ca65/error.c +++ b/src/ca65/error.c @@ -75,6 +75,7 @@ void WarningMsg (const FilePos* Pos, unsigned WarnNum, va_list ap) { 2, "Symbol `%s' is defined but never used" }, { 2, "Symbol `%s' is imported but never used" }, { 1, "Cannot track processor status byte" }, + { 1, "Suspicious address expression" }, { 0, "User warning: %s" }, }; diff --git a/src/ca65/error.h b/src/ca65/error.h index 665664531..ca7ef370e 100644 --- a/src/ca65/error.h +++ b/src/ca65/error.h @@ -55,6 +55,7 @@ enum Warnings { WARN_SYM_NOT_REFERENCED, WARN_IMPORT_NOT_REFERENCED, WARN_CANNOT_TRACK_STATUS, + WARN_SUSPICIOUS_ADDREXPR, WARN_USER, WARN_COUNT /* Warning count */ }; diff --git a/src/ca65/instr.c b/src/ca65/instr.c index 942650816..6cd78b62c 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -48,6 +48,7 @@ #include "global.h" #include "nexttok.h" #include "objcode.h" +#include "symtab.h" #include "instr.h" @@ -606,21 +607,42 @@ static void PutAll (const InsDesc* Ins) * modes. */ if (Expr && (AddrModeSet & AM_ZP) && !IsByteExpr (Expr)) { - AddrModeSet &= ~AM_ZP; + AddrModeSet &= ~AM_ZP; } /* Check if we have any adressing modes left */ if (AddrModeSet == 0) { - Error (ERR_ILLEGAL_ADDR_MODE); - return; + Error (ERR_ILLEGAL_ADDR_MODE); + return; } AddrMode = BitFind (AddrModeSet); + /* If the instruction has a one byte operand and immediate addressing is + * allowed but not used, check for an operand expression in the form + * <label or >label, where label is a far or absolute label. If found, + * emit a warning. This warning protects against a typo, where the '#' + * for the immediate operand is omitted. + */ + if (Expr && (Ins->AddrMode & AM_IMM) && + (AddrModeSet & (AM_DIR | AM_ABS | AM_ABS_LONG)) && + ExtBytes[AddrMode] == 1) { + + /* Found, check the expression */ + ExprNode* Left = Expr->Left; + if ((Expr->Op == EXPR_BYTE0 || Expr->Op == EXPR_BYTE1) && + Left->Op == EXPR_SYMBOL && + !SymIsZP (Left->V.Sym)) { + + /* Output a warning */ + Warning (WARN_SUSPICIOUS_ADDREXPR); + } + } + /* Build the opcode */ OpCode = Ins->BaseCode | EATab [Ins->ExtCode][AddrMode]; /* Check how many extension bytes are needed and output the instruction */ - switch (ExtBytes [AddrMode]) { + switch (ExtBytes[AddrMode]) { case 0: Emit0 (OpCode); @@ -637,7 +659,7 @@ static void PutAll (const InsDesc* Ins) * mode, force this address into 16 bit range to allow * addressing inside a 64K segment. */ - Emit2 (OpCode, ForceWordExpr (Expr)); + Emit2 (OpCode, ForceWordExpr (Expr)); } else { Emit2 (OpCode, Expr); } diff --git a/src/ca65/instr.h b/src/ca65/instr.h index 23627f29e..7d01e15ea 100644 --- a/src/ca65/instr.h +++ b/src/ca65/instr.h @@ -95,19 +95,19 @@ /* Description for one instruction */ -typedef struct InsDesc_ InsDesc; -struct InsDesc_ { - char Mnemonic [4]; +typedef struct InsDesc InsDesc; +struct InsDesc { + char Mnemonic [4]; unsigned long AddrMode; /* Valid adressing modes */ - unsigned char BaseCode; /* Base opcode */ - unsigned char ExtCode; /* Number of ext code table */ + unsigned char BaseCode; /* Base opcode */ + unsigned char ExtCode; /* Number of ext code table */ void (*Emit) (const InsDesc*);/* Handler function */ }; /* An instruction table */ -typedef struct InsTable_ InsTable; -struct InsTable_ { - unsigned Count; /* Number of intstructions */ +typedef struct InsTable InsTable; +struct InsTable { + unsigned Count; /* Number of intstructions */ InsDesc Ins[1]; /* Varying length */ }; @@ -125,7 +125,7 @@ extern unsigned char ExtBytes [AMI_COUNT]; /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/