Merge pull request #1357 from TomHarte/EasyWins

Improve MEMC speed.
This commit is contained in:
Thomas Harte 2024-04-17 22:47:04 -04:00 committed by GitHub
commit 2acb853021
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 51 additions and 43 deletions

View File

@ -42,7 +42,7 @@ struct NullStatusHandler {
template <Model model, typename MemoryT, typename StatusObserverT = NullStatusHandler>
struct Executor {
template <typename... Args>
Executor(StatusObserverT &observer, Args &&...args) : status_observer_(observer), bus(std::forward<Args>(args)...) {}
Executor(StatusObserverT &observer, Args &&...args) : bus(std::forward<Args>(args)...), status_observer_(observer) {}
template <typename... Args>
Executor(Args &&...args) : bus(std::forward<Args>(args)...) {}
@ -327,7 +327,7 @@ struct Executor {
}
} else {
bool did_read;
uint32_t value;
uint32_t value = 0;
if constexpr (flags.transfer_byte()) {
uint8_t target;
@ -480,7 +480,7 @@ struct Executor {
// undo the previous load.
struct {
uint32_t *target = nullptr;
uint32_t value;
uint32_t value = 0;
} last_replacement;
for(uint32_t c = 0; c < total; c++) {

View File

@ -272,6 +272,7 @@ struct Registers {
case Condition::GT: return !le();
case Condition::LE: return le();
default:
case Condition::AL: return true;
case Condition::NV: return false;
}
@ -351,6 +352,7 @@ struct Registers {
}
switch(mode_) {
default:
case Mode::User: return active_[offset];
case Mode::Supervisor:

View File

@ -34,15 +34,13 @@
#include <set>
#include <vector>
namespace {
Log::Logger<Log::Source::Archimedes> logger;
}
namespace Archimedes {
#ifndef NDEBUG
namespace {
Log::Logger<Log::Source::Archimedes> logger;
}
template <InstructionSet::ARM::Model model, typename Executor>
struct HackyDebugger {
void notify(uint32_t address, uint32_t instruction, Executor &executor) {
@ -452,7 +450,7 @@ class ConcreteMachine:
int video_divider_ = 1;
void tick_cpu() {
uint32_t instruction;
uint32_t instruction = 0;
if(!executor_.bus.read(executor_.pc(), instruction, executor_.registers().mode(), false)) {
// logger.info().append("Prefetch abort at %08x; last good was at %08x", executor_.pc(), last_pc);
executor_.prefetch_abort();

View File

@ -71,13 +71,10 @@ struct MemoryController {
template <typename IntT>
bool write(uint32_t address, IntT source, InstructionSet::ARM::Mode, bool trans) {
// User mode may only _write_ to logically-mapped RAM (subject to further testing below).
if(trans && address >= 0x200'0000) {
return false;
}
switch(write_zones_[(address >> 21) & 31]) {
case Zone::DMAAndMEMC: {
if(trans) return false;
const auto buffer_address = [](uint32_t source) -> uint32_t {
return (source & 0x1'fffc) << 2;
};
@ -110,6 +107,25 @@ struct MemoryController {
high_rom_access_time_ = ROMAccessTime((address >> 6) & 3);
low_rom_access_time_ = ROMAccessTime((address >> 4) & 3);
page_size_ = PageSize((address >> 2) & 3);
switch(page_size_) {
default:
case PageSize::kb4:
page_address_shift_ = 12;
page_adddress_mask_ = 0x0fff;
break;
case PageSize::kb8:
page_address_shift_ = 13;
page_adddress_mask_ = 0x1fff;
break;
case PageSize::kb16:
page_address_shift_ = 14;
page_adddress_mask_ = 0x3fff;
break;
case PageSize::kb32:
page_address_shift_ = 15;
page_adddress_mask_ = 0x7fff;
break;
}
logger.info().append("MEMC Control: %08x -> OS:%d sound:%d video:%d refresh:%d high:%d low:%d size:%d", address, os_mode_, sound_dma_enable_, video_dma_enable_, dynamic_ram_refresh_, high_rom_access_time_, low_rom_access_time_, page_size_);
map_dirty_ = true;
@ -126,19 +142,23 @@ struct MemoryController {
} break;
case Zone::IOControllers:
if(trans) return false;
ioc_.template write<IntT>(address, source);
break;
case Zone::VideoController:
if(trans) return false;
// TODO: handle byte writes correctly.
ioc_.video().write(source);
break;
case Zone::PhysicallyMappedRAM:
if(trans) return false;
physical_ram<IntT>(address) = source;
break;
case Zone::AddressTranslator:
if(trans) return false;
// printf("Translator write at %08x; replaces %08x\n", address, pages_[address & 0x7f]);
pages_[address & 0x7f] = address;
map_dirty_ = true;
@ -154,13 +174,9 @@ struct MemoryController {
template <typename IntT>
bool read(uint32_t address, IntT &source, InstructionSet::ARM::Mode, bool trans) {
// User mode may only read logically-maped RAM and ROM.
if(trans && address >= 0x200'0000 && address < 0x380'0000) {
return false;
}
switch (read_zones_[(address >> 21) & 31]) {
case Zone::PhysicallyMappedRAM:
if(trans) return false;
source = physical_ram<IntT>(address);
break;
@ -184,6 +200,7 @@ struct MemoryController {
break;
case Zone::IOControllers:
if(trans) return false;
ioc_.template read<IntT>(address, source);
break;
@ -298,6 +315,8 @@ struct MemoryController {
kb16 = 0b10,
kb32 = 0b11,
} page_size_ = PageSize::kb4;
int page_address_shift_ = 12;
uint32_t page_adddress_mask_ = 0xffff;
// Address translator.
//
@ -339,33 +358,14 @@ struct MemoryController {
}
address = aligned<IntT>(address);
address &= 0x1ff'ffff;
size_t page;
// TODO: eliminate switch here.
switch(page_size_) {
default:
case PageSize::kb4:
page = address >> 12;
address &= 0x0fff;
break;
case PageSize::kb8:
page = address >> 13;
address &= 0x1fff;
break;
case PageSize::kb16:
page = address >> 14;
address &= 0x3fff;
break;
case PageSize::kb32:
page = address >> 15;
address &= 0x7fff;
break;
}
const size_t page = address >> page_address_shift_;
const auto &map = mapping<is_read>(trans, os_mode_);
if(!map[page]) {
return nullptr;
}
address &= page_adddress_mask_;
return reinterpret_cast<IntT *>(&map[page][address]);
}

View File

@ -62,7 +62,7 @@
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableASanStackUseAfterReturn = "YES"

View File

@ -31,14 +31,21 @@ PCMSegmentEventSource::PCMSegmentEventSource(const PCMSegment &segment) :
}
PCMSegmentEventSource::PCMSegmentEventSource(const PCMSegmentEventSource &original) {
*this = original;
}
PCMSegmentEventSource &PCMSegmentEventSource::operator =(const PCMSegmentEventSource &original) {
// share underlying data with the original
segment_ = original.segment_;
// load up the clock rate and set initial conditions
next_event_.length.clock_rate = segment_->length_of_a_bit.clock_rate;
reset();
return *this;
}
void PCMSegmentEventSource::reset() {
// start with the first bit to be considered the zeroth, and assume that it'll be
// flux transitions for the foreseeable

View File

@ -163,6 +163,7 @@ class PCMSegmentEventSource {
but a unique pointer into it.
*/
PCMSegmentEventSource(const PCMSegmentEventSource &);
PCMSegmentEventSource &operator =(const PCMSegmentEventSource &);
/*!
@returns the next event that will occur in this event stream.