1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-01 22:41:32 +00:00

Shift operation stuff into its own namespace, making data_select_active a free function.

This commit is contained in:
Thomas Harte 2023-12-21 16:03:53 -05:00
parent 6c4905d961
commit 213dfe037d
8 changed files with 221 additions and 214 deletions

View File

@ -82,11 +82,11 @@ class ConcreteMachine:
// MARK: - MC68000::BusHandler.
using Microcycle = CPU::MC68000::Microcycle;
template <Microcycle::OperationT op> HalfCycles perform_bus_operation(const Microcycle &cycle, int) {
const auto operation = (op != Microcycle::DecodeDynamically) ? op : cycle.operation;
const auto operation = (op != CPU::MC68000::Operation::DecodeDynamically) ? op : cycle.operation;
// Do a quick advance check for Chip RAM access; add a suitable delay if required.
HalfCycles total_length;
if(operation & Microcycle::NewAddress && *cycle.address < 0x20'0000) {
if(operation & CPU::MC68000::Operation::NewAddress && *cycle.address < 0x20'0000) {
total_length = chipset_.run_until_after_cpu_slot().duration;
assert(total_length >= cycle.length);
} else {
@ -96,19 +96,19 @@ class ConcreteMachine:
mc68000_.set_interrupt_level(chipset_.get_interrupt_level());
// Check for assertion of reset.
if(operation & Microcycle::Reset) {
if(operation & CPU::MC68000::Operation::Reset) {
memory_.reset();
LOG("Reset; PC is around " << PADHEX(8) << mc68000_.get_state().registers.program_counter);
}
// Autovector interrupts.
if(operation & Microcycle::InterruptAcknowledge) {
if(operation & CPU::MC68000::Operation::InterruptAcknowledge) {
mc68000_.set_is_peripheral_address(true);
return total_length - cycle.length;
}
// Do nothing if no address is exposed.
if(!(operation & (Microcycle::NewAddress | Microcycle::SameAddress))) return total_length - cycle.length;
if(!(operation & (CPU::MC68000::Operation::NewAddress | CPU::MC68000::Operation::SameAddress))) return total_length - cycle.length;
// Grab the target address to pick a memory source.
const uint32_t address = cycle.host_endian_byte_address();
@ -117,7 +117,7 @@ class ConcreteMachine:
mc68000_.set_is_peripheral_address((address & 0xe0'0000) == 0xa0'0000);
if(!memory_.regions[address >> 18].read_write_mask) {
if((operation & (Microcycle::SelectByte | Microcycle::SelectWord))) {
if((operation & (CPU::MC68000::Operation::SelectByte | CPU::MC68000::Operation::SelectWord))) {
// Check for various potential chip accesses.
// Per the manual:
@ -135,7 +135,7 @@ class ConcreteMachine:
const bool select_a = !(address & 0x1000);
const bool select_b = !(address & 0x2000);
if(operation & Microcycle::Read) {
if(operation & CPU::MC68000::Operation::Read) {
uint16_t result = 0xffff;
if(select_a) result &= 0xff00 | (chipset_.cia_a.read(reg) << 0);
if(select_b) result &= 0x00ff | (chipset_.cia_b.read(reg) << 8);
@ -157,13 +157,13 @@ class ConcreteMachine:
memory_.perform(cycle);
} else {
// This'll do for open bus, for now.
if(operation & Microcycle::Read) {
if(operation & CPU::MC68000::Operation::Read) {
cycle.set_value16(0xffff);
}
// Don't log for the region that is definitely just ROM this machine doesn't have.
if(address < 0xf0'0000) {
LOG("Unmapped " << (operation & Microcycle::Read ? "read from " : "write to ") << PADHEX(6) << ((*cycle.address)&0xffffff) << " of " << cycle.value16());
LOG("Unmapped " << (operation & CPU::MC68000::Operation::Read ? "read from " : "write to ") << PADHEX(6) << ((*cycle.address)&0xffffff) << " of " << cycle.value16());
}
}
}

View File

@ -845,7 +845,7 @@ void Chipset::perform(const CPU::MC68000::Microcycle &cycle) {
using Microcycle = CPU::MC68000::Microcycle;
const uint32_t register_address = *cycle.address & ChipsetAddressMask;
if(cycle.operation & Microcycle::Read) {
if(cycle.operation & CPU::MC68000::Operation::Read) {
cycle.set_value16(read(register_address));
} else {
write(register_address, cycle.value16());

View File

@ -114,8 +114,7 @@ class MemoryMap {
const uint32_t register_address = *cycle.address & 0xfe;
using Microcycle = CPU::MC68000::Microcycle;
if(cycle.operation & Microcycle::Read) {
if(cycle.operation & CPU::MC68000::Operation::Read) {
// Re: Autoconf:
//
// "All read registers physically return only the top 4 bits of data, on D31-D28";

View File

@ -193,13 +193,13 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
using Microcycle = CPU::MC68000::Microcycle;
template <Microcycle::OperationT op> HalfCycles perform_bus_operation(const Microcycle &cycle, int) {
const auto operation = (op != Microcycle::DecodeDynamically) ? op : cycle.operation;
const auto operation = (op != CPU::MC68000::Operation::DecodeDynamically) ? op : cycle.operation;
// Advance time.
advance_time(cycle.length);
// A null cycle leaves nothing else to do.
if(!(operation & (Microcycle::NewAddress | Microcycle::SameAddress))) return HalfCycles(0);
if(!(operation & (CPU::MC68000::Operation::NewAddress | CPU::MC68000::Operation::SameAddress))) return HalfCycles(0);
// Grab the address.
auto address = cycle.host_endian_byte_address();
@ -219,7 +219,10 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
// having set VPA above deals with those given that the generated address
// for interrupt acknowledge cycles always has all bits set except the
// lowest explicit address lines.
if(!cycle.data_select_active() || (operation & Microcycle::InterruptAcknowledge)) return HalfCycles(0);
if(
!CPU::MC68000::Operation::data_select_active(operation) ||
(operation & CPU::MC68000::Operation::InterruptAcknowledge)
) return HalfCycles(0);
// Grab the word-precision address being accessed.
uint8_t *memory_base = nullptr;
@ -239,7 +242,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
// VIA accesses are via address 0xefe1fe + register*512,
// which at word precision is 0x77f0ff + register*256.
if(operation & Microcycle::Read) {
if(operation & CPU::MC68000::Operation::Read) {
cycle.set_value8_high(via_.read(register_address));
} else {
via_.write(register_address, cycle.value8_high());
@ -248,7 +251,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
} return delay;
case BusDevice::PhaseRead: {
if(operation & Microcycle::Read) {
if(operation & CPU::MC68000::Operation::Read) {
cycle.set_value8_low(phase_ & 7);
}
} return delay;
@ -258,7 +261,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
const int register_address = address >> 9;
// The IWM; this is a purely polled device, so can be run on demand.
if(operation & Microcycle::Read) {
if(operation & CPU::MC68000::Operation::Read) {
cycle.set_value8_low(iwm_->read(register_address));
} else {
iwm_->write(register_address, cycle.value8_low());
@ -275,14 +278,14 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
// Even accesses = read; odd = write.
if(*cycle.address & 1) {
// Odd access => this is a write. Data will be in the upper byte.
if(operation & Microcycle::Read) {
if(operation & CPU::MC68000::Operation::Read) {
scsi_.write(register_address, 0xff, dma_acknowledge);
} else {
scsi_.write(register_address, cycle.value8_high());
}
} else {
// Even access => this is a read.
if(operation & Microcycle::Read) {
if(operation & CPU::MC68000::Operation::Read) {
cycle.set_value8_high(scsi_.read(register_address, dma_acknowledge));
}
}
@ -290,19 +293,19 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
case BusDevice::SCCReadResetPhase: {
// Any word access here adjusts phase.
if(operation & Microcycle::SelectWord) {
if(operation & CPU::MC68000::Operation::SelectWord) {
adjust_phase();
} else {
// A0 = 1 => reset; A0 = 0 => read.
if(*cycle.address & 1) {
scc_.reset();
if(operation & Microcycle::Read) {
if(operation & CPU::MC68000::Operation::Read) {
cycle.set_value16(0xffff);
}
} else {
const auto read = scc_.read(int(address >> 1));
if(operation & Microcycle::Read) {
if(operation & CPU::MC68000::Operation::Read) {
cycle.set_value8_high(read);
}
}
@ -311,13 +314,13 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
case BusDevice::SCCWrite: {
// Any word access here adjusts phase.
if(operation & Microcycle::SelectWord) {
if(operation & CPU::MC68000::Operation::SelectWord) {
adjust_phase();
} else {
// This is definitely a byte access; either it's to an odd address, in which
// case it will reach the SCC, or it isn't, in which case it won't.
if(*cycle.address & 1) {
if(operation & Microcycle::Read) {
if(operation & CPU::MC68000::Operation::Read) {
scc_.write(int(address >> 1), 0xff);
cycle.value->b = 0xff;
} else {
@ -352,7 +355,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
} break;
case BusDevice::ROM: {
if(!(operation & Microcycle::Read)) return delay;
if(!(operation & CPU::MC68000::Operation::Read)) return delay;
memory_base = rom_;
address &= rom_mask_;
} break;
@ -546,8 +549,8 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
template <Microcycle::OperationT op>
forceinline void fill_unmapped(const Microcycle &cycle) {
const auto operation = (op != Microcycle::DecodeDynamically) ? op : cycle.operation;
if(!(operation & Microcycle::Read)) return;
const auto operation = (op != CPU::MC68000::Operation::DecodeDynamically) ? op : cycle.operation;
if(!(operation & CPU::MC68000::Operation::Read)) return;
cycle.set_value16(0xffff);
}

View File

@ -178,7 +178,7 @@ class ConcreteMachine:
// MARK: MC68000::BusHandler
using Microcycle = CPU::MC68000::Microcycle;
template <Microcycle::OperationT op> HalfCycles perform_bus_operation(const Microcycle &cycle, int is_supervisor) {
const auto operation = (op != Microcycle::DecodeDynamically) ? op : cycle.operation;
const auto operation = (op != CPU::MC68000::Operation::DecodeDynamically) ? op : cycle.operation;
// Just in case the last cycle was an interrupt acknowledge or bus error. TODO: find a better solution?
mc68000_.set_is_peripheral_address(false);
@ -188,15 +188,15 @@ class ConcreteMachine:
advance_time(cycle.length);
// Check for assertion of reset.
if(operation & Microcycle::Reset) {
if(operation & CPU::MC68000::Operation::Reset) {
LOG("Unhandled Reset");
}
// A null cycle leaves nothing else to do.
if(!(operation & (Microcycle::NewAddress | Microcycle::SameAddress))) return HalfCycles(0);
if(!(operation & (CPU::MC68000::Operation::NewAddress | CPU::MC68000::Operation::SameAddress))) return HalfCycles(0);
// An interrupt acknowledge, perhaps?
if(operation & Microcycle::InterruptAcknowledge) {
if(operation & CPU::MC68000::Operation::InterruptAcknowledge) {
// Current implementation: everything other than 6 (i.e. the MFP) is autovectored.
const int interrupt_level = cycle.word_address()&7;
if(interrupt_level != 6) {
@ -205,7 +205,7 @@ class ConcreteMachine:
mc68000_.set_is_peripheral_address(true);
return HalfCycles(0);
} else {
if(operation & Microcycle::SelectByte) {
if(operation & CPU::MC68000::Operation::SelectByte) {
const int interrupt = mfp_->acknowledge_interrupt();
if(interrupt != Motorola::MFP68901::MFP68901::NoAcknowledgement) {
cycle.value->b = uint8_t(interrupt);
@ -222,7 +222,7 @@ class ConcreteMachine:
// If this is a new strobing of the address signal, test for bus error and pre-DTack delay.
HalfCycles delay(0);
if(operation & Microcycle::NewAddress) {
if(operation & CPU::MC68000::Operation::NewAddress) {
// Bus error test.
if(
// Anything unassigned should generate a bus error.
@ -257,7 +257,7 @@ class ConcreteMachine:
case BusDevice::ROM:
memory = rom_.data();
if(!(operation & Microcycle::Read)) {
if(!(operation & CPU::MC68000::Operation::Read)) {
return delay;
}
address -= rom_start_;
@ -271,12 +271,12 @@ class ConcreteMachine:
TOS 1.0 appears to attempt to read from the catridge before it has setup
the bus error vector. Therefore I assume no bus error flows.
*/
switch(operation & (Microcycle::SelectWord | Microcycle::SelectByte | Microcycle::Read)) {
switch(operation & (CPU::MC68000::Operation::SelectWord | CPU::MC68000::Operation::SelectByte | CPU::MC68000::Operation::Read)) {
default: break;
case Microcycle::SelectWord | Microcycle::Read:
case CPU::MC68000::Operation::SelectWord | CPU::MC68000::Operation::Read:
cycle.value->w = 0xffff;
break;
case Microcycle::SelectByte | Microcycle::Read:
case CPU::MC68000::Operation::SelectByte | CPU::MC68000::Operation::Read:
cycle.value->b = 0xff;
break;
}
@ -313,9 +313,9 @@ class ConcreteMachine:
case 0x8250: case 0x8252: case 0x8254: case 0x8256:
case 0x8258: case 0x825a: case 0x825c: case 0x825e:
case 0x8260: case 0x8262:
if(!cycle.data_select_active()) return delay;
if(!CPU::MC68000::Operation::data_select_active(operation)) return delay;
if(operation & Microcycle::Read) {
if(operation & CPU::MC68000::Operation::Read) {
cycle.set_value16(video_->read(int(address >> 1)));
} else {
video_->write(int(address >> 1), cycle.value16());
@ -324,9 +324,9 @@ class ConcreteMachine:
// DMA.
case 0x8604: case 0x8606: case 0x8608: case 0x860a: case 0x860c:
if(!cycle.data_select_active()) return delay;
if(!CPU::MC68000::Operation::data_select_active(operation)) return delay;
if(operation & Microcycle::Read) {
if(operation & CPU::MC68000::Operation::Read) {
cycle.set_value16(dma_->read(int(address >> 1)));
} else {
dma_->write(int(address >> 1), cycle.value16());
@ -356,13 +356,12 @@ class ConcreteMachine:
case 0x88d0: case 0x88d2: case 0x88d4: case 0x88d6: case 0x88d8: case 0x88da: case 0x88dc: case 0x88de:
case 0x88e0: case 0x88e2: case 0x88e4: case 0x88e6: case 0x88e8: case 0x88ea: case 0x88ec: case 0x88ee:
case 0x88f0: case 0x88f2: case 0x88f4: case 0x88f6: case 0x88f8: case 0x88fa: case 0x88fc: case 0x88fe:
if(!cycle.data_select_active()) return delay;
if(!CPU::MC68000::Operation::data_select_active(operation)) return delay;
advance_time(HalfCycles(2));
update_audio();
if(operation & Microcycle::Read) {
if(operation & CPU::MC68000::Operation::Read) {
cycle.set_value8_high(GI::AY38910::Utility::read(ay_));
} else {
// Net effect here: addresses with bit 1 set write to a register,
@ -380,9 +379,9 @@ class ConcreteMachine:
case 0xfa28: case 0xfa2a: case 0xfa2c: case 0xfa2e:
case 0xfa30: case 0xfa32: case 0xfa34: case 0xfa36:
case 0xfa38: case 0xfa3a: case 0xfa3c: case 0xfa3e:
if(!cycle.data_select_active()) return delay;
if(!CPU::MC68000::Operation::data_select_active(operation)) return delay;
if(operation & Microcycle::Read) {
if(operation & CPU::MC68000::Operation::Read) {
cycle.set_value8_low(mfp_->read(int(address >> 1)));
} else {
mfp_->write(int(address >> 1), cycle.value8_low());
@ -392,11 +391,11 @@ class ConcreteMachine:
// ACIAs.
case 0xfc00: case 0xfc02: case 0xfc04: case 0xfc06: {
// Set VPA.
mc68000_.set_is_peripheral_address(!cycle.data_select_active());
if(!cycle.data_select_active()) return delay;
mc68000_.set_is_peripheral_address(!CPU::MC68000::Operation::data_select_active(operation));
if(!CPU::MC68000::Operation::data_select_active(operation)) return delay;
const auto acia_ = (address & 4) ? &midi_acia_ : &keyboard_acia_;
if(operation & Microcycle::Read) {
if(operation & CPU::MC68000::Operation::Read) {
cycle.set_value8_high((*acia_)->read(int(address >> 1)));
} else {
(*acia_)->write(int(address >> 1), cycle.value8_high());
@ -410,23 +409,23 @@ class ConcreteMachine:
//
// In both write cases, immediately reinstall the first eight bytes of RAM from ROM, so that any write to
// that area is in effect a no-op. This is cheaper than the conditionality of actually checking.
switch(operation & (Microcycle::SelectWord | Microcycle::SelectByte | Microcycle::Read)) {
switch(operation & (CPU::MC68000::Operation::SelectWord | CPU::MC68000::Operation::SelectByte | CPU::MC68000::Operation::Read)) {
default:
break;
case Microcycle::SelectWord | Microcycle::Read:
case CPU::MC68000::Operation::SelectWord | CPU::MC68000::Operation::Read:
cycle.value->w = *reinterpret_cast<uint16_t *>(&memory[address]);
break;
case Microcycle::SelectByte | Microcycle::Read:
case CPU::MC68000::Operation::SelectByte | CPU::MC68000::Operation::Read:
cycle.value->b = memory[address];
break;
case Microcycle::SelectWord:
case CPU::MC68000::Operation::SelectWord:
if(address >= video_range_.low_address && address < video_range_.high_address)
video_.flush();
*reinterpret_cast<uint16_t *>(&memory[address]) = cycle.value->w;
reinstall_rom_vector();
break;
case Microcycle::SelectByte:
case CPU::MC68000::Operation::SelectByte:
if(address >= video_range_.low_address && address < video_range_.high_address)
video_.flush();
memory[address] = cycle.value->b;

View File

@ -15,6 +15,66 @@
namespace CPU::MC68000 {
using OperationT = unsigned int;
namespace Operation {
/// Indicates that the address strobe and exactly one of the data strobes are active; you can determine
/// which by inspecting the low bit of the provided address. The RW line indicates a read.
static constexpr OperationT SelectByte = 1 << 0;
// Maintenance note: this is bit 0 to reduce the cost of getting a host-endian
// bytewise address. The assumption that it is bit 0 is also used for branchless
// selection in a few places. See implementation of host_endian_byte_address(),
// value8_high(), value8_low() and value16().
/// Indicates that the address and both data select strobes are active.
static constexpr OperationT SelectWord = 1 << 1;
/// If set, indicates a read. Otherwise, a write.
static constexpr OperationT Read = 1 << 2;
// Two-bit gap deliberately left here for PermitRead/Write below.
/// A NewAddress cycle is one in which the address strobe is initially low but becomes high;
/// this correlates to states 0 to 5 of a standard read/write cycle.
static constexpr OperationT NewAddress = 1 << 5;
/// A SameAddress cycle is one in which the address strobe is continuously asserted, but neither
/// of the data strobes are.
static constexpr OperationT SameAddress = 1 << 6;
/// A Reset cycle is one in which the RESET output is asserted.
static constexpr OperationT Reset = 1 << 7;
/// Contains the value of line FC0 if it is not implicit via InterruptAcknowledge.
static constexpr OperationT IsData = 1 << 8;
/// Contains the value of line FC1 if it is not implicit via InterruptAcknowledge.
static constexpr OperationT IsProgram = 1 << 9;
/// The interrupt acknowledge cycle is that during which the 68000 seeks to obtain the vector for
/// an interrupt it plans to observe. Noted on a real 68000 by all FCs being set to 1.
static constexpr OperationT InterruptAcknowledge = 1 << 10;
/// Represents the state of the 68000's valid memory address line — indicating whether this microcycle
/// is synchronised with the E clock to satisfy a valid peripheral address request.
static constexpr OperationT IsPeripheral = 1 << 11;
/// Provides the 68000's bus grant line — indicating whether a bus request has been acknowledged.
static constexpr OperationT BusGrant = 1 << 12;
/// An otherwise invalid combination; used as the operaiton template parameter to @c perform_bus_operation if
/// the operation wasn't knowable in advance and the receiver should decode dynamically using the microcycle's
/// .operation field.
static constexpr OperationT DecodeDynamically = NewAddress | SameAddress;
/*! @returns true if any data select line is active; @c false otherwise. */
constexpr bool data_select_active(OperationT operation) {
return bool(operation & (SelectWord | SelectByte | InterruptAcknowledge));
}
};
/*!
A microcycle is an atomic unit of 68000 bus activity it is a single item large enough
fully to specify a sequence of bus events that occur without any possible interruption.
@ -39,56 +99,7 @@ namespace CPU::MC68000 {
avoid the runtime cost of actual DTack emulation. But such as the bus allows.)
*/
struct Microcycle {
using OperationT = unsigned int;
/// Indicates that the address strobe and exactly one of the data strobes are active; you can determine
/// which by inspecting the low bit of the provided address. The RW line indicates a read.
static constexpr OperationT SelectByte = 1 << 0;
// Maintenance note: this is bit 0 to reduce the cost of getting a host-endian
// bytewise address. The assumption that it is bit 0 is also used for branchless
// selection in a few places. See implementation of host_endian_byte_address(),
// value8_high(), value8_low() and value16().
/// Indicates that the address and both data select strobes are active.
static constexpr OperationT SelectWord = 1 << 1;
/// If set, indicates a read. Otherwise, a write.
static constexpr OperationT Read = 1 << 2;
// Two-bit gap deliberately left here for PermitRead/Write below.
/// A NewAddress cycle is one in which the address strobe is initially low but becomes high;
/// this correlates to states 0 to 5 of a standard read/write cycle.
static constexpr OperationT NewAddress = 1 << 5;
/// A SameAddress cycle is one in which the address strobe is continuously asserted, but neither
/// of the data strobes are.
static constexpr OperationT SameAddress = 1 << 6;
/// A Reset cycle is one in which the RESET output is asserted.
static constexpr OperationT Reset = 1 << 7;
/// Contains the value of line FC0 if it is not implicit via InterruptAcknowledge.
static constexpr OperationT IsData = 1 << 8;
/// Contains the value of line FC1 if it is not implicit via InterruptAcknowledge.
static constexpr OperationT IsProgram = 1 << 9;
/// The interrupt acknowledge cycle is that during which the 68000 seeks to obtain the vector for
/// an interrupt it plans to observe. Noted on a real 68000 by all FCs being set to 1.
static constexpr OperationT InterruptAcknowledge = 1 << 10;
/// Represents the state of the 68000's valid memory address line — indicating whether this microcycle
/// is synchronised with the E clock to satisfy a valid peripheral address request.
static constexpr OperationT IsPeripheral = 1 << 11;
/// Provides the 68000's bus grant line — indicating whether a bus request has been acknowledged.
static constexpr OperationT BusGrant = 1 << 12;
/// An otherwise invalid combination; used as the operaiton template parameter to @c perform_bus_operation if
/// the operation wasn't knowable in advance and the receiver should decode dynamically using the microcycle's
/// .operation field.
static constexpr OperationT DecodeDynamically = NewAddress | SameAddress;
using OperationT = OperationT;
/// Contains a valid combination of the various static constexpr int flags, describing the operation
/// performed by this Microcycle.
@ -139,11 +150,6 @@ struct Microcycle {
// Various inspectors.
/*! @returns true if any data select line is active; @c false otherwise. */
forceinline bool data_select_active() const {
return bool(operation & (SelectWord | SelectByte | InterruptAcknowledge));
}
/*!
@returns 0 if this byte access wants the low part of a 16-bit word; 8 if it wants the high part,
i.e. take a word quantity and shift it right by this amount to get the quantity being
@ -184,14 +190,14 @@ struct Microcycle {
@returns non-zero if the 68000 LDS is asserted; zero otherwise.
*/
forceinline int lower_data_select() const {
return (operation & SelectByte & *address) | (operation & SelectWord);
return (operation & Operation::SelectByte & *address) | (operation & Operation::SelectWord);
}
/*!
@returns non-zero if the 68000 UDS is asserted; zero otherwise.
*/
forceinline int upper_data_select() const {
return (operation & SelectByte & ~*address) | (operation & SelectWord);
return (operation & Operation::SelectByte & ~*address) | (operation & Operation::SelectWord);
}
/*!
@ -228,7 +234,7 @@ struct Microcycle {
#if TARGET_RT_BIG_ENDIAN
return *address & 0xffffff;
#else
return (*address ^ (operation & SelectByte)) & 0xffffff;
return (*address ^ (operation & Operation::SelectByte)) & 0xffffff;
#endif
}
@ -239,7 +245,7 @@ struct Microcycle {
*/
forceinline uint16_t value16() const {
const uint16_t values[] = { value->w, uint16_t((value->b << 8) | value->b) };
return values[operation & SelectByte];
return values[operation & Operation::SelectByte];
}
/*!
@ -247,7 +253,7 @@ struct Microcycle {
*/
forceinline uint8_t value8_high() const {
const uint8_t values[] = { uint8_t(value->w >> 8), value->b};
return values[operation & SelectByte];
return values[operation & Operation::SelectByte];
}
/*!
@ -262,8 +268,8 @@ struct Microcycle {
currently being read. Assumes this is a read cycle.
*/
forceinline void set_value16(uint16_t v) const {
assert(operation & Microcycle::Read);
if(operation & Microcycle::SelectWord) {
assert(operation & Operation::Read);
if(operation & Operation::SelectWord) {
value->w = v;
} else {
value->b = uint8_t(v >> byte_shift());
@ -274,8 +280,8 @@ struct Microcycle {
Equivalent to set_value16((v << 8) | 0x00ff).
*/
forceinline void set_value8_high(uint8_t v) const {
assert(operation & Microcycle::Read);
if(operation & Microcycle::SelectWord) {
assert(operation & Operation::Read);
if(operation & Operation::SelectWord) {
value->w = uint16_t(0x00ff | (v << 8));
} else {
value->b = uint8_t(v | byte_mask());
@ -286,8 +292,8 @@ struct Microcycle {
Equivalent to set_value16(v | 0xff00).
*/
forceinline void set_value8_low(uint8_t v) const {
assert(operation & Microcycle::Read);
if(operation & Microcycle::SelectWord) {
assert(operation & Operation::Read);
if(operation & Operation::SelectWord) {
value->w = 0xff00 | v;
} else {
value->b = uint8_t(v | untouched_byte_mask());
@ -309,26 +315,26 @@ struct Microcycle {
* if this is a write, does the converse of a read.
*/
forceinline void apply(uint8_t *target, OperationT read_write_mask = PermitRead | PermitWrite) const {
assert( (operation & (SelectWord | SelectByte)) != (SelectWord | SelectByte));
assert( (operation & (Operation::SelectWord | Operation::SelectByte)) != (Operation::SelectWord | Operation::SelectByte));
switch((operation | read_write_mask) & (SelectWord | SelectByte | Read | PermitRead | PermitWrite)) {
switch((operation | read_write_mask) & (Operation::SelectWord | Operation::SelectByte | Operation::Read | PermitRead | PermitWrite)) {
default:
break;
case SelectWord | Read | PermitRead:
case SelectWord | Read | PermitRead | PermitWrite:
case Operation::SelectWord | Operation::Read | PermitRead:
case Operation::SelectWord | Operation::Read | PermitRead | PermitWrite:
value->w = *reinterpret_cast<uint16_t *>(target);
break;
case SelectByte | Read | PermitRead:
case SelectByte | Read | PermitRead | PermitWrite:
case Operation::SelectByte | Operation::Read | PermitRead:
case Operation::SelectByte | Operation::Read | PermitRead | PermitWrite:
value->b = *target;
break;
case SelectWord | PermitWrite:
case SelectWord | PermitWrite | PermitRead:
case Operation::SelectWord | PermitWrite:
case Operation::SelectWord | PermitWrite | PermitRead:
*reinterpret_cast<uint16_t *>(target) = value->w;
break;
case SelectByte | PermitWrite:
case SelectByte | PermitWrite | PermitRead:
case Operation::SelectByte | PermitWrite:
case Operation::SelectByte | PermitWrite | PermitRead:
*target = value->b;
break;
}

View File

@ -342,8 +342,8 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
// Sets up the next data access size and read flags.
#define SetupDataAccess(read_flag, select_flag) \
access_announce.operation = Microcycle::NewAddress | Microcycle::IsData | (read_flag); \
access.operation = Microcycle::SameAddress | Microcycle::IsData | (read_flag) | (select_flag);
access_announce.operation = Operation::NewAddress | Operation::IsData | (read_flag); \
access.operation = Operation::SameAddress | Operation::IsData | (read_flag) | (select_flag);
// Sets the address source for the next data access.
#define SetDataAddress(addr) \
@ -351,11 +351,11 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
// Performs the access established by SetupDataAccess into val.
#define Access(val) \
AccessPair(val, access_announce, Microcycle::DecodeDynamically, access, Microcycle::DecodeDynamically)
AccessPair(val, access_announce, Operation::DecodeDynamically, access, Operation::DecodeDynamically)
// Performs the access established by SetupDataAccess into val.
#define AccessOp(val, read_flag, select_flag) \
AccessPair(val, access_announce, Microcycle::NewAddress | Microcycle::IsData | (read_flag), access, Microcycle::SameAddress | Microcycle::IsData | (read_flag) | (select_flag))
AccessPair(val, access_announce, Operation::NewAddress | Operation::IsData | (read_flag), access, Operation::SameAddress | Operation::IsData | (read_flag) | (select_flag))
// Reads the program (i.e. non-data) word from addr into val.
#define ReadProgramWord(val) \
@ -424,20 +424,20 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
should_trace_ = 0;
did_update_status();
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord);
SetupDataAccess(Operation::Read, Operation::SelectWord);
SetDataAddress(temporary_address_.l);
temporary_address_.l = 0;
AccessOp(registers_[15].high, Microcycle::Read, Microcycle::SelectWord); // nF
AccessOp(registers_[15].high, Operation::Read, Operation::SelectWord); // nF
temporary_address_.l += 2;
AccessOp(registers_[15].low, Microcycle::Read, Microcycle::SelectWord); // nf
AccessOp(registers_[15].low, Operation::Read, Operation::SelectWord); // nf
temporary_address_.l += 2;
AccessOp(program_counter_.high, Microcycle::Read, Microcycle::SelectWord); // nV
AccessOp(program_counter_.high, Operation::Read, Operation::SelectWord); // nV
temporary_address_.l += 2;
AccessOp(program_counter_.low, Microcycle::Read, Microcycle::SelectWord); // nv
AccessOp(program_counter_.low, Operation::Read, Operation::SelectWord); // nv
Prefetch(); // np
IdleBus(1); // n
@ -451,30 +451,30 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
should_trace_ = 0;
did_update_status();
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
SetDataAddress(registers_[15].l);
// Push status and current program counter.
// Write order is wacky here, but I think it's correct.
registers_[15].l -= 2;
AccessOp(instruction_address_.low, 0, Microcycle::SelectWord); // ns
AccessOp(instruction_address_.low, 0, Operation::SelectWord); // ns
registers_[15].l -= 4;
AccessOp(captured_status_, 0, Microcycle::SelectWord); // ns
AccessOp(captured_status_, 0, Operation::SelectWord); // ns
registers_[15].l += 2;
AccessOp(instruction_address_.high, 0, Microcycle::SelectWord); // nS
AccessOp(instruction_address_.high, 0, Operation::SelectWord); // nS
registers_[15].l -= 2;
// Grab new program counter.
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord);
SetupDataAccess(Operation::Read, Operation::SelectWord);
SetDataAddress(temporary_address_.l);
temporary_address_.l = uint32_t(exception_vector_ << 2);
AccessOp(program_counter_.high, Microcycle::Read, Microcycle::SelectWord); // nV
AccessOp(program_counter_.high, Operation::Read, Operation::SelectWord); // nV
temporary_address_.l += 2;
AccessOp(program_counter_.low, Microcycle::Read, Microcycle::SelectWord); // nv
AccessOp(program_counter_.low, Operation::Read, Operation::SelectWord); // nv
// Populate the prefetch queue.
Prefetch(); // np
@ -523,24 +523,24 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
should_trace_ = 0;
did_update_status();
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
SetDataAddress(registers_[15].l);
// Guess: the written program counter is adjusted to discount the prefetch queue.
// COMPLETE GUESS.
temporary_address_.l = program_counter_.l - 4;
registers_[15].l -= 2;
AccessOp(temporary_address_.low, 0, Microcycle::SelectWord); // ns [pc.l]
AccessOp(temporary_address_.low, 0, Operation::SelectWord); // ns [pc.l]
registers_[15].l -= 4;
AccessOp(captured_status_, 0, Microcycle::SelectWord); // ns [sr]
AccessOp(captured_status_, 0, Operation::SelectWord); // ns [sr]
registers_[15].l += 2;
AccessOp(temporary_address_.high, 0, Microcycle::SelectWord); // nS [pc.h]
AccessOp(temporary_address_.high, 0, Operation::SelectWord); // nS [pc.h]
registers_[15].l -= 4;
temporary_value_.w = opcode_;
AccessOp(temporary_value_.low, 0, Microcycle::SelectWord); // ns [instruction register]
AccessOp(temporary_value_.low, 0, Operation::SelectWord); // ns [instruction register]
// Construct the function code; which is:
//
@ -554,31 +554,31 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
// captured status register I guess maybe it is just duplicative.
temporary_value_.w =
(temporary_value_.w & ~31) |
((bus_error_.operation & Microcycle::Read) ? 0x10 : 0x00) |
((bus_error_.operation & Microcycle::IsProgram) ? 0x08 : 0x00) |
((bus_error_.operation & Microcycle::IsProgram) ? 0x02 : 0x01) |
((bus_error_.operation & Operation::Read) ? 0x10 : 0x00) |
((bus_error_.operation & Operation::IsProgram) ? 0x08 : 0x00) |
((bus_error_.operation & Operation::IsProgram) ? 0x02 : 0x01) |
((captured_status_.w & InstructionSet::M68k::ConditionCode::Supervisor) ? 0x04 : 0x00);
temporary_address_.l = *bus_error_.address;
registers_[15].l -= 2;
AccessOp(temporary_address_.low, 0, Microcycle::SelectWord); // ns [error address.l]
AccessOp(temporary_address_.low, 0, Operation::SelectWord); // ns [error address.l]
registers_[15].l -= 4;
AccessOp(temporary_value_.low, 0, Microcycle::SelectWord); // ns [function code]
AccessOp(temporary_value_.low, 0, Operation::SelectWord); // ns [function code]
registers_[15].l += 2;
AccessOp(temporary_address_.high, 0, Microcycle::SelectWord); // nS [error address.h]
AccessOp(temporary_address_.high, 0, Operation::SelectWord); // nS [error address.h]
registers_[15].l -= 2;
// Grab new program counter.
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord);
SetupDataAccess(Operation::Read, Operation::SelectWord);
SetDataAddress(temporary_address_.l);
temporary_address_.l = uint32_t(exception_vector_ << 2);
AccessOp(program_counter_.high, Microcycle::Read, Microcycle::SelectWord); // nV
AccessOp(program_counter_.high, Operation::Read, Operation::SelectWord); // nV
temporary_address_.l += 2;
AccessOp(program_counter_.low, Microcycle::Read, Microcycle::SelectWord); // nv
AccessOp(program_counter_.low, Operation::Read, Operation::SelectWord); // nv
// Populate the prefetch queue.
Prefetch(); // np
@ -597,12 +597,12 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
did_update_status();
// Prepare for stack activity.
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
SetDataAddress(registers_[15].l);
// Push low part of program counter.
registers_[15].l -= 2;
AccessOp(instruction_address_.low, 0, Microcycle::SelectWord); // ns
AccessOp(instruction_address_.low, 0, Operation::SelectWord); // ns
// Do the interrupt cycle, to obtain a vector.
temporary_address_.l = 0xffff'fff1 | uint32_t(captured_interrupt_level_ << 1);
@ -628,21 +628,21 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
SetDataAddress(registers_[15].l);
registers_[15].l -= 4;
AccessOp(captured_status_, 0, Microcycle::SelectWord); // ns
AccessOp(captured_status_, 0, Operation::SelectWord); // ns
registers_[15].l += 2;
AccessOp(instruction_address_.high, 0, Microcycle::SelectWord); // nS
AccessOp(instruction_address_.high, 0, Operation::SelectWord); // nS
registers_[15].l -= 2;
// Grab new program counter.
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord);
SetupDataAccess(Operation::Read, Operation::SelectWord);
SetDataAddress(temporary_address_.l);
temporary_address_.l = uint32_t(temporary_value_.b << 2);
AccessOp(program_counter_.high, Microcycle::Read, Microcycle::SelectWord); // nV
AccessOp(program_counter_.high, Operation::Read, Operation::SelectWord); // nV
temporary_address_.l += 2;
AccessOp(program_counter_.low, Microcycle::Read, Microcycle::SelectWord); // nv
AccessOp(program_counter_.low, Operation::Read, Operation::SelectWord); // nv
// Populate the prefetch queue.
Prefetch(); // np
@ -707,13 +707,13 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
y; \
\
if constexpr (InstructionSet::M68k::operand_size<InstructionSet::M68k::Operation::x>() == InstructionSet::M68k::DataSize::LongWord) { \
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord); \
SetupDataAccess(Operation::Read, Operation::SelectWord); \
MoveToStateSpecific(FetchOperand_l); \
} else { \
if constexpr (InstructionSet::M68k::operand_size<InstructionSet::M68k::Operation::x>() == InstructionSet::M68k::DataSize::Byte) { \
SetupDataAccess(Microcycle::Read, Microcycle::SelectByte); \
SetupDataAccess(Operation::Read, Operation::SelectByte); \
} else { \
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord); \
SetupDataAccess(Operation::Read, Operation::SelectWord); \
} \
MoveToStateSpecific(FetchOperand_bw); \
}
@ -823,10 +823,10 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
CASE(ABCD)
if(instruction_.mode(0) == Mode::DataRegisterDirect) {
perform_state_ = Perform_np_n;
SetupDataAccess(Microcycle::Read, Microcycle::SelectByte);
SetupDataAccess(Operation::Read, Operation::SelectByte);
MoveToStateSpecific(FetchOperand_bw);
} else {
select_flag_ = Microcycle::SelectByte;
select_flag_ = Operation::SelectByte;
MoveToStateSpecific(TwoOp_Predec_bw);
}
@ -876,7 +876,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
if(instruction_.mode(0) == Mode::DataRegisterDirect) {
perform_state_ = Perform_np;
} else {
select_flag_ = Microcycle::SelectByte;
select_flag_ = Operation::SelectByte;
MoveToStateSpecific(TwoOp_Predec_bw);
}
})
@ -884,7 +884,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
if(instruction_.mode(0) == Mode::DataRegisterDirect) {
perform_state_ = Perform_np;
} else {
select_flag_ = Microcycle::SelectWord;
select_flag_ = Operation::SelectWord;
MoveToStateSpecific(TwoOp_Predec_bw);
}
})
@ -1199,7 +1199,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
effective_address_[1] = registers_[8 + instruction_.reg(1)];
SetDataAddress(effective_address_[1].l);
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
Access(operand_[next_operand_].high); // nW
effective_address_[1].l += 2;
@ -1258,7 +1258,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
BeginStateMode(MOVE_l, AddressRegisterIndirectWithPostincrement):
SetDataAddress(registers_[8 + instruction_.reg(next_operand_)].l);
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
Access(operand_[next_operand_].high); // nW
registers_[8 + instruction_.reg(next_operand_)].l += 2;
@ -1311,7 +1311,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
BeginStateMode(MOVE_l, AddressRegisterIndirectWithPredecrement):
SetDataAddress(registers_[8 + instruction_.reg(1)].l);
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
Prefetch(); // np
@ -1374,7 +1374,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
uint32_t(int16_t(prefetch_.w));
SetDataAddress(effective_address_[1].l);
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
Prefetch(); // np
Access(operand_[next_operand_].high); // nW
@ -1450,7 +1450,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
uint32_t(int16_t(prefetch_.w));
SetDataAddress(effective_address_[1].l);
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
Prefetch(); // np
Access(operand_[next_operand_].high); // nW
@ -1529,7 +1529,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
effective_address_[1].l = d8Xn(registers_[8 + instruction_.reg(1)].l);
SetDataAddress(effective_address_[1].l);
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
IdleBus(1); // n
Prefetch(); // np
@ -1607,7 +1607,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
effective_address_[1].l = d8Xn(program_counter_.l - 2);
SetDataAddress(effective_address_[1].l);
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
IdleBus(1); // n
Prefetch(); // np
@ -1685,7 +1685,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
effective_address_[1].l = uint32_t(int16_t(prefetch_.w));
SetDataAddress(effective_address_[1].l);
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
Prefetch(); // np
Access(operand_[next_operand_].high); // nW
@ -1767,7 +1767,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
effective_address_[1].l = prefetch_.l;
SetDataAddress(effective_address_[1].l);
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
switch(instruction_.mode(0)) {
case Mode::AddressRegisterDirect:
@ -1867,15 +1867,15 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
BeginState(StoreOperand):
switch(instruction_.operand_size()) {
case InstructionSet::M68k::DataSize::LongWord:
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
MoveToStateSpecific(StoreOperand_l);
case InstructionSet::M68k::DataSize::Word:
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
MoveToStateSpecific(StoreOperand_bw);
case InstructionSet::M68k::DataSize::Byte:
SetupDataAccess(0, Microcycle::SelectByte);
SetupDataAccess(0, Operation::SelectByte);
MoveToStateSpecific(StoreOperand_bw);
}
@ -1919,7 +1919,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
MoveToNextOperand(StoreOperand_l);
}
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
SetDataAddress(effective_address_[next_operand_].l);
Access(operand_[next_operand_].low); // nw
@ -1995,7 +1995,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
BeginState(TwoOp_Predec_bw):
IdleBus(1); // n
SetupDataAccess(Microcycle::Read, select_flag_);
SetupDataAccess(Operation::Read, select_flag_);
SetDataAddress(registers_[8 + instruction_.reg(0)].l);
registers_[8 + instruction_.reg(0)].l -= address_increments[int(instruction_.operand_size())][instruction_.reg(0)];
@ -2016,7 +2016,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
BeginState(TwoOp_Predec_l):
IdleBus(1); // n
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord);
SetupDataAccess(Operation::Read, Operation::SelectWord);
SetDataAddress(registers_[8 + instruction_.reg(0)].l);
registers_[8 + instruction_.reg(0)].l -= 2;
@ -2034,7 +2034,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
PerformDynamic();
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
registers_[8 + instruction_.reg(1)].l += 2;
Access(operand_[1].low); // nw
@ -2160,7 +2160,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
#define Push(x) \
SetupDataAccess(0, Microcycle::SelectWord); \
SetupDataAccess(0, Operation::SelectWord); \
SetDataAddress(registers_[15].l); \
registers_[15].l -= 4; \
Access(x.high); \
@ -2169,7 +2169,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
registers_[15].l -= 2;
#define Pop(x) \
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord); \
SetupDataAccess(Operation::Read, Operation::SelectWord); \
SetDataAddress(registers_[15].l); \
Access(x.high); \
registers_[15].l += 2; \
@ -2246,7 +2246,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
BeginState(MOVEPtoM_l):
temporary_address_.l = registers_[8 + instruction_.reg(1)].l + uint32_t(int16_t(prefetch_.w));
SetDataAddress(temporary_address_.l);
SetupDataAccess(0, Microcycle::SelectByte);
SetupDataAccess(0, Operation::SelectByte);
Prefetch(); // np
@ -2271,7 +2271,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
BeginState(MOVEPtoM_w):
temporary_address_.l = registers_[8 + instruction_.reg(1)].l + uint32_t(int16_t(prefetch_.w));
SetDataAddress(temporary_address_.l);
SetupDataAccess(0, Microcycle::SelectByte);
SetupDataAccess(0, Operation::SelectByte);
Prefetch(); // np
@ -2288,7 +2288,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
BeginState(MOVEPtoR_l):
temporary_address_.l = registers_[8 + instruction_.reg(0)].l + uint32_t(int16_t(prefetch_.w));
SetDataAddress(temporary_address_.l);
SetupDataAccess(Microcycle::Read, Microcycle::SelectByte);
SetupDataAccess(Operation::Read, Operation::SelectByte);
Prefetch(); // np
@ -2313,7 +2313,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
BeginState(MOVEPtoR_w):
temporary_address_.l = registers_[8 + instruction_.reg(0)].l + uint32_t(int16_t(prefetch_.w));
SetDataAddress(temporary_address_.l);
SetupDataAccess(Microcycle::Read, Microcycle::SelectByte);
SetupDataAccess(Operation::Read, Operation::SelectByte);
Prefetch(); // np
@ -2353,7 +2353,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
register_index_ = 0;
SetDataAddress(effective_address_[1].l);
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord);
SetupDataAccess(Operation::Read, Operation::SelectWord);
switch(instruction_.mode(1)) {
case Mode::AddressRegisterIndirectWithIndex8bitDisplacement:
@ -2426,7 +2426,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
BeginState(MOVEMtoM):
next_operand_ = 1;
SetDataAddress(effective_address_[1].l);
SetupDataAccess(0, Microcycle::SelectWord);
SetupDataAccess(0, Operation::SelectWord);
register_index_ = 0;
post_ea_state_ =
@ -2670,7 +2670,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
// RTR, RTS, RTE
//
BeginState(RTS):
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord);
SetupDataAccess(Operation::Read, Operation::SelectWord);
SetDataAddress(registers_[15].l);
Access(program_counter_.high);
@ -2688,7 +2688,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
// being the converse of the write order.
BeginState(RTE):
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord);
SetupDataAccess(Operation::Read, Operation::SelectWord);
SetDataAddress(registers_[15].l);
registers_[15].l += 2;
@ -2709,7 +2709,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
MoveToStateSpecific(Decode);
BeginState(RTR):
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord);
SetupDataAccess(Operation::Read, Operation::SelectWord);
SetDataAddress(registers_[15].l);
registers_[15].l += 2;

View File

@ -185,28 +185,28 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
// Read a program word. All accesses via the program counter are word sized.
static constexpr Microcycle::OperationT
ReadProgramAnnounceOperation = Microcycle::Read | Microcycle::NewAddress | Microcycle::IsProgram;
ReadProgramAnnounceOperation = Operation::Read | Operation::NewAddress | Operation::IsProgram;
static constexpr Microcycle::OperationT
ReadProgramOperation = Microcycle::Read | Microcycle::SameAddress | Microcycle::SelectWord | Microcycle::IsProgram;
ReadProgramOperation = Operation::Read | Operation::SameAddress | Operation::SelectWord | Operation::IsProgram;
Microcycle read_program_announce { ReadProgramAnnounceOperation };
Microcycle read_program { ReadProgramOperation };
// Read a data word or byte.
Microcycle access_announce {
Microcycle::Read | Microcycle::NewAddress | Microcycle::IsData
Operation::Read | Operation::NewAddress | Operation::IsData
};
Microcycle access {
Microcycle::Read | Microcycle::SameAddress | Microcycle::SelectWord | Microcycle::IsData
Operation::Read | Operation::SameAddress | Operation::SelectWord | Operation::IsData
};
// TAS.
static constexpr Microcycle::OperationT
TASOperations[5] = {
Microcycle::Read | Microcycle::NewAddress | Microcycle::IsData,
Microcycle::Read | Microcycle::SameAddress | Microcycle::IsData | Microcycle::SelectByte,
Microcycle::SameAddress,
Microcycle::SameAddress | Microcycle::IsData,
Microcycle::SameAddress | Microcycle::IsData | Microcycle::SelectByte,
Operation::Read | Operation::NewAddress | Operation::IsData,
Operation::Read | Operation::SameAddress | Operation::IsData | Operation::SelectByte,
Operation::SameAddress,
Operation::SameAddress | Operation::IsData,
Operation::SameAddress | Operation::IsData | Operation::SelectByte,
};
Microcycle tas_cycles[5] = {
{ TASOperations[0] },
@ -217,14 +217,14 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
};
// Reset.
static constexpr Microcycle::OperationT ResetOperation = Microcycle::Reset;
static constexpr Microcycle::OperationT ResetOperation = CPU::MC68000::Operation::Reset;
Microcycle reset_cycle { ResetOperation, HalfCycles(248) };
// Interrupt acknowledge.
static constexpr Microcycle::OperationT
InterruptCycleOperations[2] = {
Microcycle::InterruptAcknowledge | Microcycle::Read | Microcycle::NewAddress,
Microcycle::InterruptAcknowledge | Microcycle::Read | Microcycle::SameAddress | Microcycle::SelectByte
Operation::InterruptAcknowledge | Operation::Read | Operation::NewAddress,
Operation::InterruptAcknowledge | Operation::Read | Operation::SameAddress | Operation::SelectByte
};
Microcycle interrupt_cycles[2] = {
{ InterruptCycleOperations[0] },