1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-23 03:32:32 +00:00

Starts slowly, with flag manipulation.

This commit is contained in:
Thomas Harte 2020-10-06 16:25:30 -04:00
parent 7be983ec00
commit 993eff1d3d
3 changed files with 93 additions and 34 deletions

View File

@ -17,12 +17,14 @@
#include "../RegisterSizes.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
#include "../6502Esque/6502Esque.hpp"
#include "../6502Esque/Implementation/LazyFlags.hpp"
namespace CPU {
namespace WDC65816 {
using BusOperation = CPU::MOS6502Esque::BusOperation;
using Register = CPU::MOS6502Esque::Register;
using Flag = CPU::MOS6502Esque::Flag;
#include "Implementation/65816Storage.hpp"

View File

@ -21,6 +21,9 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
#define read(address, value) perform_bus(address, value, MOS6502Esque::Read)
#define write(address, value) perform_bus(address, value, MOS6502Esque::Write)
#define m_flag() mx_flags_[0]
#define x_flag() mx_flags_[1]
#define x() (x_.full & x_masks_[1])
#define y() (y_.full & x_masks_[1])
@ -160,29 +163,29 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
case OperationCopyPCToData:
data_buffer_.size = 2;
data_buffer_.value = pc_;
break;
continue;
case OperationCopyInstructionToData:
data_buffer_ = instruction_buffer_;
break;
continue;
case OperationCopyAToData:
if(mx_flags_[0]) {
if(m_flag()) {
data_buffer_.size = 1;
data_buffer_.value = a_.halves.high;
} else {
data_buffer_.size = 2;
data_buffer_.value = a_.full;
}
break;
continue;
case OperationCopyDataToA:
if(mx_flags_[0]) {
if(m_flag()) {
a_.halves.high = data_buffer_.value;
} else {
a_.full = data_buffer_.value;
}
break;
continue;
//
// Address construction.
@ -194,11 +197,11 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
case OperationConstructAbsoluteIndexedIndirect:
data_address_ = (instruction_buffer_.value + x()) & 0xffff;
break;
continue;
case OperationConstructAbsoluteLongX:
data_address_ = (instruction_buffer_.value + x()) & 0xffff + instruction_buffer_.value & 0xff0000;
break;
continue;
case OperationConstructAbsoluteXRead:
case OperationConstructAbsoluteX:
@ -209,7 +212,7 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
if(operation == OperationConstructAbsoluteXRead && data_address_ == incorrect_data_address_) {
++next_op_;
}
break;
continue;
case OperationConstructAbsoluteYRead:
case OperationConstructAbsoluteY:
@ -220,38 +223,38 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
if(operation == OperationConstructAbsoluteYRead && data_address_ == incorrect_data_address_) {
++next_op_;
}
break;
continue;
case OperationConstructDirect:
data_address_ = (direct_ + instruction_buffer_.value) & 0xffff;
if(!(direct_&0xff)) {
++next_op_;
}
break;
continue;
case OperationConstructDirectIndexedIndirect:
data_address_ = data_bank_ + (direct_ + x() + instruction_buffer_.value) & 0xffff;
if(!(direct_&0xff)) {
++next_op_;
}
break;
continue;
case OperationConstructDirectIndirect:
data_address_ = data_bank_ + (direct_ + instruction_buffer_.value) & 0xffff;
if(!(direct_&0xff)) {
++next_op_;
}
break;
continue;
case OperationConstructDirectIndirectIndexedLong:
// TODO: assumed here is that the low 16-bit calculation can't carry into
// the high byte. Test this!
data_address_ = (y() + instruction_buffer_.value) & 0xffff + instruction_buffer_.value & 0xff0000;
break;
continue;
case OperationConstructDirectIndirectLong:
data_address_ = instruction_buffer_.value;
break;
continue;
case OperationConstructDirectX:
data_address_ = (direct_ + x()) & 0xffff;
@ -259,7 +262,7 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
if(!(direct_&0xff)) {
++next_op_;
}
break;
continue;
case OperationConstructDirectY:
data_address_ = (direct_ + y()) & 0xffff;
@ -267,41 +270,37 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
if(!(direct_&0xff)) {
++next_op_;
}
break;
continue;
case OperationConstructPER:
data_buffer_.value = instruction_buffer_.value + pc_;
data_buffer_.size = 2;
break;
continue;
case OperationConstructStackRelative:
data_address_ = (s_.full + instruction_buffer_.value) & 0xffff;
break;
continue;
case OperationConstructStackRelativeIndexedIndirect:
data_address_ = data_bank_ + (instruction_buffer_.value + y()) & 0xffff;
break;
continue;
//
// Performance.
//
#define LD(dest, src, masks) dest.full = (dest.full & masks[0]) | (src & masks[1])
#define m_top() (instruction_buffer_.value >> m_shift_) & 0xff
#define x_top() (x_.full >> x_shift_) & 0xff
#define y_top() (y_.full >> x_shift_) & 0xff
case OperationPerform:
switch(active_instruction_->operation) {
//
// Flag manipulation.
//
case CLD:
decimal_flag_ = 0;
break;
//
// Loads, stores and transfers
//
#define LD(dest, src, masks) dest.full = (dest.full & masks[0]) | (src & masks[1])
case LDA:
LD(a_, data_buffer_.value, m_masks_);
@ -320,11 +319,9 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
LD(s_, x_.full, x_masks_);
break;
#undef LD
case STA:
data_buffer_.value = a_.full & m_masks_[1];
data_buffer_.size = 2 - mx_flags_[0];
data_buffer_.size = 2 - m_flag();
break;
//
@ -367,10 +364,61 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
if(a_.full) pc_ -= 3;
break;
//
// Flag manipulation.
//
case CLC: flags_.carry = 0; break;
case CLI: flags_.inverse_interrupt = Flag::Interrupt; break;
case CLV: flags_.overflow = 0; break;
case CLD: flags_.decimal = 0; break;
case SEC: flags_.carry = Flag::Carry; break;
case SEI: flags_.inverse_interrupt = 0; break;
case SED: flags_.decimal = Flag::Decimal; break;
//
// Increments and decrements.
//
case INC:
++instruction_buffer_.value;
flags_.set_nz(m_top());
break;;
case DEC:
--instruction_buffer_.value;
flags_.set_nz(m_top());
break;
case INX: {
const uint16_t x_inc = x_.full + 1;
LD(x_, x_inc, x_masks_);
flags_.set_nz(x_top());
} break;
case DEX: {
const uint16_t x_dec = x_.full - 1;
LD(x_, x_dec, x_masks_);
flags_.set_nz(x_top());
} break;
case INY: {
const uint16_t y_inc = y_.full + 1;
LD(y_, y_inc, x_masks_);
flags_.set_nz(y_top());
} break;
case DEY: {
const uint16_t y_dec = y_.full - 1;
LD(y_, y_dec, x_masks_);
flags_.set_nz(y_top());
} break;
default:
assert(false);
}
break;
continue;
// TODO: OperationCopyPBRToData, OperationPrepareException
@ -378,6 +426,11 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
assert(false);
}
#undef LD
#undef m_top
#undef x_top
#undef y_top
number_of_cycles -= bus_handler_.perform_bus_operation(bus_operation, bus_address, bus_value);
}
@ -386,6 +439,8 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
#undef bus_operation
#undef x
#undef y
#undef m_flag
#undef x_flag
cycles_left_to_run_ = number_of_cycles;
}

View File

@ -228,10 +228,12 @@ struct ProcessorStorage {
Cycles cycles_left_to_run_;
// Flags aplenty.
uint8_t carry_flag_, negative_result_, zero_result_, decimal_flag_, overflow_flag_, inverse_interrupt_flag_ = 0;
MOS6502Esque::LazyFlags flags_;
uint8_t mx_flags_[2] = {1, 1}; // [0] = m; [1] = x. In both cases either `0` or `1`; `1` => 8-bit.
uint16_t m_masks_[2] = {0xff00, 0x00ff}; // [0] = src mask; [1] = dst mask.
uint16_t x_masks_[2] = {0xff00, 0x00ff}; // [0] = src mask; [1] = dst mask.
int m_shift_ = 0;
int x_shift_ = 0;
bool emulation_flag_ = true;
// I.e. the offset for direct addressing (outside of emulation mode).