More speedups...

This commit is contained in:
Marco Satti 2018-04-28 19:14:47 +08:00
parent c7e37542a2
commit ba73a24a8a
41 changed files with 1092 additions and 1308 deletions

View file

@ -1,5 +1,8 @@
# CMake 3.8.2 is needed for C++17 support.
cmake_minimum_required(VERSION 3.8.2)
# CMake 3.9 is needed for LTO support.
cmake_minimum_required(VERSION 3.9)
cmake_policy(SET CMP0069 NEW) # Link time optimization support
#######################
# Pre-project options #
@ -13,20 +16,29 @@ project(orbum CXX)
###########
# Options #
###########
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/out")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/out")
set(BUILD_SHARED_LIBS on)
set(CMAKE_POSITION_INDEPENDENT_CODE on)
include(CheckIPOSupported)
check_ipo_supported(RESULT ipo_result)
if(ipo_result)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION on)
endif()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -pthread")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -pthread")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
endif()
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/out")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/out")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
################
# Dependencies #

View file

@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.8.2)
cmake_minimum_required(VERSION 3.9)
cmake_policy(SET CMP0069 NEW) # Link time optimization support
project(liborbum CXX)
@ -10,16 +11,11 @@ set(COMMON_SRC_FILES
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Bus/ByteBus.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Bus/ByteBusMappable.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/FifoQueue/DmaFifoQueue.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/FifoQueue/FifoQueue.cpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/FifoQueue/FifoQueue.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/FpuFlags.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Memory/ArrayByteMemory.cpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Memory/ArrayByteMemory.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Memory/ArrayHwordMemory.cpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Memory/ArrayHwordMemory.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Memory/ByteMemory.cpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Memory/ByteMemory.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Memory/HwordMemory.cpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Memory/HwordMemory.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Mips/BranchDelaySlot.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Mips/MipsCoprocessor.hpp"
@ -28,27 +24,16 @@ set(COMMON_SRC_FILES
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Mips/MipsInstructionInfo.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Mips/MmuAccess.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Primitive.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/ByteRegister.cpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/ByteRegister.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/DwordRegister.cpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/DwordRegister.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/HwordRegister.cpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/HwordRegister.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/MapperHwordWordRegister.cpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/MapperHwordWordRegister.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/QwordRegister.cpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/QwordRegister.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/SizedByteRegister.cpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/SizedByteRegister.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/SizedDwordRegister.cpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/SizedDwordRegister.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/SizedHwordRegister.cpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/SizedHwordRegister.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/SizedQwordRegister.cpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/SizedQwordRegister.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/SizedWordRegister.cpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/SizedWordRegister.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/WordRegister.cpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/WordRegister.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/Register/PcRegisters.hpp"
"${CMAKE_SOURCE_DIR}/liborbum/src/Common/Types/ScopeLock.hpp"

View file

@ -1,86 +0,0 @@
#include "Common/Types/FifoQueue/FifoQueue.hpp"
void FifoQueue::read(ubyte* buffer, const size_t length)
{
for (size_t i = 0; i < length; i++)
buffer[i] = read_ubyte();
}
void FifoQueue::write(const ubyte* buffer, const size_t length)
{
for (size_t i = 0; i < length; i++)
write_ubyte(buffer[i]);
}
ubyte FifoQueue::byte_bus_read_ubyte(const BusContext context, const usize offset)
{
return read_ubyte();
}
void FifoQueue::byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value)
{
write_ubyte(value);
}
uhword FifoQueue::byte_bus_read_uhword(const BusContext context, const usize offset)
{
uhword value;
read(reinterpret_cast<ubyte*>(&value), NUMBER_BYTES_IN_HWORD);
return value;
}
void FifoQueue::byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value)
{
write(reinterpret_cast<const ubyte*>(&value), NUMBER_BYTES_IN_HWORD);
}
uword FifoQueue::byte_bus_read_uword(const BusContext context, const usize offset)
{
uword value;
read(reinterpret_cast<ubyte*>(&value), NUMBER_BYTES_IN_WORD);
return value;
}
void FifoQueue::byte_bus_write_uword(const BusContext context, const usize offset, const uword value)
{
write(reinterpret_cast<const ubyte*>(&value), NUMBER_BYTES_IN_WORD);
}
udword FifoQueue::byte_bus_read_udword(const BusContext context, const usize offset)
{
udword value;
read(reinterpret_cast<ubyte*>(&value), NUMBER_BYTES_IN_DWORD);
return value;
}
void FifoQueue::byte_bus_write_udword(const BusContext context, const usize offset, const udword value)
{
write(reinterpret_cast<const ubyte*>(&value), NUMBER_BYTES_IN_DWORD);
}
uqword FifoQueue::byte_bus_read_uqword(const BusContext context, const usize offset)
{
uqword value;
read(reinterpret_cast<ubyte*>(&value), NUMBER_BYTES_IN_QWORD);
return value;
}
void FifoQueue::byte_bus_write_uqword(const BusContext context, const usize offset, const uqword value)
{
write(reinterpret_cast<const ubyte*>(&value), NUMBER_BYTES_IN_QWORD);
}
bool FifoQueue::is_empty() const
{
return !has_read_available(1);
}
bool FifoQueue::is_full() const
{
return !has_write_available(1);
}
usize FifoQueue::byte_bus_map_size() const
{
return static_cast<usize>(1);
}

View file

@ -22,11 +22,19 @@ public:
/// Reads bytes to the buffer given.
/// This is a wrapper around the read_ubyte function, and should not be treated as a separate interface (not made virtual).
void read(ubyte * buffer, const size_t length);
void read(ubyte * buffer, const size_t length)
{
for (size_t i = 0; i < length; i++)
buffer[i] = read_ubyte();
}
/// Writes bytes from the buffer given.
/// This is a wrapper around the write_ubyte function, and should not be treated as a separate interface (not made virtual).
void write(const ubyte * buffer, const size_t length);
void write(const ubyte * buffer, const size_t length)
{
for (size_t i = 0; i < length; i++)
write_ubyte(buffer[i]);
}
/// Checks if the queue has at least n_bytes available for reading.
virtual bool has_read_available(const size_t n_bytes) const = 0;
@ -35,23 +43,80 @@ public:
virtual bool has_write_available(const size_t n_bytes) const = 0;
/// Check if queue is full/empty (wrappers around above functions).
bool is_empty() const;
bool is_full() const;
bool is_empty() const
{
return !has_read_available(1);
}
bool is_full() const
{
return !has_write_available(1);
}
/// ByteBusMappable overrides.
/// For the FifoQueue object, the map size is always one byte.
/// The offset is not used in reading or writing to the queue.
/// For a larger mapping, map the queue multiple times.
usize byte_bus_map_size() const override;
ubyte byte_bus_read_ubyte(const BusContext context, const usize offset) override;
void byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value) override;
uhword byte_bus_read_uhword(const BusContext context, const usize offset) override;
void byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value) override;
uword byte_bus_read_uword(const BusContext context, const usize offset) override;
void byte_bus_write_uword(const BusContext context, const usize offset, const uword value) override;
udword byte_bus_read_udword(const BusContext context, const usize offset) override;
void byte_bus_write_udword(const BusContext context, const usize offset, const udword value) override;
uqword byte_bus_read_uqword(const BusContext context, const usize offset) override;
void byte_bus_write_uqword(const BusContext context, const usize offset, const uqword value) override;
};
usize byte_bus_map_size() const override
{
return static_cast<usize>(1);
}
ubyte byte_bus_read_ubyte(const BusContext context, const usize offset) override
{
return read_ubyte();
}
void byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value) override
{
write_ubyte(value);
}
uhword byte_bus_read_uhword(const BusContext context, const usize offset) override
{
uhword value;
read(reinterpret_cast<ubyte*>(&value), NUMBER_BYTES_IN_HWORD);
return value;
}
void byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value) override
{
write(reinterpret_cast<const ubyte*>(&value), NUMBER_BYTES_IN_HWORD);
}
uword byte_bus_read_uword(const BusContext context, const usize offset) override
{
uword value;
read(reinterpret_cast<ubyte*>(&value), NUMBER_BYTES_IN_WORD);
return value;
}
void byte_bus_write_uword(const BusContext context, const usize offset, const uword value) override
{
write(reinterpret_cast<const ubyte*>(&value), NUMBER_BYTES_IN_WORD);
}
udword byte_bus_read_udword(const BusContext context, const usize offset) override
{
udword value;
read(reinterpret_cast<ubyte*>(&value), NUMBER_BYTES_IN_DWORD);
return value;
}
void byte_bus_write_udword(const BusContext context, const usize offset, const udword value) override
{
write(reinterpret_cast<const ubyte*>(&value), NUMBER_BYTES_IN_DWORD);
}
uqword byte_bus_read_uqword(const BusContext context, const usize offset) override
{
uqword value;
read(reinterpret_cast<ubyte*>(&value), NUMBER_BYTES_IN_QWORD);
return value;
}
void byte_bus_write_uqword(const BusContext context, const usize offset, const uqword value) override
{
write(reinterpret_cast<const ubyte*>(&value), NUMBER_BYTES_IN_QWORD);
}
};

