CPU: Added all idle cycles + added DRAM refresh delay
This commit is contained in:
parent
97c7d06156
commit
0b7ad7c0db
5 changed files with 666 additions and 174 deletions
|
@ -1,5 +1,6 @@
|
|||
#include "stdafx.h"
|
||||
#include "Cpu.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
/************************
|
||||
Add/substract operations
|
||||
|
@ -217,6 +218,12 @@ void Cpu::BranchRelative(bool branch)
|
|||
{
|
||||
int8_t offset = _operand;
|
||||
if(branch) {
|
||||
Idle();
|
||||
if(_state.EmulationMode) {
|
||||
if(((uint16_t)(_state.PC + offset) & 0xFF00) != (_state.PC & 0xFF00)) {
|
||||
Idle();
|
||||
}
|
||||
}
|
||||
_state.PC = (uint16_t)(_state.PC + offset);
|
||||
}
|
||||
}
|
||||
|
@ -307,6 +314,16 @@ void Cpu::INC()
|
|||
IncDec(1);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void Cpu::IncDecReg(uint16_t ®, int8_t offset)
|
||||
{
|
||||
SetRegister(reg, reg + offset, CheckFlag(ProcFlags::IndexMode8));
|
||||
|
@ -314,19 +331,17 @@ void Cpu::IncDecReg(uint16_t ®, int8_t offset)
|
|||
|
||||
void Cpu::IncDec(int8_t offset)
|
||||
{
|
||||
if(_instAddrMode == AddrMode::Acc) {
|
||||
SetRegister(_state.A, _state.A + offset, CheckFlag(ProcFlags::MemoryMode8));
|
||||
} else {
|
||||
if(CheckFlag(ProcFlags::MemoryMode8)) {
|
||||
uint8_t value = GetByteValue() + offset;
|
||||
SetZeroNegativeFlags(value);
|
||||
Idle();
|
||||
Write(_operand, value);
|
||||
} else {
|
||||
uint16_t value = GetWordValue() + offset;
|
||||
SetZeroNegativeFlags(value);
|
||||
Idle();
|
||||
WriteWord(_operand, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************
|
||||
|
@ -388,6 +403,7 @@ void Cpu::JMP()
|
|||
void Cpu::JSL()
|
||||
{
|
||||
PushByte(_state.K);
|
||||
Idle();
|
||||
PushWord(_state.PC - 1);
|
||||
_state.K = (_operand >> 16) & 0xFF;
|
||||
_state.PC = (uint16_t)_operand;
|
||||
|
@ -401,6 +417,9 @@ void Cpu::JSR()
|
|||
|
||||
void Cpu::RTI()
|
||||
{
|
||||
Idle();
|
||||
Idle();
|
||||
|
||||
if(_state.EmulationMode) {
|
||||
SetPS(PopByte());
|
||||
_state.PC = PopWord();
|
||||
|
@ -413,6 +432,9 @@ void Cpu::RTI()
|
|||
|
||||
void Cpu::RTL()
|
||||
{
|
||||
Idle();
|
||||
Idle();
|
||||
|
||||
_state.PC = PopWord();
|
||||
_state.PC++;
|
||||
_state.K = PopByte();
|
||||
|
@ -420,7 +442,11 @@ void Cpu::RTL()
|
|||
|
||||
void Cpu::RTS()
|
||||
{
|
||||
Idle();
|
||||
Idle();
|
||||
|
||||
_state.PC = PopWord();
|
||||
Idle();
|
||||
_state.PC++;
|
||||
}
|
||||
|
||||
|
@ -429,6 +455,9 @@ Interrupts
|
|||
***********/
|
||||
void Cpu::ProcessInterrupt(uint16_t vector)
|
||||
{
|
||||
Idle();
|
||||
Idle();
|
||||
|
||||
if(_state.EmulationMode) {
|
||||
PushWord(_state.PC);
|
||||
PushByte(_state.PS | 0x20);
|
||||
|
@ -541,72 +570,84 @@ template<typename T> T Cpu::RollRight(T value)
|
|||
return result;
|
||||
}
|
||||
|
||||
void Cpu::ASL()
|
||||
void Cpu::ASL_Acc()
|
||||
{
|
||||
if(_instAddrMode == AddrMode::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);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
void Cpu::ASL()
|
||||
{
|
||||
if(CheckFlag(ProcFlags::MemoryMode8)) {
|
||||
Idle();
|
||||
Write(_operand, ShiftLeft<uint8_t>(GetByteValue()));
|
||||
} else {
|
||||
Idle();
|
||||
WriteWord(_operand, ShiftLeft<uint16_t>(GetWordValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cpu::LSR()
|
||||
void Cpu::LSR_Acc()
|
||||
{
|
||||
if(_instAddrMode == AddrMode::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);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
void Cpu::LSR()
|
||||
{
|
||||
if(CheckFlag(ProcFlags::MemoryMode8)) {
|
||||
Idle();
|
||||
Write(_operand, ShiftRight<uint8_t>(GetByteValue()));
|
||||
} else {
|
||||
Idle();
|
||||
WriteWord(_operand, ShiftRight<uint16_t>(GetWordValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cpu::ROL()
|
||||
void Cpu::ROL_Acc()
|
||||
{
|
||||
if(_instAddrMode == AddrMode::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);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
void Cpu::ROL()
|
||||
{
|
||||
if(CheckFlag(ProcFlags::MemoryMode8)) {
|
||||
Idle();
|
||||
Write(_operand, RollLeft<uint8_t>(GetByteValue()));
|
||||
} else {
|
||||
Idle();
|
||||
WriteWord(_operand, RollLeft<uint16_t>(GetWordValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cpu::ROR()
|
||||
void Cpu::ROR_Acc()
|
||||
{
|
||||
if(_instAddrMode == AddrMode::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);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
void Cpu::ROR()
|
||||
{
|
||||
if(CheckFlag(ProcFlags::MemoryMode8)) {
|
||||
Idle();
|
||||
Write(_operand, RollRight<uint8_t>(GetByteValue()));
|
||||
} else {
|
||||
Idle();
|
||||
WriteWord(_operand, RollRight<uint16_t>(GetWordValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************
|
||||
|
@ -621,9 +662,19 @@ void Cpu::MVN()
|
|||
uint8_t value = ReadData(srcBank | _state.X);
|
||||
Write(destBank | _state.Y, value);
|
||||
|
||||
Idle();
|
||||
Idle();
|
||||
|
||||
_state.X++;
|
||||
_state.Y++;
|
||||
_state.A--;
|
||||
|
||||
if(_state.A != 0xFFFF) {
|
||||
//"Idle" cycles, instruction re-reads OP code and operands before every new byte
|
||||
_memoryManager->Read((_state.K << 16) | (_state.PC - 3), MemoryOperationType::Read);
|
||||
_memoryManager->Read((_state.K << 16) | (_state.PC - 2), MemoryOperationType::Read);
|
||||
_memoryManager->Read((_state.K << 16) | (_state.PC - 1), MemoryOperationType::Read);
|
||||
}
|
||||
} while(_state.A != 0xFFFF);
|
||||
}
|
||||
|
||||
|
@ -636,9 +687,19 @@ void Cpu::MVP()
|
|||
uint8_t value = ReadData(srcBank | _state.X);
|
||||
Write(destBank | _state.Y, value);
|
||||
|
||||
Idle();
|
||||
Idle();
|
||||
|
||||
_state.X--;
|
||||
_state.Y--;
|
||||
_state.A--;
|
||||
|
||||
if(_state.A != 0xFFFF) {
|
||||
//"Idle" cycles, instruction re-reads OP code and operands before every new byte
|
||||
_memoryManager->Read((_state.K << 16) | (_state.PC - 3), MemoryOperationType::Read);
|
||||
_memoryManager->Read((_state.K << 16) | (_state.PC - 2), MemoryOperationType::Read);
|
||||
_memoryManager->Read((_state.K << 16) | (_state.PC - 1), MemoryOperationType::Read);
|
||||
}
|
||||
} while(_state.A != 0xFFFF);
|
||||
}
|
||||
|
||||
|
@ -654,52 +715,64 @@ void Cpu::PEA()
|
|||
void Cpu::PEI()
|
||||
{
|
||||
//Push Effective Indirect address
|
||||
Idle();
|
||||
PushWord(ReadDataWord(_operand));
|
||||
}
|
||||
|
||||
void Cpu::PER()
|
||||
{
|
||||
//Push Effective Relative address
|
||||
Idle();
|
||||
PushWord((uint16_t)((int16_t)_operand + _state.PC));
|
||||
}
|
||||
|
||||
void Cpu::PHB()
|
||||
{
|
||||
Idle();
|
||||
PushByte(_state.DBR);
|
||||
}
|
||||
|
||||
void Cpu::PHD()
|
||||
{
|
||||
Idle();
|
||||
PushWord(_state.D);
|
||||
}
|
||||
|
||||
void Cpu::PHK()
|
||||
{
|
||||
//"PHP, PHK, PHP, PLB, and PLP push and pull one byte from the stack"
|
||||
Idle();
|
||||
PushByte(_state.K);
|
||||
}
|
||||
|
||||
void Cpu::PHP()
|
||||
{
|
||||
//"PHP, PHK, PHP, PLB, and PLP push and pull one byte from the stack"
|
||||
Idle();
|
||||
PushByte(_state.PS);
|
||||
}
|
||||
|
||||
void Cpu::PLB()
|
||||
{
|
||||
//"PHP, PHK, PHP, PLB, and PLP push and pull one byte from the stack"
|
||||
Idle();
|
||||
Idle();
|
||||
SetRegister(_state.DBR, PopByte());
|
||||
}
|
||||
|
||||
void Cpu::PLD()
|
||||
{
|
||||
//"PHD and PLD push and pull two bytes from the stack."
|
||||
Idle();
|
||||
Idle();
|
||||
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."
|
||||
Idle();
|
||||
Idle();
|
||||
if(_state.EmulationMode) {
|
||||
SetPS(PopByte() | ProcFlags::MemoryMode8 | ProcFlags::IndexMode8);
|
||||
} else {
|
||||
|
@ -710,32 +783,41 @@ void Cpu::PLP()
|
|||
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. "
|
||||
Idle();
|
||||
PushRegister(_state.A, CheckFlag(ProcFlags::MemoryMode8));
|
||||
}
|
||||
|
||||
void Cpu::PHX()
|
||||
{
|
||||
Idle();
|
||||
PushRegister(_state.X, CheckFlag(ProcFlags::IndexMode8));
|
||||
}
|
||||
|
||||
void Cpu::PHY()
|
||||
{
|
||||
Idle();
|
||||
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."
|
||||
Idle();
|
||||
Idle();
|
||||
PullRegister(_state.A, CheckFlag(ProcFlags::MemoryMode8));
|
||||
}
|
||||
|
||||
void Cpu::PLX()
|
||||
{
|
||||
Idle();
|
||||
Idle();
|
||||
PullRegister(_state.X, CheckFlag(ProcFlags::IndexMode8));
|
||||
}
|
||||
|
||||
void Cpu::PLY()
|
||||
{
|
||||
Idle();
|
||||
Idle();
|
||||
PullRegister(_state.Y, CheckFlag(ProcFlags::IndexMode8));
|
||||
}
|
||||
|
||||
|
@ -853,9 +935,9 @@ template<typename T> void Cpu::TestBits(T value, bool alterZeroFlagOnly)
|
|||
void Cpu::BIT()
|
||||
{
|
||||
if(CheckFlag(ProcFlags::MemoryMode8)) {
|
||||
TestBits<uint8_t>(GetByteValue(), _instAddrMode <= AddrMode::ImmM);
|
||||
TestBits<uint8_t>(GetByteValue(), _immediateMode);
|
||||
} else {
|
||||
TestBits<uint16_t>(GetWordValue(), _instAddrMode <= AddrMode::ImmM);
|
||||
TestBits<uint16_t>(GetWordValue(), _immediateMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -866,12 +948,14 @@ void Cpu::TRB()
|
|||
|
||||
uint8_t value = ReadData(_operand);
|
||||
value &= ~_state.A;
|
||||
Idle();
|
||||
Write(_operand, value);
|
||||
} else {
|
||||
TestBits<uint16_t>(GetWordValue(), true);
|
||||
|
||||
uint16_t value = ReadDataWord(_operand);
|
||||
value &= ~_state.A;
|
||||
Idle();
|
||||
WriteWord(_operand, value);
|
||||
}
|
||||
}
|
||||
|
@ -958,6 +1042,7 @@ void Cpu::TYX()
|
|||
|
||||
void Cpu::XBA()
|
||||
{
|
||||
Idle();
|
||||
_state.A = ((_state.A & 0xFF) << 8) | ((_state.A >> 8) & 0xFF);
|
||||
SetZeroNegativeFlags((uint8_t)_state.A);
|
||||
}
|
||||
|
@ -1003,3 +1088,178 @@ void Cpu::WAI()
|
|||
{
|
||||
//Wait for interrupt
|
||||
}
|
||||
|
||||
/****************
|
||||
Addressing modes
|
||||
*****************/
|
||||
void Cpu::AddrMode_Abs()
|
||||
{
|
||||
_operand = GetDataAddress(ReadOperandWord());
|
||||
}
|
||||
|
||||
void Cpu::AddrMode_AbsIdxX()
|
||||
{
|
||||
_operand = (GetDataAddress(ReadOperandWord()) + _state.X) & 0xFFFFFF;
|
||||
Idle();
|
||||
}
|
||||
|
||||
void Cpu::AddrMode_AbsIdxY()
|
||||
{
|
||||
_operand = (GetDataAddress(ReadOperandWord()) + _state.Y) & 0xFFFFFF;
|
||||
Idle();
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
Idle();
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void Cpu::AddrMode_DirIndIdxY()
|
||||
{
|
||||
_operand = (GetDataAddress(GetDirectAddressIndirectWord(ReadDirectOperandByte())) + _state.Y) & 0xFFFFFF;
|
||||
Idle();
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
Idle();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
370
Core/Cpu.cpp
370
Core/Cpu.cpp
|
@ -5,51 +5,6 @@
|
|||
|
||||
Cpu::Cpu(shared_ptr<MemoryManager> memoryManager)
|
||||
{
|
||||
typedef Cpu C;
|
||||
Func opTable[256] = {
|
||||
//0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
&C::BRK, &C::ORA, &C::COP, &C::ORA, &C::TSB, &C::ORA, &C::ASL, &C::ORA, &C::PHP, &C::ORA, &C::ASL, &C::PHD, &C::TSB, &C::ORA, &C::ASL, &C::ORA, // 0
|
||||
&C::BPL, &C::ORA, &C::ORA, &C::ORA, &C::TRB, &C::ORA, &C::ASL, &C::ORA, &C::CLC, &C::ORA, &C::INC, &C::TCS, &C::TRB, &C::ORA, &C::ASL, &C::ORA, // 1
|
||||
&C::JSR, &C::AND, &C::JSL, &C::AND, &C::BIT, &C::AND, &C::ROL, &C::AND, &C::PLP, &C::AND, &C::ROL, &C::PLD, &C::BIT, &C::AND, &C::ROL, &C::AND, // 2
|
||||
&C::BMI, &C::AND, &C::AND, &C::AND, &C::BIT, &C::AND, &C::ROL, &C::AND, &C::SEC, &C::AND, &C::DEC, &C::TSC, &C::BIT, &C::AND, &C::ROL, &C::AND, // 3
|
||||
&C::RTI, &C::EOR, &C::WDM, &C::EOR, &C::MVP, &C::EOR, &C::LSR, &C::EOR, &C::PHA, &C::EOR, &C::LSR, &C::PHK, &C::JMP, &C::EOR, &C::LSR, &C::EOR, // 4
|
||||
&C::BVC, &C::EOR, &C::EOR, &C::EOR, &C::MVN, &C::EOR, &C::LSR, &C::EOR, &C::CLI, &C::EOR, &C::PHY, &C::TCD, &C::JML, &C::EOR, &C::LSR, &C::EOR, // 5
|
||||
&C::RTS, &C::ADC, &C::PER, &C::ADC, &C::STZ, &C::ADC, &C::ROR, &C::ADC, &C::PLA, &C::ADC, &C::ROR, &C::RTL, &C::JMP, &C::ADC, &C::ROR, &C::ADC, // 6
|
||||
&C::BVS, &C::ADC, &C::ADC, &C::ADC, &C::STZ, &C::ADC, &C::ROR, &C::ADC, &C::SEI, &C::ADC, &C::PLY, &C::TDC, &C::JMP, &C::ADC, &C::ROR, &C::ADC, // 7
|
||||
&C::BRA, &C::STA, &C::BRL, &C::STA, &C::STY, &C::STA, &C::STX, &C::STA, &C::DEY, &C::BIT, &C::TXA, &C::PHB, &C::STY, &C::STA, &C::STX, &C::STA, // 8
|
||||
&C::BCC, &C::STA, &C::STA, &C::STA, &C::STY, &C::STA, &C::STX, &C::STA, &C::TYA, &C::STA, &C::TXS, &C::TXY, &C::STZ, &C::STA, &C::STZ, &C::STA, // 9
|
||||
&C::LDY, &C::LDA, &C::LDX, &C::LDA, &C::LDY, &C::LDA, &C::LDX, &C::LDA, &C::TAY, &C::LDA, &C::TAX, &C::PLB, &C::LDY, &C::LDA, &C::LDX, &C::LDA, // A
|
||||
&C::BCS, &C::LDA, &C::LDA, &C::LDA, &C::LDY, &C::LDA, &C::LDX, &C::LDA, &C::CLV, &C::LDA, &C::TSX, &C::TYX, &C::LDY, &C::LDA, &C::LDX, &C::LDA, // B
|
||||
&C::CPY, &C::CMP, &C::REP, &C::CMP, &C::CPY, &C::CMP, &C::DEC, &C::CMP, &C::INY, &C::CMP, &C::DEX, &C::WAI, &C::CPY, &C::CMP, &C::DEC, &C::CMP, // C
|
||||
&C::BNE, &C::CMP, &C::CMP, &C::CMP, &C::PEI, &C::CMP, &C::DEC, &C::CMP, &C::CLD, &C::CMP, &C::PHX, &C::STP, &C::JML, &C::CMP, &C::DEC, &C::CMP, // D
|
||||
&C::CPX, &C::SBC, &C::SEP, &C::SBC, &C::CPX, &C::SBC, &C::INC, &C::SBC, &C::INX, &C::SBC, &C::NOP, &C::XBA, &C::CPX, &C::SBC, &C::INC, &C::SBC, // E
|
||||
&C::BEQ, &C::SBC, &C::SBC, &C::SBC, &C::PEA, &C::SBC, &C::INC, &C::SBC, &C::SED, &C::SBC, &C::PLX, &C::XCE, &C::JSR, &C::SBC, &C::INC, &C::SBC // F
|
||||
};
|
||||
|
||||
typedef AddrMode M;
|
||||
AddrMode addrMode[256] = {
|
||||
//0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
M::Stk, M::DirIdxIndX, M::Stk, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Stk, M::ImmM, M::Acc, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // 0
|
||||
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::Dir, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Acc, M::Imp, M::Abs, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 1
|
||||
M::AbsJmp,M::DirIdxIndX, M::AbsLngJmp,M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Stk, M::ImmM, M::Acc, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // 2
|
||||
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::DirIdxX, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Acc, M::Imp, M::AbsIdxX, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 3
|
||||
M::Stk, M::DirIdxIndX, M::Imm8, M::StkRel, M::BlkMov, M::Dir, M::Dir, M::DirIndLng, M::Stk, M::ImmM, M::Acc, M::Stk, M::AbsJmp, M::Abs, M::Abs, M::AbsLng, // 4
|
||||
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::BlkMov, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Stk, M::Imp, M::AbsLngJmp, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 5
|
||||
M::Stk, M::DirIdxIndX, M::RelLng, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Stk, M::ImmM, M::Acc, M::Stk, M::AbsInd, M::Abs, M::Abs, M::AbsLng, // 6
|
||||
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::DirIdxX, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Stk, M::Imp, M::AbsIdxXInd, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 7
|
||||
M::Rel, M::DirIdxIndX, M::RelLng, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Imp, M::ImmM, M::Imp, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // 8
|
||||
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::DirIdxX, M::DirIdxX, M::DirIdxY, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Imp, M::Imp, M::Abs, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 9
|
||||
M::ImmX, M::DirIdxIndX, M::ImmX, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Imp, M::ImmM, M::Imp, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // A
|
||||
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::DirIdxX, M::DirIdxX, M::DirIdxY, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Imp, M::Imp, M::AbsIdxX, M::AbsIdxX, M::AbsIdxY, M::AbsLngIdxX, // B
|
||||
M::ImmX, M::DirIdxIndX, M::Imm8, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Imp, M::ImmM, M::Imp, M::Imp, M::Abs, M::Abs, M::Abs, M::AbsLng, // C
|
||||
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::Dir, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Stk, M::Imp, M::AbsIndLng, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // D
|
||||
M::ImmX, M::DirIdxIndX, M::Imm8, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Imp, M::ImmM, M::Imp, M::Imp, M::Abs, M::Abs, M::Abs, M::AbsLng, // E
|
||||
M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::Imm16, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Stk, M::Imp, M::AbsIdxXInd, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX // F
|
||||
};
|
||||
|
||||
memcpy(_opTable, opTable, sizeof(opTable));
|
||||
memcpy(_addrMode, addrMode, sizeof(addrMode));
|
||||
|
||||
_memoryManager = memoryManager;
|
||||
_state = {};
|
||||
_state.PC = ReadDataWord(Cpu::ResetVector);
|
||||
|
@ -71,12 +26,266 @@ void Cpu::Reset()
|
|||
|
||||
void Cpu::Exec()
|
||||
{
|
||||
uint8_t opCode = GetOpCode();
|
||||
_instAddrMode = _addrMode[opCode];
|
||||
_operand = FetchEffectiveAddress();
|
||||
(this->*_opTable[opCode])();
|
||||
_immediateMode = false;
|
||||
|
||||
opCount++;
|
||||
switch(GetOpCode()) {
|
||||
case 0x00: BRK(); break;
|
||||
case 0x01: AddrMode_DirIdxIndX(); ORA(); break;
|
||||
case 0x02: COP(); break;
|
||||
case 0x03: AddrMode_StkRel(); ORA(); break;
|
||||
case 0x04: AddrMode_Dir(); TSB(); break;
|
||||
case 0x05: AddrMode_Dir(); ORA(); break;
|
||||
case 0x06: AddrMode_Dir(); ASL(); break;
|
||||
case 0x07: AddrMode_DirIndLng(); ORA(); break;
|
||||
case 0x08: PHP(); break;
|
||||
case 0x09: AddrMode_ImmM(); ORA(); break;
|
||||
case 0x0A: AddrMode_Acc(); ASL_Acc(); break;
|
||||
case 0x0B: PHD(); break;
|
||||
case 0x0C: AddrMode_Abs(); TSB(); break;
|
||||
case 0x0D: AddrMode_Abs(); ORA(); break;
|
||||
case 0x0E: AddrMode_Abs(); ASL(); break;
|
||||
case 0x0F: AddrMode_AbsLng(); ORA(); break;
|
||||
case 0x10: AddrMode_Rel(); BPL(); break;
|
||||
case 0x11: AddrMode_DirIndIdxY(); ORA(); break;
|
||||
case 0x12: AddrMode_DirInd(); ORA(); break;
|
||||
case 0x13: AddrMode_StkRelIndIdxY(); ORA(); break;
|
||||
case 0x14: AddrMode_Dir(); TRB(); break;
|
||||
case 0x15: AddrMode_DirIdxX(); ORA(); break;
|
||||
case 0x16: AddrMode_DirIdxX(); ASL(); break;
|
||||
case 0x17: AddrMode_DirIndLngIdxY(); ORA(); break;
|
||||
case 0x18: AddrMode_Imp(); CLC(); break;
|
||||
case 0x19: AddrMode_AbsIdxY(); ORA(); break;
|
||||
case 0x1A: AddrMode_Acc(); INC_Acc(); break;
|
||||
case 0x1B: AddrMode_Imp(); TCS(); break;
|
||||
case 0x1C: AddrMode_Abs(); TRB(); break;
|
||||
case 0x1D: AddrMode_AbsIdxX(); ORA(); break;
|
||||
case 0x1E: AddrMode_AbsIdxX(); ASL(); break;
|
||||
case 0x1F: AddrMode_AbsLngIdxX(); ORA(); break;
|
||||
case 0x20: AddrMode_AbsJmp(); Idle(); JSR(); break;
|
||||
case 0x21: AddrMode_DirIdxIndX(); AND(); break;
|
||||
case 0x22: AddrMode_AbsLngJmp(); JSL(); break;
|
||||
case 0x23: AddrMode_StkRel(); AND(); break;
|
||||
case 0x24: AddrMode_Dir(); BIT(); break;
|
||||
case 0x25: AddrMode_Dir(); AND(); break;
|
||||
case 0x26: AddrMode_Dir(); ROL(); break;
|
||||
case 0x27: AddrMode_DirIndLng(); AND(); break;
|
||||
case 0x28: PLP(); break;
|
||||
case 0x29: AddrMode_ImmM(); AND(); break;
|
||||
case 0x2A: AddrMode_Acc(); ROL_Acc(); break;
|
||||
case 0x2B: PLD(); break;
|
||||
case 0x2C: AddrMode_Abs(); BIT(); break;
|
||||
case 0x2D: AddrMode_Abs(); AND(); break;
|
||||
case 0x2E: AddrMode_Abs(); ROL(); break;
|
||||
case 0x2F: AddrMode_AbsLng(); AND(); break;
|
||||
case 0x30: AddrMode_Rel(); BMI(); break;
|
||||
case 0x31: AddrMode_DirIndIdxY(); AND(); break;
|
||||
case 0x32: AddrMode_DirInd(); AND(); break;
|
||||
case 0x33: AddrMode_StkRelIndIdxY(); AND(); break;
|
||||
case 0x34: AddrMode_DirIdxX(); BIT(); break;
|
||||
case 0x35: AddrMode_DirIdxX(); AND(); break;
|
||||
case 0x36: AddrMode_DirIdxX(); ROL(); break;
|
||||
case 0x37: AddrMode_DirIndLngIdxY(); AND(); break;
|
||||
case 0x38: AddrMode_Imp(); SEC(); break;
|
||||
case 0x39: AddrMode_AbsIdxY(); AND(); break;
|
||||
case 0x3A: AddrMode_Acc(); DEC_Acc(); break;
|
||||
case 0x3B: AddrMode_Imp(); TSC(); break;
|
||||
case 0x3C: AddrMode_AbsIdxX(); BIT(); break;
|
||||
case 0x3D: AddrMode_AbsIdxX(); AND(); break;
|
||||
case 0x3E: AddrMode_AbsIdxX(); ROL(); break;
|
||||
case 0x3F: AddrMode_AbsLngIdxX(); AND(); break;
|
||||
case 0x40: RTI(); break;
|
||||
case 0x41: AddrMode_DirIdxIndX(); EOR(); break;
|
||||
case 0x42: AddrMode_Imm8(); WDM(); break;
|
||||
case 0x43: AddrMode_StkRel(); EOR(); break;
|
||||
case 0x44: AddrMode_BlkMov(); MVP(); break;
|
||||
case 0x45: AddrMode_Dir(); EOR(); break;
|
||||
case 0x46: AddrMode_Dir(); LSR(); break;
|
||||
case 0x47: AddrMode_DirIndLng(); EOR(); break;
|
||||
case 0x48: PHA(); break;
|
||||
case 0x49: AddrMode_ImmM(); EOR(); break;
|
||||
case 0x4A: AddrMode_Acc(); LSR_Acc(); break;
|
||||
case 0x4B: PHK(); break;
|
||||
case 0x4C: AddrMode_AbsJmp(); JMP(); break;
|
||||
case 0x4D: AddrMode_Abs(); EOR(); break;
|
||||
case 0x4E: AddrMode_Abs(); LSR(); break;
|
||||
case 0x4F: AddrMode_AbsLng(); EOR(); break;
|
||||
case 0x50: AddrMode_Rel(); BVC(); break;
|
||||
case 0x51: AddrMode_DirIndIdxY(); EOR(); break;
|
||||
case 0x52: AddrMode_DirInd(); EOR(); break;
|
||||
case 0x53: AddrMode_StkRelIndIdxY(); EOR(); break;
|
||||
case 0x54: AddrMode_BlkMov(); MVN(); break;
|
||||
case 0x55: AddrMode_DirIdxX(); EOR(); break;
|
||||
case 0x56: AddrMode_DirIdxX(); LSR(); break;
|
||||
case 0x57: AddrMode_DirIndLngIdxY(); EOR(); break;
|
||||
case 0x58: AddrMode_Imp(); CLI(); break;
|
||||
case 0x59: AddrMode_AbsIdxY(); EOR(); break;
|
||||
case 0x5A: PHY(); break;
|
||||
case 0x5B: AddrMode_Imp(); TCD(); break;
|
||||
case 0x5C: AddrMode_AbsLngJmp(); JML(); break;
|
||||
case 0x5D: AddrMode_AbsIdxX(); EOR(); break;
|
||||
case 0x5E: AddrMode_AbsIdxX(); LSR(); break;
|
||||
case 0x5F: AddrMode_AbsLngIdxX(); EOR(); break;
|
||||
case 0x60: RTS(); break;
|
||||
case 0x61: AddrMode_DirIdxIndX(); ADC(); break;
|
||||
case 0x62: AddrMode_RelLng(); PER(); break;
|
||||
case 0x63: AddrMode_StkRel(); ADC(); break;
|
||||
case 0x64: AddrMode_Dir(); STZ(); break;
|
||||
case 0x65: AddrMode_Dir(); ADC(); break;
|
||||
case 0x66: AddrMode_Dir(); ROR(); break;
|
||||
case 0x67: AddrMode_DirIndLng(); ADC(); break;
|
||||
case 0x68: PLA(); break;
|
||||
case 0x69: AddrMode_ImmM(); ADC(); break;
|
||||
case 0x6A: AddrMode_Acc(); ROR_Acc(); break;
|
||||
case 0x6B: RTL(); break;
|
||||
case 0x6C: AddrMode_AbsInd(); JMP(); break;
|
||||
case 0x6D: AddrMode_Abs(); ADC(); break;
|
||||
case 0x6E: AddrMode_Abs(); ROR(); break;
|
||||
case 0x6F: AddrMode_AbsLng(); ADC(); break;
|
||||
case 0x70: AddrMode_Rel(); BVS(); break;
|
||||
case 0x71: AddrMode_DirIndIdxY(); ADC(); break;
|
||||
case 0x72: AddrMode_DirInd(); ADC(); break;
|
||||
case 0x73: AddrMode_StkRelIndIdxY(); ADC(); break;
|
||||
case 0x74: AddrMode_DirIdxX(); STZ(); break;
|
||||
case 0x75: AddrMode_DirIdxX(); ADC(); break;
|
||||
case 0x76: AddrMode_DirIdxX(); ROR(); break;
|
||||
case 0x77: AddrMode_DirIndLngIdxY(); ADC(); break;
|
||||
case 0x78: AddrMode_Imp(); SEI(); break;
|
||||
case 0x79: AddrMode_AbsIdxY(); ADC(); break;
|
||||
case 0x7A: PLY(); break;
|
||||
case 0x7B: AddrMode_Imp(); TDC(); break;
|
||||
case 0x7C: AddrMode_AbsIdxXInd(); JMP(); break;
|
||||
case 0x7D: AddrMode_AbsIdxX(); ADC(); break;
|
||||
case 0x7E: AddrMode_AbsIdxX(); ROR(); break;
|
||||
case 0x7F: AddrMode_AbsLngIdxX(); ADC(); break;
|
||||
case 0x80: AddrMode_Rel(); BRA(); break;
|
||||
case 0x81: AddrMode_DirIdxIndX(); STA(); break;
|
||||
case 0x82: AddrMode_RelLng(); BRL(); break;
|
||||
case 0x83: AddrMode_StkRel(); STA(); break;
|
||||
case 0x84: AddrMode_Dir(); STY(); break;
|
||||
case 0x85: AddrMode_Dir(); STA(); break;
|
||||
case 0x86: AddrMode_Dir(); STX(); break;
|
||||
case 0x87: AddrMode_DirIndLng(); STA(); break;
|
||||
case 0x88: AddrMode_Imp(); DEY(); break;
|
||||
case 0x89: AddrMode_ImmM(); BIT(); break;
|
||||
case 0x8A: AddrMode_Imp(); TXA(); break;
|
||||
case 0x8B: PHB(); break;
|
||||
case 0x8C: AddrMode_Abs(); STY(); break;
|
||||
case 0x8D: AddrMode_Abs(); STA(); break;
|
||||
case 0x8E: AddrMode_Abs(); STX(); break;
|
||||
case 0x8F: AddrMode_AbsLng(); STA(); break;
|
||||
case 0x90: AddrMode_Rel(); BCC(); break;
|
||||
case 0x91: AddrMode_DirIndIdxY(); STA(); break;
|
||||
case 0x92: AddrMode_DirInd(); STA(); break;
|
||||
case 0x93: AddrMode_StkRelIndIdxY(); STA(); break;
|
||||
case 0x94: AddrMode_DirIdxX(); STY(); break;
|
||||
case 0x95: AddrMode_DirIdxX(); STA(); break;
|
||||
case 0x96: AddrMode_DirIdxY(); STX(); break;
|
||||
case 0x97: AddrMode_DirIndLngIdxY(); STA(); break;
|
||||
case 0x98: AddrMode_Imp(); TYA(); break;
|
||||
case 0x99: AddrMode_AbsIdxY(); STA(); break;
|
||||
case 0x9A: AddrMode_Imp(); TXS(); break;
|
||||
case 0x9B: AddrMode_Imp(); TXY(); break;
|
||||
case 0x9C: AddrMode_Abs(); STZ(); break;
|
||||
case 0x9D: AddrMode_AbsIdxX(); STA(); break;
|
||||
case 0x9E: AddrMode_AbsIdxX(); STZ(); break;
|
||||
case 0x9F: AddrMode_AbsLngIdxX(); STA(); break;
|
||||
case 0xA0: AddrMode_ImmX(); LDY(); break;
|
||||
case 0xA1: AddrMode_DirIdxIndX(); LDA(); break;
|
||||
case 0xA2: AddrMode_ImmX(); LDX(); break;
|
||||
case 0xA3: AddrMode_StkRel(); LDA(); break;
|
||||
case 0xA4: AddrMode_Dir(); LDY(); break;
|
||||
case 0xA5: AddrMode_Dir(); LDA(); break;
|
||||
case 0xA6: AddrMode_Dir(); LDX(); break;
|
||||
case 0xA7: AddrMode_DirIndLng(); LDA(); break;
|
||||
case 0xA8: AddrMode_Imp(); TAY(); break;
|
||||
case 0xA9: AddrMode_ImmM(); LDA(); break;
|
||||
case 0xAA: AddrMode_Imp(); TAX(); break;
|
||||
case 0xAB: PLB(); break;
|
||||
case 0xAC: AddrMode_Abs(); LDY(); break;
|
||||
case 0xAD: AddrMode_Abs(); LDA(); break;
|
||||
case 0xAE: AddrMode_Abs(); LDX(); break;
|
||||
case 0xAF: AddrMode_AbsLng(); LDA(); break;
|
||||
case 0xB0: AddrMode_Rel(); BCS(); break;
|
||||
case 0xB1: AddrMode_DirIndIdxY(); LDA(); break;
|
||||
case 0xB2: AddrMode_DirInd(); LDA(); break;
|
||||
case 0xB3: AddrMode_StkRelIndIdxY(); LDA(); break;
|
||||
case 0xB4: AddrMode_DirIdxX(); LDY(); break;
|
||||
case 0xB5: AddrMode_DirIdxX(); LDA(); break;
|
||||
case 0xB6: AddrMode_DirIdxY(); LDX(); break;
|
||||
case 0xB7: AddrMode_DirIndLngIdxY(); LDA(); break;
|
||||
case 0xB8: AddrMode_Imp(); CLV(); break;
|
||||
case 0xB9: AddrMode_AbsIdxY(); LDA(); break;
|
||||
case 0xBA: AddrMode_Imp(); TSX(); break;
|
||||
case 0xBB: AddrMode_Imp(); TYX(); break;
|
||||
case 0xBC: AddrMode_AbsIdxX(); LDY(); break;
|
||||
case 0xBD: AddrMode_AbsIdxX(); LDA(); break;
|
||||
case 0xBE: AddrMode_AbsIdxY(); LDX(); break;
|
||||
case 0xBF: AddrMode_AbsLngIdxX(); LDA(); break;
|
||||
case 0xC0: AddrMode_ImmX(); CPY(); break;
|
||||
case 0xC1: AddrMode_DirIdxIndX(); CMP(); break;
|
||||
case 0xC2: AddrMode_Imm8(); REP(); break;
|
||||
case 0xC3: AddrMode_StkRel(); CMP(); break;
|
||||
case 0xC4: AddrMode_Dir(); CPY(); break;
|
||||
case 0xC5: AddrMode_Dir(); CMP(); break;
|
||||
case 0xC6: AddrMode_Dir(); DEC(); break;
|
||||
case 0xC7: AddrMode_DirIndLng(); CMP(); break;
|
||||
case 0xC8: AddrMode_Imp(); INY(); break;
|
||||
case 0xC9: AddrMode_ImmM(); CMP(); break;
|
||||
case 0xCA: AddrMode_Imp(); DEX(); break;
|
||||
case 0xCB: AddrMode_Imp(); WAI(); break;
|
||||
case 0xCC: AddrMode_Abs(); CPY(); break;
|
||||
case 0xCD: AddrMode_Abs(); CMP(); break;
|
||||
case 0xCE: AddrMode_Abs(); DEC(); break;
|
||||
case 0xCF: AddrMode_AbsLng(); CMP(); break;
|
||||
case 0xD0: AddrMode_Rel(); BNE(); break;
|
||||
case 0xD1: AddrMode_DirIndIdxY(); CMP(); break;
|
||||
case 0xD2: AddrMode_DirInd(); CMP(); break;
|
||||
case 0xD3: AddrMode_StkRelIndIdxY(); CMP(); break;
|
||||
case 0xD4: AddrMode_Dir(); PEI(); break;
|
||||
case 0xD5: AddrMode_DirIdxX(); CMP(); break;
|
||||
case 0xD6: AddrMode_DirIdxX(); DEC(); break;
|
||||
case 0xD7: AddrMode_DirIndLngIdxY(); CMP(); break;
|
||||
case 0xD8: AddrMode_Imp(); CLD(); break;
|
||||
case 0xD9: AddrMode_AbsIdxY(); CMP(); break;
|
||||
case 0xDA: PHX(); break;
|
||||
case 0xDB: AddrMode_Imp(); STP(); break;
|
||||
case 0xDC: AddrMode_AbsIndLng(); JML(); break;
|
||||
case 0xDD: AddrMode_AbsIdxX(); CMP(); break;
|
||||
case 0xDE: AddrMode_AbsIdxX(); DEC(); break;
|
||||
case 0xDF: AddrMode_AbsLngIdxX(); CMP(); break;
|
||||
case 0xE0: AddrMode_ImmX(); CPX(); break;
|
||||
case 0xE1: AddrMode_DirIdxIndX(); SBC(); break;
|
||||
case 0xE2: AddrMode_Imm8(); SEP(); break;
|
||||
case 0xE3: AddrMode_StkRel(); SBC(); break;
|
||||
case 0xE4: AddrMode_Dir(); CPX(); break;
|
||||
case 0xE5: AddrMode_Dir(); SBC(); break;
|
||||
case 0xE6: AddrMode_Dir(); INC(); break;
|
||||
case 0xE7: AddrMode_DirIndLng(); SBC(); break;
|
||||
case 0xE8: AddrMode_Imp(); INX(); break;
|
||||
case 0xE9: AddrMode_ImmM(); SBC(); break;
|
||||
case 0xEA: AddrMode_Imp(); NOP(); break;
|
||||
case 0xEB: AddrMode_Imp(); XBA(); break;
|
||||
case 0xEC: AddrMode_Abs(); CPX(); break;
|
||||
case 0xED: AddrMode_Abs(); SBC(); break;
|
||||
case 0xEE: AddrMode_Abs(); INC(); break;
|
||||
case 0xEF: AddrMode_AbsLng(); SBC(); break;
|
||||
case 0xF0: AddrMode_Rel(); BEQ(); break;
|
||||
case 0xF1: AddrMode_DirIndIdxY(); SBC(); break;
|
||||
case 0xF2: AddrMode_DirInd(); SBC(); break;
|
||||
case 0xF3: AddrMode_StkRelIndIdxY(); SBC(); break;
|
||||
case 0xF4: AddrMode_Imm16(); PEA(); break;
|
||||
case 0xF5: AddrMode_DirIdxX(); SBC(); break;
|
||||
case 0xF6: AddrMode_DirIdxX(); INC(); break;
|
||||
case 0xF7: AddrMode_DirIndLngIdxY(); SBC(); break;
|
||||
case 0xF8: AddrMode_Imp(); SED(); break;
|
||||
case 0xF9: AddrMode_AbsIdxY(); SBC(); break;
|
||||
case 0xFA: PLX(); break;
|
||||
case 0xFB: AddrMode_Imp(); XCE(); break;
|
||||
case 0xFC: AddrMode_AbsIdxXInd(); JSR(); break;
|
||||
case 0xFD: AddrMode_AbsIdxX(); SBC(); break;
|
||||
case 0xFE: AddrMode_AbsIdxX(); INC(); break;
|
||||
case 0xFF: AddrMode_AbsLngIdxX(); SBC(); break;
|
||||
}
|
||||
|
||||
if(_nmiFlag) {
|
||||
ProcessInterrupt(_state.EmulationMode ? Cpu::LegacyNmiVector : Cpu::NmiVector);
|
||||
|
@ -127,9 +336,9 @@ uint8_t Cpu::GetOpCode()
|
|||
return opCode;
|
||||
}
|
||||
|
||||
void Cpu::DummyRead()
|
||||
void Cpu::Idle()
|
||||
{
|
||||
ReadCode(_state.PC, MemoryOperationType::DummyRead);
|
||||
_memoryManager->ProcessCpuInternalOperation();
|
||||
}
|
||||
|
||||
uint8_t Cpu::ReadOperandByte()
|
||||
|
@ -168,7 +377,7 @@ uint16_t Cpu::ReadCodeWord(uint16_t addr, MemoryOperationType type)
|
|||
uint8_t Cpu::ReadData(uint32_t addr, MemoryOperationType type)
|
||||
{
|
||||
_state.CycleCount++;
|
||||
return _memoryManager->Read(addr, type);
|
||||
return _memoryManager->Read(addr & 0xFFFFFF, type);
|
||||
}
|
||||
|
||||
uint16_t Cpu::ReadDataWord(uint32_t addr, MemoryOperationType type)
|
||||
|
@ -200,7 +409,7 @@ void Cpu::WriteWord(uint32_t addr, uint16_t value, MemoryOperationType type)
|
|||
|
||||
uint8_t Cpu::GetByteValue()
|
||||
{
|
||||
if(_instAddrMode <= AddrMode::ImmM) {
|
||||
if(_immediateMode) {
|
||||
return (uint8_t)_operand;
|
||||
} else {
|
||||
return ReadData(_operand);
|
||||
|
@ -209,7 +418,7 @@ uint8_t Cpu::GetByteValue()
|
|||
|
||||
uint16_t Cpu::GetWordValue()
|
||||
{
|
||||
if(_instAddrMode <= AddrMode::ImmM) {
|
||||
if(_immediateMode) {
|
||||
return (uint16_t)_operand;
|
||||
} else {
|
||||
return ReadDataWord(_operand);
|
||||
|
@ -266,57 +475,6 @@ uint32_t Cpu::GetDirectAddressIndirectLong(uint16_t offset, bool allowEmulationM
|
|||
return (b3 << 16) | (b2 << 8) | b1;
|
||||
}
|
||||
|
||||
uint32_t Cpu::FetchEffectiveAddress()
|
||||
{
|
||||
switch(_instAddrMode) {
|
||||
case AddrMode::Abs: return GetDataAddress(ReadOperandWord());
|
||||
case AddrMode::AbsIdxX: return (GetDataAddress(ReadOperandWord()) + _state.X) & 0xFFFFFF;
|
||||
case AddrMode::AbsIdxY: return (GetDataAddress(ReadOperandWord()) + _state.Y) & 0xFFFFFF;
|
||||
case AddrMode::AbsLng: return ReadOperandLong();
|
||||
case AddrMode::AbsLngIdxX: return (ReadOperandLong() + _state.X) & 0xFFFFFF;
|
||||
|
||||
case AddrMode::AbsJmp: return GetProgramAddress(ReadOperandWord());
|
||||
case AddrMode::AbsLngJmp: return ReadOperandLong();
|
||||
case AddrMode::AbsIdxXInd: return GetProgramAddress(ReadDataWord(GetProgramAddress(ReadOperandWord() + _state.X))); //JMP/JSR
|
||||
case AddrMode::AbsInd: return ReadDataWord(ReadOperandWord()); //JMP only
|
||||
case AddrMode::AbsIndLng: return ReadDataLong(ReadOperandWord()); //JML only
|
||||
|
||||
case AddrMode::Acc: DummyRead(); return 0;
|
||||
|
||||
case AddrMode::BlkMov: return ReadOperandWord();
|
||||
|
||||
case AddrMode::Dir: return GetDirectAddress(ReadOperandByte());
|
||||
case AddrMode::DirIdxX: return GetDirectAddress(ReadOperandByte() + _state.X);
|
||||
case AddrMode::DirIdxY: return GetDirectAddress(ReadOperandByte() + _state.Y);
|
||||
|
||||
case AddrMode::DirInd: return GetDataAddress(GetDirectAddressIndirectWord(ReadOperandByte()));
|
||||
case AddrMode::DirIdxIndX: return GetDataAddress(GetDirectAddressIndirectWord(ReadOperandByte() + _state.X));
|
||||
case AddrMode::DirIndIdxY: return (GetDataAddress(GetDirectAddressIndirectWord(ReadOperandByte())) + _state.Y) & 0xFFFFFF;
|
||||
case AddrMode::DirIndLng: return GetDirectAddressIndirectLong(ReadOperandByte());
|
||||
case AddrMode::DirIndLngIdxY: return (GetDirectAddressIndirectLong(ReadOperandByte()) + _state.Y) & 0xFFFFFF;
|
||||
|
||||
case AddrMode::Imm8: return ReadOperandByte();
|
||||
case AddrMode::Imm16: return ReadOperandWord();
|
||||
case AddrMode::ImmX: return CheckFlag(ProcFlags::IndexMode8) ? ReadOperandByte() : ReadOperandWord();
|
||||
case AddrMode::ImmM: return CheckFlag(ProcFlags::MemoryMode8) ? ReadOperandByte() : ReadOperandWord();
|
||||
|
||||
case AddrMode::Imp: DummyRead(); return 0;
|
||||
|
||||
case AddrMode::RelLng: return ReadOperandWord();
|
||||
case AddrMode::Rel: return ReadOperandByte();
|
||||
|
||||
case AddrMode::Stk: return 0;
|
||||
case AddrMode::StkRel: return (uint16_t)(ReadOperandByte() + _state.SP);
|
||||
|
||||
case AddrMode::StkRelIndIdxY: {
|
||||
uint16_t addr = (uint16_t)(ReadOperandByte() + _state.SP);
|
||||
return (GetDataAddress(ReadDataWord(addr)) + _state.Y) & 0xFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unreacheable code");
|
||||
}
|
||||
|
||||
void Cpu::SetSP(uint16_t sp)
|
||||
{
|
||||
if(_state.EmulationMode) {
|
||||
|
|
55
Core/Cpu.h
55
Core/Cpu.h
|
@ -7,7 +7,6 @@ class MemoryManager;
|
|||
class Cpu
|
||||
{
|
||||
public:
|
||||
uint64_t opCount = 0;
|
||||
uint16_t GetPc() { return _state.PC; }
|
||||
CpuState GetState() { return _state; }
|
||||
int32_t GetLastOperand() { return (int32_t)_operand; }
|
||||
|
@ -27,8 +26,10 @@ private:
|
|||
typedef void(Cpu::*Func)();
|
||||
|
||||
shared_ptr<MemoryManager> _memoryManager;
|
||||
|
||||
bool _immediateMode = false;
|
||||
|
||||
CpuState _state;
|
||||
AddrMode _instAddrMode;
|
||||
uint32_t _operand;
|
||||
bool _nmiFlag;
|
||||
uint8_t _irqSource;
|
||||
|
@ -46,12 +47,11 @@ private:
|
|||
|
||||
uint8_t GetOpCode();
|
||||
|
||||
void DummyRead();
|
||||
void Idle();
|
||||
|
||||
uint8_t ReadOperandByte();
|
||||
uint16_t ReadOperandWord();
|
||||
uint32_t ReadOperandLong();
|
||||
uint32_t FetchEffectiveAddress();
|
||||
|
||||
void SetSP(uint16_t sp);
|
||||
void SetPS(uint8_t ps);
|
||||
|
@ -128,6 +128,9 @@ private:
|
|||
void DEC();
|
||||
void INC();
|
||||
|
||||
void DEC_Acc();
|
||||
void INC_Acc();
|
||||
|
||||
void IncDecReg(uint16_t & reg, int8_t offset);
|
||||
void IncDec(int8_t offset);
|
||||
|
||||
|
@ -162,9 +165,13 @@ private:
|
|||
template<typename T> T RollRight(T value);
|
||||
|
||||
//Shift operations
|
||||
void ASL_Acc();
|
||||
void ASL();
|
||||
void LSR_Acc();
|
||||
void LSR();
|
||||
void ROL_Acc();
|
||||
void ROL();
|
||||
void ROR_Acc();
|
||||
void ROR();
|
||||
|
||||
//Move operations
|
||||
|
@ -237,6 +244,46 @@ private:
|
|||
void STP();
|
||||
void WAI();
|
||||
|
||||
//Addressing modes
|
||||
void AddrMode_Abs();
|
||||
void AddrMode_AbsIdxX();
|
||||
void AddrMode_AbsIdxY();
|
||||
void AddrMode_AbsLng();
|
||||
void AddrMode_AbsLngIdxX();
|
||||
|
||||
void AddrMode_AbsJmp();
|
||||
void AddrMode_AbsLngJmp();
|
||||
void AddrMode_AbsIdxXInd(); //JMP/JSR
|
||||
void AddrMode_AbsInd(); //JMP only
|
||||
void AddrMode_AbsIndLng(); //JML only
|
||||
|
||||
void AddrMode_Acc();
|
||||
|
||||
void AddrMode_BlkMov();
|
||||
|
||||
uint8_t ReadDirectOperandByte();
|
||||
void AddrMode_Dir();
|
||||
void AddrMode_DirIdxX();
|
||||
void AddrMode_DirIdxY();
|
||||
void AddrMode_DirInd();
|
||||
void AddrMode_DirIdxIndX();
|
||||
void AddrMode_DirIndIdxY();
|
||||
void AddrMode_DirIndLng();
|
||||
void AddrMode_DirIndLngIdxY();
|
||||
|
||||
void AddrMode_Imm8();
|
||||
void AddrMode_Imm16();
|
||||
void AddrMode_ImmX();
|
||||
void AddrMode_ImmM();
|
||||
|
||||
void AddrMode_Imp();
|
||||
|
||||
void AddrMode_RelLng();
|
||||
void AddrMode_Rel();
|
||||
|
||||
void AddrMode_StkRel();
|
||||
void AddrMode_StkRelIndIdxY();
|
||||
|
||||
public:
|
||||
Cpu(shared_ptr<MemoryManager> memoryManager);
|
||||
~Cpu();
|
||||
|
|
|
@ -101,6 +101,7 @@ private:
|
|||
uint8_t * _workRam;
|
||||
|
||||
uint64_t _masterClock;
|
||||
uint8_t _previousSpeed;
|
||||
uint64_t _lastMasterClock;
|
||||
uint8_t _masterClockTable[2][0x10000];
|
||||
|
||||
|
@ -217,7 +218,26 @@ public:
|
|||
|
||||
void IncrementMasterClock(uint32_t addr)
|
||||
{
|
||||
_masterClock += _masterClockTable[(uint8_t)_regs->IsFastRomEnabled()][addr >> 8];
|
||||
_previousSpeed = _masterClockTable[(uint8_t)_regs->IsFastRomEnabled()][addr >> 8];
|
||||
_masterClock += _previousSpeed;
|
||||
while(_lastMasterClock < _masterClock - 3) {
|
||||
_ppu->Exec();
|
||||
_lastMasterClock += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessCpuInternalOperation()
|
||||
{
|
||||
_masterClock += 6;
|
||||
while(_lastMasterClock < _masterClock - 3) {
|
||||
_ppu->Exec();
|
||||
_lastMasterClock += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessDramRefresh()
|
||||
{
|
||||
_masterClock += 40;
|
||||
while(_lastMasterClock < _masterClock - 3) {
|
||||
_ppu->Exec();
|
||||
_lastMasterClock += 4;
|
||||
|
|
|
@ -90,9 +90,13 @@ void Ppu::Exec()
|
|||
if(_regs->IsNmiEnabled()) {
|
||||
_console->GetCpu()->SetNmiFlag();
|
||||
}
|
||||
} else if(_scanline == 240 && _cycle == 0 && _frameCount & 0x01) {
|
||||
//Skip 1 tick every other frame
|
||||
_cycle++;
|
||||
} else if(_scanline == 261) {
|
||||
_regs->SetNmiFlag(false);
|
||||
_scanline = 0;
|
||||
|
||||
if(_mosaicEnabled) {
|
||||
_mosaicStartScanline = 0;
|
||||
}
|
||||
|
@ -115,6 +119,9 @@ void Ppu::Exec()
|
|||
|
||||
if(_cycle == 278 && _scanline < 225) {
|
||||
_console->GetDmaController()->ProcessHdmaChannels();
|
||||
} else if(_cycle == 134) {
|
||||
//TODO Approximation
|
||||
_console->GetMemoryManager()->ProcessDramRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue