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

Attempts to complete all addressing modes.

So, if bugs didn't exist, it'd just be members of the Operation enum to go.
This commit is contained in:
Thomas Harte 2020-10-05 17:04:57 -04:00
parent 825201f4f2
commit b7ba0d4327
3 changed files with 101 additions and 23 deletions

View File

@ -166,12 +166,30 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
data_buffer_ = instruction_buffer_;
break;
case OperationCopyAToData:
if(mx_flags_[0]) {
data_buffer_.size = 1;
data_buffer_.value = a_.halves.high;
} else {
data_buffer_.size = 2;
data_buffer_.value = a_.full;
}
break;
case OperationCopyDataToA:
if(mx_flags_[0]) {
a_.halves.high = data_buffer_.value;
} else {
a_.full = data_buffer_.value;
}
break;
//
// Address construction.
//
case OperationConstructAbsolute:
data_address_ = instruction_buffer_.value | data_bank_;
data_address_ = instruction_buffer_.value + data_bank_;
break;
case OperationConstructAbsoluteIndexedIndirect:
@ -179,13 +197,13 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
break;
case OperationConstructAbsoluteLongX:
data_address_ = instruction_buffer_.value + x();
data_address_ = (instruction_buffer_.value + x()) & 0xffff + instruction_buffer_.value & 0xff0000;
break;
case OperationConstructAbsoluteXRead:
case OperationConstructAbsoluteX:
data_address_ = ((instruction_buffer_.value + x()) & 0xffff) | data_bank_;
incorrect_data_address_ = (data_address_ & 0xff) | (instruction_buffer_.value & 0xff00) | data_bank_;
data_address_ = ((instruction_buffer_.value + x()) & 0xffff) + data_bank_;
incorrect_data_address_ = (data_address_ & 0xff) | (instruction_buffer_.value & 0xff00) + data_bank_;
// If the incorrect address isn't actually incorrect, skip its usage.
if(operation == OperationConstructAbsoluteXRead && data_address_ == incorrect_data_address_) {
@ -195,8 +213,8 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
case OperationConstructAbsoluteYRead:
case OperationConstructAbsoluteY:
data_address_ = ((instruction_buffer_.value + y()) & 0xffff) | data_bank_;
incorrect_data_address_ = (data_address_ & 0xff) | (instruction_buffer_.value & 0xff00) | data_bank_;
data_address_ = ((instruction_buffer_.value + y()) & 0xffff) + data_bank_;
incorrect_data_address_ = (data_address_ & 0xff) + (instruction_buffer_.value & 0xff00) + data_bank_;
// If the incorrect address isn't actually incorrect, skip its usage.
if(operation == OperationConstructAbsoluteYRead && data_address_ == incorrect_data_address_) {
@ -225,6 +243,45 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
}
break;
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;
case OperationConstructDirectIndirectLong:
data_address_ = instruction_buffer_.value;
break;
case OperationConstructDirectX:
data_address_ = (direct_ + x()) & 0xffff;
incorrect_data_address_ = (direct_ & 0xff00) + (data_address_ & 0x00ff);
if(!(direct_&0xff)) {
++next_op_;
}
break;
case OperationConstructDirectY:
data_address_ = (direct_ + y()) & 0xffff;
incorrect_data_address_ = (direct_ & 0xff00) + (data_address_ & 0x00ff);
if(!(direct_&0xff)) {
++next_op_;
}
break;
case OperationConstructPER:
data_buffer_.value = instruction_buffer_.value + pc_;
data_buffer_.size = 2;
break;
case OperationConstructStackRelative:
data_address_ = (s_.full + instruction_buffer_.value) & 0xffff;
break;
case OperationConstructStackRelativeIndexedIndirect:
data_address_ = data_bank_ + (instruction_buffer_.value + y()) & 0xffff;
break;
//
// Performance.
//
@ -315,8 +372,8 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
}
break;
default:
assert(false);
// default:
// assert(false);
}
number_of_cycles -= bus_handler_.perform_bus_operation(bus_operation, bus_address, bus_value);

View File

