diff --git a/Machines/Amiga/Amiga.cpp b/Machines/Amiga/Amiga.cpp index 775e89695..cf85dc1e1 100644 --- a/Machines/Amiga/Amiga.cpp +++ b/Machines/Amiga/Amiga.cpp @@ -82,11 +82,11 @@ class ConcreteMachine: // MARK: - MC68000::BusHandler. using Microcycle = CPU::MC68000::Microcycle; template 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()); } } } diff --git a/Machines/Amiga/Chipset.cpp b/Machines/Amiga/Chipset.cpp index 534486e9d..70821a7ca 100644 --- a/Machines/Amiga/Chipset.cpp +++ b/Machines/Amiga/Chipset.cpp @@ -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()); diff --git a/Machines/Amiga/MemoryMap.hpp b/Machines/Amiga/MemoryMap.hpp index 9e6c8fdf1..575aa02af 100644 --- a/Machines/Amiga/MemoryMap.hpp +++ b/Machines/Amiga/MemoryMap.hpp @@ -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"; diff --git a/Machines/Apple/Macintosh/Macintosh.cpp b/Machines/Apple/Macintosh/Macintosh.cpp index 24d6e9623..102349c92 100644 --- a/Machines/Apple/Macintosh/Macintosh.cpp +++ b/Machines/Apple/Macintosh/Macintosh.cpp @@ -193,13 +193,13 @@ template class ConcreteMachin using Microcycle = CPU::MC68000::Microcycle; template 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 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 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 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 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 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 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 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 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 class ConcreteMachin template 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); } diff --git a/Machines/Atari/ST/AtariST.cpp b/Machines/Atari/ST/AtariST.cpp index 935d26b63..9f093b51a 100644 --- a/Machines/Atari/ST/AtariST.cpp +++ b/Machines/Atari/ST/AtariST.cpp @@ -178,7 +178,7 @@ class ConcreteMachine: // MARK: MC68000::BusHandler using Microcycle = CPU::MC68000::Microcycle; template 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(&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(&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; diff --git a/Processors/68000/68000.hpp b/Processors/68000/68000.hpp index ba6732710..05b3c1755 100644 --- a/Processors/68000/68000.hpp +++ b/Processors/68000/68000.hpp @@ -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(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(target) = value->w; break; - case SelectByte | PermitWrite: - case SelectByte | PermitWrite | PermitRead: + case Operation::SelectByte | PermitWrite: + case Operation::SelectByte | PermitWrite | PermitRead: *target = value->b; break; } diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index 6c217d533..6860094eb 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -342,8 +342,8 @@ void Processor() == 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::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