Skip to content
Snippets Groups Projects
Commit 8653f76f authored by Geo Ster's avatar Geo Ster
Browse files

Implement read/write operations and KUSEG regions

* Now that the BIOS is loaded we can start executing it!
The starting address the EE uses is 0xbfc00000 which maps
to KUSEG1. Since all KUSEG regions except KUSEG2 are mirrors
of each other we only need to translate the address to the
KUSEG appropriate.

* The functional differences between KUSEG0/1 are minimal and
very niche so I won't bother emulating them now. Address wise
we can notice that the only difference between addresses is the
most significant half byte. By using that byte as an index in
a mask table we can define an appropriate mask for each KUSEG
address. Idea taken from a very handy PSX document I discovered
last year [1]

[1] https://svkt.org/~simias/guide.pdf (43)
parent a54398cc
No related branches found
No related tags found
No related merge requests found
......@@ -3,8 +3,6 @@
#include <vector>
#include <cpu/ee.hpp>
constexpr uint32_t MEMORY_RANGE = 0x20000000;
/* This class act as the "motherboard" of sorts */
class ComponentManager {
public:
......@@ -13,6 +11,13 @@ public:
void tick_components();
/* Memory operations */
template <typename T>
T read_memory(uint32_t addr);
template <typename T>
void write_memory(uint32_t addr, T data);
protected:
void read_bios();
......
#pragma once
#include <cstdint>
/* Each KUSEG region is 0x1FFFFFFF (512MB) in length and
contains the RAM (32MB) and mirrors of the RAM (cached, uncached, accelerated)
+ other things like some EE registers/VU memory/Timers. The user
KUSEG extends up to 0x7FFFFFFF (2048MB) which doesn't
seem to be used by anything (scratchpad is at 0x70000000 though)
*/
constexpr uint32_t MEMORY_RANGE = 512 * 1024 * 1024;
constexpr uint32_t KUSEG_MASKS[8] = {
/* KUSEG: Don't touch the address, it's fine */
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
/* KSEG0: Strip the MSB (0x8 -> 0x0 and 0x9 -> 0x1) */
0x7fffffff,
/* KSEG1: Strip the 3 MSB's (0xA -> 0x0 and 0xB -> 0x1) */
0x1fffffff,
/* KSEG2: Don't touch the address, it's fine */
0xffffffff, 0xffffffff,
};
/* Just a simple nice wrapper over memory ranges, with constexpr so no overhead */
struct Range {
constexpr Range(unsigned int begin, unsigned long size) :
constexpr Range(uint32_t begin, uint64_t size) :
start(begin), length(size) {}
inline bool contains(unsigned int addr) const
inline bool contains(uint32_t addr) const
{
return (addr >= start && addr < start + length);
}
inline uint offset(unsigned int addr) const
inline uint offset(uint32_t addr) const
{
return addr - start;
}
unsigned int start = 0;
unsigned long length = 0;
uint32_t start = 0;
uint64_t length = 0;
};
/* Memory ranges. */
......@@ -25,4 +45,4 @@ constexpr Range IO_REGISTERS = Range(0x10000000, 64 * 1024LL);
constexpr Range VU_MEMORY = Range(0x11000000, 40 * 1024LL);
constexpr Range GS_PRIV_REGS = Range(0x12000000, 8 * 1024LL);
constexpr Range IOP_RAM = Range(0x1c000000, 2 * 1024 * 1024LL);
constexpr Range BIOS = Range(0x1fc00000, 4 * 1024 * 1024LL);
\ No newline at end of file
constexpr Range BIOS = Range(0x1fc00000, 4 * 1024 * 1024LL);
......@@ -8,6 +8,10 @@ ComponentManager::ComponentManager() :
memory(MEMORY_RANGE, 0)
{
ee = std::make_unique<EmotionEngine>(this);
/* Load the BIOS in our memory */
/* NOTE: Must make a GUI for this someday */
this->read_bios();
}
void ComponentManager::read_bios()
......@@ -20,11 +24,35 @@ void ComponentManager::read_bios()
exit(1);
reader.seekg(0);
reader.read((char*)(memory.data() + BIOS.start), 4 * 1024 * 1024);
reader.read((char*)memory.data() + BIOS.start, BIOS.length);
reader.close();
}
void ComponentManager::tick_components()
{
ee->tick();
}
\ No newline at end of file
}
/* Instanciate the templates here so we can limit their types below */
template <typename T>
T ComponentManager::read_memory(uint32_t addr)
{
uint32_t vaddr = addr & KUSEG_MASKS[addr >> 29];
auto ptr = (T*)(memory.data() + vaddr);
return ptr[0];
}
/* Instanciate the templates here so we can limit their types below */
template <typename T>
void ComponentManager::write_memory(uint32_t addr, T data)
{
uint32_t vaddr = addr & KUSEG_MASKS[addr >> 29];
auto ptr = (T*)(memory.data() + vaddr);
ptr[0] = data;
}
/* Template definitions. */
template uint32_t ComponentManager::read_memory<uint32_t>(uint32_t);
template void ComponentManager::write_memory<uint32_t>(uint32_t, uint32_t);
\ No newline at end of file
......@@ -23,5 +23,5 @@ void EmotionEngine::reset_state()
void EmotionEngine::fetch_instruction()
{
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment