2019-02-13 13:32:21 -05:00
/************************
Add / substract operations
* * * * * * * * * * * * * * * * * * * * * * * * */
void Cpu : : Add8 ( uint8_t value )
{
uint32_t result ;
if ( CheckFlag ( ProcFlags : : Decimal ) ) {
result = ( _state . A & 0x0F ) + ( value & 0x0F ) + ( _state . PS & ProcFlags : : Carry ) ;
if ( result > 0x09 ) result + = 0x06 ;
result = ( _state . A & 0xF0 ) + ( value & 0xF0 ) + ( result > 0x0F ? 0x10 : 0 ) + ( result & 0x0F ) ;
} else {
2019-02-18 23:04:08 -05:00
result = ( _state . A & 0xFF ) + value + ( _state . PS & ProcFlags : : Carry ) ;
2019-02-13 13:32:21 -05:00
}
if ( ~ ( _state . A ^ value ) & ( _state . A ^ result ) & 0x80 ) {
SetFlags ( ProcFlags : : Overflow ) ;
} else {
ClearFlags ( ProcFlags : : Overflow ) ;
}
if ( CheckFlag ( ProcFlags : : Decimal ) & & result > 0x9F ) {
result + = 0x60 ;
}
ClearFlags ( ProcFlags : : Carry | ProcFlags : : Negative | ProcFlags : : Zero ) ;
SetZeroNegativeFlags ( ( uint8_t ) result ) ;
2019-02-18 23:04:08 -05:00
if ( result > 0xFF ) {
2019-02-13 13:32:21 -05:00
SetFlags ( ProcFlags : : Carry ) ;
}
2019-02-18 23:04:08 -05:00
_state . A = ( _state . A & 0xFF00 ) | ( uint8_t ) result ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : Add16 ( uint16_t value )
{
uint32_t result ;
if ( CheckFlag ( ProcFlags : : Decimal ) ) {
result = ( _state . A & 0x0F ) + ( value & 0x0F ) + ( _state . PS & ProcFlags : : Carry ) ;
if ( result > 0x09 ) result + = 0x06 ;
result = ( _state . A & 0xF0 ) + ( value & 0xF0 ) + ( result > 0x0F ? 0x10 : 0 ) + ( result & 0x0F ) ;
if ( result > 0x9F ) result + = 0x60 ;
result = ( _state . A & 0xF00 ) + ( value & 0xF00 ) + ( result > 0xFF ? 0x100 : 0 ) + ( result & 0xFF ) ;
if ( result > 0x9FF ) result + = 0x600 ;
result = ( _state . A & 0xF000 ) + ( value & 0xF000 ) + ( result > 0xFFF ? 0x1000 : 0 ) + ( result & 0xFFF ) ;
} else {
2019-02-18 23:04:08 -05:00
result = _state . A + value + ( _state . PS & ProcFlags : : Carry ) ;
2019-02-13 13:32:21 -05:00
}
if ( ~ ( _state . A ^ value ) & ( _state . A ^ result ) & 0x8000 ) {
SetFlags ( ProcFlags : : Overflow ) ;
} else {
ClearFlags ( ProcFlags : : Overflow ) ;
}
if ( CheckFlag ( ProcFlags : : Decimal ) & & result > 0x9FFF ) {
result + = 0x6000 ;
}
ClearFlags ( ProcFlags : : Carry | ProcFlags : : Negative | ProcFlags : : Zero ) ;
SetZeroNegativeFlags ( ( uint16_t ) result ) ;
2019-02-18 23:04:08 -05:00
if ( result > 0xFFFF ) {
2019-02-13 13:32:21 -05:00
SetFlags ( ProcFlags : : Carry ) ;
}
_state . A = ( uint16_t ) result ;
}
void Cpu : : ADC ( )
{
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
Add8 ( GetByteValue ( ) ) ;
} else {
Add16 ( GetWordValue ( ) ) ;
}
}
void Cpu : : Sub8 ( uint8_t value )
{
2019-02-18 23:04:08 -05:00
int32_t result ;
2019-02-13 13:32:21 -05:00
if ( CheckFlag ( ProcFlags : : Decimal ) ) {
result = ( _state . A & 0x0F ) + ( value & 0x0F ) + ( _state . PS & ProcFlags : : Carry ) ;
if ( result < = 0x0F ) result - = 0x06 ;
result = ( _state . A & 0xF0 ) + ( value & 0xF0 ) + ( result > 0x0F ? 0x10 : 0 ) + ( result & 0x0F ) ;
} else {
2019-02-18 23:04:08 -05:00
result = ( _state . A & 0xFF ) + value + ( _state . PS & ProcFlags : : Carry ) ;
2019-02-13 13:32:21 -05:00
}
if ( ~ ( _state . A ^ value ) & ( _state . A ^ result ) & 0x80 ) {
SetFlags ( ProcFlags : : Overflow ) ;
} else {
ClearFlags ( ProcFlags : : Overflow ) ;
}
if ( CheckFlag ( ProcFlags : : Decimal ) & & result < = 0xFF ) {
result - = 0x60 ;
}
ClearFlags ( ProcFlags : : Carry | ProcFlags : : Negative | ProcFlags : : Zero ) ;
SetZeroNegativeFlags ( ( uint8_t ) result ) ;
2019-02-18 23:04:08 -05:00
if ( result > 0xFF ) {
2019-02-13 13:32:21 -05:00
SetFlags ( ProcFlags : : Carry ) ;
}
2019-02-18 23:04:08 -05:00
_state . A = ( _state . A & 0xFF00 ) | ( uint8_t ) result ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : Sub16 ( uint16_t value )
{
2019-02-18 23:04:08 -05:00
int32_t result ;
2019-02-13 13:32:21 -05:00
if ( CheckFlag ( ProcFlags : : Decimal ) ) {
result = ( _state . A & 0x0F ) + ( value & 0x0F ) + ( _state . PS & ProcFlags : : Carry ) ;
if ( result < = 0x0F ) result - = 0x06 ;
result = ( _state . A & 0xF0 ) + ( value & 0xF0 ) + ( result > 0x0F ? 0x10 : 0 ) + ( result & 0x0F ) ;
if ( result < = 0xFF ) result - = 0x60 ;
result = ( _state . A & 0xF00 ) + ( value & 0xF00 ) + ( result > 0xFF ? 0x100 : 0 ) + ( result & 0xFF ) ;
if ( result < = 0xFFF ) result - = 0x600 ;
result = ( _state . A & 0xF000 ) + ( value & 0xF000 ) + ( result > 0xFFF ? 0x1000 : 0 ) + ( result & 0xFFF ) ;
} else {
2019-02-18 23:04:08 -05:00
result = _state . A + value + ( _state . PS & ProcFlags : : Carry ) ;
2019-02-13 13:32:21 -05:00
}
if ( ~ ( _state . A ^ value ) & ( _state . A ^ result ) & 0x8000 ) {
SetFlags ( ProcFlags : : Overflow ) ;
} else {
ClearFlags ( ProcFlags : : Overflow ) ;
}
if ( CheckFlag ( ProcFlags : : Decimal ) & & result < = 0xFFFF ) {
result - = 0x6000 ;
}
ClearFlags ( ProcFlags : : Carry | ProcFlags : : Negative | ProcFlags : : Zero ) ;
SetZeroNegativeFlags ( ( uint16_t ) result ) ;
2019-02-18 23:04:08 -05:00
if ( result > 0xFFFF ) {
2019-02-13 13:32:21 -05:00
SetFlags ( ProcFlags : : Carry ) ;
}
_state . A = ( uint16_t ) result ;
}
void Cpu : : SBC ( )
{
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
Sub8 ( ~ GetByteValue ( ) ) ;
} else {
Sub16 ( ~ GetWordValue ( ) ) ;
}
}
/****************
Branch operations
* * * * * * * * * * * * * * * */
void Cpu : : BCC ( )
{
BranchRelative ( ! CheckFlag ( ProcFlags : : Carry ) ) ;
}
void Cpu : : BCS ( )
{
BranchRelative ( CheckFlag ( ProcFlags : : Carry ) ) ;
}
void Cpu : : BEQ ( )
{
BranchRelative ( CheckFlag ( ProcFlags : : Zero ) ) ;
}
void Cpu : : BMI ( )
{
BranchRelative ( CheckFlag ( ProcFlags : : Negative ) ) ;
}
void Cpu : : BNE ( )
{
BranchRelative ( ! CheckFlag ( ProcFlags : : Zero ) ) ;
}
void Cpu : : BPL ( )
{
BranchRelative ( ! CheckFlag ( ProcFlags : : Negative ) ) ;
}
void Cpu : : BRA ( )
{
BranchRelative ( true ) ;
}
void Cpu : : BRL ( )
{
_state . PC = ( uint16_t ) ( _state . PC + ( int16_t ) _operand ) ;
2019-11-25 21:01:21 -05:00
IdleTakeBranch ( ) ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : BVC ( )
{
BranchRelative ( ! CheckFlag ( ProcFlags : : Overflow ) ) ;
}
void Cpu : : BVS ( )
{
BranchRelative ( CheckFlag ( ProcFlags : : Overflow ) ) ;
}
void Cpu : : BranchRelative ( bool branch )
{
if ( branch ) {
2019-06-30 12:36:15 -04:00
int8_t offset = _operand ;
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-06-30 12:36:15 -04:00
if ( _state . EmulationMode & & ( ( uint16_t ) ( _state . PC + offset ) & 0xFF00 ) ! = ( _state . PC & 0xFF00 ) ) {
//Extra cycle in emulation mode if crossing a page
Idle ( ) ;
2019-02-21 22:10:41 -05:00
}
2019-02-13 13:32:21 -05:00
_state . PC = ( uint16_t ) ( _state . PC + offset ) ;
2019-07-25 22:22:09 -04:00
IdleTakeBranch ( ) ;
2019-02-13 13:32:21 -05:00
}
}
/***************************
Set / clear flag instructions
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
void Cpu : : CLC ( )
{
ClearFlags ( ProcFlags : : Carry ) ;
}
void Cpu : : CLD ( )
{
ClearFlags ( ProcFlags : : Decimal ) ;
}
void Cpu : : CLI ( )
{
ClearFlags ( ProcFlags : : IrqDisable ) ;
}
void Cpu : : CLV ( )
{
ClearFlags ( ProcFlags : : Overflow ) ;
}
void Cpu : : SEC ( )
{
SetFlags ( ProcFlags : : Carry ) ;
}
void Cpu : : SED ( )
{
SetFlags ( ProcFlags : : Decimal ) ;
}
void Cpu : : SEI ( )
{
SetFlags ( ProcFlags : : IrqDisable ) ;
}
void Cpu : : REP ( )
{
2019-03-04 17:49:14 -05:00
Idle ( ) ;
2019-02-13 13:32:21 -05:00
ClearFlags ( ( uint8_t ) _operand ) ;
}
void Cpu : : SEP ( )
{
2019-03-04 17:49:14 -05:00
Idle ( ) ;
2019-02-13 13:32:21 -05:00
SetFlags ( ( uint8_t ) _operand ) ;
2019-02-20 19:53:45 -05:00
if ( CheckFlag ( ProcFlags : : IndexMode8 ) ) {
//Truncate X/Y when 8-bit indexes are enabled
_state . Y & = 0xFF ;
_state . X & = 0xFF ;
}
2019-02-13 13:32:21 -05:00
}
/******************************
Increment / decrement operations
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void Cpu : : DEX ( )
{
IncDecReg ( _state . X , - 1 ) ;
}
void Cpu : : DEY ( )
{
IncDecReg ( _state . Y , - 1 ) ;
}
void Cpu : : INX ( )
{
IncDecReg ( _state . X , 1 ) ;
}
void Cpu : : INY ( )
{
IncDecReg ( _state . Y , 1 ) ;
}
void Cpu : : DEC ( )
{
IncDec ( - 1 ) ;
}
void Cpu : : INC ( )
{
IncDec ( 1 ) ;
}
2019-02-21 22:10:41 -05:00
void Cpu : : DEC_Acc ( )
{
SetRegister ( _state . A , _state . A - 1 , CheckFlag ( ProcFlags : : MemoryMode8 ) ) ;
}
void Cpu : : INC_Acc ( )
{
SetRegister ( _state . A , _state . A + 1 , CheckFlag ( ProcFlags : : MemoryMode8 ) ) ;
}
2019-02-13 13:32:21 -05:00
void Cpu : : IncDecReg ( uint16_t & reg , int8_t offset )
{
SetRegister ( reg , reg + offset , CheckFlag ( ProcFlags : : IndexMode8 ) ) ;
}
void Cpu : : IncDec ( int8_t offset )
{
2019-02-21 22:10:41 -05:00
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
uint8_t value = GetByteValue ( ) + offset ;
SetZeroNegativeFlags ( value ) ;
Idle ( ) ;
Write ( _operand , value ) ;
2019-02-13 13:32:21 -05:00
} else {
2019-02-21 22:10:41 -05:00
uint16_t value = GetWordValue ( ) + offset ;
SetZeroNegativeFlags ( value ) ;
Idle ( ) ;
WriteWord ( _operand , value ) ;
2019-02-13 13:32:21 -05:00
}
}
/********************
Compare instructions
* * * * * * * * * * * * * * * * * * * * */
void Cpu : : Compare ( uint16_t reg , bool eightBitMode )
{
if ( eightBitMode ) {
uint8_t value = GetByteValue ( ) ;
if ( ( uint8_t ) reg > = value ) {
SetFlags ( ProcFlags : : Carry ) ;
} else {
ClearFlags ( ProcFlags : : Carry ) ;
}
uint8_t result = ( uint8_t ) reg - value ;
SetZeroNegativeFlags ( result ) ;
} else {
uint16_t value = GetWordValue ( ) ;
if ( reg > = value ) {
SetFlags ( ProcFlags : : Carry ) ;
} else {
ClearFlags ( ProcFlags : : Carry ) ;
}
uint16_t result = reg - value ;
SetZeroNegativeFlags ( result ) ;
}
}
void Cpu : : CMP ( )
{
Compare ( _state . A , CheckFlag ( ProcFlags : : MemoryMode8 ) ) ;
}
void Cpu : : CPX ( )
{
Compare ( _state . X , CheckFlag ( ProcFlags : : IndexMode8 ) ) ;
}
void Cpu : : CPY ( )
{
Compare ( _state . Y , CheckFlag ( ProcFlags : : IndexMode8 ) ) ;
}
/*****************
Jump instructions
* * * * * * * * * * * * * * * * * */
void Cpu : : JML ( )
{
_state . K = ( _operand > > 16 ) & 0xFF ;
_state . PC = ( uint16_t ) _operand ;
2019-07-25 22:22:09 -04:00
IdleEndJump ( ) ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : JMP ( )
{
_state . PC = ( uint16_t ) _operand ;
2019-07-25 22:22:09 -04:00
IdleEndJump ( ) ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : JSL ( )
{
PushByte ( _state . K ) ;
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-02-13 13:32:21 -05:00
PushWord ( _state . PC - 1 ) ;
_state . K = ( _operand > > 16 ) & 0xFF ;
_state . PC = ( uint16_t ) _operand ;
2019-07-25 22:22:09 -04:00
IdleEndJump ( ) ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : JSR ( )
{
PushWord ( _state . PC - 1 ) ;
_state . PC = ( uint16_t ) _operand ;
2019-07-25 22:22:09 -04:00
IdleEndJump ( ) ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : RTI ( )
{
2019-02-21 22:10:41 -05:00
Idle ( ) ;
Idle ( ) ;
2019-02-13 13:32:21 -05:00
if ( _state . EmulationMode ) {
2019-02-20 22:46:14 -05:00
SetPS ( PopByte ( ) ) ;
2019-02-13 13:32:21 -05:00
_state . PC = PopWord ( ) ;
} else {
2019-02-20 22:46:14 -05:00
SetPS ( PopByte ( ) ) ;
2019-02-13 13:32:21 -05:00
_state . PC = PopWord ( ) ;
_state . K = PopByte ( ) ;
}
2019-07-25 22:22:09 -04:00
IdleEndJump ( ) ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : RTL ( )
{
2019-02-21 22:10:41 -05:00
Idle ( ) ;
Idle ( ) ;
2019-02-13 13:32:21 -05:00
_state . PC = PopWord ( ) ;
_state . PC + + ;
_state . K = PopByte ( ) ;
2019-07-25 22:22:09 -04:00
IdleEndJump ( ) ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : RTS ( )
{
2019-02-21 22:10:41 -05:00
Idle ( ) ;
Idle ( ) ;
2019-02-13 13:32:21 -05:00
_state . PC = PopWord ( ) ;
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-02-13 13:32:21 -05:00
_state . PC + + ;
2019-07-25 22:22:09 -04:00
IdleEndJump ( ) ;
2019-02-13 13:32:21 -05:00
}
/**********
Interrupts
* * * * * * * * * * */
2019-06-30 12:36:15 -04:00
void Cpu : : ProcessInterrupt ( uint16_t vector , bool forHardwareInterrupt )
2019-02-13 13:32:21 -05:00
{
2019-06-30 12:36:15 -04:00
if ( forHardwareInterrupt ) {
//IRQ/NMI waste 2 cycles here. BRK/COP do not (because they do those 2 cycles while loading the OP code + signature byte)
ReadCode ( _state . PC ) ;
Idle ( ) ;
}
2019-02-21 22:10:41 -05:00
2019-02-13 13:32:21 -05:00
if ( _state . EmulationMode ) {
2019-02-15 00:09:46 -05:00
PushWord ( _state . PC ) ;
2019-02-13 13:32:21 -05:00
PushByte ( _state . PS | 0x20 ) ;
SetFlags ( ProcFlags : : IrqDisable ) ;
ClearFlags ( ProcFlags : : Decimal ) ;
2019-03-16 12:20:18 -04:00
_state . K = 0 ;
2020-03-01 17:51:02 -05:00
_state . PC = ReadVector ( vector ) ;
2019-02-13 13:32:21 -05:00
} else {
PushByte ( _state . K ) ;
2019-02-15 00:09:46 -05:00
PushWord ( _state . PC ) ;
2019-02-13 13:32:21 -05:00
PushByte ( _state . PS ) ;
SetFlags ( ProcFlags : : IrqDisable ) ;
ClearFlags ( ProcFlags : : Decimal ) ;
2019-02-15 00:09:46 -05:00
_state . K = 0 ;
2020-03-01 17:51:02 -05:00
_state . PC = ReadVector ( vector ) ;
2019-02-13 13:32:21 -05:00
}
}
void Cpu : : BRK ( )
{
2019-06-30 12:36:15 -04:00
ProcessInterrupt ( _state . EmulationMode ? Cpu : : LegacyIrqVector : Cpu : : BreakVector , false ) ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : COP ( )
{
2019-06-30 12:36:15 -04:00
ProcessInterrupt ( _state . EmulationMode ? Cpu : : LegacyCoprocessorVector : Cpu : : CoprocessorVector , false ) ;
2019-02-13 13:32:21 -05:00
}
/******************
Bitwise operations
* * * * * * * * * * * * * * * * * * */
void Cpu : : AND ( )
{
2019-02-14 00:48:16 -05:00
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
SetRegister ( _state . A , _state . A & GetByteValue ( ) , true ) ;
} else {
SetRegister ( _state . A , _state . A & GetWordValue ( ) , false ) ;
}
2019-02-13 13:32:21 -05:00
}
void Cpu : : EOR ( )
{
2019-02-14 00:48:16 -05:00
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
SetRegister ( _state . A , _state . A ^ GetByteValue ( ) , true ) ;
} else {
SetRegister ( _state . A , _state . A ^ GetWordValue ( ) , false ) ;
}
2019-02-13 13:32:21 -05:00
}
void Cpu : : ORA ( )
{
2019-02-14 00:48:16 -05:00
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
SetRegister ( _state . A , _state . A | GetByteValue ( ) , true ) ;
} else {
SetRegister ( _state . A , _state . A | GetWordValue ( ) , false ) ;
}
2019-02-13 13:32:21 -05:00
}
/****************
Shift operations
* * * * * * * * * * * * * * * * */
template < typename T > T Cpu : : ShiftLeft ( T value )
{
T result = value < < 1 ;
if ( value & ( 1 < < ( sizeof ( T ) * 8 - 1 ) ) ) {
SetFlags ( ProcFlags : : Carry ) ;
} else {
ClearFlags ( ProcFlags : : Carry ) ;
}
SetZeroNegativeFlags ( result ) ;
return result ;
}
template < typename T > T Cpu : : RollLeft ( T value )
{
T result = value < < 1 | ( _state . PS & ProcFlags : : Carry ) ;
if ( value & ( 1 < < ( sizeof ( T ) * 8 - 1 ) ) ) {
SetFlags ( ProcFlags : : Carry ) ;
} else {
ClearFlags ( ProcFlags : : Carry ) ;
}
SetZeroNegativeFlags ( result ) ;
return result ;
}
template < typename T > T Cpu : : ShiftRight ( T value )
{
T result = value > > 1 ;
if ( value & 0x01 ) {
SetFlags ( ProcFlags : : Carry ) ;
} else {
ClearFlags ( ProcFlags : : Carry ) ;
}
SetZeroNegativeFlags ( result ) ;
return result ;
}
template < typename T > T Cpu : : RollRight ( T value )
{
T result = value > > 1 | ( ( _state . PS & 0x01 ) < < ( sizeof ( T ) * 8 - 1 ) ) ;
if ( value & 0x01 ) {
SetFlags ( ProcFlags : : Carry ) ;
} else {
ClearFlags ( ProcFlags : : Carry ) ;
}
SetZeroNegativeFlags ( result ) ;
return result ;
}
2019-02-21 22:10:41 -05:00
void Cpu : : ASL_Acc ( )
{
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
_state . A = ( _state . A & 0xFF00 ) | ( ShiftLeft < uint8_t > ( ( uint8_t ) _state . A ) ) ;
} else {
_state . A = ShiftLeft < uint16_t > ( _state . A ) ;
}
}
2019-02-13 13:32:21 -05:00
void Cpu : : ASL ( )
{
2019-02-21 22:10:41 -05:00
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
2019-06-30 12:36:15 -04:00
uint8_t value = GetByteValue ( ) ;
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-06-30 12:36:15 -04:00
Write ( _operand , ShiftLeft < uint8_t > ( value ) ) ;
2019-02-13 13:32:21 -05:00
} else {
2019-06-30 12:36:15 -04:00
uint16_t value = GetWordValue ( ) ;
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-06-30 12:36:15 -04:00
WriteWord ( _operand , ShiftLeft < uint16_t > ( value ) ) ;
2019-02-21 22:10:41 -05:00
}
}
void Cpu : : LSR_Acc ( )
{
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
_state . A = ( _state . A & 0xFF00 ) | ShiftRight < uint8_t > ( ( uint8_t ) _state . A ) ;
} else {
_state . A = ShiftRight < uint16_t > ( _state . A ) ;
2019-02-13 13:32:21 -05:00
}
}
void Cpu : : LSR ( )
{
2019-02-21 22:10:41 -05:00
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
2019-06-30 12:36:15 -04:00
uint8_t value = GetByteValue ( ) ;
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-06-30 12:36:15 -04:00
Write ( _operand , ShiftRight < uint8_t > ( value ) ) ;
2019-02-13 13:32:21 -05:00
} else {
2019-06-30 12:36:15 -04:00
uint16_t value = GetWordValue ( ) ;
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-06-30 12:36:15 -04:00
WriteWord ( _operand , ShiftRight < uint16_t > ( value ) ) ;
2019-02-21 22:10:41 -05:00
}
}
void Cpu : : ROL_Acc ( )
{
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
_state . A = ( _state . A & 0xFF00 ) | RollLeft < uint8_t > ( ( uint8_t ) _state . A ) ;
} else {
_state . A = RollLeft < uint16_t > ( _state . A ) ;
2019-02-13 13:32:21 -05:00
}
}
void Cpu : : ROL ( )
{
2019-02-21 22:10:41 -05:00
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
2019-06-30 12:36:15 -04:00
uint8_t value = GetByteValue ( ) ;
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-06-30 12:36:15 -04:00
Write ( _operand , RollLeft < uint8_t > ( value ) ) ;
2019-02-13 13:32:21 -05:00
} else {
2019-06-30 12:36:15 -04:00
uint16_t value = GetWordValue ( ) ;
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-06-30 12:36:15 -04:00
WriteWord ( _operand , RollLeft < uint16_t > ( value ) ) ;
2019-02-21 22:10:41 -05:00
}
}
void Cpu : : ROR_Acc ( )
{
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
_state . A = ( _state . A & 0xFF00 ) | RollRight < uint8_t > ( ( uint8_t ) _state . A ) ;
} else {
_state . A = RollRight < uint16_t > ( _state . A ) ;
2019-02-13 13:32:21 -05:00
}
}
void Cpu : : ROR ( )
{
2019-02-21 22:10:41 -05:00
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
2019-06-30 12:36:15 -04:00
uint8_t value = GetByteValue ( ) ;
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-06-30 12:36:15 -04:00
Write ( _operand , RollRight < uint8_t > ( value ) ) ;
2019-02-13 13:32:21 -05:00
} else {
2019-06-30 12:36:15 -04:00
uint16_t value = GetWordValue ( ) ;
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-06-30 12:36:15 -04:00
WriteWord ( _operand , RollRight < uint16_t > ( value ) ) ;
2019-02-13 13:32:21 -05:00
}
}
/***************
Move operations
* * * * * * * * * * * * * * * */
void Cpu : : MVN ( )
{
2019-02-21 00:40:32 -05:00
_state . DBR = _operand & 0xFF ;
uint32_t destBank = _state . DBR < < 16 ;
2019-02-20 20:00:59 -05:00
uint32_t srcBank = ( _operand < < 8 ) & 0xFF0000 ;
2019-02-21 22:10:41 -05:00
2019-03-02 10:58:25 -05:00
uint8_t value = ReadData ( srcBank | _state . X ) ;
Write ( destBank | _state . Y , value ) ;
2019-02-21 22:10:41 -05:00
2019-03-02 10:58:25 -05:00
Idle ( ) ;
Idle ( ) ;
2019-02-21 22:10:41 -05:00
2019-03-02 10:58:25 -05:00
_state . X + + ;
_state . Y + + ;
2019-03-24 20:20:43 -04:00
if ( CheckFlag ( ProcFlags : : IndexMode8 ) ) {
_state . X & = 0xFF ;
_state . Y & = 0xFF ;
}
2019-03-02 10:58:25 -05:00
2019-03-24 20:20:43 -04:00
_state . A - - ;
2019-03-02 10:58:25 -05:00
if ( _state . A ! = 0xFFFF ) {
//Operation isn't done, set the PC back to the start of the instruction
_state . PC - = 3 ;
}
2019-02-13 13:32:21 -05:00
}
void Cpu : : MVP ( )
{
2019-02-21 00:40:32 -05:00
_state . DBR = _operand & 0xFF ;
uint32_t destBank = _state . DBR < < 16 ;
2019-02-20 20:00:59 -05:00
uint32_t srcBank = ( _operand < < 8 ) & 0xFF0000 ;
2019-02-14 20:11:21 -05:00
2019-03-02 10:58:25 -05:00
uint8_t value = ReadData ( srcBank | _state . X ) ;
Write ( destBank | _state . Y , value ) ;
Idle ( ) ;
Idle ( ) ;
2019-02-21 22:10:41 -05:00
2019-03-02 10:58:25 -05:00
_state . X - - ;
_state . Y - - ;
2019-03-24 20:20:43 -04:00
if ( CheckFlag ( ProcFlags : : IndexMode8 ) ) {
_state . X & = 0xFF ;
_state . Y & = 0xFF ;
}
2019-03-02 10:58:25 -05:00
_state . A - - ;
2019-02-21 22:10:41 -05:00
2019-03-02 10:58:25 -05:00
if ( _state . A ! = 0xFFFF ) {
//Operation isn't done, set the PC back to the start of the instruction
_state . PC - = 3 ;
}
2019-02-13 13:32:21 -05:00
}
/********************
Push / pull operations
* * * * * * * * * * * * * * * * * * * * */
void Cpu : : PEA ( )
{
//Push Effective Address
PushWord ( ( uint16_t ) _operand ) ;
}
void Cpu : : PEI ( )
{
//Push Effective Indirect address
2019-02-14 19:00:17 -05:00
PushWord ( ReadDataWord ( _operand ) ) ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : PER ( )
{
//Push Effective Relative address
2019-02-14 19:00:17 -05:00
PushWord ( ( uint16_t ) ( ( int16_t ) _operand + _state . PC ) ) ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : PHB ( )
{
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-02-13 13:33:10 -05:00
PushByte ( _state . DBR ) ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : PHD ( )
{
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-02-13 13:32:21 -05:00
PushWord ( _state . D ) ;
}
void Cpu : : PHK ( )
{
//"PHP, PHK, PHP, PLB, and PLP push and pull one byte from the stack"
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-02-13 13:32:21 -05:00
PushByte ( _state . K ) ;
}
void Cpu : : PHP ( )
{
//"PHP, PHK, PHP, PLB, and PLP push and pull one byte from the stack"
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-02-13 13:32:21 -05:00
PushByte ( _state . PS ) ;
}
void Cpu : : PLB ( )
{
//"PHP, PHK, PHP, PLB, and PLP push and pull one byte from the stack"
2019-02-21 22:10:41 -05:00
Idle ( ) ;
Idle ( ) ;
2019-02-13 13:32:21 -05:00
SetRegister ( _state . DBR , PopByte ( ) ) ;
}
void Cpu : : PLD ( )
{
//"PHD and PLD push and pull two bytes from the stack."
2019-02-21 22:10:41 -05:00
Idle ( ) ;
Idle ( ) ;
2019-02-13 13:32:21 -05:00
SetRegister ( _state . D , PopWord ( ) , false ) ;
}
void Cpu : : PLP ( )
{
//"For PLP, (all of) the flags are pulled from the stack. Note that when the e flag is 1, the m and x flag are forced to 1, so after the PLP, both flags will still be 1 no matter what value is pulled from the stack."
2019-02-21 22:10:41 -05:00
Idle ( ) ;
Idle ( ) ;
2019-02-13 13:32:21 -05:00
if ( _state . EmulationMode ) {
2019-02-20 22:46:14 -05:00
SetPS ( PopByte ( ) | ProcFlags : : MemoryMode8 | ProcFlags : : IndexMode8 ) ;
2019-02-13 13:32:21 -05:00
} else {
2019-02-20 22:46:14 -05:00
SetPS ( PopByte ( ) ) ;
2019-02-13 13:32:21 -05:00
}
}
void Cpu : : PHA ( )
{
//"When the m flag is 0, PHA and PLA push and pull a 16-bit value, and when the m flag is 1, PHA and PLA push and pull an 8-bit value. "
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-02-13 13:32:21 -05:00
PushRegister ( _state . A , CheckFlag ( ProcFlags : : MemoryMode8 ) ) ;
}
void Cpu : : PHX ( )
{
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-02-13 13:32:21 -05:00
PushRegister ( _state . X , CheckFlag ( ProcFlags : : IndexMode8 ) ) ;
}
void Cpu : : PHY ( )
{
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-02-13 13:32:21 -05:00
PushRegister ( _state . Y , CheckFlag ( ProcFlags : : IndexMode8 ) ) ;
}
void Cpu : : PLA ( )
{
//"When the m flag is 0, PHA and PLA push and pull a 16-bit value, and when the m flag is 1, PHA and PLA push and pull an 8-bit value."
2019-02-21 22:10:41 -05:00
Idle ( ) ;
Idle ( ) ;
2019-02-13 13:32:21 -05:00
PullRegister ( _state . A , CheckFlag ( ProcFlags : : MemoryMode8 ) ) ;
}
void Cpu : : PLX ( )
{
2019-02-21 22:10:41 -05:00
Idle ( ) ;
Idle ( ) ;
2019-02-13 13:32:21 -05:00
PullRegister ( _state . X , CheckFlag ( ProcFlags : : IndexMode8 ) ) ;
}
void Cpu : : PLY ( )
{
2019-02-21 22:10:41 -05:00
Idle ( ) ;
Idle ( ) ;
2019-02-13 13:32:21 -05:00
PullRegister ( _state . Y , CheckFlag ( ProcFlags : : IndexMode8 ) ) ;
}
void Cpu : : PushRegister ( uint16_t reg , bool eightBitMode )
{
//"When the x flag is 0, PHX, PHY, PLX, and PLY push and pull a 16-bit value, and when the x flag is 1, PHX, PHY, PLX, and PLY push and pull an 8-bit value."
if ( eightBitMode ) {
PushByte ( ( uint8_t ) reg ) ;
} else {
PushWord ( reg ) ;
}
}
void Cpu : : PullRegister ( uint16_t & reg , bool eightBitMode )
{
//"When the x flag is 0, PHX, PHY, PLX, and PLY push and pull a 16-bit value, and when the x flag is 1, PHX, PHY, PLX, and PLY push and pull an 8-bit value."
if ( eightBitMode ) {
SetRegister ( reg , PopByte ( ) , true ) ;
} else {
SetRegister ( reg , PopWord ( ) , false ) ;
}
}
/*********************
Store / load operations
* * * * * * * * * * * * * * * * * * * * * */
void Cpu : : LoadRegister ( uint16_t & reg , bool eightBitMode )
{
if ( eightBitMode ) {
SetRegister ( reg , GetByteValue ( ) , true ) ;
} else {
SetRegister ( reg , GetWordValue ( ) , false ) ;
}
}
void Cpu : : StoreRegister ( uint16_t val , bool eightBitMode )
{
if ( eightBitMode ) {
Write ( _operand , ( uint8_t ) val ) ;
} else {
WriteWord ( _operand , val ) ;
}
}
void Cpu : : LDA ( )
{
//"When the m flag is 0, LDA, STA, and STZ are 16-bit operations"
LoadRegister ( _state . A , CheckFlag ( ProcFlags : : MemoryMode8 ) ) ;
}
void Cpu : : LDX ( )
{
//"When the x flag is 0, LDX, LDY, STX, and STY are 16-bit operations"
LoadRegister ( _state . X , CheckFlag ( ProcFlags : : IndexMode8 ) ) ;
}
void Cpu : : LDY ( )
{
//"When the x flag is 0, LDX, LDY, STX, and STY are 16-bit operations"
LoadRegister ( _state . Y , CheckFlag ( ProcFlags : : IndexMode8 ) ) ;
}
void Cpu : : STA ( )
{
//"When the m flag is 0, LDA, STA, and STZ are 16-bit operations"
StoreRegister ( _state . A , CheckFlag ( ProcFlags : : MemoryMode8 ) ) ;
}
void Cpu : : STX ( )
{
//"When the x flag is 0, LDX, LDY, STX, and STY are 16-bit operations"
StoreRegister ( _state . X , CheckFlag ( ProcFlags : : IndexMode8 ) ) ;
}
void Cpu : : STY ( )
{
//"When the x flag is 0, LDX, LDY, STX, and STY are 16-bit operations"
StoreRegister ( _state . Y , CheckFlag ( ProcFlags : : IndexMode8 ) ) ;
}
void Cpu : : STZ ( )
{
//"When the m flag is 0, LDA, STA, and STZ are 16-bit operations"
StoreRegister ( 0 , CheckFlag ( ProcFlags : : MemoryMode8 ) ) ;
}
/*******************
Bit test operations
* * * * * * * * * * * * * * * * * * * */
2019-02-14 07:08:46 -05:00
template < typename T > void Cpu : : TestBits ( T value , bool alterZeroFlagOnly )
2019-02-13 13:32:21 -05:00
{
2019-02-14 07:08:46 -05:00
if ( alterZeroFlagOnly ) {
2019-02-14 00:49:34 -05:00
//"Immediate addressing only affects the z flag (with the result of the bitwise And), but does not affect the n and v flags."
if ( ( ( T ) _state . A & value ) = = 0 ) {
SetFlags ( ProcFlags : : Zero ) ;
} else {
ClearFlags ( ProcFlags : : Zero ) ;
}
} else {
ClearFlags ( ProcFlags : : Zero | ProcFlags : : Overflow | ProcFlags : : Negative ) ;
if ( ( ( T ) _state . A & value ) = = 0 ) {
SetFlags ( ProcFlags : : Zero ) ;
}
if ( value & ( 1 < < ( sizeof ( T ) * 8 - 2 ) ) ) {
SetFlags ( ProcFlags : : Overflow ) ;
}
if ( value & ( 1 < < ( sizeof ( T ) * 8 - 1 ) ) ) {
SetFlags ( ProcFlags : : Negative ) ;
}
2019-02-13 13:32:21 -05:00
}
}
void Cpu : : BIT ( )
{
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
2019-02-21 22:10:41 -05:00
TestBits < uint8_t > ( GetByteValue ( ) , _immediateMode ) ;
2019-02-13 13:32:21 -05:00
} else {
2019-02-21 22:10:41 -05:00
TestBits < uint16_t > ( GetWordValue ( ) , _immediateMode ) ;
2019-02-13 13:32:21 -05:00
}
}
void Cpu : : TRB ( )
{
2019-02-14 07:08:46 -05:00
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
2019-06-30 12:36:15 -04:00
uint8_t value = GetByteValue ( ) ;
TestBits < uint8_t > ( value , true ) ;
2019-02-14 07:08:46 -05:00
value & = ~ _state . A ;
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-06-30 12:36:15 -04:00
2019-02-14 07:08:46 -05:00
Write ( _operand , value ) ;
} else {
2019-06-30 12:36:15 -04:00
uint16_t value = GetWordValue ( ) ;
TestBits < uint16_t > ( value , true ) ;
2019-02-21 22:10:41 -05:00
2019-02-14 07:08:46 -05:00
value & = ~ _state . A ;
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-06-30 12:36:15 -04:00
2019-02-14 07:08:46 -05:00
WriteWord ( _operand , value ) ;
2019-02-21 22:10:41 -05:00
}
2019-02-13 13:32:21 -05:00
}
void Cpu : : TSB ( )
{
2019-02-14 07:08:46 -05:00
if ( CheckFlag ( ProcFlags : : MemoryMode8 ) ) {
2019-06-30 12:36:15 -04:00
uint8_t value = GetByteValue ( ) ;
TestBits < uint8_t > ( value , true ) ;
2019-02-14 07:08:46 -05:00
value | = _state . A ;
2019-06-30 12:36:15 -04:00
Idle ( ) ;
2019-02-14 07:08:46 -05:00
Write ( _operand , value ) ;
} else {
2019-06-30 12:36:15 -04:00
uint16_t value = GetWordValue ( ) ;
TestBits < uint16_t > ( value , true ) ;
2019-02-14 07:08:46 -05:00
value | = _state . A ;
2019-06-30 12:36:15 -04:00
Idle ( ) ;
2019-02-14 07:08:46 -05:00
WriteWord ( _operand , value ) ;
}
2019-02-13 13:32:21 -05:00
}
/******************
Transfer operations
* * * * * * * * * * * * * * * * * * */
void Cpu : : TAX ( )
{
SetRegister ( _state . X , _state . A , CheckFlag ( ProcFlags : : IndexMode8 ) ) ;
}
void Cpu : : TAY ( )
{
SetRegister ( _state . Y , _state . A , CheckFlag ( ProcFlags : : IndexMode8 ) ) ;
}
void Cpu : : TCD ( )
{
2019-02-13 23:41:00 -05:00
SetRegister ( _state . D , _state . A , false ) ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : TCS ( )
{
2019-02-14 00:48:16 -05:00
SetSP ( _state . A ) ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : TDC ( )
{
2019-02-20 22:01:04 -05:00
SetRegister ( _state . A , _state . D , false ) ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : TSC ( )
{
2019-02-20 22:01:04 -05:00
SetRegister ( _state . A , _state . SP , false ) ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : TSX ( )
{
SetRegister ( _state . X , _state . SP , CheckFlag ( ProcFlags : : IndexMode8 ) ) ;
}
void Cpu : : TXA ( )
{
SetRegister ( _state . A , _state . X , CheckFlag ( ProcFlags : : MemoryMode8 ) ) ;
}
void Cpu : : TXS ( )
{
2019-02-14 00:48:16 -05:00
SetSP ( _state . X ) ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : TXY ( )
{
SetRegister ( _state . Y , _state . X , CheckFlag ( ProcFlags : : IndexMode8 ) ) ;
}
void Cpu : : TYA ( )
{
SetRegister ( _state . A , _state . Y , CheckFlag ( ProcFlags : : MemoryMode8 ) ) ;
}
void Cpu : : TYX ( )
{
SetRegister ( _state . X , _state . Y , CheckFlag ( ProcFlags : : IndexMode8 ) ) ;
}
void Cpu : : XBA ( )
{
2019-02-21 22:10:41 -05:00
Idle ( ) ;
2019-02-13 13:32:21 -05:00
_state . A = ( ( _state . A & 0xFF ) < < 8 ) | ( ( _state . A > > 8 ) & 0xFF ) ;
SetZeroNegativeFlags ( ( uint8_t ) _state . A ) ;
}
void Cpu : : XCE ( )
{
2019-02-13 23:41:00 -05:00
bool carry = CheckFlag ( ProcFlags : : Carry ) ;
2019-02-13 13:33:10 -05:00
if ( _state . EmulationMode ) {
SetFlags ( ProcFlags : : Carry ) ;
} else {
ClearFlags ( ProcFlags : : Carry ) ;
}
_state . EmulationMode = carry ;
2019-02-13 23:41:00 -05:00
if ( _state . EmulationMode ) {
2019-02-20 22:46:14 -05:00
SetPS ( _state . PS | ProcFlags : : IndexMode8 | ProcFlags : : MemoryMode8 ) ;
2019-02-13 23:41:00 -05:00
_state . SP = 0x100 | ( _state . SP & 0xFF ) ;
}
2019-02-13 13:32:21 -05:00
}
/*****************
No operation ( NOP )
* * * * * * * * * * * * * * * * * */
void Cpu : : NOP ( )
{
//1-byte NOP
}
void Cpu : : WDM ( )
{
//2-byte NOP
}
/****************
Misc . operations
* * * * * * * * * * * * * * * * */
void Cpu : : STP ( )
{
//Stop the CPU
2019-03-09 16:03:48 -05:00
_state . StopState = CpuStopState : : Stopped ;
2019-02-13 13:32:21 -05:00
}
void Cpu : : WAI ( )
{
//Wait for interrupt
2019-03-09 16:03:48 -05:00
_state . StopState = CpuStopState : : WaitingForIrq ;
2019-02-21 22:10:41 -05:00
}
/****************
Addressing modes
* * * * * * * * * * * * * * * * */
void Cpu : : AddrMode_Abs ( )
{
_operand = GetDataAddress ( ReadOperandWord ( ) ) ;
}
2019-06-30 12:36:15 -04:00
void Cpu : : AddrMode_AbsIdxX ( bool isWrite )
2019-02-21 22:10:41 -05:00
{
2019-06-30 12:36:15 -04:00
uint32_t baseAddr = GetDataAddress ( ReadOperandWord ( ) ) ;
_operand = ( baseAddr + _state . X ) & 0xFFFFFF ;
if ( isWrite | | ! CheckFlag ( ProcFlags : : IndexMode8 ) | | ( _operand & 0xFF00 ) ! = ( baseAddr & 0xFF00 ) ) {
Idle ( ) ;
}
2019-02-21 22:10:41 -05:00
}
2019-06-30 12:36:15 -04:00
void Cpu : : AddrMode_AbsIdxY ( bool isWrite )
2019-02-21 22:10:41 -05:00
{
2019-06-30 12:36:15 -04:00
uint32_t baseAddr = GetDataAddress ( ReadOperandWord ( ) ) ;
_operand = ( baseAddr + _state . Y ) & 0xFFFFFF ;
if ( isWrite | | ! CheckFlag ( ProcFlags : : IndexMode8 ) | | ( _operand & 0xFF00 ) ! = ( baseAddr & 0xFF00 ) ) {
Idle ( ) ;
}
2019-02-21 22:10:41 -05:00
}
void Cpu : : AddrMode_AbsLng ( )
{
_operand = ReadOperandLong ( ) ;
}
void Cpu : : AddrMode_AbsLngIdxX ( )
{
_operand = ( ReadOperandLong ( ) + _state . X ) & 0xFFFFFF ;
}
void Cpu : : AddrMode_AbsJmp ( )
{
_operand = GetProgramAddress ( ReadOperandWord ( ) ) ;
}
void Cpu : : AddrMode_AbsLngJmp ( )
{
_operand = ReadOperandLong ( ) ;
}
void Cpu : : AddrMode_AbsIdxXInd ( )
{
_operand = GetProgramAddress ( ReadDataWord ( GetProgramAddress ( ReadOperandWord ( ) + _state . X ) ) ) ;
Idle ( ) ;
}
void Cpu : : AddrMode_AbsInd ( )
{
_operand = ReadDataWord ( ReadOperandWord ( ) ) ;
}
void Cpu : : AddrMode_AbsIndLng ( )
{
_operand = ReadDataLong ( ReadOperandWord ( ) ) ;
}
void Cpu : : AddrMode_Acc ( )
{
2019-04-20 09:30:51 -04:00
IdleOrRead ( ) ;
2019-02-21 22:10:41 -05:00
}
void Cpu : : AddrMode_BlkMov ( )
{
_operand = ReadOperandWord ( ) ;
}
uint8_t Cpu : : ReadDirectOperandByte ( )
{
uint8_t value = ReadOperandByte ( ) ;
if ( _state . D & 0xFF ) {
//Add 1 cycle for direct register low (DL) not equal 0
Idle ( ) ;
}
return value ;
}
void Cpu : : AddrMode_Dir ( )
{
_operand = GetDirectAddress ( ReadDirectOperandByte ( ) ) ;
}
void Cpu : : AddrMode_DirIdxX ( )
{
_operand = GetDirectAddress ( ReadDirectOperandByte ( ) + _state . X ) ;
Idle ( ) ;
}
void Cpu : : AddrMode_DirIdxY ( )
{
_operand = GetDirectAddress ( ReadDirectOperandByte ( ) + _state . Y ) ;
Idle ( ) ;
}
void Cpu : : AddrMode_DirInd ( )
{
_operand = GetDataAddress ( GetDirectAddressIndirectWord ( ReadDirectOperandByte ( ) ) ) ;
}
void Cpu : : AddrMode_DirIdxIndX ( )
{
uint8_t operandByte = ReadDirectOperandByte ( ) ;
Idle ( ) ;
_operand = GetDataAddress ( GetDirectAddressIndirectWord ( operandByte + _state . X ) ) ;
}
2019-06-30 12:36:15 -04:00
void Cpu : : AddrMode_DirIndIdxY ( bool isWrite )
2019-02-21 22:10:41 -05:00
{
2019-06-30 12:36:15 -04:00
uint32_t baseAddr = GetDataAddress ( GetDirectAddressIndirectWord ( ReadDirectOperandByte ( ) ) ) ;
_operand = ( baseAddr + _state . Y ) & 0xFFFFFF ;
if ( isWrite | | ! CheckFlag ( ProcFlags : : IndexMode8 ) | | ( _operand & 0xFF00 ) ! = ( baseAddr & 0xFF00 ) ) {
Idle ( ) ;
}
2019-02-21 22:10:41 -05:00
}
void Cpu : : AddrMode_DirIndLng ( )
{
_operand = GetDirectAddressIndirectLong ( ReadDirectOperandByte ( ) ) ;
}
void Cpu : : AddrMode_DirIndLngIdxY ( )
{
_operand = ( GetDirectAddressIndirectLong ( ReadDirectOperandByte ( ) ) + _state . Y ) & 0xFFFFFF ;
}
void Cpu : : AddrMode_Imm8 ( )
{
_immediateMode = true ;
_operand = ReadOperandByte ( ) ;
}
void Cpu : : AddrMode_Imm16 ( )
{
_immediateMode = true ;
_operand = ReadOperandWord ( ) ;
}
void Cpu : : AddrMode_ImmX ( )
{
_immediateMode = true ;
_operand = CheckFlag ( ProcFlags : : IndexMode8 ) ? ReadOperandByte ( ) : ReadOperandWord ( ) ;
}
void Cpu : : AddrMode_ImmM ( )
{
_immediateMode = true ;
_operand = CheckFlag ( ProcFlags : : MemoryMode8 ) ? ReadOperandByte ( ) : ReadOperandWord ( ) ;
}
void Cpu : : AddrMode_Imp ( )
{
2019-04-20 09:30:51 -04:00
IdleOrRead ( ) ;
2019-02-21 22:10:41 -05:00
}
void Cpu : : AddrMode_RelLng ( )
{
_operand = ReadOperandWord ( ) ;
Idle ( ) ;
}
void Cpu : : AddrMode_Rel ( )
{
_operand = ReadOperandByte ( ) ;
}
void Cpu : : AddrMode_StkRel ( )
{
_operand = ( uint16_t ) ( ReadOperandByte ( ) + _state . SP ) ;
Idle ( ) ;
}
void Cpu : : AddrMode_StkRelIndIdxY ( )
{
uint16_t addr = ( uint16_t ) ( ReadOperandByte ( ) + _state . SP ) ;
Idle ( ) ;
_operand = ( GetDataAddress ( ReadDataWord ( addr ) ) + _state . Y ) & 0xFFFFFF ;
Idle ( ) ;
}