View file

@ -1,147 +0,0 @@
#include <fstream>
#include "Common/Types/Memory/ArrayByteMemory.hpp"
ArrayByteMemory::ArrayByteMemory(const size_t size, const ubyte initial_value, const bool read_only) :
size(size),
memory(size, initial_value),
initial_value(initial_value),
read_only(read_only)
{
}
void ArrayByteMemory::initialise()
{
std::vector<ubyte>(size, initial_value).swap(memory);
}
void ArrayByteMemory::read_from_file(const std::string & path, const size_t file_length)
{
std::ifstream file(path, std::ios_base::binary);
if (!file)
throw std::runtime_error("Unable to read file");
file.read(reinterpret_cast<char*>(&memory[0]), file_length);
}
void ArrayByteMemory::write_to_file(const std::string & path)
{
std::ofstream file(path, std::ios_base::binary);
if (!file)
throw std::runtime_error("Unable to write file");
file.write(reinterpret_cast<char*>(&memory[0]), size);
}
ubyte ArrayByteMemory::read_ubyte(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
return *reinterpret_cast<ubyte*>(&memory[offset]);
}
void ArrayByteMemory::write_ubyte(const size_t offset, const ubyte value)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<ubyte*>(&memory[offset]) = value;
}
uhword ArrayByteMemory::read_uhword(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
return *reinterpret_cast<uhword*>(&memory[offset]);
}
void ArrayByteMemory::write_uhword(const size_t offset, const uhword value)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<uhword*>(&memory[offset]) = value;
}
uword ArrayByteMemory::read_uword(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
return *reinterpret_cast<uword*>(&memory[offset]);
}
void ArrayByteMemory::write_uword(const size_t offset, const uword value)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<uword*>(&memory[offset]) = value;
}
udword ArrayByteMemory::read_udword(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
return *reinterpret_cast<udword*>(&memory[offset]);
}
void ArrayByteMemory::write_udword(const size_t offset, const udword value)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<udword*>(&memory[offset]) = value;
}
uqword ArrayByteMemory::read_uqword(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
return *reinterpret_cast<uqword*>(&memory[offset]);
}
void ArrayByteMemory::write_uqword(const size_t offset, const uqword value)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<uqword*>(&memory[offset]) = value;
}
usize ArrayByteMemory::byte_bus_map_size() const
{
return static_cast<usize>(size);
}
std::vector<ubyte>& ArrayByteMemory::get_memory()
{
return memory;
}

View file

@ -1,6 +1,7 @@
#pragma once
#include <vector>
#include <fstream>
#include "Common/Types/Memory/ByteMemory.hpp"
@ -9,37 +10,158 @@
class ArrayByteMemory : public ByteMemory
{
public:
ArrayByteMemory(const size_t size, const ubyte initial_value = 0, const bool read_only = false);
ArrayByteMemory(const size_t size, const ubyte initial_value = 0, const bool read_only = false) :
size(size),
memory(size, initial_value),
initial_value(initial_value),
read_only(read_only)
{
}
/// Initialise memory.
void initialise() override;
void initialise() override
{
std::vector<ubyte>(size, initial_value).swap(memory);
}
/// Read in a raw file to the memory (byte copy).
/// For Core use only! Do not use within the controller logic.
void read_from_file(const std::string & path, const size_t file_length);
void read_from_file(const std::string & path, const size_t file_length)
{
std::ifstream file(path, std::ios_base::binary);
if (!file)
throw std::runtime_error("Unable to read file");
file.read(reinterpret_cast<char*>(&memory[0]), file_length);
}
/// Dumps the memory contents to a file.
/// For Core use only! Do not use within the controller logic.
void write_to_file(const std::string & path);
void write_to_file(const std::string & path)
{
std::ofstream file(path, std::ios_base::binary);
if (!file)
throw std::runtime_error("Unable to write file");
file.write(reinterpret_cast<char*>(&memory[0]), size);
}
/// Read or write a value of a given type, to the specified byte index (offset).
ubyte read_ubyte(const size_t offset) override;
void write_ubyte(const size_t offset, const ubyte value) override;
uhword read_uhword(const size_t offset) override;
void write_uhword(const size_t offset, const uhword value) override;
uword read_uword(const size_t offset) override;
void write_uword(const size_t offset, const uword value) override;
udword read_udword(const size_t offset) override;
void write_udword(const size_t offset, const udword value) override;
uqword read_uqword(const size_t offset) override;
void write_uqword(const size_t offset, const uqword value) override;
ubyte read_ubyte(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
return *reinterpret_cast<ubyte*>(&memory[offset]);
}
void write_ubyte(const size_t offset, const ubyte value) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<ubyte*>(&memory[offset]) = value;
}
uhword read_uhword(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
return *reinterpret_cast<uhword*>(&memory[offset]);
}
void write_uhword(const size_t offset, const uhword value) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<uhword*>(&memory[offset]) = value;
}
uword read_uword(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
return *reinterpret_cast<uword*>(&memory[offset]);
}
void write_uword(const size_t offset, const uword value) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<uword*>(&memory[offset]) = value;
}
udword read_udword(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
return *reinterpret_cast<udword*>(&memory[offset]);
}
void write_udword(const size_t offset, const udword value) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<udword*>(&memory[offset]) = value;
}
uqword read_uqword(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
return *reinterpret_cast<uqword*>(&memory[offset]);
}
void write_uqword(const size_t offset, const uqword value) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayByteMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<uqword*>(&memory[offset]) = value;
}
/// ByteBusMappable overrides.
usize byte_bus_map_size() const override;
usize byte_bus_map_size() const override
{
return static_cast<usize>(size);
}
/// Get a reference to the memory storage.
/// Used for the emulator: sometimes we need to peek and poke directly.
std::vector<ubyte> & get_memory();
std::vector<ubyte> & get_memory()
{
return memory;
}
private:
/// Total size of the byte memory.
@ -55,4 +177,3 @@ private:
/// Writes are silently discarded if turned on.
bool read_only;
};

View file

@ -1,121 +0,0 @@
#include <fstream>
#include "Common/Types/Memory/ArrayHwordMemory.hpp"
ArrayHwordMemory::ArrayHwordMemory(const size_t size, const uhword initial_value, const bool read_only) :
size(size),
memory(size, initial_value),
initial_value(initial_value),
read_only(read_only)
{
}
void ArrayHwordMemory::initialise()
{
std::vector<uhword>(size, initial_value).swap(memory);
}
uhword ArrayHwordMemory::read_uhword(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayHwordMemory with an invalid offset.");
#endif
return *reinterpret_cast<uhword*>(&memory[offset]);
}
void ArrayHwordMemory::write_uhword(const size_t offset, const uhword value)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayHwordMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<uhword*>(&memory[offset]) = value;
}
uword ArrayHwordMemory::read_uword(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayHwordMemory with an invalid offset.");
#endif
return *reinterpret_cast<uword*>(&memory[offset]);
}
void ArrayHwordMemory::write_uword(const size_t offset, const uword value)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayHwordMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<uword*>(&memory[offset]) = value;
}
udword ArrayHwordMemory::read_udword(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayHwordMemory with an invalid offset.");
#endif
return *reinterpret_cast<udword*>(&memory[offset]);
}
void ArrayHwordMemory::write_udword(const size_t offset, const udword value)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayHwordMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<udword*>(&memory[offset]) = value;
}
uqword ArrayHwordMemory::read_uqword(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayHwordMemory with an invalid offset.");
#endif
return *reinterpret_cast<uqword*>(&memory[offset]);
}
void ArrayHwordMemory::write_uqword(const size_t offset, const uqword value)
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayHwordMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<uqword*>(&memory[offset]) = value;
}
std::vector<uhword>& ArrayHwordMemory::get_memory()
{
return memory;
}
void ArrayHwordMemory::read_from_file(const std::string & path, const size_t file_length)
{
std::ifstream file(path, std::ios_base::binary);
if (!file)
throw std::runtime_error("Unable to read file");
file.read(reinterpret_cast<char*>(&memory[0]), file_length * NUMBER_BYTES_IN_HWORD);
}
void ArrayHwordMemory::write_to_file(const std::string & path)
{
std::ofstream file(path, std::ios_base::binary);
if (!file)
throw std::runtime_error("Unable to write file");
file.write(reinterpret_cast<char*>(&memory[0]), size * NUMBER_BYTES_IN_HWORD);
}

