diff --git a/README.txt b/README.txt index 6176f30..49e93a1 100644 --- a/README.txt +++ b/README.txt @@ -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] diff --git a/asm6502.c b/asm6502.c index c159096..61408d8 100644 --- a/asm6502.c +++ b/asm6502.c @@ -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" diff --git a/asm6502.h b/asm6502.h index e123b2c..c8b524b 100644 --- a/asm6502.h +++ b/asm6502.h @@ -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 diff --git a/doc/asm6502.but b/doc/asm6502.but index bcc93e2..55393af 100644 --- a/doc/asm6502.but +++ b/doc/asm6502.but @@ -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 diff --git a/itbl.c b/itbl.c index d36282f..12cd6db 100644 --- a/itbl.c +++ b/itbl.c @@ -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 }}, diff --git a/tests/testwarn.a65 b/tests/testwarn.a65 index 6c6bfd3..f61abd6 100644 --- a/tests/testwarn.a65 +++ b/tests/testwarn.a65 @@ -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 \ No newline at end of file +.warning "This is a warning" ; warning level >= 1 + +hello: + jsr hello + rts + +world: + jsr world + .byte 1 + rts