fxos/lib/memory.cpp

152 lines
3.0 KiB
C++

#include <fxos/memory.h>
#include <stdexcept>
#include <array>
namespace FxOS {
//---
// Overview of the memory areas
//---
uint32_t MemoryArea::start() const noexcept
{
switch(m_name)
{
case U0: return 0x00000000;
case P0: return 0x00000000;
case P1: return 0x80000000;
case P2: return 0xa0000000;
case P3: return 0xc0000000;
case P4: return 0xe0000000;
}
return 0;
}
uint32_t MemoryArea::end() const noexcept
{
switch(m_name)
{
case U0: return 0x7fffffff;
case P0: return 0x7fffffff;
case P1: return 0x9fffffff;
case P2: return 0xbfffffff;
case P3: return 0xdfffffff;
case P4: return 0xffffffff;
}
return -1;
}
uint32_t MemoryArea::size() const noexcept
{
return this->end() - this->start() + 1;
}
//---
// Fine memory region management
//---
MemoryRegion::MemoryRegion():
name {"null"}, start {0x00000000}, end {0x00000000}, writable {false}
{
}
MemoryRegion::MemoryRegion(std::string name, uint32_t start, uint32_t end,
bool writable):
name {name}, start {start}, end {end}, writable {writable}
{
this->guess_flags();
}
uint32_t MemoryRegion::size() const noexcept
{
return end - start;
}
MemoryArea MemoryRegion::area() const noexcept
{
using Area = MemoryArea;
Area areas[5] = { Area::P4, Area::P3, Area::P2, Area::P1, Area::P0 };
for(int i = 0; i < 5; i++)
{
if(start >= areas[i].start()) return areas[i];
}
return Area::P0;
}
void MemoryRegion::guess_flags() noexcept
{
switch(this->area())
{
case MemoryArea::U0:
case MemoryArea::P0:
case MemoryArea::P3:
cacheable = true;
mappable = true;
break;
case MemoryArea::P1:
cacheable = true;
mappable = false;
break;
case MemoryArea::P2:
case MemoryArea::P4:
cacheable = false;
mappable = false;
break;
}
}
using R = MemoryRegion;
/* Basic memory regions */
R const &R::ROM = MemoryRegion("ROM", 0x80000000, 0x81ffffff, false);
R const &R::RAM = MemoryRegion("RAM", 0x88000000, 0x88040000, true);
R const &R::ROM_P2 = MemoryRegion("ROM_P2", 0xa0000000, 0xa07fffff, false);
R const &R::RAM_P2 = MemoryRegion("RAM_P2", 0xa8000000, 0xa8040000, true);
R const &R::RS = MemoryRegion("RS", 0xfd800000, 0xfd8007ff, true);
R const &R::ILRAM = MemoryRegion("ILRAM", 0xe5200000, 0xe5203fff, true);
R const &R::XRAM = MemoryRegion("XRAM", 0xe5007000, 0xe5008fff, true);
R const &R::YRAM = MemoryRegion("YRAM", 0xe5017000, 0xe5018fff, true);
MemoryRegion const *MemoryRegion::region_for(uint32_t address)
{
MemoryRegion const *regs[8] = {
&R::ROM, &R::RAM, &R::ROM_P2, &R::RAM_P2,
&R::RS, &R::ILRAM, &R::XRAM, &R::YRAM
};
for(int i = 0; i < 8; i++)
{
if(regs[i]->start <= address && address < regs[i]->end)
return regs[i];
}
return nullptr;
}
MemoryRegion::MemoryRegion(std::string name)
{
MemoryRegion const *regs[8] = {
&R::ROM, &R::RAM, &R::ROM_P2, &R::RAM_P2,
&R::RS, &R::ILRAM, &R::XRAM, &R::YRAM
};
for(int i = 0; i < 8; i++)
{
if(regs[i]->name == name)
{
*this = *regs[i];
return;
}
}
throw std::runtime_error("No standard region named '" + name + "'");
}
} /* namespace FxOS */