View file

@ -1,6 +1,7 @@
#pragma once
#include <vector>
#include <fstream>
#include "Common/Types/Memory/HwordMemory.hpp"
@ -9,32 +10,131 @@
class ArrayHwordMemory : public HwordMemory
{
public:
ArrayHwordMemory(const size_t size, const uhword initial_value = 0, const bool read_only = false);
ArrayHwordMemory(const size_t size, const uhword initial_value = 0, const bool read_only = false) :
size(size),
memory(size, initial_value),
initial_value(initial_value),
read_only(read_only)
{
}
/// Initialise memory.
void initialise() override;
void initialise() override
{
std::vector<uhword>(size, initial_value).swap(memory);
}
/// Read in a raw file to the memory (hword copy).
/// For Core use only! Do not use within the controller logic.
void read_from_file(const std::string & path, const size_t file_length);
void read_from_file(const std::string & path, const size_t file_length)
{
std::ifstream file(path, std::ios_base::binary);
if (!file)
throw std::runtime_error("Unable to read file");
file.read(reinterpret_cast<char*>(&memory[0]), file_length * NUMBER_BYTES_IN_HWORD);
}
/// Dumps the memory contents to a file.
/// For Core use only! Do not use within the controller logic.
void write_to_file(const std::string & path);
void write_to_file(const std::string & path)
{
std::ofstream file(path, std::ios_base::binary);
if (!file)
throw std::runtime_error("Unable to write file");
file.write(reinterpret_cast<char*>(&memory[0]), size * NUMBER_BYTES_IN_HWORD);
}
/// Read or write a value of a given type, to the specified hword index (offset).
uhword read_uhword(const size_t offset) override;
void write_uhword(const size_t offset, const uhword value) override;
uword read_uword(const size_t offset) override;
void write_uword(const size_t offset, const uword value) override;
udword read_udword(const size_t offset) override;
void write_udword(const size_t offset, const udword value) override;
uqword read_uqword(const size_t offset) override;
void write_uqword(const size_t offset, const uqword value) override;
uhword read_uhword(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayHwordMemory with an invalid offset.");
#endif
return *reinterpret_cast<uhword*>(&memory[offset]);
}
void write_uhword(const size_t offset, const uhword value) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayHwordMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<uhword*>(&memory[offset]) = value;
}
uword read_uword(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayHwordMemory with an invalid offset.");
#endif
return *reinterpret_cast<uword*>(&memory[offset]);
}
void write_uword(const size_t offset, const uword value) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayHwordMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<uword*>(&memory[offset]) = value;
}
udword read_udword(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayHwordMemory with an invalid offset.");
#endif
return *reinterpret_cast<udword*>(&memory[offset]);
}
void write_udword(const size_t offset, const udword value) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayHwordMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<udword*>(&memory[offset]) = value;
}
uqword read_uqword(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayHwordMemory with an invalid offset.");
#endif
return *reinterpret_cast<uqword*>(&memory[offset]);
}
void write_uqword(const size_t offset, const uqword value) override
{
#if defined(BUILD_DEBUG)
if (offset >= size)
throw std::runtime_error("Tried to access ArrayHwordMemory with an invalid offset.");
#endif
if (!read_only)
*reinterpret_cast<uqword*>(&memory[offset]) = value;
}
/// Get a reference to the memory storage.
/// Used for the emulator: sometimes we need to peek and poke directly.
std::vector<uhword> & get_memory();
std::vector<uhword> & get_memory()
{
return memory;
}
private:
/// Total size of the hword memory.
@ -50,4 +150,3 @@ private:
/// Writes are silently discarded if turned on.
bool read_only;
};

View file

@ -1,63 +0,0 @@
#include "Common/Types/Memory/ByteMemory.hpp"
void ByteMemory::read(const size_t offset, ubyte * buffer, const size_t length)
{
for (size_t i = 0; i < length; i++)
buffer[i] = read_ubyte(offset + i);
}
void ByteMemory::write(const size_t offset, const ubyte * buffer, const size_t length)
{
for (size_t i = 0; i < length; i++)
write_ubyte(offset + i, buffer[i]);
}
ubyte ByteMemory::byte_bus_read_ubyte(const BusContext context, const usize offset)
{
return read_ubyte(offset);
}
void ByteMemory::byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value)
{
write_ubyte(offset, value);
}
uhword ByteMemory::byte_bus_read_uhword(const BusContext context, const usize offset)
{
return read_uhword(offset);
}
void ByteMemory::byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value)
{
write_uhword(offset, value);
}
uword ByteMemory::byte_bus_read_uword(const BusContext context, const usize offset)
{
return read_uword(offset);
}
void ByteMemory::byte_bus_write_uword(const BusContext context, const usize offset, const uword value)
{
write_uword(offset, value);
}
udword ByteMemory::byte_bus_read_udword(const BusContext context, const usize offset)
{
return read_udword(offset);
}
void ByteMemory::byte_bus_write_udword(const BusContext context, const usize offset, const udword value)
{
write_udword(offset, value);
}
uqword ByteMemory::byte_bus_read_uqword(const BusContext context, const usize offset)
{
return read_uqword(offset);
}
void ByteMemory::byte_bus_write_uqword(const BusContext context, const usize offset, const uqword value)
{
write_uqword(offset, value);
}

View file

@ -27,22 +27,68 @@ public:
/// Reads bytes to the buffer given.
/// This is a wrapper around the read_ubyte function, and should not be treated as a separate interface (not made virtual).
void read(const size_t offset, ubyte * buffer, const size_t length);
void read(const size_t offset, ubyte * buffer, const size_t length)
{
for (size_t i = 0; i < length; i++)
buffer[i] = read_ubyte(offset + i);
}
/// Writes bytes from the buffer given.
/// This is a wrapper around the write_ubyte function, and should not be treated as a separate interface (not made virtual).
void write(const size_t offset, const ubyte * buffer, const size_t length);
void write(const size_t offset, const ubyte * buffer, const size_t length)
{
for (size_t i = 0; i < length; i++)
write_ubyte(offset + i, buffer[i]);
}
/// ByteBusMappable overrides.
ubyte byte_bus_read_ubyte(const BusContext context, const usize offset) override;
void byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value) override;
uhword byte_bus_read_uhword(const BusContext context, const usize offset) override;
void byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value) override;
uword byte_bus_read_uword(const BusContext context, const usize offset) override;
void byte_bus_write_uword(const BusContext context, const usize offset, const uword value) override;
udword byte_bus_read_udword(const BusContext context, const usize offset) override;
void byte_bus_write_udword(const BusContext context, const usize offset, const udword value) override;
uqword byte_bus_read_uqword(const BusContext context, const usize offset) override;
void byte_bus_write_uqword(const BusContext context, const usize offset, const uqword value) override;
};
ubyte byte_bus_read_ubyte(const BusContext context, const usize offset)
{
return read_ubyte(offset);
}
void byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value)
{
write_ubyte(offset, value);
}
uhword byte_bus_read_uhword(const BusContext context, const usize offset)
{
return read_uhword(offset);
}
void byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value)
{
write_uhword(offset, value);
}
uword byte_bus_read_uword(const BusContext context, const usize offset)
{
return read_uword(offset);
}
void byte_bus_write_uword(const BusContext context, const usize offset, const uword value)
{
write_uword(offset, value);
}
udword byte_bus_read_udword(const BusContext context, const usize offset)
{
return read_udword(offset);
}
void byte_bus_write_udword(const BusContext context, const usize offset, const udword value)
{
write_udword(offset, value);
}
uqword byte_bus_read_uqword(const BusContext context, const usize offset)
{
return read_uqword(offset);
}
void byte_bus_write_uqword(const BusContext context, const usize offset, const uqword value)
{
write_uqword(offset, value);
}
};

View file

@ -1,13 +0,0 @@
#include "Common/Types/Memory/HwordMemory.hpp"
void HwordMemory::read(const size_t offset, uhword * buffer, const size_t length)
{
for (size_t i = 0; i < length; i++)
buffer[i] = read_uhword(offset + i);
}
void HwordMemory::write(const size_t offset, const uhword * buffer, const size_t length)
{
for (size_t i = 0; i < length; i++)
write_uhword(offset + i, buffer[i]);
}

View file

@ -23,10 +23,17 @@ public:
/// Reads hwords to the buffer given.
/// This is a wrapper around the read_uhword function, and should not be treated as a separate interface (not made virtual).
void read(const size_t offset, uhword * buffer, const size_t length);
void read(const size_t offset, uhword * buffer, const size_t length)
{
for (size_t i = 0; i < length; i++)
buffer[i] = read_uhword(offset + i);
}
/// Writes hwords from the buffer given.
/// This is a wrapper around the write_uhword function, and should not be treated as a separate interface (not made virtual).
void write(const size_t offset, const uhword * buffer, const size_t length);
void write(const size_t offset, const uhword * buffer, const size_t length)
{
for (size_t i = 0; i < length; i++)
write_uhword(offset + i, buffer[i]);
}
};

View file

@ -1,7 +1,7 @@
#pragma once
#include "Common/Types/Primitive.hpp"
#include "Common/Types/Register/WordRegister.hpp"
#include "Common/Types/Register/PcRegisters.hpp"
/// Contains functionallity for the branch delay slot featured in MIPS CPU's.
/// A branch delay occurs when a jump/branch instruction is hit,
@ -10,7 +10,7 @@
/// configured branch slots have been run, and then the jump/branch occurs.
/// A default slot size of 1 is used by the EE and IOP cores.
/// slot + 1 is used internally as this is the real amount of instruction cycles.
template<int slots = 1>
template<size_t slots = 1>
class BranchDelaySlot
{
public:
@ -75,6 +75,6 @@ public:
}
private:
int current_slot;
size_t current_slot;
uptr branch_pc;
};

View file

@ -1,31 +0,0 @@
#include "Common/Types/Register/ByteRegister.hpp"
ubyte ByteRegister::extract_field(const Bitfield field)
{
return field.extract_from(read_ubyte());
}
void ByteRegister::insert_field(const Bitfield field, const ubyte value)
{
write_ubyte(field.insert_into(read_ubyte(), value));
}
ubyte ByteRegister::byte_bus_read_ubyte(const BusContext context, const usize offset)
{
return read_ubyte();
}
void ByteRegister::byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value)
{
write_ubyte(value);
}
void ByteRegister::offset(const sbyte value)
{
write_ubyte(read_ubyte() + value);
}
usize ByteRegister::byte_bus_map_size() const
{
return static_cast<usize>(1);
}

View file

@ -2,6 +2,7 @@
#include <cstddef>
#include "Common/Types/Primitive.hpp"
#include "Common/Types/Bus/ByteBusMappable.hpp"
#include "Common/Types/Bitfield.hpp"
@ -17,14 +18,35 @@ public:
virtual void write_ubyte(const ubyte value) = 0;
/// Bitfield extraction/insertion.
ubyte extract_field(const Bitfield field);
void insert_field(const Bitfield field, const ubyte value);
ubyte extract_field(const Bitfield field)
{
return field.extract_from(read_ubyte());
}
void insert_field(const Bitfield field, const ubyte value)
{
write_ubyte(field.insert_into(read_ubyte(), value));
}
/// Offsets the register by the specified (signed) value.
void offset(const sbyte value);
void offset(const sbyte value)
{
write_ubyte(read_ubyte() + value);
}
/// ByteBusMappable overrides.
usize byte_bus_map_size() const override;
ubyte byte_bus_read_ubyte(const BusContext context, const usize offset) override;
void byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value) override;
usize byte_bus_map_size() const override
{
return static_cast<usize>(1);
}
ubyte byte_bus_read_ubyte(const BusContext context, const usize offset) override
{
return read_ubyte();
}
void byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value) override
{
write_ubyte(value);
}
};

View file

@ -1,61 +0,0 @@
#include "Common/Types/Register/DwordRegister.hpp"
udword DwordRegister::extract_field(const Bitfield field)
{
return field.extract_from(read_udword());
}
void DwordRegister::insert_field(const Bitfield field, const udword value)
{
write_udword(field.insert_into(read_udword(), value));
}
ubyte DwordRegister::byte_bus_read_ubyte(const BusContext context, const usize offset)
{
return read_ubyte(offset);
}
void DwordRegister::byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value)
{
write_ubyte(offset, value);
}
uhword DwordRegister::byte_bus_read_uhword(const BusContext context, const usize offset)
{
return read_uhword(offset / NUMBER_BYTES_IN_HWORD);
}
void DwordRegister::byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value)
{
write_uhword(offset / NUMBER_BYTES_IN_HWORD, value);
}
uword DwordRegister::byte_bus_read_uword(const BusContext context, const usize offset)
{
return read_uword(offset / NUMBER_BYTES_IN_WORD);
}
void DwordRegister::byte_bus_write_uword(const BusContext context, const usize offset, const uword value)
{
write_uword(offset / NUMBER_BYTES_IN_WORD, value);
}
udword DwordRegister::byte_bus_read_udword(const BusContext context, const usize offset)
{
return read_udword();
}
void DwordRegister::byte_bus_write_udword(const BusContext context, const usize offset, const udword value)
{
write_udword(value);
}
void DwordRegister::offset(const sdword value)
{
write_udword(read_udword() + value);
}
usize DwordRegister::byte_bus_map_size() const
{
return static_cast<usize>(NUMBER_BYTES_IN_DWORD);
}

View file

@ -2,6 +2,7 @@
#include <cstddef>
#include "Common/Types/Primitive.hpp"
#include "Common/Types/Bus/ByteBusMappable.hpp"
#include "Common/Types/Bitfield.hpp"
@ -23,20 +24,65 @@ public:
virtual void write_udword(const udword value) = 0;
/// Bitfield extraction/insertion.
udword extract_field(const Bitfield field);
void insert_field(const Bitfield field, const udword value);
udword extract_field(const Bitfield field)
{
return field.extract_from(read_udword());
}
void insert_field(const Bitfield field, const udword value)
{
write_udword(field.insert_into(read_udword(), value));
}
/// Offsets the register by the specified (signed) value.
void offset(const sdword value);
void offset(const sdword value)
{
write_udword(read_udword() + value);
}
/// ByteBusMappable overrides.
usize byte_bus_map_size() const override;
ubyte byte_bus_read_ubyte(const BusContext context, const usize offset) override;
void byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value) override;
uhword byte_bus_read_uhword(const BusContext context, const usize offset) override;
void byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value) override;
uword byte_bus_read_uword(const BusContext context, const usize offset) override;
void byte_bus_write_uword(const BusContext context, const usize offset, const uword value) override;
udword byte_bus_read_udword(const BusContext context, const usize offset) override;
void byte_bus_write_udword(const BusContext context, const usize offset, const udword value) override;
};
usize byte_bus_map_size() const override
{
return static_cast<usize>(NUMBER_BYTES_IN_DWORD);
}
ubyte byte_bus_read_ubyte(const BusContext context, const usize offset) override
{
return read_ubyte(offset);
}
void byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value) override
{
write_ubyte(offset, value);
}
uhword byte_bus_read_uhword(const BusContext context, const usize offset) override
{
return read_uhword(offset / NUMBER_BYTES_IN_HWORD);
}
void byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value) override
{
write_uhword(offset / NUMBER_BYTES_IN_HWORD, value);
}
uword byte_bus_read_uword(const BusContext context, const usize offset) override
{
return read_uword(offset / NUMBER_BYTES_IN_WORD);
}
void byte_bus_write_uword(const BusContext context, const usize offset, const uword value) override
{
write_uword(offset / NUMBER_BYTES_IN_WORD, value);
}
udword byte_bus_read_udword(const BusContext context, const usize offset) override
{
return read_udword();
}
void byte_bus_write_udword(const BusContext context, const usize offset, const udword value) override
{
write_udword(value);
}
};

View file

@ -1,41 +0,0 @@
#include "Common/Types/Register/HwordRegister.hpp"
uhword HwordRegister::extract_field(const Bitfield field)
{
return field.extract_from(read_uhword());
}
void HwordRegister::insert_field(const Bitfield field, const uhword value)
{
write_uhword(field.insert_into(read_uhword(), value));
}
ubyte HwordRegister::byte_bus_read_ubyte(const BusContext context, const usize offset)
{
return read_ubyte(offset);
}
void HwordRegister::byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value)
{
write_ubyte(offset, value);
}
uhword HwordRegister::byte_bus_read_uhword(const BusContext context, const usize offset)
{
return read_uhword();
}
void HwordRegister::byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value)
{
write_uhword(value);
}
void HwordRegister::offset(const shword value)
{
write_uhword(read_uhword() + value);
}
usize HwordRegister::byte_bus_map_size() const
{
return static_cast<usize>(NUMBER_BYTES_IN_HWORD);
}

View file

