2023-11-26 12:11:49 -05:00
# include <stdbool.h>
# include <assert.h>
# include "op.h"
# include "cpu.h"
2024-01-09 15:56:54 -05:00
# include "decoding.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) \
2023-12-03 00:27:07 -05:00
case op_code : \
2024-01-06 14:27:09 -05:00
op_ # # op ( system , ADDR_MODE_ # # addr_mode ) ; \
2023-10-05 17:05:06 -04:00
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 ) \
2024-01-06 14:27:09 -05:00
IS_RMW_OP_CODE_ ( op , line , 0x0a , ACCUMULATOR ) \
2023-10-05 17:05:06 -04:00
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 )
2024-01-06 14:27:09 -05:00
void write_operand ( System * system , Operand operand , byte value ) {
2023-11-26 12:11:49 -05:00
switch ( operand . type ) {
case OPERAND_TYPE_ACCUMULATOR :
2024-01-06 14:27:09 -05:00
system - > cpu . accumulator = value ;
2023-11-26 12:11:49 -05:00
break ;
case OPERAND_TYPE_ADDRESS :
2024-01-06 14:27:09 -05:00
mem_set_byte ( system , operand . value , value ) ;
2023-11-26 12:11:49 -05:00
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 :
2024-01-06 14:27:09 -05:00
case ADDR_MODE_IMMEDIATE :
2023-11-26 12:11:49 -05:00
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 :
2024-01-06 14:27:09 -05:00
case ADDR_MODE_ABSOLUTE_INDEXED_Y :
2023-11-26 12:11:49 -05:00
return 7 ;
2024-01-06 14:27:09 -05:00
case ADDR_MODE_INDIRECT_X :
case ADDR_MODE_INDIRECT_Y :
return 8 ;
2023-11-26 12:11:49 -05:00
default :
assert ( false ) ;
}
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
void set_acl_flags ( System * system , byte result ) {
cpu_set_flag ( system , CPU_STATUS_ZERO_MASK , result = = 0 ) ;
cpu_set_flag ( system , CPU_STATUS_NEGATIVE_MASK , result & 0x80 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
byte get_branch_cycle_count ( System * system , bool branching , char offset ) {
address target = system - > cpu . program_counter ;
2023-11-26 12:11:49 -05:00
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
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_branch ( System * system , bool branching ) {
char offset = ( char ) cpu_get_next_byte ( system ) ;
2023-11-26 12:11:49 -05:00
if ( branching ) {
2024-01-06 14:27:09 -05:00
address counter = system - > cpu . program_counter ;
2023-11-26 12:11:49 -05:00
address target = counter + offset ;
2024-01-06 14:27:09 -05:00
system - > cpu . program_counter = target ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
cpu_add_cycles ( system , get_branch_cycle_count ( system , branching , offset ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
void add_with_carry ( System * system , byte value ) {
byte acc = system - > cpu . 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
2024-01-06 14:27:09 -05:00
byte result = addition + cpu_get_flag ( system , CPU_STATUS_CARRY_MASK ) ;
2023-11-26 12:11:49 -05:00
if ( result < addition ) {
overflow = true ;
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
system - > cpu . accumulator = result ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
cpu_set_flag ( system , CPU_STATUS_CARRY_MASK , overflow ) ;
cpu_set_flag ( system , CPU_STATUS_OVERFLOW_MASK , is_sign_overflow ( acc , value , result ) ) ;
2023-11-26 12:11:49 -05:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , result ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_ADC ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
byte value = read_operand ( system , operand ) ;
add_with_carry ( system , value ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_AHX ( System * system , AddressingMode addr_mode ) {
2023-11-26 12:11:49 -05:00
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_ALR ( System * system , AddressingMode addr_mode ) {
2023-11-26 12:11:49 -05:00
assert ( false ) ;
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_ANC ( System * system , AddressingMode addr_mode ) {
2023-11-26 12:11:49 -05:00
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_AND ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
byte acc = system - > cpu . accumulator ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
byte result = acc & value ;
2024-01-06 14:27:09 -05:00
system - > cpu . accumulator = result ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , result ) ;
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_ARR ( System * system , AddressingMode addr_mode ) {
2023-11-26 12:11:49 -05:00
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_ASL ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
2023-11-26 12:11:49 -05:00
byte result = value < < 1 ;
2024-01-06 14:27:09 -05:00
write_operand ( system , operand , result ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
cpu_set_flag ( system , CPU_STATUS_CARRY_MASK , value & 0x80 ) ;
set_acl_flags ( system , result ) ;
cpu_add_cycles ( system , get_shift_cycle_count ( addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_AXS ( System * system , AddressingMode addr_mode ) {
2023-11-26 12:11:49 -05:00
assert ( false ) ;
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_BCC ( System * system , AddressingMode addr_mode ) {
op_branch ( system , ! cpu_get_flag ( system , CPU_STATUS_CARRY_MASK ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_BCS ( System * system , AddressingMode addr_mode ) {
op_branch ( system , cpu_get_flag ( system , CPU_STATUS_CARRY_MASK ) ) ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_BEQ ( System * system , AddressingMode addr_mode ) {
op_branch ( system , cpu_get_flag ( system , CPU_STATUS_ZERO_MASK ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_BIT ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
byte acc = system - > cpu . 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
2024-01-06 14:27:09 -05:00
cpu_set_flag ( system , CPU_STATUS_ZERO_MASK , result = = 0 ) ;
cpu_set_flag ( system , CPU_STATUS_OVERFLOW_MASK , value & 0x40 ) ;
cpu_set_flag ( system , CPU_STATUS_NEGATIVE_MASK , value & 0x80 ) ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_BMI ( System * system , AddressingMode addr_mode ) {
op_branch ( system , cpu_get_flag ( system , CPU_STATUS_NEGATIVE_MASK ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_BNE ( System * system , AddressingMode addr_mode ) {
op_branch ( system , ! cpu_get_flag ( system , CPU_STATUS_ZERO_MASK ) ) ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_BPL ( System * system , AddressingMode addr_mode ) {
op_branch ( system , ! cpu_get_flag ( system , 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
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_BRK ( System * system , AddressingMode addr_mode ) {
cpu_stack_push_context ( system ) ;
2023-11-26 12:11:49 -05:00
// TODO Load IRQ interrupt vector in PC at $FFFE/F
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
assert ( false ) ;
cpu_set_flag ( system , CPU_STATUS_B_MASK , true ) ;
cpu_add_cycles ( system , 7 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_BVC ( System * system , AddressingMode addr_mode ) {
op_branch ( system , ! cpu_get_flag ( system , CPU_STATUS_OVERFLOW_MASK ) ) ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_BVS ( System * system , AddressingMode addr_mode ) {
op_branch ( system , cpu_get_flag ( system , CPU_STATUS_OVERFLOW_MASK ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_CLC ( System * system , AddressingMode addr_mode ) {
cpu_set_flag ( system , CPU_STATUS_CARRY_MASK , false ) ;
cpu_add_cycles ( system , 2 ) ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_CLD ( System * system , AddressingMode addr_mode ) {
cpu_set_flag ( system , CPU_STATUS_DECIMAL_MASK , false ) ;
cpu_add_cycles ( system , 2 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_CLI ( System * system , AddressingMode addr_mode ) {
cpu_set_flag ( system , CPU_STATUS_INTERRUPT_DISABLE_MASK , false ) ;
cpu_add_cycles ( system , 2 ) ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_CLV ( System * system , AddressingMode addr_mode ) {
cpu_set_flag ( system , CPU_STATUS_OVERFLOW_MASK , false ) ;
cpu_add_cycles ( system , 2 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_CMP ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
byte acc = system - > cpu . 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
2024-01-06 14:27:09 -05:00
cpu_set_flag ( system , CPU_STATUS_CARRY_MASK , acc > = value ) ;
cpu_set_flag ( system , CPU_STATUS_ZERO_MASK , result = = 0 ) ;
cpu_set_flag ( system , CPU_STATUS_NEGATIVE_MASK , result & 0x80 ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_CPX ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
byte x = system - > cpu . 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
2024-01-06 14:27:09 -05:00
cpu_set_flag ( system , CPU_STATUS_CARRY_MASK , x > = value ) ;
cpu_set_flag ( system , CPU_STATUS_ZERO_MASK , result = = 0 ) ;
cpu_set_flag ( system , CPU_STATUS_NEGATIVE_MASK , result & 0x80 ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_CPY ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
byte y = system - > cpu . 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
2024-01-06 14:27:09 -05:00
cpu_set_flag ( system , CPU_STATUS_CARRY_MASK , y > = value ) ;
cpu_set_flag ( system , CPU_STATUS_ZERO_MASK , result = = 0 ) ;
cpu_set_flag ( system , CPU_STATUS_NEGATIVE_MASK , result & 0x80 ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_DCP ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
byte acc = system - > cpu . accumulator ;
byte result = value - 1 ;
byte cmp_result = acc - result ;
cpu_set_flag ( system , CPU_STATUS_CARRY_MASK , acc > = value ) ;
cpu_set_flag ( system , CPU_STATUS_ZERO_MASK , cmp_result = = 0 ) ;
cpu_set_flag ( system , CPU_STATUS_NEGATIVE_MASK , cmp_result & 0x80 ) ;
write_operand ( system , operand , result ) ;
byte cycle_count ;
switch ( addr_mode ) {
case ADDR_MODE_ZERO_PAGE :
cycle_count = 5 ;
break ;
case ADDR_MODE_ZERO_PAGE_INDEXED_X :
case ADDR_MODE_ABSOLUTE :
cycle_count = 6 ;
break ;
case ADDR_MODE_ABSOLUTE_INDEXED_X :
case ADDR_MODE_ABSOLUTE_INDEXED_Y :
cycle_count = 7 ;
break ;
case ADDR_MODE_INDIRECT_X :
case ADDR_MODE_INDIRECT_Y :
cycle_count = 8 ;
break ;
default :
assert ( false ) ;
}
cpu_add_cycles ( system , cycle_count ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_DEC ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
2023-11-26 12:11:49 -05:00
byte result = value - 1 ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , result ) ;
write_operand ( system , operand , result ) ;
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_DEX ( System * system , AddressingMode addr_mode ) {
byte x = system - > cpu . x ;
2023-11-26 12:11:49 -05:00
byte result = x - 1 ;
2024-01-06 14:27:09 -05:00
system - > cpu . x = result ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , result ) ;
cpu_add_cycles ( system , 2 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_DEY ( System * system , AddressingMode addr_mode ) {
byte y = system - > cpu . y ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
byte result = y - 1 ;
2024-01-06 14:27:09 -05:00
system - > cpu . y = result ;
2023-11-26 12:11:49 -05:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , result ) ;
cpu_add_cycles ( system , 2 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_EOR ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
byte acc = system - > cpu . accumulator ;
2023-11-26 12:11:49 -05:00
acc ^ = value ;
2024-01-06 14:27:09 -05:00
system - > cpu . accumulator = acc ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , acc ) ;
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_INC ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
value + = 1 ;
2024-01-06 14:27:09 -05:00
write_operand ( system , operand , value ) ;
2023-11-26 12:11:49 -05:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , value ) ;
cpu_add_cycles ( system , get_shift_cycle_count ( addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_INX ( System * system , AddressingMode addr_mode ) {
byte x = system - > cpu . x ;
2023-11-26 12:11:49 -05:00
x + = 1 ;
2024-01-06 14:27:09 -05:00
system - > cpu . x = x ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , x ) ;
cpu_add_cycles ( system , 2 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_INY ( System * system , AddressingMode addr_mode ) {
byte y = system - > cpu . y ;
2023-11-26 12:11:49 -05:00
y + = 1 ;
2024-01-06 14:27:09 -05:00
system - > cpu . y = y ;
2023-11-26 12:11:49 -05:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , y ) ;
cpu_add_cycles ( system , 2 ) ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_ISC ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
value + = 1 ;
write_operand ( system , operand , value ) ;
add_with_carry ( system , ~ value ) ;
cpu_add_cycles ( system , get_shift_cycle_count ( addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_JMP ( System * system , AddressingMode addr_mode ) {
word addr = decode_operand_addr ( system , addr_mode , NULL ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
system - > cpu . program_counter = addr ;
2023-11-26 12:11:49 -05:00
// 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.
2024-01-06 14:27:09 -05:00
int cycle_count = 3 ;
if ( addr_mode = = ADDR_MODE_INDIRECT_JUMP ) {
cycle_count = 5 ;
}
cpu_add_cycles ( system , cycle_count ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_JSR ( System * system , AddressingMode addr_mode ) {
2023-11-26 12:11:49 -05:00
// Push the program counter on the stack
2024-01-06 14:27:09 -05:00
address program_counter = system - > cpu . program_counter + 1 ;
cpu_stack_push ( system , program_counter > > 8 ) ;
cpu_stack_push ( system , program_counter & 0xff ) ;
2023-11-26 12:11:49 -05:00
// Updates the program counter to the address in the operand
2024-01-06 14:27:09 -05:00
address addr = decode_operand_addr ( system , addr_mode , NULL ) ;
system - > cpu . program_counter = addr ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
cpu_add_cycles ( system , 6 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_LAS ( System * system , AddressingMode addr_mode ) {
2023-11-26 12:11:49 -05:00
assert ( false ) ;
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_LAX ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
2023-11-26 12:11:49 -05:00
2024-01-06 14:27:09 -05:00
system - > cpu . accumulator = value ;
system - > cpu . x = value ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , value ) ;
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_LDA ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
system - > cpu . accumulator = value ;
2023-11-26 12:11:49 -05:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , value ) ;
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_LDX ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
2023-11-26 12:11:49 -05:00
2024-01-06 14:27:09 -05:00
system - > cpu . x = value ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , value ) ;
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_LDY ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
system - > cpu . y = value ;
set_acl_flags ( system , value ) ;
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
}
__attribute__ ( ( unused ) )
void op_LSR ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
// Put bit 0 in the carry flag
2024-01-06 14:27:09 -05:00
cpu_set_flag ( system , CPU_STATUS_CARRY_MASK , value & 0x01 ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
value > > = 1 ;
2024-01-06 14:27:09 -05:00
write_operand ( system , operand , value ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , value ) ;
cpu_add_cycles ( system , get_shift_cycle_count ( addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_NOP ( System * system , AddressingMode addr_mode ) {
if ( addr_mode ! = ADDR_MODE_IMPLICIT ) {
Operand operand = decode_operand ( system , addr_mode ) ;
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
} else {
cpu_add_cycles ( system , 2 ) ;
}
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_ORA ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
byte acc = system - > cpu . accumulator ;
2023-11-26 12:11:49 -05:00
acc | = value ;
2024-01-06 14:27:09 -05:00
system - > cpu . accumulator = acc ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , acc ) ;
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_PHA ( System * system , AddressingMode addr_mode ) {
byte acc = system - > cpu . accumulator ;
cpu_stack_push ( system , acc ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
cpu_add_cycles ( system , 3 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_PHP ( System * system , AddressingMode addr_mode ) {
byte status = system - > cpu . status ;
cpu_stack_push ( system , status ) ;
// cpu_set_flag(system, CPU_STATUS_B_MASK, true);
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
cpu_add_cycles ( system , 3 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_PLA ( System * system , AddressingMode addr_mode ) {
byte value = cpu_stack_pop ( system ) ;
system - > cpu . accumulator = value ;
set_acl_flags ( system , value ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
cpu_add_cycles ( system , 4 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_PLP ( System * system , AddressingMode addr_mode ) {
byte value = cpu_stack_pop ( system ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
value & = 0xef ; // The B mask cannot be set as it is a CPU signal
value | = 0x20 ; // This value is always set
system - > cpu . status = value ;
cpu_add_cycles ( system , 4 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_RLA ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
byte carry = cpu_get_flag ( system , CPU_STATUS_CARRY_MASK ) ;
byte acc = system - > cpu . accumulator ;
cpu_set_flag ( system , CPU_STATUS_CARRY_MASK , value & 0x80 ) ;
value = ( value < < 1 ) | carry ;
byte and_result = acc & value ;
system - > cpu . accumulator = and_result ;
write_operand ( system , operand , value ) ;
set_acl_flags ( system , value ) ;
cpu_add_cycles ( system , get_shift_cycle_count ( addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_ROL ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
byte carry = cpu_get_flag ( system , CPU_STATUS_CARRY_MASK ) ;
2023-11-26 12:11:49 -05:00
2024-01-06 14:27:09 -05:00
cpu_set_flag ( system , CPU_STATUS_CARRY_MASK , value & 0x80 ) ;
2023-11-26 12:11:49 -05:00
value = ( value < < 1 ) | carry ;
2024-01-06 14:27:09 -05:00
write_operand ( system , operand , value ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , value ) ;
cpu_add_cycles ( system , get_shift_cycle_count ( addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_ROR ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
byte carry = cpu_get_flag ( system , CPU_STATUS_CARRY_MASK ) ;
2023-11-26 12:11:49 -05:00
2024-01-06 14:27:09 -05:00
cpu_set_flag ( system , CPU_STATUS_CARRY_MASK , value & 0x01 ) ;
2023-11-26 12:11:49 -05:00
value = ( value > > 1 ) | ( carry < < 7 ) ;
2024-01-06 14:27:09 -05:00
write_operand ( system , operand , value ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , value ) ;
cpu_add_cycles ( system , get_shift_cycle_count ( addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_RRA ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
byte carry = cpu_get_flag ( system , CPU_STATUS_CARRY_MASK ) ;
cpu_set_flag ( system , CPU_STATUS_CARRY_MASK , value & 0x01 ) ;
value = ( value > > 1 ) | ( carry < < 7 ) ;
add_with_carry ( system , value ) ;
write_operand ( system , operand , value ) ;
// set_acl_flags(system, value);
cpu_add_cycles ( system , get_shift_cycle_count ( addr_mode ) ) ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_RTI ( System * system , AddressingMode addr_mode ) {
cpu_stack_pop_context ( system ) ;
cpu_add_cycles ( system , 6 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_RTS ( System * system , AddressingMode addr_mode ) {
byte lo = cpu_stack_pop ( system ) ;
address pc = cpu_stack_pop ( system ) < < 8 ;
2023-11-26 12:11:49 -05:00
pc + = lo ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
system - > cpu . program_counter = pc + 1 ;
cpu_add_cycles ( system , 6 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_SAX ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte x = system - > cpu . x ;
byte acc = system - > cpu . accumulator ;
byte result = acc & x ;
write_operand ( system , operand , result ) ;
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_SBC ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
add_with_carry ( system , ~ value ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_SEC ( System * system , AddressingMode addr_mode ) {
cpu_set_flag ( system , CPU_STATUS_CARRY_MASK , true ) ;
cpu_add_cycles ( system , 2 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_SED ( System * system , AddressingMode addr_mode ) {
cpu_set_flag ( system , CPU_STATUS_DECIMAL_MASK , true ) ;
cpu_add_cycles ( system , 2 ) ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_SEI ( System * system , AddressingMode addr_mode ) {
cpu_set_flag ( system , CPU_STATUS_INTERRUPT_DISABLE_MASK , true ) ;
cpu_add_cycles ( system , 2 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_SHX ( System * system , AddressingMode addr_mode ) {
2023-11-26 12:11:49 -05:00
assert ( false ) ;
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_SHY ( System * system , AddressingMode addr_mode ) {
2023-11-26 12:11:49 -05:00
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_SLO ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
byte acc = system - > cpu . accumulator ;
byte result = value < < 1 ;
acc | = result ;
system - > cpu . accumulator = acc ;
write_operand ( system , operand , result ) ;
cpu_set_flag ( system , CPU_STATUS_CARRY_MASK , value & 0x80 ) ;
set_acl_flags ( system , acc ) ;
cpu_add_cycles ( system , get_shift_cycle_count ( addr_mode ) ) ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_SRE ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte value = read_operand ( system , operand ) ;
byte acc = system - > cpu . accumulator ;
// Put bit 0 in the carry flag
cpu_set_flag ( system , CPU_STATUS_CARRY_MASK , value & 0x01 ) ;
value > > = 1 ;
acc ^ = value ;
system - > cpu . accumulator = acc ;
write_operand ( system , operand , value ) ;
set_acl_flags ( system , acc ) ;
cpu_add_cycles ( system , get_shift_cycle_count ( addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_STA ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte acc = system - > cpu . accumulator ;
2023-11-26 12:11:49 -05:00
assert ( operand . type = = OPERAND_TYPE_ADDRESS ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
mem_set_byte ( system , operand . value , acc ) ;
2023-10-05 17:05:06 -04:00
2023-11-26 12:11:49 -05:00
operand . is_page_crossing = true ;
2024-01-06 14:27:09 -05:00
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_STP ( System * system , AddressingMode addr_mode ) {
2023-11-26 12:11:49 -05:00
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_STX ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte x = system - > cpu . x ;
2023-11-26 12:11:49 -05:00
assert ( operand . type = = OPERAND_TYPE_ADDRESS ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
mem_set_byte ( system , operand . value , x ) ;
2023-11-26 12:11:49 -05:00
2024-01-06 14:27:09 -05:00
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_STY ( System * system , AddressingMode addr_mode ) {
Operand operand = decode_operand ( system , addr_mode ) ;
byte y = system - > cpu . y ;
2023-11-26 12:11:49 -05:00
assert ( operand . type = = OPERAND_TYPE_ADDRESS ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
mem_set_byte ( system , operand . value , y ) ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
cpu_add_cycles ( system , get_cycle_count ( operand , addr_mode ) ) ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_TAS ( System * system , AddressingMode addr_mode ) {
2023-11-26 12:11:49 -05:00
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_TAX ( System * system , AddressingMode addr_mode ) {
byte acc = system - > cpu . accumulator ;
system - > cpu . x = acc ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , acc ) ;
cpu_add_cycles ( system , 2 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_TAY ( System * system , AddressingMode addr_mode ) {
byte acc = system - > cpu . accumulator ;
system - > cpu . y = acc ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , acc ) ;
cpu_add_cycles ( system , 2 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_TSX ( System * system , AddressingMode addr_mode ) {
byte value = system - > cpu . stack_pointer ;
system - > cpu . x = value ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , value ) ;
cpu_add_cycles ( system , 2 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_TXA ( System * system , AddressingMode addr_mode ) {
byte x = system - > cpu . x ;
system - > cpu . accumulator = x ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , x ) ;
cpu_add_cycles ( system , 2 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_TXS ( System * system , AddressingMode addr_mode ) {
byte x = system - > cpu . x ;
system - > cpu . stack_pointer = x ;
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
cpu_add_cycles ( system , 2 ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_TYA ( System * system , AddressingMode addr_mode ) {
byte y = system - > cpu . y ;
system - > cpu . accumulator = y ;
2023-11-26 12:11:49 -05:00
2024-01-06 14:27:09 -05:00
set_acl_flags ( system , y ) ;
cpu_add_cycles ( system , 2 ) ;
2023-11-26 12:11:49 -05:00
}
2023-10-05 17:05:06 -04:00
2024-01-06 14:27:09 -05:00
__attribute__ ( ( unused ) )
void op_XAA ( System * system , AddressingMode addr_mode ) {
2023-11-26 12:11:49 -05:00
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-06 14:27:09 -05:00
void process_op_code ( System * system , byte op ) {
2023-10-05 17:05:06 -04:00
switch ( op ) {
2024-01-06 14:27:09 -05:00
// CTRL
2023-10-05 17:05:06 -04:00
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 )
2024-01-11 16:02:53 -05:00
IS_OP_CODE_MODE ( JMP , 0x4c , ABSOLUTE )
2024-01-06 14:27:09 -05:00
IS_OP_CODE_MODE ( JMP , 0x6c , INDIRECT_JUMP )
2023-10-05 17:05:06 -04:00
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 )
2024-01-06 14:27:09 -05:00
IS_OP_CODE_MODE ( NOP , 0x7c , ABSOLUTE_INDEXED_X )
2023-10-05 17:05:06 -04:00
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 )
2024-01-06 14:27:09 -05:00
// ALU
2023-10-05 17:05:06 -04:00
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 )
2024-01-06 14:27:09 -05:00
// RMW
2023-10-05 17:05:06 -04:00
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 )
2024-01-06 14:27:09 -05:00
IS_OP_CODE ( TXS , 0x9a )
2023-10-05 17:05:06 -04:00
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 )
2024-01-06 14:27:09 -05:00
IS_OP_CODE_MODE ( DEC , 0xd6 , ZERO_PAGE_INDEXED_X )
2023-10-05 17:05:06 -04:00
IS_OP_CODE ( NOP , 0xda )
2024-01-06 14:27:09 -05:00
IS_OP_CODE_MODE ( DEC , 0xde , ABSOLUTE_INDEXED_X )
2023-10-05 17:05:06 -04:00
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 )
2024-01-06 14:27:09 -05:00
IS_OP_CODE_MODE ( INC , 0xf6 , ZERO_PAGE_INDEXED_X )
2023-10-05 17:05:06 -04:00
IS_OP_CODE ( NOP , 0xfa )
IS_OP_CODE_MODE ( INC , 0xfe , ABSOLUTE_INDEXED_X )
2024-01-06 14:27:09 -05:00
// Unofficial
2023-10-05 17:05:06 -04:00
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 )
2024-01-06 14:27:09 -05:00
IS_OP_CODE_MODE ( LAS , 0xbb , ABSOLUTE_INDEXED_Y )
2023-10-05 17:05:06 -04:00
IS_OP_CODE_MODE ( LAX , 0xbf , ABSOLUTE_INDEXED_Y )
2024-01-06 14:27:09 -05:00
default :
assert ( false ) ;
2023-10-05 17:05:06 -04:00
}
2024-01-11 16:02:53 -05:00
}
AddressingMode get_op_addr_mode ( byte op_code ) {
switch ( op_code ) {
case 0x0c :
case 0x0d :
case 0x0e :
case 0x0f :
case 0x20 :
case 0x2c :
case 0x2d :
case 0x2e :
case 0x2f :
case 0x4c :
case 0x4d :
case 0x4e :
case 0x4f :
case 0x6d :
case 0x6e :
case 0x6f :
case 0x8c :
case 0x8d :
case 0x8e :
case 0x8f :
case 0xac :
case 0xad :
case 0xae :
case 0xaf :
case 0xcc :
case 0xcd :
case 0xce :
case 0xcf :
case 0xec :
case 0xed :
case 0xee :
case 0xef :
return ADDR_MODE_ABSOLUTE ;
case 0x1c :
case 0x1d :
case 0x1e :
case 0x1f :
case 0x3c :
case 0x3d :
case 0x3e :
case 0x3f :
case 0x5c :
case 0x5d :
case 0x5e :
case 0x5f :
case 0x7c :
case 0x7d :
case 0x7e :
case 0x7f :
case 0x9c :
case 0x9d :
case 0xbc :
case 0xbd :
case 0xdc :
case 0xdd :
case 0xde :
case 0xdf :
case 0xfc :
case 0xfd :
case 0xfe :
case 0xff :
return ADDR_MODE_ABSOLUTE_INDEXED_X ;
case 0x19 :
case 0x1b :
case 0x39 :
case 0x3b :
case 0x59 :
case 0x5b :
case 0x79 :
case 0x7b :
case 0x99 :
case 0x9b :
case 0x9e :
case 0x9f :
case 0xb9 :
case 0xbb :
case 0xbe :
case 0xbf :
case 0xd9 :
case 0xdb :
case 0xf9 :
case 0xfb :
return ADDR_MODE_ABSOLUTE_INDEXED_Y ;
case 0x0a :
case 0x2a :
case 0x4a :
case 0x6a :
return ADDR_MODE_ACCUMULATOR ;
case 0x09 :
case 0x0b :
case 0x29 :
case 0x2b :
case 0x49 :
case 0x4b :
case 0x69 :
case 0x6b :
case 0x80 :
case 0x82 :
case 0x89 :
case 0x8b :
case 0xa0 :
case 0xa2 :
case 0xa9 :
case 0xab :
case 0xc0 :
case 0xc2 :
case 0xc9 :
case 0xcb :
case 0xe0 :
case 0xe2 :
case 0xe9 :
case 0xeb :
return ADDR_MODE_IMMEDIATE ;
case 0x00 :
case 0x02 :
case 0x08 :
case 0x12 :
case 0x18 :
case 0x1a :
case 0x22 :
case 0x28 :
case 0x32 :
case 0x3a :
case 0x40 :
case 0x42 :
case 0x48 :
case 0x52 :
case 0x58 :
case 0x5a :
case 0x60 :
case 0x62 :
case 0x68 :
case 0x72 :
case 0x78 :
case 0x7a :
case 0x88 :
case 0x8a :
case 0x92 :
case 0x98 :
case 0x9a :
case 0xa8 :
case 0xaa :
case 0xb2 :
case 0xb8 :
case 0xba :
case 0xc8 :
case 0xca :
case 0xd2 :
case 0xd8 :
case 0xda :
case 0xe8 :
case 0xea :
case 0xf2 :
case 0xf8 :
case 0xfa :
return ADDR_MODE_IMPLICIT ;
case 0x01 :
case 0x03 :
case 0x21 :
case 0x23 :
case 0x41 :
case 0x43 :
case 0x61 :
case 0x63 :
case 0x81 :
case 0x83 :
case 0xa1 :
case 0xa3 :
case 0xc1 :
case 0xc3 :
case 0xe1 :
case 0xe3 :
return ADDR_MODE_INDIRECT_X ;
case 0x6c :
return ADDR_MODE_INDIRECT_JUMP ;
case 0x11 :
case 0x13 :
case 0x31 :
case 0x33 :
case 0x51 :
case 0x53 :
case 0x71 :
case 0x73 :
case 0x91 :
case 0x93 :
case 0xb1 :
case 0xb3 :
case 0xd1 :
case 0xd3 :
case 0xf1 :
case 0xf3 :
return ADDR_MODE_INDIRECT_Y ;
case 0x10 :
case 0x30 :
case 0x50 :
case 0x70 :
case 0x90 :
case 0xb0 :
case 0xd0 :
case 0xf0 :
return ADDR_MODE_RELATIVE ;
case 0x04 :
case 0x05 :
case 0x06 :
case 0x07 :
case 0x24 :
case 0x25 :
case 0x26 :
case 0x27 :
case 0x44 :
case 0x45 :
case 0x46 :
case 0x47 :
case 0x64 :
case 0x65 :
case 0x66 :
case 0x67 :
case 0x84 :
case 0x85 :
case 0x86 :
case 0x87 :
case 0xa4 :
case 0xa5 :
case 0xa6 :
case 0xa7 :
case 0xc4 :
case 0xc5 :
case 0xc6 :
case 0xc7 :
case 0xe4 :
case 0xe5 :
case 0xe6 :
case 0xe7 :
return ADDR_MODE_ZERO_PAGE ;
case 0x14 :
case 0x15 :
case 0x16 :
case 0x17 :
case 0x34 :
case 0x35 :
case 0x36 :
case 0x37 :
case 0x54 :
case 0x55 :
case 0x56 :
case 0x57 :
case 0x74 :
case 0x75 :
case 0x76 :
case 0x77 :
case 0x94 :
case 0x95 :
case 0xb4 :
case 0xb5 :
case 0xd4 :
case 0xd5 :
case 0xd6 :
case 0xd7 :
case 0xf4 :
case 0xf5 :
case 0xf6 :
case 0xf7 :
return ADDR_MODE_ZERO_PAGE_INDEXED_X ;
case 0x96 :
case 0x97 :
case 0xb6 :
case 0xb7 :
return ADDR_MODE_ZERO_PAGE_INDEXED_Y ;
default :
assert ( false ) ;
}
2023-11-26 12:11:49 -05:00
}