mirror of
https://github.com/TomHarte/CLK.git
synced 2024-06-29 00:29:34 +00:00
Bifurcate Zone enum, possibly to help compiler.
This commit is contained in:
parent
c7747ec5a0
commit
03c3da7338
|
@ -35,7 +35,7 @@ template <typename InterruptObserverT, typename ClockRateObserverT>
|
||||||
struct MemoryController {
|
struct MemoryController {
|
||||||
MemoryController(InterruptObserverT &observer, ClockRateObserverT &clock_rate_observer) :
|
MemoryController(InterruptObserverT &observer, ClockRateObserverT &clock_rate_observer) :
|
||||||
ioc_(observer, clock_rate_observer, ram_.data()) {
|
ioc_(observer, clock_rate_observer, ram_.data()) {
|
||||||
read_zones_[0] = Zone::HighROM; // Temporarily put high ROM at address 0.
|
read_zones_[0] = ReadZone::HighROM; // Temporarily put high ROM at address 0.
|
||||||
// TODO: could I just copy it in? Or, at least,
|
// TODO: could I just copy it in? Or, at least,
|
||||||
// could I detect at ROM loading time whether I can?
|
// could I detect at ROM loading time whether I can?
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,20 @@ struct MemoryController {
|
||||||
template <typename IntT>
|
template <typename IntT>
|
||||||
bool write(uint32_t address, IntT source, InstructionSet::ARM::Mode, bool trans) {
|
bool write(uint32_t address, IntT source, InstructionSet::ARM::Mode, bool trans) {
|
||||||
switch(write_zones_[(address >> 21) & 31]) {
|
switch(write_zones_[(address >> 21) & 31]) {
|
||||||
case Zone::DMAAndMEMC: {
|
case WriteZone::LogicallyMappedRAM: {
|
||||||
|
const auto item = logical_ram<IntT, false>(address, trans);
|
||||||
|
if(item < reinterpret_cast<IntT *>(ram_.data())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*item = source;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case WriteZone::PhysicallyMappedRAM:
|
||||||
|
if(trans) return false;
|
||||||
|
physical_ram<IntT>(address) = source;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WriteZone::DMAAndMEMC: {
|
||||||
if(trans) return false;
|
if(trans) return false;
|
||||||
|
|
||||||
const auto buffer_address = [](uint32_t source) -> uint32_t {
|
const auto buffer_address = [](uint32_t source) -> uint32_t {
|
||||||
|
@ -133,40 +146,23 @@ struct MemoryController {
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Zone::LogicallyMappedRAM: {
|
case WriteZone::IOControllers:
|
||||||
const auto item = logical_ram<IntT, false>(address, trans);
|
|
||||||
if(item < reinterpret_cast<IntT *>(ram_.data())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*item = source;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case Zone::IOControllers:
|
|
||||||
if(trans) return false;
|
if(trans) return false;
|
||||||
ioc_.template write<IntT>(address, source);
|
ioc_.template write<IntT>(address, source);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Zone::VideoController:
|
case WriteZone::VideoController:
|
||||||
if(trans) return false;
|
if(trans) return false;
|
||||||
// TODO: handle byte writes correctly.
|
// TODO: handle byte writes correctly.
|
||||||
ioc_.video().write(source);
|
ioc_.video().write(source);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Zone::PhysicallyMappedRAM:
|
case WriteZone::AddressTranslator:
|
||||||
if(trans) return false;
|
|
||||||
physical_ram<IntT>(address) = source;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Zone::AddressTranslator:
|
|
||||||
if(trans) return false;
|
if(trans) return false;
|
||||||
// printf("Translator write at %08x; replaces %08x\n", address, pages_[address & 0x7f]);
|
// printf("Translator write at %08x; replaces %08x\n", address, pages_[address & 0x7f]);
|
||||||
pages_[address & 0x7f] = address;
|
pages_[address & 0x7f] = address;
|
||||||
map_dirty_ = true;
|
map_dirty_ = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
|
||||||
printf("TODO: write of %08x to %08x [%lu]\n", source, address, sizeof(IntT));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -174,13 +170,8 @@ struct MemoryController {
|
||||||
|
|
||||||
template <typename IntT>
|
template <typename IntT>
|
||||||
bool read(uint32_t address, IntT &source, bool trans) {
|
bool read(uint32_t address, IntT &source, bool trans) {
|
||||||
switch (read_zones_[(address >> 21) & 31]) {
|
switch(read_zones_[(address >> 21) & 31]) {
|
||||||
case Zone::PhysicallyMappedRAM:
|
case ReadZone::LogicallyMappedRAM: {
|
||||||
if(trans) return false;
|
|
||||||
source = physical_ram<IntT>(address);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Zone::LogicallyMappedRAM: {
|
|
||||||
const auto item = logical_ram<IntT, true>(address, trans);
|
const auto item = logical_ram<IntT, true>(address, trans);
|
||||||
if(item < reinterpret_cast<IntT *>(ram_.data())) {
|
if(item < reinterpret_cast<IntT *>(ram_.data())) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -188,25 +179,26 @@ struct MemoryController {
|
||||||
source = *item;
|
source = *item;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Zone::LowROM:
|
case ReadZone::HighROM:
|
||||||
|
// Real test is: require A24=A25=0, then A25=1.
|
||||||
|
read_zones_[0] = ReadZone::LogicallyMappedRAM;
|
||||||
|
source = high_rom<IntT>(address);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ReadZone::PhysicallyMappedRAM:
|
||||||
|
if(trans) return false;
|
||||||
|
source = physical_ram<IntT>(address);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ReadZone::LowROM:
|
||||||
// logger.error().append("TODO: Low ROM read from %08x", address);
|
// logger.error().append("TODO: Low ROM read from %08x", address);
|
||||||
source = IntT(~0);
|
source = IntT(~0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Zone::HighROM:
|
case ReadZone::IOControllers:
|
||||||
// Real test is: require A24=A25=0, then A25=1.
|
|
||||||
read_zones_[0] = Zone::LogicallyMappedRAM;
|
|
||||||
source = high_rom<IntT>(address);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Zone::IOControllers:
|
|
||||||
if(trans) return false;
|
if(trans) return false;
|
||||||
ioc_.template read<IntT>(address, source);
|
ioc_.template read<IntT>(address, source);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
|
||||||
logger.error().append("TODO: read from %08x", address);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -244,32 +236,53 @@ struct MemoryController {
|
||||||
private:
|
private:
|
||||||
Log::Logger<Log::Source::ARMIOC> logger;
|
Log::Logger<Log::Source::ARMIOC> logger;
|
||||||
|
|
||||||
enum class Zone {
|
enum class ReadZone {
|
||||||
LogicallyMappedRAM,
|
LogicallyMappedRAM,
|
||||||
PhysicallyMappedRAM,
|
PhysicallyMappedRAM,
|
||||||
IOControllers,
|
IOControllers,
|
||||||
LowROM,
|
LowROM,
|
||||||
HighROM,
|
HighROM,
|
||||||
|
};
|
||||||
|
enum class WriteZone {
|
||||||
|
LogicallyMappedRAM,
|
||||||
|
PhysicallyMappedRAM,
|
||||||
|
IOControllers,
|
||||||
VideoController,
|
VideoController,
|
||||||
DMAAndMEMC,
|
DMAAndMEMC,
|
||||||
AddressTranslator,
|
AddressTranslator,
|
||||||
};
|
};
|
||||||
static std::array<Zone, 0x20> zones(bool is_read) {
|
template <bool is_read>
|
||||||
std::array<Zone, 0x20> zones{};
|
using Zone = std::conditional_t<is_read, ReadZone, WriteZone>;
|
||||||
|
|
||||||
|
template <bool is_read>
|
||||||
|
static std::array<Zone<is_read>, 0x20> zones() {
|
||||||
|
std::array<Zone<is_read>, 0x20> zones{};
|
||||||
for(size_t c = 0; c < zones.size(); c++) {
|
for(size_t c = 0; c < zones.size(); c++) {
|
||||||
const auto address = c << 21;
|
const auto address = c << 21;
|
||||||
if(address < 0x200'0000) {
|
if(address < 0x200'0000) {
|
||||||
zones[c] = Zone::LogicallyMappedRAM;
|
zones[c] = Zone<is_read>::LogicallyMappedRAM;
|
||||||
} else if(address < 0x300'0000) {
|
} else if(address < 0x300'0000) {
|
||||||
zones[c] = Zone::PhysicallyMappedRAM;
|
zones[c] = Zone<is_read>::PhysicallyMappedRAM;
|
||||||
} else if(address < 0x340'0000) {
|
} else if(address < 0x340'0000) {
|
||||||
zones[c] = Zone::IOControllers;
|
zones[c] = Zone<is_read>::IOControllers;
|
||||||
} else if(address < 0x360'0000) {
|
} else if(address < 0x360'0000) {
|
||||||
zones[c] = is_read ? Zone::LowROM : Zone::VideoController;
|
if constexpr (is_read) {
|
||||||
} else if(address < 0x380'0000) {
|
zones[c] = Zone<is_read>::LowROM;
|
||||||
zones[c] = is_read ? Zone::LowROM : Zone::DMAAndMEMC;
|
|
||||||
} else {
|
} else {
|
||||||
zones[c] = is_read ? Zone::HighROM : Zone::AddressTranslator;
|
zones[c] = Zone<is_read>::VideoController;
|
||||||
|
}
|
||||||
|
} else if(address < 0x380'0000) {
|
||||||
|
if constexpr (is_read) {
|
||||||
|
zones[c] = Zone<is_read>::LowROM;
|
||||||
|
} else {
|
||||||
|
zones[c] = Zone<is_read>::DMAAndMEMC;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if constexpr (is_read) {
|
||||||
|
zones[c] = Zone<is_read>::HighROM;
|
||||||
|
} else {
|
||||||
|
zones[c] = Zone<is_read>::AddressTranslator;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return zones;
|
return zones;
|
||||||
|
@ -293,8 +306,8 @@ struct MemoryController {
|
||||||
return *reinterpret_cast<IntT *>(&rom_[address & (rom_.size() - 1)]);
|
return *reinterpret_cast<IntT *>(&rom_[address & (rom_.size() - 1)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<Zone, 0x20> read_zones_ = zones(true);
|
std::array<ReadZone, 0x20> read_zones_ = zones<true>();
|
||||||
const std::array<Zone, 0x20> write_zones_ = zones(false);
|
const std::array<WriteZone, 0x20> write_zones_ = zones<false>();
|
||||||
|
|
||||||
// Control register values.
|
// Control register values.
|
||||||
bool os_mode_ = false;
|
bool os_mode_ = false;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user