@ -2,6 +2,7 @@
#include <cstddef>
#include "Common/Types/Primitive.hpp"
#include "Common/Types/Bus/ByteBusMappable.hpp"
#include "Common/Types/Bitfield.hpp"
@ -19,16 +20,45 @@ public:
virtual void write_uhword(const uhword value) = 0;
/// Bitfield extraction/insertion.
uhword extract_field(const Bitfield field);
void insert_field(const Bitfield field, const uhword value);
uhword extract_field(const Bitfield field)
{
return field.extract_from(read_uhword());
}
void insert_field(const Bitfield field, const uhword value)
{
write_uhword(field.insert_into(read_uhword(), value));
}
/// Offsets the register by the specified (signed) value.
void offset(const shword value);
void offset(const shword value)
{
write_uhword(read_uhword() + value);
}
/// ByteBusMappable overrides.
usize byte_bus_map_size() const override;
ubyte byte_bus_read_ubyte(const BusContext context, const usize offset) override;
void byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value) override;
uhword byte_bus_read_uhword(const BusContext context, const usize offset) override;
void byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value) override;
};
usize byte_bus_map_size() const override
{
return static_cast<usize>(NUMBER_BYTES_IN_HWORD);
}
ubyte byte_bus_read_ubyte(const BusContext context, const usize offset) override
{
return read_ubyte(offset);
}
void byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value) override
{
write_ubyte(offset, value);
}
uhword byte_bus_read_uhword(const BusContext context, const usize offset) override
{
return read_uhword();
}
void byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value) override
{
write_uhword(value);
}
};

View file

@ -1,37 +0,0 @@
#include "Common/Types/Register/MapperHwordWordRegister.hpp"
#include "Common/Types/Register/HwordRegister.hpp"
void MapperHwordWordRegister::initialise()
{
hword_register->initialise();
}
ubyte MapperHwordWordRegister::read_ubyte(const size_t offset)
{
throw std::runtime_error("Only Word R/W wrapper calls to HwordRegister are allowed.");
}
void MapperHwordWordRegister::write_ubyte(const size_t offset, const ubyte value)
{
throw std::runtime_error("Only Word R/W wrapper calls to HwordRegister are allowed.");
}
uhword MapperHwordWordRegister::read_uhword(const size_t offset)
{
throw std::runtime_error("Only Word R/W wrapper calls to HwordRegister are allowed.");
}
void MapperHwordWordRegister::write_uhword(const size_t offset, const uhword value)
{
throw std::runtime_error("Only Word R/W wrapper calls to HwordRegister are allowed.");
}
uword MapperHwordWordRegister::read_uword()
{
return static_cast<uword>(hword_register->read_uhword());
}
void MapperHwordWordRegister::write_uword(const uword value)
{
hword_register->write_uhword(static_cast<uhword>(value));
}

View file

@ -1,22 +1,50 @@
#pragma once
#include "Common/Types/Register/WordRegister.hpp"
#include <stdexcept>
class HwordRegister;
#include "Common/Types/Primitive.hpp"
#include "Common/Types/Register/WordRegister.hpp"
#include "Common/Types/Register/HwordRegister.hpp"
/// Maps a hword register to word register by zero-filling or truncating.
class MapperHwordWordRegister : public WordRegister
{
public:
/// Initialise register (initialise underlying register).
void initialise() override;
void initialise() override
{
hword_register->initialise();
}
ubyte read_ubyte(const size_t offset) override;
void write_ubyte(const size_t offset, const ubyte value) override;
uhword read_uhword(const size_t offset) override;
void write_uhword(const size_t offset, const uhword value) override;
uword read_uword() override;
void write_uword(const uword value) override;
ubyte read_ubyte(const size_t offset) override
{
throw std::runtime_error("Only Word R/W wrapper calls to HwordRegister are allowed.");
}
void write_ubyte(const size_t offset, const ubyte value) override
{
throw std::runtime_error("Only Word R/W wrapper calls to HwordRegister are allowed.");
}
uhword read_uhword(const size_t offset) override
{
throw std::runtime_error("Only Word R/W wrapper calls to HwordRegister are allowed.");
}
void write_uhword(const size_t offset, const uhword value) override
{
throw std::runtime_error("Only Word R/W wrapper calls to HwordRegister are allowed.");
}
uword read_uword() override
{
return static_cast<uword>(hword_register->read_uhword());
}
void write_uword(const uword value) override
{
hword_register->write_uhword(static_cast<uhword>(value));
}
/// Reference to mapped hword register.
HwordRegister * hword_register;

View file

@ -1,66 +0,0 @@
#include "Common/Types/Register/QwordRegister.hpp"
ubyte QwordRegister::byte_bus_read_ubyte(const BusContext context, const usize offset)
{
return read_ubyte(offset);
}
void QwordRegister::byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value)
{
write_ubyte(offset, value);
}
uhword QwordRegister::byte_bus_read_uhword(const BusContext context, const usize offset)
{
return read_uhword(offset / NUMBER_BYTES_IN_HWORD);
}
void QwordRegister::byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value)
{
write_uhword(offset / NUMBER_BYTES_IN_HWORD, value);
}
uword QwordRegister::byte_bus_read_uword(const BusContext context, const usize offset)
{
return read_uword(offset / NUMBER_BYTES_IN_WORD);
}
void QwordRegister::byte_bus_write_uword(const BusContext context, const usize offset, const uword value)
{
write_uword(offset / NUMBER_BYTES_IN_WORD, value);
}
udword QwordRegister::byte_bus_read_udword(const BusContext context, const usize offset)
{
return read_udword(offset / NUMBER_BYTES_IN_DWORD);
}
void QwordRegister::byte_bus_write_udword(const BusContext context, const usize offset, const udword value)
{
write_udword(offset / NUMBER_BYTES_IN_DWORD, value);
}
uqword QwordRegister::byte_bus_read_uqword(const BusContext context, const usize offset)
{
return read_uqword();
}
void QwordRegister::byte_bus_write_uqword(const BusContext context, const usize offset, const uqword value)
{
write_uqword(value);
}
f32 QwordRegister::read_float(const size_t offset)
{
return static_cast<f32>(read_uword(offset));
}
void QwordRegister::write_float(const size_t offset, const f32 value)
{
write_uword(offset, static_cast<uword>(value));
}
usize QwordRegister::byte_bus_map_size() const
{
return static_cast<usize>(NUMBER_BYTES_IN_QWORD);
}

View file

@ -2,6 +2,7 @@
#include <cstddef>
#include "Common/Types/Primitive.hpp"
#include "Common/Types/Bus/ByteBusMappable.hpp"
/// Qword register.
@ -24,19 +25,73 @@ public:
virtual void write_uqword(const uqword value) = 0;
/// Read/write floats - wrappers around read/write uword.
f32 read_float(const size_t offset);
void write_float(const size_t offset, const f32 value);
f32 read_float(const size_t offset)
{
return static_cast<f32>(read_uword(offset));
}
void write_float(const size_t offset, const f32 value)
{
write_uword(offset, static_cast<uword>(value));
}
/// ByteBusMappable overrides.
usize byte_bus_map_size() const override;
ubyte byte_bus_read_ubyte(const BusContext context, const usize offset) override;
void byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value) override;
uhword byte_bus_read_uhword(const BusContext context, const usize offset) override;
void byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value) override;
uword byte_bus_read_uword(const BusContext context, const usize offset) override;
void byte_bus_write_uword(const BusContext context, const usize offset, const uword value) override;
udword byte_bus_read_udword(const BusContext context, const usize offset) override;
void byte_bus_write_udword(const BusContext context, const usize offset, const udword value) override;
uqword byte_bus_read_uqword(const BusContext context, const usize offset) override;
void byte_bus_write_uqword(const BusContext context, const usize offset, const uqword value) override;
};
usize byte_bus_map_size() const override
{
return static_cast<usize>(NUMBER_BYTES_IN_QWORD);
}
ubyte byte_bus_read_ubyte(const BusContext context, const usize offset) override
{
return read_ubyte(offset);
}
void byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value) override
{
write_ubyte(offset, value);
}
uhword byte_bus_read_uhword(const BusContext context, const usize offset) override
{
return read_uhword(offset / NUMBER_BYTES_IN_HWORD);
}
void byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value) override
{
write_uhword(offset / NUMBER_BYTES_IN_HWORD, value);
}
uword byte_bus_read_uword(const BusContext context, const usize offset) override
{
return read_uword(offset / NUMBER_BYTES_IN_WORD);
}
void byte_bus_write_uword(const BusContext context, const usize offset, const uword value) override
{
write_uword(offset / NUMBER_BYTES_IN_WORD, value);
}
udword byte_bus_read_udword(const BusContext context, const usize offset) override
{
return read_udword(offset / NUMBER_BYTES_IN_DWORD);
}
void byte_bus_write_udword(const BusContext context, const usize offset, const udword value) override
{
write_udword(offset / NUMBER_BYTES_IN_DWORD, value);
}
uqword byte_bus_read_uqword(const BusContext context, const usize offset) override
{
return read_uqword();
}
void byte_bus_write_uqword(const BusContext context, const usize offset, const uqword value) override
{
write_uqword(value);
}
};

View file