@ -424,21 +424,17 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
static void direct_indirect_indexed(AccessType type, bool is8bit, const std::function<void(MicroOp)> &target) {
target(CycleFetchIncrementPC); // DO.
target(OperationConstructDirectIndirect);
target(OperationConstructDirect);
target(CycleFetchPC); // IO.
target(CycleFetchIncrementData); // AAL.
target(CycleFetchData); // AAH.
target(OperationConstructDirectIndirectIndexed);
target(OperationConstructAbsoluteYRead);
target(CycleFetchIncorrectDataAddress); // IO.
read_write(type, is8bit, target);
}
// TODO: verify, especially re: false addresses.
// i.e. it currently looks to me superficially as though I can reuse
// OperationConstructDirectIndirect here, but writing the proper
// interpreter will help to clarify.
// 14. Direct Indirect Indexed Long; [d], y.
static void direct_indirect_indexed_long(AccessType type, bool is8bit, const std::function<void(MicroOp)> &target) {

View File

@ -22,9 +22,6 @@ enum MicroOp: uint8_t {
/// of the instruction buffer, throwing the result away.
CycleFetchIncorrectDataAddress,
/// Fetches a vector (i.e. IRQ, NMI, etc) into the data buffer.
CycleFetchVector,
// Dedicated block-move cycles; these use the data buffer as an intermediary.
CycleFetchBlockX,
CycleFetchBlockY,
@ -44,11 +41,15 @@ enum MicroOp: uint8_t {
/// Pulls a single byte to the data buffer from the stack.
CyclePull,
/// Sets the data address by copying the final two bytes of the instruction buffer.
/// Sets the data address by copying the final two bytes of the instruction buffer and
/// using the data register as a high byte.
OperationConstructAbsolute,
/// Sets the data address to the result of (a, x).
/// TODO: explain better once implemented.
/// Sets the data address to the 16-bit result of adding x to the value in the instruction buffer.
OperationConstructAbsoluteIndexedIndirect,
/// Sets the data address to the 24-bit result of adding x to the low 16-bits of the value in the
/// instruction buffer and retaining the highest 8-bits as specified.
OperationConstructAbsoluteLongX,
/// Calculates an a, x address; if:
@ -68,19 +69,40 @@ enum MicroOp: uint8_t {
/// Skips the next micro-op if the low byte of the direct register is 0.
OperationConstructDirect,
// These follow similar skip-one-if-possible logic to OperationConstructDirect.
/// Constructs the current direct indexed indirect address using the data bank,
/// direct and x registers plus the value currently in the instruction buffer.
/// Skips the next micro-op if the low byte of the direct register is 0.
OperationConstructDirectIndexedIndirect,
/// Constructs the current direct indexed indirect address using the data bank and
/// direct registers plus the value currently in the instruction buffer.
/// Skips the next micro-op if the low byte of the direct register is 0.
OperationConstructDirectIndirect,
OperationConstructDirectIndirectIndexed,
/// Adds y to the low 16-bits currently in the instruction buffer and appends a high 8-bits
/// also from the instruction buffer.
OperationConstructDirectIndirectIndexedLong,
/// Uses the 24-bit address currently in the instruction buffer.
OperationConstructDirectIndirectLong,
/// Adds the x register to the direct register to produce a 16-bit address;
/// skips the next micro-op if the low byte of the direct register is 0.
OperationConstructDirectX,
/// Adds the y register to the direct register to produce a 16-bit address;
/// skips the next micro-op if the low byte of the direct register is 0.
OperationConstructDirectY,
/// Adds the instruction buffer to the program counter, making a 16-bit result,
/// *and stores it into the data buffer*.
OperationConstructPER,
OperationConstructBRK,
/// Adds the stack pointer to the instruction buffer to produce a 16-bit address.
OperationConstructStackRelative,
/// Adds y to the value in the instruction buffer to produce a 16-bit result and
/// prefixes the current data bank.
OperationConstructStackRelativeIndexedIndirect,
/// Performs whatever operation goes with this program.
@ -93,7 +115,10 @@ enum MicroOp: uint8_t {
/// Copies the current PBR to the data buffer.
OperationCopyPBRToData,
/// Copies A to the data buffer.
OperationCopyAToData,
/// Copies the data buffer to A.
OperationCopyDataToA,
/// Fills the data buffer with three or four bytes, depending on emulation mode, containing the program