2023-11-26 12:11:49 -05:00
# include <stdbool.h>
# include <stdlib.h>
# include <assert.h>
# include "op.h"
# include "cpu.h"
# include "../include/cpu.h"
2023-10-05 17:05:06 -04:00
// Reference: https://www.nesdev.org/wiki/CPU_unofficial_opcodes
2023-11-26 12:11:49 -05:00
// https://www.middle-engine.com/blog/posts/2020/06/23/programming-the-nes-the-6502-in-detail
2023-10-05 17:05:06 -04:00
# define IS_OP_CODE_MODE(op, op_code, addr_mode) \
case op_code : \
op_ # # op ( ADDR_MODE_ # # addr_mode ) ; \
break ;
# define IS_OP_CODE(op, op_code) \
IS_OP_CODE_MODE ( op , op_code , IMPLICIT )
# define IS_ALU_OP_CODE_(op, offset, addr_mode) \
IS_OP_CODE_MODE ( op , OP_CODE_BASE_ # # op + offset , addr_mode )
# define IS_ALU_OP_CODE(op) \
2023-11-26 12:11:49 -05:00
IS_ALU_OP_CODE_ ( op , 0x01 , INDIRECT_X ) \
2023-10-05 17:05:06 -04:00
IS_ALU_OP_CODE_ ( op , 0x05 , ZERO_PAGE ) \
IS_ALU_OP_CODE_ ( op , 0x09 , IMMEDIATE ) \
IS_ALU_OP_CODE_ ( op , 0x0d , ABSOLUTE ) \
2023-11-26 12:11:49 -05:00
IS_ALU_OP_CODE_ ( op , 0x11 , INDIRECT_Y ) \
2023-10-05 17:05:06 -04:00
IS_ALU_OP_CODE_ ( op , 0x15 , ZERO_PAGE_INDEXED_X ) \
IS_ALU_OP_CODE_ ( op , 0x19 , ABSOLUTE_INDEXED_Y ) \
IS_ALU_OP_CODE_ ( op , 0x1d , ABSOLUTE_INDEXED_X )
# define IS_ALU_OP_CODE_NO_IMMEDIATE(op) \
2023-11-26 12:11:49 -05:00
IS_ALU_OP_CODE_ ( op , 0x01 , INDIRECT_X ) \
2023-10-05 17:05:06 -04:00
IS_ALU_OP_CODE_ ( op , 0x05 , ZERO_PAGE ) \
IS_ALU_OP_CODE_ ( op , 0x0d , ABSOLUTE ) \
2023-11-26 12:11:49 -05:00
IS_ALU_OP_CODE_ ( op , 0x11 , INDIRECT_Y ) \
2023-10-05 17:05:06 -04:00
IS_ALU_OP_CODE_ ( op , 0x15 , ZERO_PAGE_INDEXED_X ) \
IS_ALU_OP_CODE_ ( op , 0x19 , ABSOLUTE_INDEXED_Y ) \
IS_ALU_OP_CODE_ ( op , 0x1d , ABSOLUTE_INDEXED_X )
# define IS_RMW_OP_CODE_(op, line, offset, addr_mode) \
IS_OP_CODE_MODE ( op , OP_CODE_BASE_ # # line + offset , addr_mode )
# define IS_RMW_OP_CODE(op, line) \
IS_RMW_OP_CODE_ ( op , line , 0x06 , ZERO_PAGE ) \
IS_RMW_OP_CODE_ ( op , line , 0x0a , IMPLICIT ) \
IS_RMW_OP_CODE_ ( op , line , 0x0e , ABSOLUTE ) \
IS_RMW_OP_CODE_ ( op , line , 0x16 , ZERO_PAGE_INDEXED_X ) \
IS_RMW_OP_CODE_ ( op , line , 0x1e , ABSOLUTE_INDEXED_X )
# define IS_UNOFFICIAL_OP_CODE_(op, line, offset, addr_mode) \
IS_OP_CODE_MODE ( op , OP_CODE_BASE_ # # line + offset , addr_mode )
# define IS_UNOFFICIAL_OP_CODE(op, line) \
2023-11-26 12:11:49 -05:00
IS_UNOFFICIAL_OP_CODE_ ( op , line , 0x03 , INDIRECT_X ) \
2023-10-05 17:05:06 -04:00
IS_UNOFFICIAL_OP_CODE_ ( op , line , 0x07 , ZERO_PAGE ) \
IS_UNOFFICIAL_OP_CODE_ ( op , line , 0x0f , ABSOLUTE ) \
2023-11-26 12:11:49 -05:00
IS_UNOFFICIAL_OP_CODE_ ( op , line , 0x13 , INDIRECT_Y ) \
2023-10-05 17:05:06 -04:00
IS_UNOFFICIAL_OP_CODE_ ( op , line , 0x17 , ZERO_PAGE_INDEXED_X ) \
IS_UNOFFICIAL_OP_CODE_ ( op , line , 0x1b , ABSOLUTE_INDEXED_Y ) \
IS_UNOFFICIAL_OP_CODE_ ( op , line , 0x1f , ABSOLUTE_INDEXED_X )
2023-11-26 12:11:49 -05:00
address decode_operand_addr ( AddressingMode addr_mode , bool * page_crossing ) {
CpuRegisters * registers = cpu_get_registers ( ) ;
if ( addr_mode = = ADDR_MODE_ZERO_PAGE ) {
return cpu_get_next_byte ( ) ;
} else if ( addr_mode = = ADDR_MODE_ZERO_PAGE_INDEXED_X ) {
return ( cpu_get_next_byte ( ) + registers - > x ) & 0xff ;
} else if ( addr_mode = = ADDR_MODE_ZERO_PAGE_INDEXED_Y ) {
return ( cpu_get_next_byte ( ) + registers - > y ) & 0xff ;
} else if ( addr_mode = = ADDR_MODE_ABSOLUTE | | addr_mode = = ADDR_MODE_ABSOLUTE_JUMP ) {
return cpu_get_next_word ( ) ;
} else if ( addr_mode = = ADDR_MODE_ABSOLUTE_INDEXED_X ) {
word addr = cpu_get_next_word ( ) ;
word new_addr = addr + registers - > x ;
* page_crossing = ( addr & 0xff00 ) ! = ( new_addr & 0xff00 ) ;
return new_addr ;
} else if ( addr_mode = = ADDR_MODE_ABSOLUTE_INDEXED_Y ) {
word addr = cpu_get_next_word ( ) ;
word new_addr = addr + registers - > y ;
* page_crossing = ( addr & 0xff00 ) ! = ( new_addr & 0xff00 ) ;
return new_addr ;
} else if ( addr_mode = = ADDR_MODE_INDIRECT_JUMP ) {
word addr = cpu_get_next_word ( ) ;
if ( ( addr & 0xff ) = = 0xff ) {
// Error in NES CPU for JMP op
word result = cpu_peek_byte ( addr ) ;
result + = cpu_peek_byte ( addr & 0xff00 ) < < 8 ;
return result ;
}
return cpu_peek_word ( addr ) ;
} else if ( addr_mode = = ADDR_MODE_INDIRECT_X ) {
byte addr = cpu_get_next_byte ( ) ;
word result = cpu_peek_byte ( ( addr + registers - > x ) & 0xff ) ;
result + = cpu_peek_byte ( ( addr + registers - > x + 1 ) & 0xff ) < < 8 ;
return result ;
} else if ( addr_mode = = ADDR_MODE_INDIRECT_Y ) {
byte arg_addr = cpu_get_next_byte ( ) ;
word addr = cpu_peek_byte ( arg_addr ) + ( cpu_peek_byte ( ( arg_addr + 1 ) & 0xff ) < < 8 ) ;
word new_addr = addr + registers - > y ;
* page_crossing = ( addr & 0xff00 ) ! = ( new_addr & 0xff00 ) ;
return new_addr ;
} else {
assert ( false ) ;
}
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
Operand decode_operand ( AddressingMode addr_mode ) {
Operand operand ;
if ( addr_mode = = ADDR_MODE_ACCUMULATOR ) {
operand . type = OPERAND_TYPE_ACCUMULATOR ;
operand . value = 0 ;
operand . is_page_crossing = false ;
} else if ( addr_mode = = ADDR_MODE_IMMEDIATE ) {
operand . type = OPERAND_TYPE_IMMEDIATE ;
operand . value = cpu_get_next_byte ( ) ;
operand . is_page_crossing = false ;
} else {
operand . type = OPERAND_TYPE_ADDRESS ;
operand . value = decode_operand_addr ( addr_mode , & operand . is_page_crossing ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
return operand ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
byte read_operand ( Operand operand ) {
switch ( operand . type ) {
case OPERAND_TYPE_ACCUMULATOR :
return cpu_get_registers ( ) - > accumulator ;
case OPERAND_TYPE_IMMEDIATE :
return ( byte ) operand . value ;
case OPERAND_TYPE_ADDRESS :
return cpu_peek_byte ( operand . value ) ;
default :
assert ( false ) ;
}
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void write_operand ( Operand operand , byte value ) {
switch ( operand . type ) {
case OPERAND_TYPE_ACCUMULATOR :
cpu_get_registers ( ) - > accumulator = value ;
break ;
case OPERAND_TYPE_ADDRESS :
cpu_push_byte ( operand . value , value ) ;
break ;
default :
assert ( false ) ;
}
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
bool is_sign_overflow ( byte val1 , byte val2 , byte result ) {
return ( ( val1 & 0x80 ) = = ( val2 & 0x80 ) ) & &
( ( val1 & 0x80 ) ! = ( result & 0x80 ) ) ;
}
byte get_cycle_count ( Operand operand , AddressingMode addr_mode ) {
switch ( addr_mode ) {
case ADDR_MODE_ACCUMULATOR :
case ADDR_MODE_IMPLICIT :
return 2 ;
case ADDR_MODE_ZERO_PAGE :
return 3 ;
case ADDR_MODE_ZERO_PAGE_INDEXED_X :
case ADDR_MODE_ZERO_PAGE_INDEXED_Y :
case ADDR_MODE_ABSOLUTE :
return 4 ;
case ADDR_MODE_ABSOLUTE_INDEXED_X :
case ADDR_MODE_ABSOLUTE_INDEXED_Y :
return operand . is_page_crossing ? 5 : 4 ;
case ADDR_MODE_INDIRECT_X :
return 6 ;
case ADDR_MODE_INDIRECT_Y :
return operand . is_page_crossing ? 6 : 5 ;
default :
assert ( false ) ;
}
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
byte get_shift_cycle_count ( AddressingMode addr_mode ) {
switch ( addr_mode ) {
case ADDR_MODE_ACCUMULATOR :
return 2 ;
case ADDR_MODE_ZERO_PAGE :
return 5 ;
case ADDR_MODE_ZERO_PAGE_INDEXED_X :
case ADDR_MODE_ABSOLUTE :
return 6 ;
case ADDR_MODE_ABSOLUTE_INDEXED_X :
return 7 ;
default :
assert ( false ) ;
}
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void set_acl_flags ( byte result ) {
cpu_set_flag ( result = = 0 , CPU_STATUS_ZERO_MASK ) ;
cpu_set_flag ( result & 0x80 , CPU_STATUS_NEGATIVE_MASK ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
byte get_branch_cycle_count ( bool branching , char offset ) {
address target = cpu_get_registers ( ) - > program_counter ;
byte cycle_count = 2 ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
if ( branching ) {
cycle_count + = 1 ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
if ( ( target & 0xff00 ) ! = ( ( target - offset ) & 0xff00 ) ) {
cycle_count + = 2 ;
}
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
return cycle_count ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_branch ( bool branching ) {
char offset = ( char ) cpu_get_next_byte ( ) ;
if ( branching ) {
address counter = cpu_get_registers ( ) - > program_counter ;
address target = counter + offset ;
cpu_get_registers ( ) - > program_counter = target ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_add_cycles ( get_branch_cycle_count ( branching , offset ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void add_with_carry ( byte value ) {
byte acc = cpu_get_registers ( ) - > accumulator ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
byte addition = acc + value ;
bool overflow = false ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
// Check for overflow
if ( addition < acc ) {
overflow = true ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
// Add carry flag and check for overflow again
byte result = addition + cpu_get_flag ( CPU_STATUS_CARRY_MASK ) ;
if ( result < addition ) {
overflow = true ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_get_registers ( ) - > accumulator = acc ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_set_flag ( overflow , CPU_STATUS_CARRY_MASK ) ;
cpu_set_flag ( is_sign_overflow ( acc , value , result ) ) ;
set_acl_flags ( result ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_ADC ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
byte value = read_operand ( operand ) ;
add_with_carry ( value ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_add_cycles ( get_cycle_count ( operand , addr_mode ) ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_AHX ( AddressingMode addr_mode ) {
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_ALR ( AddressingMode addr_mode ) {
assert ( false ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_ANC ( AddressingMode addr_mode ) {
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_AND ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
byte acc = cpu_get_registers ( ) - > accumulator ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
byte result = acc & value ;
cpu_get_registers ( ) - > accumulator = result ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
set_acl_flags ( result ) ;
cpu_add_cycles ( get_cycle_count ( operand , addr_mode ) ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_ARR ( AddressingMode addr_mode ) {
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_ASL ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
byte result = value < < 1 ;
write_operand ( operand , result ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_set_flag ( value & 0x80 , CPU_STATUS_CARRY_MASK ) ;
set_acl_flags ( result ) ;
cpu_add_cycles ( get_shift_cycle_count ( addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_AXS ( AddressingMode addr_mode ) {
assert ( false ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_BCC ( AddressingMode addr_mode ) {
op_branch ( ! cpu_get_flag ( CPU_STATUS_CARRY_MASK ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_BCS ( AddressingMode addr_mode ) {
op_branch ( cpu_get_flag ( CPU_STATUS_CARRY_MASK ) ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_BEQ ( AddressingMode addr_mode ) {
op_branch ( cpu_get_flag ( CPU_STATUS_ZERO_MASK ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_BIT ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
byte acc = cpu_get_registers ( ) - > accumulator ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
byte result = value & acc ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_set_flag ( result = = 0 , CPU_STATUS_ZERO_MASK ) ;
cpu_set_flag ( result & 0x40 , CPU_STATUS_OVERFLOW_MASK ) ;
cpu_set_flag ( result & 0x80 , CPU_STATUS_NEGATIVE_MASK ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_BMI ( AddressingMode addr_mode ) {
op_branch ( cpu_get_flag ( CPU_STATUS_NEGATIVE_MASK ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_BNE ( AddressingMode addr_mode ) {
op_branch ( ! cpu_get_flag ( CPU_STATUS_ZERO_MASK ) ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_BPL ( AddressingMode addr_mode ) {
op_branch ( ! cpu_get_flag ( CPU_STATUS_NEGATIVE_MASK ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
// Stops program execution, useful for debugging
void op_BRK ( AddressingMode addr_mode ) {
cpu_stack_push_context ( ) ;
// TODO Load IRQ interrupt vector in PC at $FFFE/F
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_set_flag ( true , CPU_STATUS_B_MASK ) ;
cpu_add_cycles ( 7 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_BVC ( AddressingMode addr_mode ) {
op_branch ( ! cpu_get_flag ( CPU_STATUS_OVERFLOW_MASK ) ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_BVS ( AddressingMode addr_mode ) {
op_branch ( cpu_get_flag ( CPU_STATUS_OVERFLOW_MASK ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_CLC ( AddressingMode addr_mode ) {
cpu_set_flag ( false , CPU_STATUS_CARRY_MASK ) ;
cpu_add_cycles ( 2 ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_CLD ( AddressingMode addr_mode ) {
cpu_set_flag ( false , CPU_STATUS_DECIMAL_MASK ) ;
cpu_add_cycles ( 2 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_CLI ( AddressingMode addr_mode ) {
cpu_set_flag ( false , CPU_STATUS_INTERRUPT_DISABLE_MASK ) ;
cpu_add_cycles ( 2 ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_CLV ( AddressingMode addr_mode ) {
cpu_set_flag ( false , CPU_STATUS_OVERFLOW_MASK ) ;
cpu_add_cycles ( 2 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_CMP ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
byte acc = cpu_get_registers ( ) - > accumulator ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
byte result = acc - value ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_set_flag ( acc > = value , CPU_STATUS_CARRY_MASK ) ;
cpu_set_flag ( result = = 0 , CPU_STATUS_ZERO_MASK ) ;
cpu_set_flag ( result & 0x80 , CPU_STATUS_NEGATIVE_MASK ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_add_cycles ( get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_CPX ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
byte x = cpu_get_registers ( ) - > x ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
byte result = x - value ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_set_flag ( x > = value , CPU_STATUS_CARRY_MASK ) ;
cpu_set_flag ( result = = 0 , CPU_STATUS_ZERO_MASK ) ;
cpu_set_flag ( result & 0x80 , CPU_STATUS_NEGATIVE_MASK ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_add_cycles ( get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_CPY ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
byte y = cpu_get_registers ( ) - > y ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
byte result = y - value ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_set_flag ( y > = value , CPU_STATUS_CARRY_MASK ) ;
cpu_set_flag ( result = = 0 , CPU_STATUS_ZERO_MASK ) ;
cpu_set_flag ( result & 0x80 , CPU_STATUS_NEGATIVE_MASK ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_add_cycles ( get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_DCP ( AddressingMode addr_mode ) {
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_DEC ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
byte result = value - 1 ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
set_acl_flags ( result ) ;
write_operand ( operand , result ) ;
cpu_add_cycles ( get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_DEX ( AddressingMode addr_mode ) {
byte x = cpu_get_registers ( ) - > x ;
byte result = x - 1 ;
cpu_get_registers ( ) - > x = result ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
set_acl_flags ( result ) ;
cpu_add_cycles ( 2 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_DEY ( AddressingMode addr_mode ) {
byte y = cpu_get_registers ( ) - > y ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
byte result = y - 1 ;
cpu_get_registers ( ) - > y = result ;
set_acl_flags ( result ) ;
cpu_add_cycles ( 2 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_EOR ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
byte acc = cpu_get_registers ( ) - > accumulator ;
acc ^ = value ;
cpu_get_registers ( ) - > accumulator = acc ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
set_acl_flags ( acc ) ;
cpu_add_cycles ( get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_INC ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
value + = 1 ;
write_operand ( operand , value ) ;
set_acl_flags ( value ) ;
cpu_add_cycles ( get_shift_cycle_count ( addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_INX ( AddressingMode addr_mode ) {
byte x = cpu_get_registers ( ) - > x ;
x + = 1 ;
cpu_get_registers ( ) - > x = x ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
set_acl_flags ( x ) ;
cpu_add_cycles ( 2 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_INY ( AddressingMode addr_mode ) {
byte y = cpu_get_registers ( ) - > y ;
y + = 1 ;
cpu_get_registers ( ) - > y = y ;
set_acl_flags ( y ) ;
cpu_add_cycles ( 2 ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_ISC ( AddressingMode addr_mode ) {
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_JMP ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte addr = read_operand ( operand ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_get_registers ( ) - > program_counter = addr ;
// TODO WN: Handle CPU bug?
// > An original 6502 has does not correctly fetch the target address if the indirect vector falls on a page boundary (e.g. $xxFF where xx is any value from $00 to $FF).
// > In this case fetches the LSB from $xxFF as expected but takes the MSB from $xx00.
// > This is fixed in some later chips like the 65SC02 so for compatibility always ensure the indirect vector is not at the end of the page.
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_JSR ( AddressingMode addr_mode ) {
// Push the program counter on the stack
address program_counter = cpu_get_registers ( ) - > program_counter - 1 ;
cpu_stack_push ( program_counter > > 8 ) ;
cpu_stack_push ( program_counter & 0xff ) ;
// Updates the program counter to the address in the operand
address addr = decode_operand_addr ( addr_mode , NULL ) ;
cpu_get_registers ( ) - > program_counter = addr ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_add_cycles ( 6 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_LAX ( AddressingMode addr_mode ) {
assert ( false ) ;
}
void op_LDA ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
cpu_get_registers ( ) - > accumulator = value ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
set_acl_flags ( value ) ;
cpu_add_cycles ( get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_LDX ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_get_registers ( ) - > x = value ;
set_acl_flags ( value ) ;
cpu_add_cycles ( get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_LDY ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
cpu_get_registers ( ) - > y = value ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
set_acl_flags ( value ) ;
cpu_add_cycles ( get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_LSR ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
// Put bit 0 in the carry flag
cpu_set_flag ( value & 0x01 , CPU_STATUS_CARRY_MASK ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
value > > = 1 ;
write_operand ( operand , value ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
set_acl_flags ( value ) ;
cpu_add_cycles ( get_shift_cycle_count ( addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_NOP ( AddressingMode addr_mode ) {
cpu_add_cycles ( 2 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_ORA ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
byte acc = cpu_get_registers ( ) - > accumulator ;
acc | = value ;
cpu_get_registers ( ) - > accumulator = acc ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
set_acl_flags ( acc ) ;
cpu_add_cycles ( get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_PHA ( AddressingMode addr_mode ) {
byte acc = cpu_get_registers ( ) - > accumulator ;
cpu_stack_push ( acc ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_add_cycles ( 3 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_PHP ( AddressingMode addr_mode ) {
byte status = cpu_get_registers ( ) - > status ;
cpu_stack_push ( status ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_add_cycles ( 3 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_PLA ( AddressingMode addr_mode ) {
byte value = cpu_stack_pop ( ) ;
cpu_get_registers ( ) - > accumulator = value ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_add_cycles ( 4 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_PLP ( AddressingMode addr_mode ) {
byte value = cpu_stack_pop ( ) ;
cpu_get_registers ( ) - > status = value ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_add_cycles ( 4 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_RLA ( AddressingMode addr_mode ) {
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_ROL ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
byte carry = cpu_get_flag ( CPU_STATUS_CARRY_MASK ) ;
cpu_set_flag ( value & 0x80 , CPU_STATUS_CARRY_MASK ) ;
value = ( value < < 1 ) | carry ;
write_operand ( operand , value ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
set_acl_flags ( value ) ;
cpu_add_cycles ( get_shift_cycle_count ( addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_ROR ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
byte carry = cpu_get_flag ( CPU_STATUS_CARRY_MASK ) ;
cpu_set_flag ( value & 0x01 , CPU_STATUS_CARRY_MASK ) ;
value = ( value > > 1 ) | ( carry < < 7 ) ;
write_operand ( operand , value ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
set_acl_flags ( value ) ;
cpu_add_cycles ( get_shift_cycle_count ( addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_RRA ( AddressingMode addr_mode ) {
assert ( false ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_RTI ( AddressingMode addr_mode ) {
cpu_stack_pop_context ( ) ;
cpu_add_cycles ( 6 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_RTS ( AddressingMode addr_mode ) {
byte lo = cpu_stack_pop ( ) ;
address pc = cpu_stack_pop ( ) < < 8 ;
pc + = lo ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_get_registers ( ) - > program_counter = pc - 1 ;
cpu_add_cycles ( 6 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_SAX ( AddressingMode addr_mode ) {
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_SBC ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte value = read_operand ( operand ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
add_with_carry ( ~ value ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_add_cycles ( get_cycle_count ( operand , addr_mode ) ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_SEC ( AddressingMode addr_mode ) {
cpu_set_flag ( 1 , CPU_STATUS_CARRY_MASK ) ;
cpu_add_cycles ( 2 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_SED ( AddressingMode addr_mode ) {
cpu_set_flag ( 1 , CPU_STATUS_DECIMAL_MASK ) ;
cpu_add_cycles ( 2 ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_SEI ( AddressingMode addr_mode ) {
cpu_set_flag ( 1 , CPU_STATUS_INTERRUPT_DISABLE_MASK ) ;
cpu_add_cycles ( 2 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_SHX ( AddressingMode addr_mode ) {
assert ( false ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_SHY ( AddressingMode addr_mode ) {
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_SLO ( AddressingMode addr_mode ) {
assert ( false ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_SRE ( AddressingMode addr_mode ) {
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_STA ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte acc = cpu_get_registers ( ) - > accumulator ;
assert ( operand . type = = OPERAND_TYPE_ADDRESS ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_push_byte ( acc , operand . value ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
operand . is_page_crossing = true ;
cpu_add_cycles ( get_cycle_count ( operand , addr_mode ) ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_STP ( AddressingMode addr_mode ) {
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_STX ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte x = cpu_get_registers ( ) - > x ;
assert ( operand . type = = OPERAND_TYPE_ADDRESS ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_push_byte ( x , operand . value ) ;
cpu_add_cycles ( get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_STY ( AddressingMode addr_mode ) {
Operand operand = decode_operand ( addr_mode ) ;
byte y = cpu_get_registers ( ) - > y ;
assert ( operand . type = = OPERAND_TYPE_ADDRESS ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_push_byte ( y , operand . value ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_add_cycles ( get_cycle_count ( operand , addr_mode ) ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_TAS ( AddressingMode addr_mode ) {
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_TAX ( AddressingMode addr_mode ) {
byte acc = cpu_get_registers ( ) - > accumulator ;
cpu_get_registers ( ) - > x = acc ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
set_acl_flags ( acc ) ;
cpu_add_cycles ( 2 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_TAY ( AddressingMode addr_mode ) {
byte acc = cpu_get_registers ( ) - > accumulator ;
cpu_get_registers ( ) - > y = acc ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
set_acl_flags ( acc ) ;
cpu_add_cycles ( 2 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_TSX ( AddressingMode addr_mode ) {
byte value = cpu_stack_pop ( ) ;
cpu_get_registers ( ) - > x = value ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
set_acl_flags ( value ) ;
cpu_add_cycles ( 2 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_TXA ( AddressingMode addr_mode ) {
byte x = cpu_get_registers ( ) - > x ;
cpu_get_registers ( ) - > accumulator = x ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
set_acl_flags ( x ) ;
cpu_add_cycles ( 2 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_TXS ( AddressingMode addr_mode ) {
byte x = cpu_get_registers ( ) - > x ;
cpu_stack_push ( x ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
cpu_add_cycles ( 2 ) ;
2023-10-05 17:05:06 -04:00
}
2023-11-26 12:11:49 -05:00
void op_TYA ( AddressingMode addr_mode ) {
byte y = cpu_get_registers ( ) - > y ;
cpu_get_registers ( ) - > accumulator = y ;
set_acl_flags ( y ) ;
cpu_add_cycles ( 2 ) ;
}
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
void op_XAA ( AddressingMode addr_mode ) {
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
void process_op_code ( int op ) {
switch ( op ) {
// CTRL
IS_OP_CODE ( BRK , 0x00 )
IS_OP_CODE ( PHP , 0x08 )
IS_OP_CODE ( CLC , 0x18 )
IS_OP_CODE ( PLP , 0x28 )
IS_OP_CODE ( SEC , 0x38 )
IS_OP_CODE ( RTI , 0x40 )
IS_OP_CODE ( PHA , 0x48 )
IS_OP_CODE ( CLI , 0x58 )
IS_OP_CODE ( RTS , 0x60 )
IS_OP_CODE ( PLA , 0x68 )
IS_OP_CODE ( SEI , 0x78 )
IS_OP_CODE ( DEY , 0x88 )
IS_OP_CODE ( TYA , 0x98 )
IS_OP_CODE ( TAY , 0xa8 )
IS_OP_CODE ( CLV , 0xb8 )
IS_OP_CODE ( INY , 0xc8 )
IS_OP_CODE ( CLD , 0xd8 )
IS_OP_CODE ( INX , 0xe8 )
IS_OP_CODE ( SED , 0xf8 )
IS_OP_CODE_MODE ( JSR , 0x20 , ABSOLUTE )
IS_OP_CODE_MODE ( BIT , 0x24 , ZERO_PAGE )
IS_OP_CODE_MODE ( BIT , 0x2c , ABSOLUTE )
IS_OP_CODE_MODE ( JMP , 0x4c , ABSOLUTE )
IS_OP_CODE_MODE ( JMP , 0x6c , ABSOLUTE_JUMP )
IS_OP_CODE_MODE ( STY , 0x84 , ZERO_PAGE )
IS_OP_CODE_MODE ( STY , 0x8c , ABSOLUTE )
IS_OP_CODE_MODE ( STY , 0x94 , ZERO_PAGE_INDEXED_X )
IS_OP_CODE_MODE ( SHY , 0x9c , ABSOLUTE_INDEXED_X )
IS_OP_CODE_MODE ( LDY , 0xa0 , IMMEDIATE )
IS_OP_CODE_MODE ( LDY , 0xa4 , ZERO_PAGE )
IS_OP_CODE_MODE ( LDY , 0xac , ABSOLUTE )
IS_OP_CODE_MODE ( LDY , 0xb4 , ZERO_PAGE_INDEXED_X )
IS_OP_CODE_MODE ( LDY , 0xbc , ABSOLUTE_INDEXED_X )
IS_OP_CODE_MODE ( CPY , 0xc0 , IMMEDIATE )
IS_OP_CODE_MODE ( CPY , 0xc4 , ZERO_PAGE )
IS_OP_CODE_MODE ( CPY , 0xcc , ABSOLUTE )
IS_OP_CODE_MODE ( CPX , 0xe0 , IMMEDIATE )
IS_OP_CODE_MODE ( CPX , 0xe4 , ZERO_PAGE )
IS_OP_CODE_MODE ( CPX , 0xec , ABSOLUTE )
2023-11-26 12:11:49 -05:00
IS_OP_CODE_MODE ( BPL , 0x10 , RELATIVE )
2023-10-05 17:05:06 -04:00
IS_OP_CODE_MODE ( BMI , 0x30 , RELATIVE )
IS_OP_CODE_MODE ( BVC , 0x50 , RELATIVE )
IS_OP_CODE_MODE ( BVS , 0x70 , RELATIVE )
IS_OP_CODE_MODE ( BCC , 0x90 , RELATIVE )
IS_OP_CODE_MODE ( BCS , 0xb0 , RELATIVE )
IS_OP_CODE_MODE ( BNE , 0xd0 , RELATIVE )
IS_OP_CODE_MODE ( BEQ , 0xf0 , RELATIVE )
IS_OP_CODE_MODE ( NOP , 0x04 , ZERO_PAGE )
IS_OP_CODE_MODE ( NOP , 0x0c , ABSOLUTE )
IS_OP_CODE_MODE ( NOP , 0x14 , ZERO_PAGE_INDEXED_X )
IS_OP_CODE_MODE ( NOP , 0x1c , ABSOLUTE_INDEXED_X )
IS_OP_CODE_MODE ( NOP , 0x34 , ZERO_PAGE_INDEXED_X )
IS_OP_CODE_MODE ( NOP , 0x3c , ABSOLUTE_INDEXED_X )
IS_OP_CODE_MODE ( NOP , 0x44 , ZERO_PAGE )
IS_OP_CODE_MODE ( NOP , 0x54 , ZERO_PAGE_INDEXED_X )
IS_OP_CODE_MODE ( NOP , 0x5c , ABSOLUTE_INDEXED_X )
IS_OP_CODE_MODE ( NOP , 0x64 , ZERO_PAGE )
IS_OP_CODE_MODE ( NOP , 0x74 , ZERO_PAGE_INDEXED_X )
IS_OP_CODE_MODE ( NOP , 0x7c , ZERO_PAGE_INDEXED_X )
IS_OP_CODE_MODE ( NOP , 0x80 , IMMEDIATE )
IS_OP_CODE_MODE ( NOP , 0xd4 , ZERO_PAGE_INDEXED_X )
IS_OP_CODE_MODE ( NOP , 0xdc , ABSOLUTE_INDEXED_X )
IS_OP_CODE_MODE ( NOP , 0xf4 , ZERO_PAGE_INDEXED_X )
IS_OP_CODE_MODE ( NOP , 0xfc , ABSOLUTE_INDEXED_X )
// ALU
IS_ALU_OP_CODE ( ORA )
IS_ALU_OP_CODE ( AND )
IS_ALU_OP_CODE ( EOR )
IS_ALU_OP_CODE ( ADC )
IS_ALU_OP_CODE_NO_IMMEDIATE ( STA )
IS_ALU_OP_CODE ( LDA )
IS_ALU_OP_CODE ( CMP )
IS_ALU_OP_CODE ( SBC )
// RMW
IS_RMW_OP_CODE ( ASL , ORA )
IS_RMW_OP_CODE ( ROL , AND )
IS_RMW_OP_CODE ( LSR , EOR )
IS_RMW_OP_CODE ( ROR , ADC )
IS_OP_CODE ( STP , 0x02 )
IS_OP_CODE ( STP , 0x12 )
IS_OP_CODE ( NOP , 0x1a )
IS_OP_CODE ( STP , 0x22 )
IS_OP_CODE ( STP , 0x32 )
IS_OP_CODE ( NOP , 0x3a )
IS_OP_CODE ( STP , 0x42 )
IS_OP_CODE ( STP , 0x52 )
IS_OP_CODE ( NOP , 0x5a )
IS_OP_CODE ( STP , 0x62 )
IS_OP_CODE ( STP , 0x72 )
IS_OP_CODE ( NOP , 0x7a )
IS_OP_CODE_MODE ( NOP , 0x82 , IMMEDIATE )
IS_OP_CODE_MODE ( STX , 0x86 , ZERO_PAGE )
IS_OP_CODE ( TXA , 0x8a )
IS_OP_CODE_MODE ( STX , 0x8e , ABSOLUTE )
IS_OP_CODE ( STP , 0x92 )
IS_OP_CODE_MODE ( STX , 0x96 , ZERO_PAGE_INDEXED_Y )
IS_OP_CODE ( TSX , 0x9a )
IS_OP_CODE_MODE ( SHX , 0x9e , ABSOLUTE_INDEXED_Y )
IS_OP_CODE_MODE ( LDX , 0xa2 , IMMEDIATE )
IS_OP_CODE_MODE ( LDX , 0xa6 , ZERO_PAGE )
IS_OP_CODE ( TAX , 0xaa )
IS_OP_CODE_MODE ( LDX , 0xae , ABSOLUTE )
IS_OP_CODE ( STP , 0xb2 )
IS_OP_CODE_MODE ( LDX , 0xb6 , ZERO_PAGE_INDEXED_Y )
IS_OP_CODE ( TSX , 0xba )
IS_OP_CODE_MODE ( LDX , 0xbe , ABSOLUTE_INDEXED_Y )
IS_OP_CODE_MODE ( NOP , 0xc2 , IMMEDIATE )
IS_OP_CODE_MODE ( DEC , 0xc6 , ZERO_PAGE )
IS_OP_CODE ( DEX , 0xca )
IS_OP_CODE_MODE ( DEC , 0xce , ABSOLUTE )
IS_OP_CODE ( STP , 0xd2 )
IS_OP_CODE_MODE ( DEC , 0xd6 , ZERO_PAGE_INDEXED_Y )
IS_OP_CODE ( NOP , 0xda )
IS_OP_CODE_MODE ( DEC , 0xde , ABSOLUTE_INDEXED_Y )
IS_OP_CODE_MODE ( NOP , 0xe2 , IMMEDIATE )
IS_OP_CODE_MODE ( INC , 0xe6 , ZERO_PAGE )
IS_OP_CODE ( NOP , 0xea ) // The official NOP
IS_OP_CODE_MODE ( INC , 0xee , ABSOLUTE )
IS_OP_CODE ( STP , 0xf2 )
IS_OP_CODE_MODE ( INC , 0xf6 , ZERO_PAGE_INDEXED_Y )
IS_OP_CODE ( NOP , 0xfa )
IS_OP_CODE_MODE ( INC , 0xfe , ABSOLUTE_INDEXED_X )
// Unofficial
IS_UNOFFICIAL_OP_CODE ( SLO , ORA )
IS_UNOFFICIAL_OP_CODE ( RLA , AND )
IS_UNOFFICIAL_OP_CODE ( SRE , EOR )
IS_UNOFFICIAL_OP_CODE ( RRA , ADC )
IS_UNOFFICIAL_OP_CODE ( DCP , CMP )
IS_UNOFFICIAL_OP_CODE ( ISC , SBC )
IS_OP_CODE_MODE ( ANC , 0x0b , IMMEDIATE )
IS_OP_CODE_MODE ( ANC , 0x2b , IMMEDIATE )
IS_OP_CODE_MODE ( ALR , 0x4b , IMMEDIATE )
IS_OP_CODE_MODE ( ARR , 0x6b , IMMEDIATE )
IS_OP_CODE_MODE ( AXS , 0xcb , IMMEDIATE )
IS_OP_CODE_MODE ( SBC , 0xeb , IMMEDIATE )
2023-11-26 12:11:49 -05:00
IS_OP_CODE_MODE ( SAX , 0x83 , INDIRECT_X )
2023-10-05 17:05:06 -04:00
IS_OP_CODE_MODE ( SAX , 0x87 , ZERO_PAGE )
IS_OP_CODE_MODE ( XAA , 0x8b , IMMEDIATE )
IS_OP_CODE_MODE ( SAX , 0x8f , ABSOLUTE )
2023-11-26 12:11:49 -05:00
IS_OP_CODE_MODE ( AHX , 0x93 , INDIRECT_Y )
2023-10-05 17:05:06 -04:00
IS_OP_CODE_MODE ( SAX , 0x97 , ZERO_PAGE_INDEXED_Y )
IS_OP_CODE_MODE ( TAS , 0x9b , ABSOLUTE_INDEXED_Y )
IS_OP_CODE_MODE ( AHX , 0x9f , ABSOLUTE_INDEXED_Y )
2023-11-26 12:11:49 -05:00
IS_OP_CODE_MODE ( LAX , 0xa3 , INDIRECT_X )
2023-10-05 17:05:06 -04:00
IS_OP_CODE_MODE ( LAX , 0xa7 , ZERO_PAGE )
IS_OP_CODE_MODE ( LAX , 0xab , IMMEDIATE )
IS_OP_CODE_MODE ( LAX , 0xaf , ABSOLUTE )
2023-11-26 12:11:49 -05:00
IS_OP_CODE_MODE ( LAX , 0xb3 , INDIRECT_Y )
2023-10-05 17:05:06 -04:00
IS_OP_CODE_MODE ( LAX , 0xb7 , ZERO_PAGE_INDEXED_Y )
IS_OP_CODE_MODE ( LAX , 0xbb , ABSOLUTE_INDEXED_Y )
IS_OP_CODE_MODE ( LAX , 0xbf , ABSOLUTE_INDEXED_Y )
}
2023-11-26 12:11:49 -05:00
}