mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-23 20:29:42 +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:
parent
825201f4f2
commit
b7ba0d4327
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user