From d01c3061874ac78e279738eb79f28c3328ca5de6 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 3 Jan 2024 11:40:04 -0500 Subject: [PATCH 1/2] Pull `PagingType::Main` to top, eliminate macros. --- Machines/Apple/AppleIIgs/MemoryMap.hpp | 238 ++++++++++++------------- 1 file changed, 116 insertions(+), 122 deletions(-) diff --git a/Machines/Apple/AppleIIgs/MemoryMap.hpp b/Machines/Apple/AppleIIgs/MemoryMap.hpp index 20f3e4d3a..6db80ad2e 100644 --- a/Machines/Apple/AppleIIgs/MemoryMap.hpp +++ b/Machines/Apple/AppleIIgs/MemoryMap.hpp @@ -248,13 +248,124 @@ class MemoryMap { uint8_t speed_register_ = 0x00; // MARK: - Memory banking. - -#define assert_is_region(start, end) \ - assert(region_map[start] == region_map[start-1]+1); \ - assert(region_map[end-1] == region_map[start]); \ - assert(region_map[end] == region_map[end-1]+1); + void assert_is_region(uint8_t start, uint8_t end) { + assert(region_map[start] == region_map[start-1]+1); + assert(region_map[end-1] == region_map[start]); + assert(region_map[end] == region_map[end-1]+1); + } template void set_paging() { + // Establish whether main or auxiliary RAM + // is exposed in bank $00 for a bunch of regions. + if constexpr (type & PagingType::Main) { + const auto set = [&](std::size_t page, const auto &flags) { + auto ®ion = regions[region_map[page]]; + region.read = flags.read ? &ram_base[0x01'0000] : ram_base; + region.write = flags.write ? &ram_base[0x01'0000] : ram_base; + }; + const auto state = auxiliary_switches_.main_state(); + + // Base: $0200–$03FF. + set(0x02, state.base); + assert_is_region(0x02, 0x04); + + // Region $0400–$07ff. + set(0x04, state.region_04_08); + assert_is_region(0x04, 0x08); + + // Base: $0800–$1FFF. + set(0x08, state.base); + assert_is_region(0x08, 0x20); + + // Region $2000–$3FFF. + set(0x20, state.region_20_40); + assert_is_region(0x20, 0x40); + + // Base: $4000–$BFFF. + set(0x40, state.base); + assert_is_region(0x40, 0xc0); + } + + // Update whether base or auxiliary RAM is visible in: (i) the zero + // and stack pages; and (ii) anywhere that the language card is exposing RAM instead of ROM. + if constexpr (bool(type & PagingType::ZeroPage)) { + // Affects bank $00 only, and should be a single region. + auto ®ion = regions[region_map[0]]; + region.read = region.write = auxiliary_switches_.zero_state() ? &ram_base[0x01'0000] : ram_base; + assert(region_map[0x0000] == region_map[0x0001]); + assert(region_map[0x0001]+1 == region_map[0x0002]); + } + + // Establish whether ROM or card switches are exposed in the distinct + // regions C100–C2FF, C300–C3FF, C400–C7FF and C800–CFFF. + // + // On the IIgs it intersects with the current shadow register. + if constexpr (bool(type & (PagingType::CardArea | PagingType::Main))) { + const bool inhibit_banks0001 = shadow_register_ & 0x40; + const auto state = auxiliary_switches_.card_state(); + + auto apply = [&state, this](uint32_t bank_base) { + auto &c0_region = regions[region_map[bank_base | 0xc0]]; + auto &c1_region = regions[region_map[bank_base | 0xc1]]; + auto &c3_region = regions[region_map[bank_base | 0xc3]]; + auto &c4_region = regions[region_map[bank_base | 0xc4]]; + auto &c8_region = regions[region_map[bank_base | 0xc8]]; + + const uint8_t *const rom = ®ions[region_map[0xffd0]].read[0xffc100] - ((bank_base << 8) + 0xc100); + + // This is applied dynamically as it may be added or lost in banks $00 and $01. + c0_region.flags |= Region::IsIO; + + const auto apply_region = [&](bool flag, auto ®ion) { + region.write = nullptr; + if(flag) { + region.read = rom; + region.flags &= ~Region::IsIO; + } else { + region.flags |= Region::IsIO; + } + }; + + apply_region(state.region_C1_C3, c1_region); + apply_region(state.region_C3, c3_region); + apply_region(state.region_C4_C8, c4_region); + apply_region(state.region_C8_D0, c8_region); + + // Sanity checks. + assert(region_map[bank_base | 0xc1] == region_map[bank_base | 0xc0]+1); + assert(region_map[bank_base | 0xc2] == region_map[bank_base | 0xc1]); + assert(region_map[bank_base | 0xc3] == region_map[bank_base | 0xc2]+1); + assert(region_map[bank_base | 0xc4] == region_map[bank_base | 0xc3]+1); + assert(region_map[bank_base | 0xc7] == region_map[bank_base | 0xc4]); + assert(region_map[bank_base | 0xc8] == region_map[bank_base | 0xc7]+1); + assert(region_map[bank_base | 0xcf] == region_map[bank_base | 0xc8]); + assert(region_map[bank_base | 0xd0] == region_map[bank_base | 0xcf]+1); + }; + + if(inhibit_banks0001) { + // Set no IO in the Cx00 range for banks $00 and $01, just + // regular RAM (or possibly auxiliary). + const auto auxiliary_state = auxiliary_switches_.main_state(); + for(uint8_t region = region_map[0x00c0]; region < region_map[0x00d0]; region++) { + regions[region].read = auxiliary_state.base.read ? &ram_base[0x01'0000] : ram_base; + regions[region].write = auxiliary_state.base.write ? &ram_base[0x01'0000] : ram_base; + regions[region].flags &= ~Region::IsIO; + } + for(uint8_t region = region_map[0x01c0]; region < region_map[0x01d0]; region++) { + regions[region].read = regions[region].write = ram_base; + regions[region].flags &= ~Region::IsIO; + } + } else { + // Obey the card state for banks $00 and $01. + apply(0x0000); + apply(0x0100); + } + + // Obey the card state for banks $e0 and $e1. + apply(0xe000); + apply(0xe100); + } + // Update the region from // $D000 onwards as per the state of the language card flags — there may // end up being ROM or RAM (or auxiliary RAM), and the first 4kb of it @@ -314,121 +425,6 @@ class MemoryMap { apply(0xe000, e0_ram); apply(0xe100, e0_ram); } - - // Establish whether main or auxiliary RAM - // is exposed in bank $00 for a bunch of regions. - if constexpr (type & PagingType::Main) { - const auto state = auxiliary_switches_.main_state(); - -#define set(page, flags) {\ - auto ®ion = regions[region_map[page]]; \ - region.read = flags.read ? &ram_base[0x01'0000] : ram_base; \ - region.write = flags.write ? &ram_base[0x01'0000] : ram_base; \ - } - - // Base: $0200–$03FF. - set(0x02, state.base); - assert_is_region(0x02, 0x04); - - // Region $0400–$07ff. - set(0x04, state.region_04_08); - assert_is_region(0x04, 0x08); - - // Base: $0800–$1FFF. - set(0x08, state.base); - assert_is_region(0x08, 0x20); - - // Region $2000–$3FFF. - set(0x20, state.region_20_40); - assert_is_region(0x20, 0x40); - - // Base: $4000–$BFFF. - set(0x40, state.base); - assert_is_region(0x40, 0xc0); - -#undef set - } - - // Update whether base or auxiliary RAM is visible in: (i) the zero - // and stack pages; and (ii) anywhere that the language card is exposing RAM instead of ROM. - if constexpr (bool(type & PagingType::ZeroPage)) { - // Affects bank $00 only, and should be a single region. - auto ®ion = regions[region_map[0]]; - region.read = region.write = auxiliary_switches_.zero_state() ? &ram_base[0x01'0000] : ram_base; - assert(region_map[0x0000] == region_map[0x0001]); - assert(region_map[0x0001]+1 == region_map[0x0002]); - } - - // Establish whether ROM or card switches are exposed in the distinct - // regions C100–C2FF, C300–C3FF, C400–C7FF and C800–CFFF. - // - // On the IIgs it intersects with the current shadow register. - if constexpr (bool(type & (PagingType::CardArea | PagingType::Main))) { - const bool inhibit_banks0001 = shadow_register_ & 0x40; - const auto state = auxiliary_switches_.card_state(); - - auto apply = [&state, this](uint32_t bank_base) { - auto &c0_region = regions[region_map[bank_base | 0xc0]]; - auto &c1_region = regions[region_map[bank_base | 0xc1]]; - auto &c3_region = regions[region_map[bank_base | 0xc3]]; - auto &c4_region = regions[region_map[bank_base | 0xc4]]; - auto &c8_region = regions[region_map[bank_base | 0xc8]]; - - const uint8_t *const rom = ®ions[region_map[0xffd0]].read[0xffc100] - ((bank_base << 8) + 0xc100); - - // This is applied dynamically as it may be added or lost in banks $00 and $01. - c0_region.flags |= Region::IsIO; - -#define apply_region(flag, region) \ - region.write = nullptr; \ - if(flag) { \ - region.read = rom; \ - region.flags &= ~Region::IsIO; \ - } else { \ - region.flags |= Region::IsIO; \ - } - - apply_region(state.region_C1_C3, c1_region); - apply_region(state.region_C3, c3_region); - apply_region(state.region_C4_C8, c4_region); - apply_region(state.region_C8_D0, c8_region); - -#undef apply_region - - // Sanity checks. - assert(region_map[bank_base | 0xc1] == region_map[bank_base | 0xc0]+1); - assert(region_map[bank_base | 0xc2] == region_map[bank_base | 0xc1]); - assert(region_map[bank_base | 0xc3] == region_map[bank_base | 0xc2]+1); - assert(region_map[bank_base | 0xc4] == region_map[bank_base | 0xc3]+1); - assert(region_map[bank_base | 0xc7] == region_map[bank_base | 0xc4]); - assert(region_map[bank_base | 0xc8] == region_map[bank_base | 0xc7]+1); - assert(region_map[bank_base | 0xcf] == region_map[bank_base | 0xc8]); - assert(region_map[bank_base | 0xd0] == region_map[bank_base | 0xcf]+1); - }; - - if(inhibit_banks0001) { - // Set no IO in the Cx00 range for banks $00 and $01, just - // regular RAM (or possibly auxiliary). - const auto auxiliary_state = auxiliary_switches_.main_state(); - for(uint8_t region = region_map[0x00c0]; region < region_map[0x00d0]; region++) { - regions[region].read = auxiliary_state.base.read ? &ram_base[0x01'0000] : ram_base; - regions[region].write = auxiliary_state.base.write ? &ram_base[0x01'0000] : ram_base; - regions[region].flags &= ~Region::IsIO; - } - for(uint8_t region = region_map[0x01c0]; region < region_map[0x01d0]; region++) { - regions[region].read = regions[region].write = ram_base; - regions[region].flags &= ~Region::IsIO; - } - } else { - // Obey the card state for banks $00 and $01. - apply(0x0000); - apply(0x0100); - } - - // Obey the card state for banks $e0 and $e1. - apply(0xe000); - apply(0xe100); - } } // IIgs specific: sets or resets the ::IsShadowed flag across affected banks as @@ -563,8 +559,6 @@ class MemoryMap { } } -#undef assert_is_region - private: // Various precomputed bitsets describing key regions; std::bitset doesn't support constexpr instantiation // beyond the first 64 bits at the time of writing, alas, so these are generated at runtime. From bbaaa520c84bde2f804fbdbf84ac1591a2ac267b Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 3 Jan 2024 13:21:39 -0500 Subject: [PATCH 2/2] Eliminate MemoryMap access macros, fix tests target. --- Machines/Apple/AppleIIgs/AppleIIgs.cpp | 8 +- Machines/Apple/AppleIIgs/MemoryMap.hpp | 88 +++++++++---------- .../Clock Signal.xcodeproj/project.pbxproj | 4 - .../Mac/Clock SignalTests/EmuTOSTests.mm | 15 ++-- .../Clock SignalTests/IIgsMemoryMapTests.mm | 13 ++- OSBindings/Mac/Clock SignalTests/QLTests.mm | 11 +-- .../Mac/Clock SignalTests/TestRunner68000.hpp | 13 ++- 7 files changed, 69 insertions(+), 83 deletions(-) diff --git a/Machines/Apple/AppleIIgs/AppleIIgs.cpp b/Machines/Apple/AppleIIgs/AppleIIgs.cpp index 718cc2a4d..58b3f9220 100644 --- a/Machines/Apple/AppleIIgs/AppleIIgs.cpp +++ b/Machines/Apple/AppleIIgs/AppleIIgs.cpp @@ -384,7 +384,7 @@ class ConcreteMachine: // MARK: BusHandler. uint64_t total = 0; forceinline Cycles perform_bus_operation(const CPU::WDC65816::BusOperation operation, const uint32_t address, uint8_t *const value) { - const auto ®ion = MemoryMapRegion(memory_, address); + const auto ®ion = memory_.region(address); static bool log = false; bool is_1Mhz = false; @@ -945,7 +945,7 @@ class ConcreteMachine: is_1Mhz = region.flags & MemoryMap::Region::Is1Mhz; if(isReadOperation(operation)) { - MemoryMapRead(region, address, value); + *value = memory_.read(region, address); } else { // Shadowed writes also occur "at 1Mhz". // TODO: this is probably an approximation. I'm assuming that there's the ability asynchronously to post @@ -954,7 +954,7 @@ class ConcreteMachine: // get by adding periodic NOPs within their copy-to-shadow step. // // Maybe the interaction with 2.8Mhz refresh isn't as straightforward as I think? - const bool is_shadowed = IsShadowed(memory_, region, address); + const bool is_shadowed = memory_.is_shadowed(address); is_1Mhz |= is_shadowed; // Use a very broad test for flushing video: any write to $e0 or $e1, or any write that is shadowed. @@ -963,7 +963,7 @@ class ConcreteMachine: video_.flush(); } - MemoryMapWrite(memory_, region, address, value); + memory_.write(region, address, *value); } } diff --git a/Machines/Apple/AppleIIgs/MemoryMap.hpp b/Machines/Apple/AppleIIgs/MemoryMap.hpp index 6db80ad2e..40998fcd7 100644 --- a/Machines/Apple/AppleIIgs/MemoryMap.hpp +++ b/Machines/Apple/AppleIIgs/MemoryMap.hpp @@ -631,55 +631,49 @@ class MemoryMap { std::array regions; // An assert above ensures that this is large enough; there's no // doctrinal reason for it to be whatever size it is now, just // adjust as required. + + // The below encapsulates an assumption that Apple intends to shadow physical addresses (i.e. after mapping). + // If the Apple shadows logical addresses (i.e. prior to mapping) then see commented out alternatives. + + const Region ®ion(uint32_t address) { return regions[region_map[address >> 8]]; } + uint8_t read(const Region ®ion, uint32_t address) { + return region.read ? region.read[address] : 0xff; + } + + bool is_shadowed(uint32_t address) const { + // Logical mapping alternative: + // shadow_pages[((®ion.write[address] - ram_base) >> 10) & 127] & shadow_banks[address >> 17] + + return shadow_pages[(address >> 10) & 127] & shadow_banks[address >> 17]; + + // Quick notes on contortions above: + // + // The objective is to support shadowing: + // 1. without storing a whole extra pointer, and such that the shadowing flags + // are orthogonal to the current auxiliary memory settings; + // 2. in such a way as to support shadowing both in banks $00/$01 and elsewhere; and + // 3. to do so without introducing too much in the way of branching. + // + // Hence the implemented solution: if shadowing is enabled then use the distance from the start of + // physical RAM modulo 128k indexed into the bank $e0/$e1 RAM. + // + // With a further twist: the modulo and pointer are indexed on ::IsShadowed to eliminate a branch + // even on that. + } + void write(const Region ®ion, uint32_t address, uint8_t value) { + if(!region.write) { + return; + } + + region.write[address] = value; + const bool shadowed = is_shadowed(address); + shadow_base[shadowed][(®ion.write[address] - ram_base) & shadow_mask[shadowed]] = value; + + // Logical mapping alternative: + // shadow_base[shadowed][address & shadow_mask[shadowed]] + } }; -// TODO: branching below on region.read/write is predicated on the idea that extra scratch space -// would be less efficient. Verify that? - -#define MemoryMapRegion(map, address) map.regions[map.region_map[address >> 8]] -#define MemoryMapRead(region, address, value) *value = region.read ? region.read[address] : 0xff - -// The below encapsulates the fact that I've yet to determine whether Apple intends to -// indicate that logical addresses (i.e. those prior to being mapped per the current paging) -// or physical addresses (i.e. after mapping) are subject to shadowing. -#ifdef SHADOW_LOGICAL - -#define IsShadowed(map, region, address) \ - (map.shadow_pages[((®ion.write[address] - map.ram_base) >> 10) & 127] & map.shadow_banks[address >> 17]) - -#define MemoryMapWrite(map, region, address, value) \ - if(region.write) { \ - region.write[address] = *value; \ - const bool _mm_is_shadowed = IsShadowed(map, region, address); \ - map.shadow_base[_mm_is_shadowed][address & map.shadow_mask[_mm_is_shadowed]] = *value; \ - } - -#else - -#define IsShadowed(map, region, address) \ - (map.shadow_pages[(address >> 10) & 127] & map.shadow_banks[address >> 17]) - -#define MemoryMapWrite(map, region, address, value) \ - if(region.write) { \ - region.write[address] = *value; \ - const bool _mm_is_shadowed = IsShadowed(map, region, address); \ - map.shadow_base[_mm_is_shadowed][(®ion.write[address] - map.ram_base) & map.shadow_mask[_mm_is_shadowed]] = *value; \ - } - -#endif - -// Quick notes on ::IsShadowed contortions: -// -// The objective is to support shadowing: -// 1. without storing a whole extra pointer, and such that the shadowing flags are orthogonal to the current auxiliary memory settings; -// 2. in such a way as to support shadowing both in banks $00/$01 and elsewhere; and -// 3. to do so without introducing too much in the way of branching. -// -// Hence the implemented solution: if shadowing is enabled then use the distance from the start of physical RAM -// modulo 128k indexed into the bank $e0/$e1 RAM. -// -// With a further twist: the modulo and pointer are indexed on ::IsShadowed to eliminate a branch even on that. - } #endif /* MemoryMap_h */ diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 61a2c8c82..0825ca784 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -535,7 +535,6 @@ 4B8334861F5DA3780097E338 /* 6502Storage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334851F5DA3780097E338 /* 6502Storage.cpp */; }; 4B83348A1F5DB94B0097E338 /* IRQDelegatePortHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334891F5DB94B0097E338 /* IRQDelegatePortHandler.cpp */; }; 4B8334951F5E25B60097E338 /* C1540.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8334941F5E25B60097E338 /* C1540.cpp */; }; - 4B85322D227793CB00F26553 /* etos192uk.trace.txt.gz in Resources */ = {isa = PBXBuildFile; fileRef = 4B85322C227793CA00F26553 /* etos192uk.trace.txt.gz */; }; 4B85322F2277ABDE00F26553 /* tos100.trace.txt.gz in Resources */ = {isa = PBXBuildFile; fileRef = 4B85322E2277ABDD00F26553 /* tos100.trace.txt.gz */; }; 4B86E25B1F8C628F006FAA45 /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B86E2591F8C628F006FAA45 /* Keyboard.cpp */; }; 4B8805F01DCFC99C003085B1 /* Acorn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8805EE1DCFC99C003085B1 /* Acorn.cpp */; }; @@ -1622,7 +1621,6 @@ 4B8334911F5E24FF0097E338 /* C1540Base.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = C1540Base.hpp; path = Implementation/C1540Base.hpp; sourceTree = ""; }; 4B8334941F5E25B60097E338 /* C1540.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = C1540.cpp; path = Implementation/C1540.cpp; sourceTree = ""; }; 4B85322922778E4200F26553 /* Comparative68000.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Comparative68000.hpp; sourceTree = ""; }; - 4B85322C227793CA00F26553 /* etos192uk.trace.txt.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = etos192uk.trace.txt.gz; sourceTree = ""; }; 4B85322E2277ABDD00F26553 /* tos100.trace.txt.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = tos100.trace.txt.gz; sourceTree = ""; }; 4B86E2591F8C628F006FAA45 /* Keyboard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Keyboard.cpp; sourceTree = ""; }; 4B86E25A1F8C628F006FAA45 /* Keyboard.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Keyboard.hpp; sourceTree = ""; }; @@ -3540,7 +3538,6 @@ isa = PBXGroup; children = ( 4B85322E2277ABDD00F26553 /* tos100.trace.txt.gz */, - 4B85322C227793CA00F26553 /* etos192uk.trace.txt.gz */, ); path = "TOS Startup"; sourceTree = ""; @@ -5411,7 +5408,6 @@ 4BB298FB1B587D8400A49093 /* ancb in Resources */, 4BB299431B587D8400A49093 /* dcma in Resources */, 4BB298FD1B587D8400A49093 /* andax in Resources */, - 4B85322D227793CB00F26553 /* etos192uk.trace.txt.gz in Resources */, 4B8DF6262550D91600F3433C /* CPUEOR-trace_compare.log in Resources */, 4BB299401B587D8400A49093 /* cpya in Resources */, 4BB299BE1B587D8400A49093 /* rraix in Resources */, diff --git a/OSBindings/Mac/Clock SignalTests/EmuTOSTests.mm b/OSBindings/Mac/Clock SignalTests/EmuTOSTests.mm index 698ef7913..ae91b68b5 100644 --- a/OSBindings/Mac/Clock SignalTests/EmuTOSTests.mm +++ b/OSBindings/Mac/Clock SignalTests/EmuTOSTests.mm @@ -36,7 +36,7 @@ class EmuTOS: public ComparativeBusHandler { return m68000_.get_state(); } - template perform_bus_operation(const Microcycle &cycle, int) { + template HalfCycles perform_bus_operation(const Microcycle &cycle, int) { const uint32_t address = cycle.word_address(); uint32_t word_address = address; @@ -56,7 +56,6 @@ class EmuTOS: public ComparativeBusHandler { word_address %= ram_.size(); } - using Microcycle = CPU::MC68000::Microcycle; if(cycle.data_select_active()) { uint16_t peripheral_result = 0xffff; if(is_peripheral) { @@ -68,20 +67,20 @@ class EmuTOS: public ComparativeBusHandler { } } - const auto operation = (op != Microcycle::DecodeDynamically) ? op : cycle.operation; - switch(operation & (Microcycle::SelectWord | Microcycle::SelectByte | Microcycle::Read)) { + using namespace CPU::MC68000; + switch(cycle.operation & (Operation::SelectWord | Operation::SelectByte | Operation::Read)) { default: break; - case Microcycle::SelectWord | Microcycle::Read: + case Operation::SelectWord | Operation::Read: cycle.value->w = is_peripheral ? peripheral_result : base[word_address]; break; - case Microcycle::SelectByte | Microcycle::Read: + case Operation::SelectByte | Operation::Read: cycle.value->b = (is_peripheral ? peripheral_result : base[word_address]) >> cycle.byte_shift(); break; - case Microcycle::SelectWord: + case Operation::SelectWord: base[word_address] = cycle.value->w; break; - case Microcycle::SelectByte: + case Operation::SelectByte: base[word_address] = (cycle.value->b << cycle.byte_shift()) | (base[word_address] & (0xffff ^ cycle.byte_mask())); break; } diff --git a/OSBindings/Mac/Clock SignalTests/IIgsMemoryMapTests.mm b/OSBindings/Mac/Clock SignalTests/IIgsMemoryMapTests.mm index 58ebbe4d8..64e098783 100644 --- a/OSBindings/Mac/Clock SignalTests/IIgsMemoryMapTests.mm +++ b/OSBindings/Mac/Clock SignalTests/IIgsMemoryMapTests.mm @@ -38,16 +38,14 @@ namespace { } - (void)write:(uint8_t)value address:(uint32_t)address { - const auto ®ion = MemoryMapRegion(_memoryMap, address); + const auto ®ion = _memoryMap.region(address); XCTAssertFalse(region.flags & MemoryMap::Region::IsIO); - MemoryMapWrite(_memoryMap, region, address, &value); + _memoryMap.write(region, address, value); } - (uint8_t)readAddress:(uint32_t)address { - const auto ®ion = MemoryMapRegion(_memoryMap, address); - uint8_t value; - MemoryMapRead(region, address, &value); - return value; + const auto ®ion = _memoryMap.region(address); + return _memoryMap.read(region, address); } - (void)testAllRAM { @@ -371,8 +369,7 @@ namespace { while(logical < [next intValue]) { [[maybe_unused]] const auto ®ion = self->_memoryMap.regions[self->_memoryMap.region_map[logical]]; - const bool isShadowed = - IsShadowed(_memoryMap, region, (logical << 8)); + const bool isShadowed = _memoryMap.is_shadowed(logical << 8); XCTAssertEqual( isShadowed, diff --git a/OSBindings/Mac/Clock SignalTests/QLTests.mm b/OSBindings/Mac/Clock SignalTests/QLTests.mm index 9c656480d..35d7a95d2 100644 --- a/OSBindings/Mac/Clock SignalTests/QLTests.mm +++ b/OSBindings/Mac/Clock SignalTests/QLTests.mm @@ -59,20 +59,21 @@ class QL: public ComparativeBusHandler { if(cycle.data_select_active()) { uint16_t peripheral_result = 0xffff; - switch(cycle.operation & (Microcycle::SelectWord | Microcycle::SelectByte | Microcycle::Read)) { + using namespace CPU::MC68000; + switch(cycle.operation & (Operation::SelectWord | Operation::SelectByte | Operation::Read)) { default: break; - case Microcycle::SelectWord | Microcycle::Read: + case Operation::SelectWord | Operation::Read: cycle.value->w = is_peripheral ? peripheral_result : base[word_address]; break; - case Microcycle::SelectByte | Microcycle::Read: + case Operation::SelectByte | Operation::Read: cycle.value->b = (is_peripheral ? peripheral_result : base[word_address]) >> cycle.byte_shift(); break; - case Microcycle::SelectWord: + case Operation::SelectWord: assert(!(is_rom && !is_peripheral)); if(!is_peripheral) base[word_address] = cycle.value->w; break; - case Microcycle::SelectByte: + case Operation::SelectByte: assert(!(is_rom && !is_peripheral)); if(!is_peripheral) base[word_address] = (cycle.value->b << cycle.byte_shift()) | (base[word_address] & (0xffff ^ cycle.byte_mask())); break; diff --git a/OSBindings/Mac/Clock SignalTests/TestRunner68000.hpp b/OSBindings/Mac/Clock SignalTests/TestRunner68000.hpp index d6fa8e94f..74a0346d8 100644 --- a/OSBindings/Mac/Clock SignalTests/TestRunner68000.hpp +++ b/OSBindings/Mac/Clock SignalTests/TestRunner68000.hpp @@ -82,24 +82,23 @@ class RAM68000: public CPU::MC68000::BusHandler { const uint32_t word_address = cycle.word_address(); duration_ += cycle.length; - const auto operation = (op != Microcycle::DecodeDynamically) ? op : cycle.operation; if(cycle.data_select_active()) { - if(operation & Microcycle::InterruptAcknowledge) { + if(cycle.operation & CPU::MC68000::Operation::InterruptAcknowledge) { cycle.value->b = 10; } else { - switch(operation & (Microcycle::SelectWord | Microcycle::SelectByte | Microcycle::Read)) { + switch(cycle.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 = ram_[word_address % ram_.size()]; break; - case Microcycle::SelectByte | Microcycle::Read: + case CPU::MC68000::Operation::SelectByte | CPU::MC68000::Operation::Read: cycle.value->b = ram_[word_address % ram_.size()] >> cycle.byte_shift(); break; - case Microcycle::SelectWord: + case CPU::MC68000::Operation::SelectWord: ram_[word_address % ram_.size()] = cycle.value->w; break; - case Microcycle::SelectByte: + case CPU::MC68000::Operation::SelectByte: ram_[word_address % ram_.size()] = uint16_t( (cycle.value->b << cycle.byte_shift()) | (ram_[word_address % ram_.size()] & cycle.untouched_byte_mask())