mirror of
https://github.com/VARCem/asm6502.git
synced 2026-09-24 15:47:21 +00:00
add jsr, rts optimization notice, code and doc cleanup
This commit is contained in:
56
README.txt
56
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]
|
||||
|
||||
87
asm6502.c
87
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"
|
||||
|
||||
21
asm6502.h
21
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
|
||||
|
||||
@@ -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
32
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 }},
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user