@ -1,24 +0,0 @@
#include "Common/Types/Register/SizedByteRegister.hpp"
SizedByteRegister::SizedByteRegister(const ubyte initial_value, const bool read_only) :
b(initial_value),
initial_value(initial_value),
read_only(read_only)
{
}
void SizedByteRegister::initialise()
{
b = initial_value;
}
ubyte SizedByteRegister::read_ubyte()
{
return b;
}
void SizedByteRegister::write_ubyte(const ubyte value)
{
if (!read_only)
b = value;
}

View file

@ -6,14 +6,30 @@
class SizedByteRegister : public ByteRegister
{
public:
SizedByteRegister(const ubyte initial_value = 0, const bool read_only = false);
SizedByteRegister(const ubyte initial_value = 0, const bool read_only = false) :
b(initial_value),
initial_value(initial_value),
read_only(read_only)
{
}
/// Initialise register.
void initialise() override;
void initialise() override
{
b = initial_value;
}
/// Read/write functions to access the register.
ubyte read_ubyte() override;
void write_ubyte(const ubyte value) override;
ubyte read_ubyte() override
{
return b;
}
void write_ubyte(const ubyte value) override
{
if (!read_only)
b = value;
}
private:
/// Primitive (sized) storage for register.
@ -28,4 +44,4 @@ private:
/// Read-only flag.
/// Writes are silently discarded if turned on.
bool read_only;
};
};

View file

@ -1,87 +0,0 @@
#include "Common/Types/Register/SizedDwordRegister.hpp"
SizedDwordRegister::SizedDwordRegister(const udword initial_value, const bool read_only) :
d(initial_value),
initial_value(initial_value),
read_only(read_only)
{
}
void SizedDwordRegister::initialise()
{
d = initial_value;
}
ubyte SizedDwordRegister::read_ubyte(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_BYTES_IN_DWORD)
throw std::runtime_error("Tried to access SizedDwordRegister with an invalid offset.");
#endif
return b[offset];
}
void SizedDwordRegister::write_ubyte(const size_t offset, const ubyte value)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_BYTES_IN_DWORD)
throw std::runtime_error("Tried to access SizedDwordRegister with an invalid offset.");
#endif
if (!read_only)
b[offset] = value;
}
uhword SizedDwordRegister::read_uhword(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_HWORDS_IN_DWORD)
throw std::runtime_error("Tried to access SizedDwordRegister with an invalid offset.");
#endif
return h[offset];
}
void SizedDwordRegister::write_uhword(const size_t offset, const uhword value)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_HWORDS_IN_DWORD)
throw std::runtime_error("Tried to access SizedDwordRegister with an invalid offset.");
#endif
if (!read_only)
h[offset] = value;
}
uword SizedDwordRegister::read_uword(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_WORDS_IN_DWORD)
throw std::runtime_error("Tried to access SizedDwordRegister with an invalid offset.");
#endif
return w[offset];
}
void SizedDwordRegister::write_uword(const size_t offset, const uword value)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_WORDS_IN_DWORD)
throw std::runtime_error("Tried to access SizedDwordRegister with an invalid offset.");
#endif
if (!read_only)
w[offset] = value;
}
udword SizedDwordRegister::read_udword()
{
return d;
}
void SizedDwordRegister::write_udword(const udword value)
{
if (!read_only)
d = value;
}

View file

@ -1,25 +1,101 @@
#pragma once
#include <stdexcept>
#include "Common/Types/Primitive.hpp"
#include "Common/Types/Register/DwordRegister.hpp"
/// Sized Dword register.
class SizedDwordRegister : public DwordRegister
{
public:
SizedDwordRegister(const udword initial_value = 0, const bool read_only = false);
SizedDwordRegister(const udword initial_value = 0, const bool read_only = false) :
d(initial_value),
initial_value(initial_value),
read_only(read_only)
{
}
/// Initialise register.
void initialise() override;
void initialise() override
{
d = initial_value;
}
/// Read/write functions to access the register.
ubyte read_ubyte(const size_t offset) override;
void write_ubyte(const size_t offset, const ubyte value) override;
uhword read_uhword(const size_t offset) override;
void write_uhword(const size_t offset, const uhword value) override;
uword read_uword(const size_t offset) override;
void write_uword(const size_t offset, const uword value) override;
udword read_udword() override;
void write_udword(const udword value) override;
ubyte read_ubyte(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_BYTES_IN_DWORD)
throw std::runtime_error("Tried to access SizedDwordRegister with an invalid offset.");
#endif
return b[offset];
}
void write_ubyte(const size_t offset, const ubyte value) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_BYTES_IN_DWORD)
throw std::runtime_error("Tried to access SizedDwordRegister with an invalid offset.");
#endif
if (!read_only)
b[offset] = value;
}
uhword read_uhword(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_HWORDS_IN_DWORD)
throw std::runtime_error("Tried to access SizedDwordRegister with an invalid offset.");
#endif
return h[offset];
}
void write_uhword(const size_t offset, const uhword value) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_HWORDS_IN_DWORD)
throw std::runtime_error("Tried to access SizedDwordRegister with an invalid offset.");
#endif
if (!read_only)
h[offset] = value;
}
uword read_uword(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_WORDS_IN_DWORD)
throw std::runtime_error("Tried to access SizedDwordRegister with an invalid offset.");
#endif
return w[offset];
}
void write_uword(const size_t offset, const uword value) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_WORDS_IN_DWORD)
throw std::runtime_error("Tried to access SizedDwordRegister with an invalid offset.");
#endif
if (!read_only)
w[offset] = value;
}
udword read_udword() override
{
return d;
}
void write_udword(const udword value) override
{
if (!read_only)
d = value;
}
private:
/// Primitive (sized) storage for register.
@ -37,4 +113,5 @@ private:
/// Read-only flag.
/// Writes are silently discarded if turned on.
bool read_only;
};
};

View file

@ -1,45 +0,0 @@
#include "Common/Types/Register/SizedHwordRegister.hpp"
SizedHwordRegister::SizedHwordRegister(const uhword initial_value, const bool read_only) :
h(initial_value),
initial_value(initial_value),
read_only(read_only)
{
}
void SizedHwordRegister::initialise()
{
h = initial_value;
}
ubyte SizedHwordRegister::read_ubyte(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_BYTES_IN_HWORD)
throw std::runtime_error("Tried to access SizedHwordRegister with an invalid offset.");
#endif
return b[offset];
}
void SizedHwordRegister::write_ubyte(const size_t offset, const ubyte value)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_BYTES_IN_HWORD)
throw std::runtime_error("Tried to access SizedHwordRegister with an invalid offset.");
#endif
if (!read_only)
b[offset] = value;
}
uhword SizedHwordRegister::read_uhword()
{
return h;
}
void SizedHwordRegister::write_uhword(const uhword value)
{
if (!read_only)
h = value;
}

View file

@ -1,21 +1,59 @@
#pragma once
#include <stdexcept>
#include "Common/Types/Primitive.hpp"
#include "Common/Types/Register/HwordRegister.hpp"
/// Sized Hword register.
class SizedHwordRegister : public HwordRegister
{
public:
SizedHwordRegister(const uhword initial_value = 0, const bool read_only = false);
SizedHwordRegister(const uhword initial_value = 0, const bool read_only = false) :
h(initial_value),
initial_value(initial_value),
read_only(read_only)
{
}
/// Initialise register.
void initialise() override;
void initialise() override
{
h = initial_value;
}
/// Read/write functions to access the register.
ubyte read_ubyte(const size_t offset) override;
void write_ubyte(const size_t offset, const ubyte value) override;
uhword read_uhword() override;
void write_uhword(const uhword value) override;
ubyte read_ubyte(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_BYTES_IN_HWORD)
throw std::runtime_error("Tried to access SizedHwordRegister with an invalid offset.");
#endif
return b[offset];
}
void write_ubyte(const size_t offset, const ubyte value) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_BYTES_IN_HWORD)
throw std::runtime_error("Tried to access SizedHwordRegister with an invalid offset.");
#endif
if (!read_only)
b[offset] = value;
}
uhword read_uhword() override
{
return h;
}
void write_uhword(const uhword value) override
{
if (!read_only)
h = value;
}
private:
/// Primitive (sized) storage for register.
@ -31,4 +69,4 @@ private:
/// Read-only flag.
/// Writes are silently discarded if turned on.
bool read_only;
};
};

View file

