add jsr, rts optimization notice, code and doc cleanup

This commit is contained in:
Bernd Boeckmann
2023-04-29 20:57:08 +02:00
parent ce8d71e13d
commit 53ccf38dbe
6 changed files with 152 additions and 84 deletions

View File

@@ -116,13 +116,13 @@ Copyright 2022-2023 by Bernd Boeckmann
This listing shows the lines of the assembler source side-by-side to
the generated machine code in hexadecimal notation.
FPos PC Code Line# Assembler text
Pos Addr Code Line# Assembler text
0000 0000 69 2A 1: ADC #42
0002 0002 E8 2: INX
FPos indicates the position of the instructions regarding the output
file. PC represents the _location_ or _address_ of the code while it
is executed.
Pos indicates the position of the instructions regarding the output
file. Addr represents the _location_ or _address_ of the code while
it is executed.
Let's further elaborate what the arguments to instructions may be.
In the example above, `#42' is a numeric value that is directly used
@@ -435,7 +435,15 @@ Copyright 2022-2023 by Bernd Boeckmann
.BYTE 47, 11
.BYTE "Hello, World", 13, 10
4.6.4 .ECHO and .ECHO1 Directives
4.6.4 .CPU Directive
Selects the instruction set the assembler understands depending on
the given CPU type.
.CPU 6502 ; targets the NMOS 6502 CPU
.CPU 65C02 ; targets the CMOS 65C02 CPU (experimental)
4.6.5 .ECHO and .ECHO1 Directives
Print the arguments to standard output. .ECHO does it on the
second assembler pass, while .ECHO1 does it on the first pass. The
@@ -448,13 +456,13 @@ Copyright 2022-2023 by Bernd Boeckmann
.ECHO "hexadecimal representation of ", 4711, " is ", [$]4711
4.6.5 .ERROR directive
4.6.6 .ERROR directive
Aborts the assembly along with file name and line number
information. Accepts the same parameters as .ECHO for the error
message.
4.6.6 .FILL Directive
4.6.7 .FILL Directive
Starting from the current position of the output file, emits as many
bytes as given by the first argument. If the second argument is
@@ -466,7 +474,7 @@ Copyright 2022-2023 by Bernd Boeckmann
.FILL 100 ; fill 100 bytes with zero
.FILL 16, $EA ; insert 16 NOPs ($EA) into the code
4.6.7 .IF, .IFN, .ELSE and .ENDIF Directives
4.6.8 .IF, .IFN, .ELSE and .ENDIF Directives
Conditionally assembles code if the condition of the argument to .IF
or .IFN is met. For .IF, the condition is met if the argument yields
@@ -494,14 +502,14 @@ Copyright 2022-2023 by Bernd Boeckmann
In listing files, the unprocessed lines are indicated by a minus
after the line number instead of a colon.
4.6.8 .IFDEF and .IFNDEF Directives
4.6.9 .IFDEF and .IFNDEF Directives
An argument to .IFDEF is considered true, if its value is defined.
An argument to .IFNDEF is considered true, if its value is
undefined. Otherwise, the directives behave like their .IF and .IFN
counterparts.
4.6.9 .INCLUDE Directive
4.6.10 .INCLUDE Directive
Substitutes the directive with the assembler source contained in the
file given as argument.
@@ -510,7 +518,7 @@ Copyright 2022-2023 by Bernd Boeckmann
.INCLUDE "c64prg.i65"
4.6.10 .LIST and .NOLIST Directives
4.6.11 .LIST and .NOLIST Directives
If a listing file is given via command line, listing generation is
initially enabled. If the user wants some parts of the code to be
@@ -523,7 +531,7 @@ Copyright 2022-2023 by Bernd Boeckmann
A .NOLIST inside an include file does not propagate to the parent
file.
4.6.11 .ORG Directive
4.6.12 .ORG Directive
Sets the address counter to the numeric value of the argument. Does
not modify the offset into the output file. This means that .ORG
@@ -534,12 +542,12 @@ Copyright 2022-2023 by Bernd Boeckmann
.ORG $0801
4.6.12 .WARNING Directive
4.6.13 .WARNING Directive
Prints a warning along with file name and line number information.
Accepts the same parameters as .ECHO for the warning message.
4.6.13 .WORD Directive
4.6.14 .WORD Directive
Produces one or more output words.
@@ -651,11 +659,15 @@ Copyright 2022-2023 by Bernd Boeckmann
A Command Line Syntax
---------------------
Usage: asm6502 [-q] input -o output [-l listing] [VAR=number]...
Usage: asm6502 input -o output [options]... [VAR=number]...
Options:
-q be quiet, unless an error occurred
-o output set output file name
-l listing set optional listing file name
-w0 disable all warnings
-w1 only .warning directives
-w2 enable all warnings and hints (default)
Variables defined from the command line are known to the assembler
when assembling files. The numbers are parsed like number literals
@@ -1046,40 +1058,40 @@ B Instruction Reference
94 15 sty $15,x
8C 11 47 sty $4711
B.51 TAX - transfer X to accumulator
B.51 TAX - transfer accumulator to X
AA tax
Flags: N Z
B.52 TAY - transfer Y to accumulator
B.52 TAY - transfer accumulator to Y
A8 tay
Flags: N Z
B.53 TSX - transfer X to stack pointer
B.53 TSX - transfer stack pointer to X
Flags: N Z
BA tsx
B.54 TXA - transfer accumulator to X
B.54 TXA - transfer X to accumulator
Flags: N Z
8A txa
B.55 TXS - transfer stack pointer to X
B.55 TXS - transfer X to stack pointer
Flags: N Z
9A txs
B.56 TYA - transfer accumulator to Y
B.56 TYA - transfer Y to accumulator
Flags: N Z
98 tya
[Fr 28 Apr 14:19:56 2023]
[Sa 29 Apr 20:56:25 2023]

View File

@@ -67,7 +67,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "asm6502.h"
static int flag_quiet = 0;
static int flag_warning_level = 2;
static int flag_diagnostic_level = 2;
static u8 *code = NULL; /* holds the emitted code */
static u16 code_size;
@@ -200,8 +200,8 @@ enum {
ERR_INSTR,
ERR_AM,
ERR_CLOSING_PAREN,
ERR_INX,
ERR_INY,
ERR_ZIX,
ERR_ZIY,
ERR_NO_DIRECTIVE,
ERR_UNDEF,
ERR_ILLEGAL_TYPE,
@@ -945,10 +945,16 @@ static instruction_desc *get_instruction_descr( const char *p ) {
}
static u8 current_opcode = INV;
static u8 last_opcode = INV;
static void emit_byte( u8 b ) {
if ( pass == 2 ) {
if ( oc < code_size ) code[oc] = b;
else error( ERR_PHASE_SIZE );
current_opcode = INV;
}
oc += 1;
@@ -964,6 +970,8 @@ static void emit( const char *p, u16 len ) {
code[oc + i] = p[i];
}
} else error( ERR_PHASE_SIZE );
current_opcode = INV;
}
oc += len;
}
@@ -975,17 +983,33 @@ static void emit_word( u16 w ) {
code[oc] = w & 0xff;
code[oc + 1] = w >> 8;
} else error( ERR_PHASE_SIZE );
current_opcode = INV;
}
oc += 2;
}
static void print_notice( const char *s ) {
if ( flag_diagnostic_level >= DIAGNOSTIC_LVL_NOTICE && pass == 2 )
printf( "%s:%d: notice: %s\n", current_file->filename, line, s );
}
/* emit instruction without argument */
static void emit_instr_0( instruction_desc *instr, int am ) {
if ( pass == 2 ) {
if ( oc < code_size ) code[oc] = instr->op[am];
else error( ERR_PHASE_SIZE );
last_opcode = current_opcode;
current_opcode = code[oc];
if ( current_opcode == OP_RTS && last_opcode == OP_JSR ) {
print_notice( "JSR followed by RTS can be replaced by JMP" );
}
}
oc += 1;
}
@@ -996,6 +1020,10 @@ static void emit_instr_1( instruction_desc *instr, int am, u8 o ) {
if ( oc < code_size - 1 ) {
code[oc] = instr->op[am];
code[oc + 1] = o;
last_opcode = current_opcode;
current_opcode = code[oc];
} else error( ERR_PHASE_SIZE );
}
oc += 2;
@@ -1009,14 +1037,18 @@ static void emit_instr_2( instruction_desc *instr, int am, u16 o ) {
code[oc] = instr->op[am];
code[oc + 1] = o & 0xff;
code[oc + 2] = o >> 8;
last_opcode = current_opcode;
current_opcode = code[oc];
} else error( ERR_PHASE_SIZE );
}
oc += 3;
}
/* emit instruction with byte argument */
static void emit_instr_2p( instruction_desc *instr, int am, u8 o, u8 p ) {
/* emit instruction with two byte arguments */
static void emit_instr_2b( instruction_desc *instr, int am, u8 o, u8 p ) {
if ( pass == 2 ) {
if ( oc < code_size - 2 ) {
code[oc] = instr->op[am];
@@ -1098,7 +1130,7 @@ static int instruction_ind( char **p, instruction_desc *instr ) {
if ( **p == ',' ) {
skip_curr_and_white( p );
ident( p, id, 0, 1 );
if ( strcmp( id, "X" ) != 0 ) error( ERR_INX );
if ( strcmp( id, "X" ) != 0 ) error( ERR_ZIX );
if ( AM_VALID( *instr, AM_AIX )) am = AM_AIX;
else am = AM_ZIX;
skip_white( p );
@@ -1112,7 +1144,7 @@ static int instruction_ind( char **p, instruction_desc *instr ) {
if ( **p == ',' ) {
skip_curr_and_white( p );
ident( p, id, 0, 1 );
if ( strcmp( id, "Y" ) != 0 ) error( ERR_INY );
if ( strcmp( id, "Y" ) != 0 ) error( ERR_ZIY );
am = AM_ZIY;
} else {
if ( AM_VALID( *instr, AM_ZIN )) am = AM_ZIN;
@@ -1139,12 +1171,6 @@ static int instruction_ind( char **p, instruction_desc *instr ) {
}
static void print_warning( const char *s ) {
if ( flag_warning_level > 1 && pass == 2 )
printf( "%s:%d: warning: %s\n", current_file->filename, line, s );
}
/* handle absolute x and y, zero-page x and y addressing modes */
static int instruction_abxy_zpxy( char **p, instruction_desc *instr, value v ) {
char id[ID_LEN];
@@ -1161,7 +1187,7 @@ static int instruction_abxy_zpxy( char **p, instruction_desc *instr, value v ) {
else if ( AM_VALID( *instr, AM_ABX )) {
am = AM_ABX;
if ( pass == 2 && NUM_TYPE( v.v ) == TYPE_BYTE && AM_VALID( *instr, AM_ZPX ))
print_warning( "non-optimal code; address could be of type byte" );
print_notice( "can be zero-page,X adressing - is absolute,X" );
} else error( ERR_AM );
}
@@ -1171,7 +1197,7 @@ static int instruction_abxy_zpxy( char **p, instruction_desc *instr, value v ) {
else if ( AM_VALID( *instr, AM_ABY )) {
am = AM_ABY;
if ( pass == 2 && NUM_TYPE( v.v ) == TYPE_BYTE && AM_VALID( *instr, AM_ZPY ))
print_warning( "non-optimal code; address could be of type byte" );
print_notice( "can be zero-page,Y adressing - is absolute,Y" );
} else error( ERR_AM );
} else error( ERR_AM );
@@ -1200,7 +1226,7 @@ static int instruction_abs_zp( instruction_desc *instr, value v ) {
if ( pass == 2 ) {
if ( UNDEFINED( v )) error( ERR_UNDEF );
if ( NUM_TYPE( v.v ) == TYPE_BYTE && AM_VALID( *instr, AM_ZP ))
print_warning( "non-optimal code; address could be of type byte" );
print_notice( "can be zero-page adressing - is absolute" );
}
emit_instr_2( instr, am, v.v );
} else error( ERR_AM );
@@ -1222,7 +1248,7 @@ static int instruction_zp_rel( char **p, instruction_desc *instr, value v ) {
if ( pass == 2 ) {
if ( UNDEFINED( v ) || UNDEFINED( rel )) error( ERR_UNDEF );
}
emit_instr_2p( instr, AM_ZPR, (u8) v.v, off );
emit_instr_2b( instr, AM_ZPR, (u8) v.v, off );
return AM_ZPR;
}
@@ -1650,25 +1676,20 @@ static void directive_echo( char **p, int on_pass ) {
}
enum {
DIAGNOSTIC_WARNING,
DIAGNOSTIC_ERROR
};
static void directive_diagnostic( char **p, int level ) {
/* warnings and errors are processed at pass 1 */
if ( pass != 1 || ( level == DIAGNOSTIC_WARNING && flag_warning_level < 1 )) {
if ( pass != 1 || ( level == ERR_LVL_WARNING
&& flag_diagnostic_level < DIAGNOSTIC_LVL_WARN )) {
skip_to_eol( p );
return;
}
switch ( level ) {
case DIAGNOSTIC_WARNING: /* warning */
case ERR_LVL_WARNING: /* warning */
printf( "%s:%d: warning: ", current_file->filename, line );
echo( p );
break;
case DIAGNOSTIC_ERROR: /* error */
case ERR_LVL_FATAL: /* error */
printf( "%s:%d: error: ", current_file->filename, line );
echo( p );
error_abort();
@@ -1708,7 +1729,7 @@ static void directive_assert( char **p, int on_pass ) {
static void directive_cpu( char **p ) {
char cpu_type[ID_LEN];
skip_white(p);
skip_white( p );
ident( p, cpu_type, 1, 1 );
if ( !strcmp( cpu_type, "6502" )) {
select_6502();
@@ -1751,9 +1772,9 @@ static int directive( char **p ) {
} else if ( !strcmp( id, "ASSERT1" )) {
directive_assert( p, 2 );
} else if ( !strcmp( id, "ERROR" )) {
directive_diagnostic( p, DIAGNOSTIC_ERROR );
directive_diagnostic( p, ERR_LVL_FATAL );
} else if ( !strcmp( id, "WARNING" )) {
directive_diagnostic( p, DIAGNOSTIC_WARNING );
directive_diagnostic( p, ERR_LVL_WARNING );
} else if ( !strcmp( id, "NOLIST" )) {
listing = 0;
} else if ( !strcmp( id, "LIST" )) {
@@ -2213,11 +2234,11 @@ static int parse_args( char *argv[] ) {
if ( !*argv ) return 0;
listing_filename = *argv;
} else if ( !strcmp( *argv + 1, "w0" )) {
flag_warning_level = 0;
flag_diagnostic_level = 0;
} else if ( !strcmp( *argv + 1, "w1" )) {
flag_warning_level = 1;
flag_diagnostic_level = 1;
} else if ( !strcmp( *argv + 1, "w2" )) {
flag_warning_level = 2;
flag_diagnostic_level = 2;
} else return 0;
} else if (( p = strchr( *argv, '=' )) != NULL) {
/* variable definition */
@@ -2242,7 +2263,7 @@ void print_usage( void ) {
printf(
"Usage: asm6502 input -o output [options]... [VAR=number]...\n\n"
"Options:\n"
" -q be quiet, unless an error occurred\n"
" -q be quiet, unless errors or warnings occur\n"
" -o output set output file name\n"
" -l listing set optional listing file name\n"
" -w0 disable all warnings\n"

View File

@@ -34,13 +34,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
typedef unsigned char u8;
typedef unsigned short u16;
enum {
ERR_LVL_WARNING,
ERR_LVL_FATAL
};
enum {
DIAGNOSTIC_LVL_NONE,
DIAGNOSTIC_LVL_WARN,
DIAGNOSTIC_LVL_NOTICE
};
/* addressing modes */
enum {
AM_ACC = 0, /* accumulator */
AM_IMP = 1, /* implied */
AM_IMM = 2, /* # immediate addressing */
AM_REL = 3, /* R program counter relative */
AM_ZP = 4, /* ZP zero-page */
AM_ZP = 4, /* ZP zero-page */
AM_ZPX = 5, /* ZP,X zero-page indexed with X */
AM_ZPY = 6, /* ZP,Y zero-page indexed with Y */
AM_ABS = 7, /* A absolute */
@@ -56,6 +68,8 @@ enum {
};
enum {
OP_RTS = 0x60,
OP_JSR = 0x20,
INV = 0xfc
};
@@ -76,7 +90,8 @@ extern u16 am_size[16];
#define AM_VALID( instr, am ) ((instr).op[am] != INV)
#define MAXINT( a, b ) (((b) >= (a)) ? (b) : (a))
void select_6502(void);
void select_65c02(void);
void select_6502( void );
void select_65c02( void );
#endif

View File

@@ -1,6 +1,7 @@
\cfg{chapter}{}
\cfg{text-chapter-numeric}{true}
\cfg{text-chapter-suffix}{ }
\cfg{paper-base-font-size}{13}
\title ASM6502 Assembler Manual
@@ -81,11 +82,11 @@ The set of instructions a CPU understands is called \e{instruction set}. There a
Beside generating an output file containing machine code, ASM6502 may also generate a \e{listing file} containing a \e{program listing}. This listing shows the lines of the assembler source side-by-side to the generated machine code in hexadecimal notation.
\c FPos PC Code Line# Assembler text
\c Pos Addr Code Line# Assembler text
\c 0000 0000 69 2A 1: ADC #42
\c 0002 0002 E8 2: INX
FPos indicates the position of the instructions regarding the output file. PC represents the \e{location} or \e{address} of the code while it is executed.
Pos indicates the position of the instructions regarding the output file. Addr represents the \e{location} or \e{address} of the code while it is executed.
Let's further elaborate what the arguments to instructions may be. In the example above, \c{#42} is a numeric value that is directly used to do the addition. It is therefore called an \e{immediate} value, and the mode the processor operates in is called \e{immediate addressing} mode. The \c{INX} instruction above implicitly operates on a register called X. For this reason it is called \e{implicit addressing}. Often, the argument specifies a memory location. This memory location may be referenced to the start of the address space. In this case it is called \e{absolute addressing} mode. If the memory location is specified relative to some other location we call it \e{relative addressing} mode. Sometimes one does not want to encode a fixed memory location into the machine instruction, but instead use the content of some memory location as the address to operate on. This is called \e{indirect addressing}.
@@ -299,6 +300,12 @@ Example:
\c .BYTE 47, 11
\c .BYTE "Hello, World", 13, 10
\S{}.CPU Directive
Selects the instruction set the assembler understands depending on the given CPU type.
\c .CPU 6502 ; targets the NMOS 6502 CPU
\c .CPU 65C02 ; targets the CMOS 65C02 CPU (experimental)
\S{}.ECHO and .ECHO1 Directives
@@ -470,11 +477,15 @@ Indexed indirect by X addresses the byte referenced by the contents of the word
\A{usage}Command Line Syntax
\c Usage: asm6502 [-q] input -o output [-l listing] [VAR=number]...
\c Usage: asm6502 input -o output [options]... [VAR=number]...
\c
\c Options:
\c -q be quiet, unless an error occurred
\c -o output set output file name
\c -l listing set optional listing file name
\c -w0 disable all warnings
\c -w1 only .warning directives
\c -w2 enable all warnings and hints (default)
Variables defined from the command line are known to the assembler when assembling files. The numbers are parsed like number literals in the source code.
@@ -849,37 +860,37 @@ Flags: I=1
\c 94 15 sty $15,x
\c 8C 11 47 sty $4711
\H{tax}TAX - transfer X to accumulator
\H{tax}TAX - transfer accumulator to X
\c AA tax
Flags: N Z
\H{tay}TAY - transfer Y to accumulator
\H{tay}TAY - transfer accumulator to Y
\c A8 tay
Flags: N Z
\H{tsx}TSX - transfer X to stack pointer
\H{tsx}TSX - transfer stack pointer to X
Flags: N Z
\c BA tsx
\H{txa}TXA - transfer accumulator to X
\H{txa}TXA - transfer X to accumulator
Flags: N Z
\c 8A txa
\H{txs}TXS - transfer stack pointer to X
\H{txs}TXS - transfer X to stack pointer
Flags: N Z
\c 9A txs
\H{tya}TYA - transfer accumulator to Y
\H{tya}TYA - transfer Y to accumulator
Flags: N Z

32
itbl.c
View File

@@ -169,14 +169,14 @@ instruction_desc itbl_65c02[98] = {
{ "PLP", { INV, 0x28, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "PLX", { INV, 0xfa, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "PLY", { INV, 0x7a, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "RMB0", { INV, INV, INV, INV, 0x07, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "RMB1", { INV, INV, INV, INV, 0x17, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "RMB2", { INV, INV, INV, INV, 0x27, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "RMB3", { INV, INV, INV, INV, 0x37, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "RMB4", { INV, INV, INV, INV, 0x47, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "RMB5", { INV, INV, INV, INV, 0x57, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "RMB6", { INV, INV, INV, INV, 0x67, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "RMB7", { INV, INV, INV, INV, 0x77, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "RMB0", { INV, INV, INV, INV, 0x07, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "RMB1", { INV, INV, INV, INV, 0x17, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "RMB2", { INV, INV, INV, INV, 0x27, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "RMB3", { INV, INV, INV, INV, 0x37, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "RMB4", { INV, INV, INV, INV, 0x47, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "RMB5", { INV, INV, INV, INV, 0x57, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "RMB6", { INV, INV, INV, INV, 0x67, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "RMB7", { INV, INV, INV, INV, 0x77, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "ROL", { 0x2a, INV, INV, INV, 0x26, 0x36, INV, 0x2e, 0x3e, INV, INV, INV, INV, INV, INV, INV }},
{ "ROR", { 0x6a, INV, INV, INV, 0x66, 0x76, INV, 0x6e, 0x7e, INV, INV, INV, INV, INV, INV, INV }},
{ "RTI", { INV, 0x40, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
@@ -185,14 +185,14 @@ instruction_desc itbl_65c02[98] = {
{ "SEC", { INV, 0x38, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SED", { INV, 0xf8, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SEI", { INV, 0x78, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SMB0", { INV, INV, INV, INV, 0x87, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SMB1", { INV, INV, INV, INV, 0x97, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SMB2", { INV, INV, INV, INV, 0xa7, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SMB3", { INV, INV, INV, INV, 0xb7, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SMB4", { INV, INV, INV, INV, 0xc7, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SMB5", { INV, INV, INV, INV, 0xd7, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SMB6", { INV, INV, INV, INV, 0xe7, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SMB7", { INV, INV, INV, INV, 0xf7, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SMB0", { INV, INV, INV, INV, 0x87, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SMB1", { INV, INV, INV, INV, 0x97, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SMB2", { INV, INV, INV, INV, 0xa7, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SMB3", { INV, INV, INV, INV, 0xb7, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SMB4", { INV, INV, INV, INV, 0xc7, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SMB5", { INV, INV, INV, INV, 0xd7, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SMB6", { INV, INV, INV, INV, 0xe7, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "SMB7", { INV, INV, INV, INV, 0xf7, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "STA", { INV, INV, INV, INV, 0x85, 0x95, INV, 0x8d, 0x9d, 0x99, INV, 0x81, 0x91, 0x92, INV, INV }},
{ "STP", { INV, 0xdb, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }},
{ "STX", { INV, INV, INV, INV, 0x86, INV, 0x96, 0x8e, INV, INV, INV, INV, INV, INV, INV, INV }},

View File

@@ -2,4 +2,13 @@
lda [w]0,x ; warning level >= 2
lda [w]0,y ; warning level >= 2
.warning "This is a warning" ; warning level >= 1
.warning "This is a warning" ; warning level >= 1
hello:
jsr hello
rts
world:
jsr world
.byte 1
rts