diff --git a/asm6502.c b/asm6502.c index 8f01af2..c159096 100644 --- a/asm6502.c +++ b/asm6502.c @@ -221,7 +221,8 @@ enum { ERR_MAX_IF, ERR_PHASE, ERR_PHASE_SIZE, - ERR_DIV_BY_ZERO + ERR_DIV_BY_ZERO, + ERR_CPU_UNSUPPORTED }; static char *err_msg[] = { @@ -257,7 +258,8 @@ static char *err_msg[] = { "too many if nesting levels", "symbol value mismatch between pass one and two", "pass two code size greater than pass one code size", - "division by zero" + "division by zero", + "CPU not supported" }; enum { @@ -545,7 +547,7 @@ static value number( char **p ) { } -static void ident_( char **p, char *id, int numeric ) { +static void ident( char **p, char *id, int numeric, int uppercase ) { int i = 0; if (( !numeric && !isalpha( **p ) && ( **p != '_' )) @@ -553,7 +555,7 @@ static void ident_( char **p, char *id, int numeric ) { error( ERR_ID ); do { - *id++ = *( *p )++; + *id++ = (char) ( uppercase ? toupper( *( *p )++ ) : *( *p )++ ); i++; if ( i >= ID_LEN ) error( ERR_ID_LEN ); } while ( isalnum( **p ) || ( **p == '_' )); @@ -562,33 +564,6 @@ static void ident_( char **p, char *id, int numeric ) { } -/* read identifier which may not start with a digit */ -static void ident( char **p, char *id ) { - ident_( p, id, 0 ); -} - - -/* read identifier which may start with a digit */ -static void numbered_ident( char **p, char *id ) { - ident_( p, id, 1 ); -} - - -/* read identifier and convert to upper case */ -static void ident_uppercase( char **p, char *id ) { - int i = 0; - - if ( !isalpha( **p )) error( ERR_ID ); - do { - *id++ = (char) toupper( *( *p )++ ); - i++; - if ( i >= ID_LEN ) error( ERR_ID_LEN ); - } while ( isalnum( **p )); - - *id = '\0'; -} - - static value expr( char ** ); @@ -608,7 +583,7 @@ static value primary( char **p ) { ( *p ) += 2; } else if ( **p == LOCAL_LABEL_LETTER && isalnum( *( *p + 1 ))) { /* local label*/ ( *p )++; - numbered_ident( p, id ); + ident( p, id, 1, 0 ); sym = lookup( id, current_label->locals ); if ( sym ) { res = sym->value; @@ -630,14 +605,14 @@ static value primary( char **p ) { if ( **p != '\'' ) error( ERR_CHR ); ( *p )++; } else if ( isalpha( **p )) { - ident( p, id ); + ident( p, id, 0, 0 ); sym = lookup( id, NULL); if ( !sym ) sym = reserve_label( id, NULL); skip_white( p ); if ( **p == LOCAL_LABEL_LETTER ) { /* qualified identifier: local label or variable */ ( *p )++; - numbered_ident( p, id ); + ident( p, id, 1, 0 ); local_sym = lookup( id, sym->locals ); if ( !local_sym ) local_sym = reserve_label( id, sym ); res = local_sym->value; @@ -956,7 +931,7 @@ static void to_uppercase( char *p ) { static instruction_desc *get_instruction_descr( const char *p ) { - int l = 0, r = sizeof( instruction_tbl ) / sizeof( instruction_desc ), x; + int l = 0, r = instruction_tbl_size, x; int cmp; while ( r >= l ) { @@ -1040,6 +1015,19 @@ static void emit_instr_2( instruction_desc *instr, int am, u16 o ) { } +/* emit instruction with byte argument */ +static void emit_instr_2p( instruction_desc *instr, int am, u8 o, u8 p ) { + if ( pass == 2 ) { + if ( oc < code_size - 2 ) { + code[oc] = instr->op[am]; + code[oc + 1] = o; + code[oc + 2] = p; + } else error( ERR_PHASE_SIZE ); + } + oc += 3; +} + + static int instruction_imp_acc( instruction_desc *instr ) { int am = AM_INV; @@ -1068,8 +1056,7 @@ static int instruction_imm( char **p, instruction_desc *instr ) { } -static int instruction_rel( instruction_desc *instr, value v ) { - int am = AM_REL; +static u16 calculate_offset( value v ) { u16 pct = pc + 2u; u16 off; @@ -1086,9 +1073,14 @@ static int instruction_rel( instruction_desc *instr, value v ) { } if ( v.v >= pct ) off = v.v - pct; else off = (u16) (( ~0u ) - ( pct - v.v - 1u )); - emit_instr_1( instr, am, off & 0xffu ); + return off; +} - return am; + +static int instruction_rel( instruction_desc *instr, value v ) { + u16 off = calculate_offset( v ); + emit_instr_1( instr, AM_REL, off & 0xffu ); + return AM_REL; } @@ -1105,23 +1097,26 @@ static int instruction_ind( char **p, instruction_desc *instr ) { /* indirect X addressing mode? */ if ( **p == ',' ) { skip_curr_and_white( p ); - ident_uppercase( p, id ); + ident( p, id, 0, 1 ); if ( strcmp( id, "X" ) != 0 ) error( ERR_INX ); - am = AM_INX; + if ( AM_VALID( *instr, AM_AIX )) am = AM_AIX; + else am = AM_ZIX; skip_white( p ); if ( **p != ')' ) error( ERR_CLOSING_PAREN ); skip_curr_and_white( p ); + } else { if ( **p != ')' ) error( ERR_CLOSING_PAREN ); skip_curr_and_white( p ); /* indirect Y addressing mode? */ if ( **p == ',' ) { skip_curr_and_white( p ); - ident_uppercase( p, id ); + ident( p, id, 0, 1 ); if ( strcmp( id, "Y" ) != 0 ) error( ERR_INY ); - am = AM_INY; + am = AM_ZIY; } else { - am = AM_IND; + if ( AM_VALID( *instr, AM_ZIN )) am = AM_ZIN; + else am = AM_AIN; } } @@ -1129,11 +1124,12 @@ static int instruction_ind( char **p, instruction_desc *instr ) { if ( pass == 2 ) { if ( UNDEFINED( v )) error( ERR_UNDEF ); - if ((( am == AM_INX ) || am == ( AM_INY )) && (TYPE( v ) != TYPE_BYTE )) + if (( am == AM_ZIX || am == AM_ZIY || am == AM_ZIN ) + && (TYPE( v ) != TYPE_BYTE )) error( ERR_ILLEGAL_TYPE ); } - if ( am == AM_IND ) { + if ( am == AM_AIN || am == AM_AIX ) { emit_instr_2( instr, am, v.v ); } else { emit_instr_1( instr, am, (u8) v.v ); @@ -1158,7 +1154,7 @@ static int instruction_abxy_zpxy( char **p, instruction_desc *instr, value v ) { if ( UNDEFINED( v )) error( ERR_UNDEF ); } - ident_uppercase( p, id ); + ident( p, id, 0, 1 ); /* test for absolute and zero-page X addressing */ if ( !strcmp( id, "X" )) { if ((TYPE( v ) == TYPE_BYTE ) && AM_VALID( *instr, AM_ZPX )) am = AM_ZPX; @@ -1169,7 +1165,7 @@ static int instruction_abxy_zpxy( char **p, instruction_desc *instr, value v ) { } else error( ERR_AM ); } - /* test for absolute and zero-page Y addressing */ + /* test for absolute and zero-page Y addressing */ else if ( !strcmp( id, "Y" )) { if ((TYPE( v ) == TYPE_BYTE ) && AM_VALID( *instr, AM_ZPY )) am = AM_ZPY; else if ( AM_VALID( *instr, AM_ABY )) { @@ -1212,6 +1208,26 @@ static int instruction_abs_zp( instruction_desc *instr, value v ) { } +/* bit branch, bit set/reset instructions */ +static int instruction_zp_rel( char **p, instruction_desc *instr, value v ) { + u16 off; + value rel; + + if ( TYPE( v ) != TYPE_BYTE ) + error( ERR_BYTE_RANGE ); + + rel = expr( p ); + off = calculate_offset( rel ); + + if ( pass == 2 ) { + if ( UNDEFINED( v ) || UNDEFINED( rel )) error( ERR_UNDEF ); + } + emit_instr_2p( instr, AM_ZPR, (u8) v.v, off ); + + return AM_ZPR; +} + + /* process one instruction */ static void instruction( char **p ) { char id[ID_LEN]; @@ -1220,7 +1236,7 @@ static void instruction( char **p ) { value v; /* first get instruction for given mnemonic */ - ident_uppercase( p, id ); + ident( p, id, 0, 1 ); instr = get_instruction_descr( id ); if ( !instr ) error( ERR_INSTR ); @@ -1248,7 +1264,8 @@ static void instruction( char **p ) { /* else we go through the possible absolute addressing modes */ else if ( **p == ',' ) { skip_curr_and_white( p ); - am = instruction_abxy_zpxy( p, instr, v ); + if ( AM_VALID( *instr, AM_ZPR )) am = instruction_zp_rel( p, instr, v ); + else am = instruction_abxy_zpxy( p, instr, v ); } /* must be absolute or zero-page addressing */ else { @@ -1688,12 +1705,27 @@ static void directive_assert( char **p, int on_pass ) { } +static void directive_cpu( char **p ) { + char cpu_type[ID_LEN]; + + skip_white(p); + ident( p, cpu_type, 1, 1 ); + if ( !strcmp( cpu_type, "6502" )) { + select_6502(); + } else if ( !strcmp( cpu_type, "65C02" )) { + select_65c02(); + } else { + error( ERR_CPU_UNSUPPORTED ); + } +} + + static int directive( char **p ) { char id[ID_LEN]; value v; int again = 0; - ident_uppercase( p, id ); + ident( p, id, 0, 1 ); if ( !strcmp( id, "ORG" )) { v = expr( p ); @@ -1727,6 +1759,8 @@ static int directive( char **p ) { } else if ( !strcmp( id, "LIST" )) { listing = list_statements; list_skip_one = 1; + } else if ( !strcmp( id, "CPU" )) { + directive_cpu( p ); } else { error( ERR_NO_DIRECTIVE ); } @@ -1737,7 +1771,7 @@ static int directive( char **p ) { static int is_mnemonic( const char *id ) { char id_uppercase[ID_LEN]; - int l = 0, r = sizeof( instruction_tbl ) / sizeof( instruction_desc ), x; + int l = 0, r = instruction_tbl_size, x; int cmp; strcpy( id_uppercase, id ); to_uppercase( id_uppercase ); @@ -1770,11 +1804,11 @@ static int statement( char **p ) { /* first check for variable or label definition */ if ( **p == LOCAL_LABEL_LETTER ) { ( *p )++; - numbered_ident( p, id1 ); + ident( p, id1, 1, 0 ); skip_white( p ); label = LOCAL_LABEL; } else if ( isalpha( **p )) { - ident( p, id1 ); + ident( p, id1, 0, 0 ); skip_white( p ); label = GLOBAL_LABEL; } @@ -2011,7 +2045,7 @@ static int conditional_statement( char **p ) { if ( IS_END( **p )) return 0; if ( **p != DIRECTIVE_LETTER ) return 0; ( *p )++; - ident_uppercase( p, id ); + ident( p, id, 0, 1 ); if ( !strcmp( id, "IF" )) { directive_if( p, 1, 0 ); @@ -2245,6 +2279,8 @@ int main( int argc, char *argv[] ) { goto ret0; } + select_6502(); + /* first assembler pass */ pass = 1; source = current_file->text; diff --git a/asm6502.h b/asm6502.h index a4dd412..e123b2c 100644 --- a/asm6502.h +++ b/asm6502.h @@ -36,38 +36,47 @@ typedef unsigned short u16; /* addressing modes */ enum { - AM_ACC = 0, - AM_IMP = 1, - AM_IMM = 2, - AM_REL = 3, - AM_ZP = 4, - AM_ZPX = 5, - AM_ZPY = 6, - AM_ABS = 7, - AM_ABX = 8, - AM_ABY = 9, - AM_IND = 10, - AM_INX = 11, - AM_INY = 12, - AM_INV = 13 + 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_ZPX = 5, /* ZP,X zero-page indexed with X */ + AM_ZPY = 6, /* ZP,Y zero-page indexed with Y */ + AM_ABS = 7, /* A absolute */ + AM_ABX = 8, /* A,X absolute indexed with X */ + AM_ABY = 9, /* A,Y absolute indexed with Y */ + AM_AIN = 10, /* (A) absolute indirect */ + AM_ZIX = 11, /* (ZP,X) zero-page indexed indirect */ + AM_ZIY = 12, /* (ZP),Y zero-page indirect indexed with Y */ + AM_ZIN = 13, /* (ZP) zero-page indirect */ + AM_AIX = 14, /* (ABS,X) absolute indexed indirect */ + AM_ZPR = 15, /* ZP,R zero-page, relative */ + AM_INV = 16 }; enum { - INV = 0xff + INV = 0xfc }; typedef struct instruction_desc { - char mn[4]; - u8 op[13]; + char mn[5]; + u8 op[16]; } instruction_desc; -extern instruction_desc instruction_tbl[56]; -extern const unsigned itbl_size; -extern u16 am_size[13]; +extern instruction_desc *instruction_tbl; +extern instruction_desc itbl_6502[56]; +extern instruction_desc itbl_65c02[98]; + +extern int instruction_tbl_size; + +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); + #endif diff --git a/itbl.c b/itbl.c index 32885e7..d36282f 100644 --- a/itbl.c +++ b/itbl.c @@ -30,65 +30,181 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "asm6502.h" -u16 am_size[13] = { 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2 }; +u16 am_size[16] = { 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 3, 3 }; -const unsigned itbl_size = 56; -instruction_desc instruction_tbl[56] = { - { "ADC", { INV, INV, 0x69, INV, 0x65, 0x75, INV, 0x6d, 0x7d, 0x79, INV, 0x61, 0x71 }}, - { "AND", { INV, INV, 0x29, INV, 0x25, 0x35, INV, 0x2d, 0x3d, 0x39, INV, 0x21, 0x31 }}, - { "ASL", { 0x0a, INV, INV, INV, 0x06, 0x16, INV, 0x0e, 0x1e, INV, INV, INV, INV }}, - { "BCC", { INV, INV, INV, 0x90, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "BCS", { INV, INV, INV, 0xb0, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "BEQ", { INV, INV, INV, 0xf0, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "BIT", { INV, INV, INV, INV, 0x24, INV, INV, 0x2c, INV, INV, INV, INV, INV }}, - { "BMI", { INV, INV, INV, 0x30, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "BNE", { INV, INV, INV, 0xd0, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "BPL", { INV, INV, INV, 0x10, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "BRK", { INV, 0x00, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "BVC", { INV, INV, INV, 0x50, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "BVS", { INV, INV, INV, 0x70, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "CLC", { INV, 0x18, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "CLD", { INV, 0xd8, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "CLI", { INV, 0x58, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "CLV", { INV, 0xb8, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "CMP", { INV, INV, 0xc9, INV, 0xc5, 0xd5, INV, 0xcd, 0xdd, 0xd9, INV, 0xc1, 0xd1 }}, - { "CPX", { INV, INV, 0xe0, INV, 0xe4, INV, INV, 0xec, INV, INV, INV, INV, INV }}, - { "CPY", { INV, INV, 0xc0, INV, 0xc4, INV, INV, 0xcc, INV, INV, INV, INV, INV }}, - { "DEC", { INV, INV, INV, INV, 0xc6, 0xd6, INV, 0xce, 0xde, INV, INV, INV, INV }}, - { "DEX", { INV, 0xca, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "DEY", { INV, 0x88, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "EOR", { INV, INV, 0x49, INV, 0x45, 0x55, INV, 0x4d, 0x5d, 0x59, INV, 0x41, 0x51 }}, - { "INC", { INV, INV, INV, INV, 0xe6, 0xf6, INV, 0xee, 0xfe, INV, INV, INV, INV }}, - { "INX", { INV, 0xe8, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "INY", { INV, 0xc8, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "JMP", { INV, INV, INV, INV, INV, INV, INV, 0x4c, INV, INV, 0x6c, INV, INV }}, - { "JSR", { INV, INV, INV, INV, INV, INV, INV, 0x20, INV, INV, INV, INV, INV }}, - { "LDA", { INV, INV, 0xa9, INV, 0xa5, 0xb5, INV, 0xad, 0xbd, 0xb9, INV, 0xa1, 0xb1 }}, - { "LDX", { INV, INV, 0xa2, INV, 0xa6, INV, 0xb6, 0xae, INV, 0xbe, INV, INV, INV }}, - { "LDY", { INV, INV, 0xa0, INV, 0xa4, 0xb4, INV, 0xac, 0xbc, INV, INV, INV, INV }}, - { "LSR", { 0x4a, INV, INV, INV, 0x46, 0x56, INV, 0x4e, 0x5e, INV, INV, INV, INV }}, - { "NOP", { INV, 0xea, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "ORA", { INV, INV, 0x09, INV, 0x05, 0x15, INV, 0x0d, 0x1d, 0x19, INV, 0x01, 0x11 }}, - { "PHA", { INV, 0x48, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "PHP", { INV, 0x08, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "PLA", { INV, 0x68, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "PLP", { INV, 0x28, 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 }}, - { "ROR", { 0x6a, INV, INV, INV, 0x66, 0x76, INV, 0x6e, 0x7e, INV, INV, INV, INV }}, - { "RTI", { INV, 0x40, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "RTS", { INV, 0x60, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "SBC", { INV, INV, 0xe9, INV, 0xe5, 0xf5, INV, 0xed, 0xfd, 0xf9, INV, 0xe1, 0xf1 }}, - { "SEC", { INV, 0x38, 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 }}, - { "SEI", { INV, 0x78, 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 }}, - { "STX", { INV, INV, INV, INV, 0x86, INV, 0x96, 0x8e, INV, INV, INV, INV, INV }}, - { "STY", { INV, INV, INV, INV, 0x84, 0x94, INV, 0x8c, INV, INV, INV, INV, INV }}, - { "TAX", { INV, 0xaa, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "TAY", { INV, 0xa8, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "TSX", { INV, 0xba, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "TXA", { INV, 0x8a, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "TXS", { INV, 0x9a, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, - { "TYA", { INV, 0x98, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }} +instruction_desc *instruction_tbl; +int instruction_tbl_size; + + +void select_6502( void ) { + instruction_tbl = itbl_6502; + instruction_tbl_size = sizeof( itbl_6502 ) / sizeof( instruction_desc ); +} + + +void select_65c02( void ) { + instruction_tbl = itbl_65c02; + instruction_tbl_size = sizeof( itbl_65c02 ) / sizeof( instruction_desc ); +} + + +instruction_desc itbl_6502[56] = { + { "ADC", { INV, INV, 0x69, INV, 0x65, 0x75, INV, 0x6d, 0x7d, 0x79, INV, 0x61, 0x71, INV, INV, INV }}, + { "AND", { INV, INV, 0x29, INV, 0x25, 0x35, INV, 0x2d, 0x3d, 0x39, INV, 0x21, 0x31, INV, INV, INV }}, + { "ASL", { 0x0a, INV, INV, INV, 0x06, 0x16, INV, 0x0e, 0x1e, INV, INV, INV, INV, INV, INV, INV }}, + { "BCC", { INV, INV, INV, 0x90, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BCS", { INV, INV, INV, 0xb0, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BEQ", { INV, INV, INV, 0xf0, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BIT", { INV, INV, INV, INV, 0x24, INV, INV, 0x2c, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BMI", { INV, INV, INV, 0x30, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BNE", { INV, INV, INV, 0xd0, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BPL", { INV, INV, INV, 0x10, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BRK", { INV, 0x00, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BVC", { INV, INV, INV, 0x50, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BVS", { INV, INV, INV, 0x70, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "CLC", { INV, 0x18, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "CLD", { INV, 0xd8, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "CLI", { INV, 0x58, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "CLV", { INV, 0xb8, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "CMP", { INV, INV, 0xc9, INV, 0xc5, 0xd5, INV, 0xcd, 0xdd, 0xd9, INV, 0xc1, 0xd1, INV, INV, INV }}, + { "CPX", { INV, INV, 0xe0, INV, 0xe4, INV, INV, 0xec, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "CPY", { INV, INV, 0xc0, INV, 0xc4, INV, INV, 0xcc, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "DEC", { INV, INV, INV, INV, 0xc6, 0xd6, INV, 0xce, 0xde, INV, INV, INV, INV, INV, INV, INV }}, + { "DEX", { INV, 0xca, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "DEY", { INV, 0x88, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "EOR", { INV, INV, 0x49, INV, 0x45, 0x55, INV, 0x4d, 0x5d, 0x59, INV, 0x41, 0x51, INV, INV, INV }}, + { "INC", { INV, INV, INV, INV, 0xe6, 0xf6, INV, 0xee, 0xfe, INV, INV, INV, INV, INV, INV, INV }}, + { "INX", { INV, 0xe8, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "INY", { INV, 0xc8, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "JMP", { INV, INV, INV, INV, INV, INV, INV, 0x4c, INV, INV, 0x6c, INV, INV, INV, INV, INV }}, + { "JSR", { INV, INV, INV, INV, INV, INV, INV, 0x20, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "LDA", { INV, INV, 0xa9, INV, 0xa5, 0xb5, INV, 0xad, 0xbd, 0xb9, INV, 0xa1, 0xb1, INV, INV, INV }}, + { "LDX", { INV, INV, 0xa2, INV, 0xa6, INV, 0xb6, 0xae, INV, 0xbe, INV, INV, INV, INV, INV, INV }}, + { "LDY", { INV, INV, 0xa0, INV, 0xa4, 0xb4, INV, 0xac, 0xbc, INV, INV, INV, INV, INV, INV, INV }}, + { "LSR", { 0x4a, INV, INV, INV, 0x46, 0x56, INV, 0x4e, 0x5e, INV, INV, INV, INV, INV, INV, INV }}, + { "NOP", { INV, 0xea, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "ORA", { INV, INV, 0x09, INV, 0x05, 0x15, INV, 0x0d, 0x1d, 0x19, INV, 0x01, 0x11, INV, INV, INV }}, + { "PHA", { INV, 0x48, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "PHP", { INV, 0x08, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "PLA", { INV, 0x68, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "PLP", { INV, 0x28, INV, INV, INV, 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 }}, + { "RTS", { INV, 0x60, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "SBC", { INV, INV, 0xe9, INV, 0xe5, 0xf5, INV, 0xed, 0xfd, 0xf9, INV, 0xe1, 0xf1, INV, INV, INV }}, + { "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 }}, + { "STA", { INV, INV, INV, INV, 0x85, 0x95, INV, 0x8d, 0x9d, 0x99, INV, 0x81, 0x91, INV, INV, INV }}, + { "STX", { INV, INV, INV, INV, 0x86, INV, 0x96, 0x8e, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "STY", { INV, INV, INV, INV, 0x84, 0x94, INV, 0x8c, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "TAX", { INV, 0xaa, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "TAY", { INV, 0xa8, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "TSX", { INV, 0xba, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "TXA", { INV, 0x8a, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "TXS", { INV, 0x9a, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "TYA", { INV, 0x98, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }} +}; + +instruction_desc itbl_65c02[98] = { + { "ADC", { INV, INV, 0x69, INV, 0x65, 0x75, INV, 0x6d, 0x7d, 0x79, INV, 0x61, 0x71, 0x72, INV, INV }}, + { "AND", { INV, INV, 0x29, INV, 0x25, 0x35, INV, 0x2d, 0x3d, 0x39, INV, 0x21, 0x31, 0x32, INV, INV }}, + { "ASL", { 0x0a, INV, INV, INV, 0x06, 0x16, INV, 0x0e, 0x1e, INV, INV, INV, INV, INV, INV, INV }}, + { "BBR0", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, 0x0f }}, + { "BBR1", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, 0x1f }}, + { "BBR2", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, 0x2f }}, + { "BBR3", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, 0x3f }}, + { "BBR4", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, 0x4f }}, + { "BBR5", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, 0x5f }}, + { "BBR6", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, 0x6f }}, + { "BBR7", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, 0x7f }}, + { "BBS0", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, 0x8f }}, + { "BBS1", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, 0x9f }}, + { "BBS2", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, 0xaf }}, + { "BBS3", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, 0xbf }}, + { "BBS4", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, 0xcf }}, + { "BBS5", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, 0xdf }}, + { "BBS6", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, 0xef }}, + { "BBS7", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, 0xff }}, + { "BCC", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BCS", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BEQ", { INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BIT", { INV, INV, 0x89, INV, 0x24, 0x34, INV, 0x2c, 0x3c, INV, INV, INV, INV, INV, INV, INV }}, + { "BMI", { INV, INV, INV, 0x30, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BNE", { INV, INV, INV, 0xd0, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BPL", { INV, INV, INV, 0x10, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BRA", { INV, INV, INV, 0x80, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BRK", { INV, 0x00, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BVC", { INV, INV, INV, 0x50, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "BVS", { INV, INV, INV, 0x70, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "CLC", { INV, 0x18, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "CLD", { INV, 0xd8, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "CLI", { INV, 0x58, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "CLV", { INV, 0xb8, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "CMP", { INV, INV, 0xc9, INV, 0xc5, 0xd5, INV, 0xcd, 0xdd, 0xd9, INV, 0xc1, 0xd1, 0xd2, INV, INV }}, + { "CPX", { INV, INV, 0xe0, INV, 0xe4, INV, INV, 0xec, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "CPY", { INV, INV, 0xc0, INV, 0xc4, INV, INV, 0xcc, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "DEC", { 0x3a, INV, INV, INV, 0xc6, 0xd6, INV, 0xce, 0xde, INV, INV, INV, INV, INV, INV, INV }}, + { "DEX", { INV, 0xca, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "DEY", { INV, 0x88, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "EOR", { INV, INV, 0x49, INV, 0x45, 0x55, INV, 0x4d, 0x5d, 0x59, INV, 0x41, 0x51, 0x52, INV, INV }}, + { "INC", { 0xee, INV, INV, INV, 0xe6, 0xf6, INV, 0xee, 0xfe, INV, INV, INV, INV, INV, INV, INV }}, + { "INX", { INV, 0xe8, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "INY", { INV, 0xc8, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "JMP", { INV, INV, INV, INV, INV, INV, INV, 0x4c, INV, INV, 0x6c, INV, INV, INV, 0x7c, INV }}, + { "JSR", { INV, INV, INV, INV, INV, INV, INV, 0x20, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "LDA", { INV, INV, 0xa9, INV, 0xa5, 0xb5, INV, 0xad, 0xbd, 0xb9, INV, 0xa1, 0xb1, 0xb2, INV, INV }}, + { "LDX", { INV, INV, 0xa2, INV, 0xa6, INV, 0xb6, 0xae, INV, 0xbe, INV, INV, INV, INV, INV, INV }}, + { "LDY", { INV, INV, 0xa0, INV, 0xa4, 0xb4, INV, 0xac, 0xbc, INV, INV, INV, INV, INV, INV, INV }}, + { "LSR", { 0x4a, INV, INV, INV, 0x46, 0x56, INV, 0x4e, 0x5e, INV, INV, INV, INV, INV, INV, INV }}, + { "NOP", { INV, 0xea, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "ORA", { INV, INV, 0x09, INV, 0x05, 0x15, INV, 0x0d, 0x1d, 0x19, INV, 0x01, 0x11, 0x12, INV, INV }}, + { "PHA", { INV, 0x48, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "PHP", { INV, 0x08, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "PHX", { INV, 0xda, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "PHY", { INV, 0x5a, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "PLA", { INV, 0x68, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "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 }}, + { "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 }}, + { "RTS", { INV, 0x60, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "SBC", { INV, INV, 0xe9, INV, 0xe5, 0xf5, INV, 0xed, 0xfd, 0xf9, INV, 0xe1, 0xf1, 0xf2, INV, INV }}, + { "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 }}, + { "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 }}, + { "STY", { INV, INV, INV, INV, 0x84, 0x94, INV, 0x8c, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "STZ", { INV, INV, INV, INV, 0x64, 0x74, INV, 0x9c, 0x9e, INV, INV, INV, INV, INV, INV, INV }}, + { "TAX", { INV, 0xaa, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "TAY", { INV, 0xa8, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "TRB", { INV, INV, INV, INV, 0x14, INV, INV, 0x1c, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "TSB", { INV, INV, INV, INV, 0x04, INV, INV, 0x0c, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "TSX", { INV, 0xba, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "TXA", { INV, 0x8a, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "TXS", { INV, 0x9a, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "TYA", { INV, 0x98, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }}, + { "WAI", { INV, 0xcb, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV, INV }} }; diff --git a/tests/wdc65c02.a65 b/tests/wdc65c02.a65 new file mode 100644 index 0000000..4ff0235 --- /dev/null +++ b/tests/wdc65c02.a65 @@ -0,0 +1,85 @@ +; additional instructions provided by the WDC65C02 +; for the other instructions see MOS6502.A65 + +.cpu 65c02 + +adc ($11) +and ($11) + +bbr0 $47,@ +bbr1 $47,@ +bbr2 $47,@ +bbr3 $47,@ +bbr4 $47,@ +bbr5 $47,@ +bbr6 $47,@ +bbr7 $47,@ + +bbs0 $47,@ +bbs1 $47,@ +bbs2 $47,@ +bbs3 $47,@ +bbs4 $47,@ +bbs5 $47,@ +bbs6 $47,@ +bbs7 $47,@ + +bit $11,x +bit $4711,x +bit #42 + +bra @ + +cmp ($11) + +dec + +eor ($11) + +jmp ($4711, X) + +lda ($11) + +ora ($11) + +phx +phy +plx +ply + +rmb0 $47 +rmb1 $47 +rmb2 $47 +rmb3 $47 +rmb4 $47 +rmb5 $47 +rmb6 $47 +rmb7 $47 + +sbc ($11) + +smb0 $47 +smb1 $47 +smb2 $47 +smb3 $47 +smb4 $47 +smb5 $47 +smb6 $47 +smb7 $47 + +sta ($11) + +stp + +stz $11 +stz $11,x +stz $4711 +stz $4711,x + +trb $11 +trb $4711 + +tsb $11 +tsb $4711 + +wai