@ -1,108 +0,0 @@
#include "Common/Types/Register/SizedQwordRegister.hpp"
SizedQwordRegister::SizedQwordRegister(const uqword initial_value, const bool read_only) :
q(initial_value),
initial_value(initial_value),
read_only(read_only)
{
}
void SizedQwordRegister::initialise()
{
q = initial_value;
}
ubyte SizedQwordRegister::read_ubyte(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_BYTES_IN_QWORD)
throw std::runtime_error("Tried to access SizedQwordRegister with an invalid offset.");
#endif
return b[offset];
}
void SizedQwordRegister::write_ubyte(const size_t offset, const ubyte value)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_BYTES_IN_QWORD)
throw std::runtime_error("Tried to access SizedQwordRegister with an invalid offset.");
#endif
if (!read_only)
b[offset] = value;
}
uhword SizedQwordRegister::read_uhword(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_HWORDS_IN_QWORD)
throw std::runtime_error("Tried to access SizedQwordRegister with an invalid offset.");
#endif
return h[offset];
}
void SizedQwordRegister::write_uhword(const size_t offset, const uhword value)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_HWORDS_IN_QWORD)
throw std::runtime_error("Tried to access SizedQwordRegister with an invalid offset.");
#endif
if (!read_only)
h[offset] = value;
}
uword SizedQwordRegister::read_uword(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_WORDS_IN_QWORD)
throw std::runtime_error("Tried to access SizedQwordRegister with an invalid offset.");
#endif
return w[offset];
}
void SizedQwordRegister::write_uword(const size_t offset, const uword value)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_WORDS_IN_QWORD)
throw std::runtime_error("Tried to access SizedQwordRegister with an invalid offset.");
#endif
if (!read_only)
w[offset] = value;
}
udword SizedQwordRegister::read_udword(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_WORDS_IN_QWORD)
throw std::runtime_error("Tried to access SizedQwordRegister with an invalid offset.");
#endif
return d[offset];
}
void SizedQwordRegister::write_udword(const size_t offset, const udword value)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_WORDS_IN_QWORD)
throw std::runtime_error("Tried to access SizedQwordRegister with an invalid offset.");
#endif
if (!read_only)
d[offset] = value;
}
uqword SizedQwordRegister::read_uqword()
{
return q;
}
void SizedQwordRegister::write_uqword(const uqword value)
{
if (!read_only)
q = value;
}

View file

@ -1,27 +1,122 @@
#pragma once
#include <stdexcept>
#include "Common/Types/Primitive.hpp"
#include "Common/Types/Register/QwordRegister.hpp"
/// Sized Qword register.
class SizedQwordRegister : public QwordRegister
{
public:
SizedQwordRegister(const uqword initial_value = 0, const bool read_only = false);
SizedQwordRegister(const uqword initial_value = 0, const bool read_only = false) :
q(initial_value),
initial_value(initial_value),
read_only(read_only)
{
}
/// Initialise register.
void initialise() override;
void initialise() override
{
q = initial_value;
}
/// Read/write functions to access the register.
ubyte read_ubyte(const size_t offset) override;
void write_ubyte(const size_t offset, const ubyte value) override;
uhword read_uhword(const size_t offset) override;
void write_uhword(const size_t offset, const uhword value) override;
uword read_uword(const size_t offset) override;
void write_uword(const size_t offset, const uword value) override;
udword read_udword(const size_t offset) override;
void write_udword(const size_t offset, const udword value) override;
uqword read_uqword() override;
void write_uqword(const uqword value) override;
ubyte read_ubyte(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_BYTES_IN_QWORD)
throw std::runtime_error("Tried to access SizedQwordRegister with an invalid offset.");
#endif
return b[offset];
}
void write_ubyte(const size_t offset, const ubyte value) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_BYTES_IN_QWORD)
throw std::runtime_error("Tried to access SizedQwordRegister with an invalid offset.");
#endif
if (!read_only)
b[offset] = value;
}
uhword read_uhword(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_HWORDS_IN_QWORD)
throw std::runtime_error("Tried to access SizedQwordRegister with an invalid offset.");
#endif
return h[offset];
}
void write_uhword(const size_t offset, const uhword value) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_HWORDS_IN_QWORD)
throw std::runtime_error("Tried to access SizedQwordRegister with an invalid offset.");
#endif
if (!read_only)
h[offset] = value;
}
uword read_uword(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_WORDS_IN_QWORD)
throw std::runtime_error("Tried to access SizedQwordRegister with an invalid offset.");
#endif
return w[offset];
}
void write_uword(const size_t offset, const uword value) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_WORDS_IN_QWORD)
throw std::runtime_error("Tried to access SizedQwordRegister with an invalid offset.");
#endif
if (!read_only)
w[offset] = value;
}
udword read_udword(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_WORDS_IN_QWORD)
throw std::runtime_error("Tried to access SizedQwordRegister with an invalid offset.");
#endif
return d[offset];
}
void write_udword(const size_t offset, const udword value) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_WORDS_IN_QWORD)
throw std::runtime_error("Tried to access SizedQwordRegister with an invalid offset.");
#endif
if (!read_only)
d[offset] = value;
}
uqword read_uqword() override
{
return q;
}
void write_uqword(const uqword value) override
{
if (!read_only)
q = value;
}
private:
/// Primitive (sized) storage for register.
@ -40,4 +135,5 @@ private:
/// Read-only flag.
/// Writes are silently discarded if turned on.
bool read_only;
};
};

View file

@ -1,66 +0,0 @@
#include "Common/Types/Register/SizedWordRegister.hpp"
SizedWordRegister::SizedWordRegister(const uword initial_value, const bool read_only) :
w(initial_value),
initial_value(initial_value),
read_only(read_only)
{
}
void SizedWordRegister::initialise()
{
w = initial_value;
}
ubyte SizedWordRegister::read_ubyte(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_BYTES_IN_WORD)
throw std::runtime_error("Tried to access SizedWordRegister with an invalid offset.");
#endif
return b[offset];
}
void SizedWordRegister::write_ubyte(const size_t offset, const ubyte value)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_BYTES_IN_WORD)
throw std::runtime_error("Tried to access SizedWordRegister with an invalid offset.");
#endif
if (!read_only)
b[offset] = value;
}
uhword SizedWordRegister::read_uhword(const size_t offset)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_HWORDS_IN_WORD)
throw std::runtime_error("Tried to access SizedWordRegister with an invalid offset.");
#endif
return h[offset];
}
void SizedWordRegister::write_uhword(const size_t offset, const uhword value)
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_HWORDS_IN_WORD)
throw std::runtime_error("Tried to access SizedWordRegister with an invalid offset.");
#endif
if (!read_only)
h[offset] = value;
}
uword SizedWordRegister::read_uword()
{
return w;
}
void SizedWordRegister::write_uword(const uword value)
{
if (!read_only)
w = value;
}

View file

@ -1,23 +1,80 @@
#pragma once
#include <stdexcept>
#include "Common/Types/Primitive.hpp"
#include "Common/Types/Register/WordRegister.hpp"
/// Sized Word register.
class SizedWordRegister : public WordRegister
{
public:
SizedWordRegister(const uword initial_value = 0, const bool read_only = false);
SizedWordRegister(const uword initial_value = 0, const bool read_only = false) :
w(initial_value),
initial_value(initial_value),
read_only(read_only)
{
}
/// Initialise register.
void initialise() override;
void initialise() override
{
w = initial_value;
}
/// Read/write functions to access the register.
ubyte read_ubyte(const size_t offset) override;
void write_ubyte(const size_t offset, const ubyte value) override;
uhword read_uhword(const size_t offset) override;
void write_uhword(const size_t offset, const uhword value) override;
uword read_uword() override;
void write_uword(const uword value) override;
ubyte read_ubyte(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_BYTES_IN_WORD)
throw std::runtime_error("Tried to access SizedWordRegister with an invalid offset.");
#endif
return b[offset];
}
void write_ubyte(const size_t offset, const ubyte value) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_BYTES_IN_WORD)
throw std::runtime_error("Tried to access SizedWordRegister with an invalid offset.");
#endif
if (!read_only)
b[offset] = value;
}
uhword read_uhword(const size_t offset) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_HWORDS_IN_WORD)
throw std::runtime_error("Tried to access SizedWordRegister with an invalid offset.");
#endif
return h[offset];
}
void write_uhword(const size_t offset, const uhword value) override
{
#if defined(BUILD_DEBUG)
if (offset >= NUMBER_HWORDS_IN_WORD)
throw std::runtime_error("Tried to access SizedWordRegister with an invalid offset.");
#endif
if (!read_only)
h[offset] = value;
}
uword read_uword() override
{
return w;
}
void write_uword(const uword value) override
{
if (!read_only)
w = value;
}
private:
/// Primitive (sized) storage for register.
@ -34,4 +91,4 @@ private:
/// Read-only flag.
/// Writes are silently discarded if turned on.
bool read_only;
};
};

View file

@ -1,61 +0,0 @@
#include "Common/Types/Register/WordRegister.hpp"
uword WordRegister::extract_field(const Bitfield field)
{
return field.extract_from(read_uword());
}
void WordRegister::insert_field(const Bitfield field, const uword value)
{
write_uword(field.insert_into(read_uword(), value));
}
ubyte WordRegister::byte_bus_read_ubyte(const BusContext context, const usize offset)
{
return read_ubyte(offset);
}
void WordRegister::byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value)
{
write_ubyte(offset, value);
}
uhword WordRegister::byte_bus_read_uhword(const BusContext context, const usize offset)
{
return read_uhword(offset / NUMBER_BYTES_IN_HWORD);
}
void WordRegister::byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value)
{
write_uhword(offset / NUMBER_BYTES_IN_HWORD, value);
}
uword WordRegister::byte_bus_read_uword(const BusContext context, const usize offset)
{
return read_uword();
}
void WordRegister::byte_bus_write_uword(const BusContext context, const usize offset, const uword value)
{
write_uword(value);
}
void WordRegister::offset(const sword value)
{
write_uword(read_uword() + value);
}
f32 WordRegister::read_float()
{
return static_cast<f32>(read_uword());
}
void WordRegister::write_float(const f32 value)
{
write_uword(static_cast<uword>(value));
}
usize WordRegister::byte_bus_map_size() const
{
return static_cast<usize>(NUMBER_BYTES_IN_WORD);
}

View file

@ -2,6 +2,7 @@
#include <cstddef>
#include "Common/Types/Primitive.hpp"
#include "Common/Types/Bus/ByteBusMappable.hpp"
#include "Common/Types/Bitfield.hpp"
@ -21,22 +22,66 @@ public:
virtual void write_uword(const uword value) = 0;
/// Read/write floats - wrappers around read/write uword.
f32 read_float();
void write_float(const f32 value);
f32 read_float()
{
return static_cast<f32>(read_uword());
}
void write_float(const f32 value)
{
write_uword(static_cast<uword>(value));
}
/// Bitfield extraction/insertion.
uword extract_field(const Bitfield field);
void insert_field(const Bitfield field, const uword value);
uword extract_field(const Bitfield field)
{
return field.extract_from(read_uword());
}
void insert_field(const Bitfield field, const uword value)
{
write_uword(field.insert_into(read_uword(), value));
}
/// Offsets the register by the specified (signed) value.
void offset(const sword value);
void offset(const sword value)
{
write_uword(read_uword() + value);
}
/// ByteBusMappable overrides.
usize byte_bus_map_size() const override;
ubyte byte_bus_read_ubyte(const BusContext context, const usize offset) override;
void byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value) override;
uhword byte_bus_read_uhword(const BusContext context, const usize offset) override;
void byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value) override;
uword byte_bus_read_uword(const BusContext context, const usize offset) override;
void byte_bus_write_uword(const BusContext context, const usize offset, const uword value) override;
};
usize byte_bus_map_size() const override
{
return static_cast<usize>(NUMBER_BYTES_IN_WORD);
}
ubyte byte_bus_read_ubyte(const BusContext context, const usize offset) override
{
return read_ubyte(offset);
}
void byte_bus_write_ubyte(const BusContext context, const usize offset, const ubyte value) override
{
write_ubyte(offset, value);
}
uhword byte_bus_read_uhword(const BusContext context, const usize offset) override
{
return read_uhword(offset / NUMBER_BYTES_IN_HWORD);
}
void byte_bus_write_uhword(const BusContext context, const usize offset, const uhword value) override
{
write_uhword(offset / NUMBER_BYTES_IN_HWORD, value);
}
uword byte_bus_read_uword(const BusContext context, const usize offset) override
{
return read_uword();
}
void byte_bus_write_uword(const BusContext context, const usize offset, const uword value) override
{
write_uword(value);
}
};

View file

@ -452,15 +452,20 @@ std::optional<uptr> CEeCore::translate_address(const uptr virtual_address, const
return translate_address_fallback(virtual_address, rw_access);
};
std::optional<uptr> result;
switch (id_access)
{
case INSTRUCTION:
return translation_cache_inst.lookup(virtual_address, rw_access, fallback_fn);
result = translation_cache_inst.lookup(virtual_address, rw_access, fallback_fn);
break;
case DATA:
return translation_cache_data.lookup(virtual_address, rw_access, fallback_fn);
result = translation_cache_data.lookup(virtual_address, rw_access, fallback_fn);
break;
default:
throw std::runtime_error("Unrecognised id_access");
}
throw std::runtime_error("Unrecognised id_access");
return result;
}
std::optional<uptr> CEeCore::translate_address_fallback(const uptr virtual_address, const MmuRwAccess rw_access)

View file

@ -111,16 +111,6 @@ Core::~Core()
BOOST_LOG(get_logger()) << "Core shutting down";
}
const CoreOptions & Core::get_options() const
{
return options;
}
RResources & Core::get_resources() const
{
return *resources;
}
void Core::run()
{
#if defined(BUILD_DEBUG)
@ -176,22 +166,6 @@ void Core::run()
#endif
}
void Core::enqueue_controller_event(const ControllerType::Type c_type, const ControllerEvent & event)
{
EventEntry qe{ c_type, event };
controller_event_queue.push(qe);
}
TaskExecutor & Core::get_task_executor() const
{
return *task_executor;
}
boost::log::sources::logger_mt & Core::get_logger()
{
return logger;
}
void Core::dump_all_memory() const
{
boost::filesystem::create_directory(options.dumps_dir_path);

View file

@ -56,24 +56,39 @@ public:
~Core();
/// Returns a reference to the logging functionality.
static boost::log::sources::logger_mt & get_logger();
static boost::log::sources::logger_mt & get_logger()
{
return logger;
}
/// Returns the runtime core options.
const CoreOptions & get_options() const;
const CoreOptions & get_options() const
{
return options;
}
/// Returns the task executor.
TaskExecutor & get_task_executor() const
{
return *task_executor;
}
/// Returns a reference to the PS2 resources.
RResources & get_resources() const
{
return *resources;
}
/// Enqueues a controller event that is dispatched on the next synchronised run.
void enqueue_controller_event(const ControllerType::Type c_type, const ControllerEvent & event)
{
controller_event_queue.push({ c_type, event });
}
/// Runs the core and updates the state.
/// This is the main loop function.
void run();
/// Returns the task executor.
TaskExecutor & get_task_executor() const;
/// Returns a reference to the PS2 resources.
RResources & get_resources() const;
/// Enqueues a controller event that is dispatched on the next synchronised run.
void enqueue_controller_event(const ControllerType::Type c_type, const ControllerEvent & event);
/// Dumps all memory objects to the ./dumps folder.
void dump_all_memory() const;

View file

@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.8.2)
cmake_minimum_required(VERSION 3.9)
cmake_policy(SET CMP0069 NEW) # Link time optimization support
project(orbumfront CXX)

View file

@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.8.2)
cmake_minimum_required(VERSION 3.9)
cmake_policy(SET CMP0069 NEW) # Link time optimization support
project(utilities CXX)

View file

@ -11,7 +11,7 @@ template<int Size, typename KeyTy, typename ValueTy>
class ArrayLfuCache
{
private:
using CacheEntry = std::tuple<KeyTy, ValueTy, int>;
using CacheEntry = std::tuple<KeyTy, ValueTy, size_t>;
using CacheContainer = std::array<CacheEntry, Size>;
public:
@ -24,7 +24,7 @@ public:
/// Returns the value associated with the key and increments the access count.
std::optional<const ValueTy> get(const KeyTy key)
{
auto entry_it = std::find_if(cache.begin(), cache.begin() + current_cache_size, [&key](const CacheEntry & e) {
auto entry_it = std::find_if(cache.begin(), cache.begin() + current_cache_size, [key](const CacheEntry & e) {
return std::get<0>(e) == key;
});
@ -52,7 +52,7 @@ public:
}
private:
int current_cache_size;
size_t current_cache_size;
CacheContainer cache;
/// Finds the entry with the lowest access count to evict, and returns its position.
@ -83,7 +83,7 @@ template<int Size, typename KeyTy, typename ValueTy>
class ArrayLruCache
{
private:
using CacheEntry = std::tuple<KeyTy, ValueTy, int>;
using CacheEntry = std::tuple<KeyTy, ValueTy, size_t>;
using CacheContainer = std::array<CacheEntry, Size>;
public:
@ -97,7 +97,7 @@ public:
/// Returns the value associated with the key and sets the access timestamp.
std::optional<const ValueTy> get(const KeyTy key)
{
auto entry_it = std::find_if(cache.begin(), cache.begin() + current_cache_size, [&key](const CacheEntry & e) {
auto entry_it = std::find_if(cache.begin(), cache.begin() + current_cache_size, [key](const CacheEntry & e) {
return std::get<0>(e) == key;
});
@ -126,8 +126,8 @@ public:
}
private:
int total_cache_access;
int current_cache_size;
size_t total_cache_access;
size_t current_cache_size;
CacheContainer cache;
/// Finds the entry with the lowest timestamp to evict, and returns its position.