parent
6ebebae770
commit
9d7ef71d3b
|
@ -0,0 +1,4 @@
|
||||||
|
[submodule "native/projects/lcpu/third_party/gmod_headers"]
|
||||||
|
path = native/projects/lcpu/third_party/gmod_headers
|
||||||
|
url = https://github.com/Facepunch/gmod-module-base
|
||||||
|
branch = development
|
|
@ -10,4 +10,4 @@ add_subdirectory(projects/lucore_test)
|
||||||
add_subdirectory(projects/riscv)
|
add_subdirectory(projects/riscv)
|
||||||
|
|
||||||
# Garry's Mod bindings
|
# Garry's Mod bindings
|
||||||
#add_subdirectory(projects/gmsv_lcpu)
|
add_subdirectory(projects/lcpu)
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
add_library()
|
|
|
@ -1,4 +0,0 @@
|
||||||
# Notes
|
|
||||||
|
|
||||||
- gmsv_lcpu doesn't use the upstream cmake buildsystem for gmod lua headers (instead crafting our own)
|
|
||||||
- this is because, in facepunchs infinite wisdom, they decided to unconditionally build the examples.
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
|
||||||
|
|
||||||
|
add_library(gmod_headers INTERFACE)
|
||||||
|
target_include_directories(gmod_headers INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/gmod_headers/include)
|
||||||
|
|
||||||
|
# Originally from facepunch cmake build system, modified to be slightly less painful
|
||||||
|
function(set_gmod_suffix_prefix library)
|
||||||
|
set_target_properties(${library} PROPERTIES PREFIX "gmsv_")
|
||||||
|
if(APPLE)
|
||||||
|
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||||
|
set_target_properties(${library} PROPERTIES SUFFIX "_osx.dll")
|
||||||
|
else()
|
||||||
|
set_target_properties(${library} PROPERTIES SUFFIX "_osx64.dll")
|
||||||
|
endif()
|
||||||
|
elseif(UNIX)
|
||||||
|
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||||
|
set_target_properties(${library} PROPERTIES SUFFIX "_linux.dll")
|
||||||
|
else()
|
||||||
|
set_target_properties(${library} PROPERTIES SUFFIX "_linux64.dll")
|
||||||
|
endif()
|
||||||
|
elseif(WIN32)
|
||||||
|
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||||
|
set_target_properties(${library} PROPERTIES SUFFIX "_win32.dll")
|
||||||
|
else()
|
||||||
|
set_target_properties(${library} PROPERTIES SUFFIX "_win64.dll")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
|
||||||
|
add_library(lcpu_native SHARED
|
||||||
|
src/main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||||
|
target_link_options(lcpu_native PRIVATE "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/gmod_abi.ver")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(lcpu_native
|
||||||
|
gmod_headers
|
||||||
|
lucore::lucore
|
||||||
|
riscv::riscv
|
||||||
|
)
|
||||||
|
|
||||||
|
set_gmod_suffix_prefix(lcpu_native)
|
|
@ -0,0 +1,9 @@
|
||||||
|
#include <GarrysMod/Lua/Interface.h>
|
||||||
|
|
||||||
|
GMOD_MODULE_OPEN() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GMOD_MODULE_CLOSE() {
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit ad1795cf84ee715a0afc75db0cfed093a42f3cd9
|
|
@ -60,9 +60,10 @@ namespace lucore {
|
||||||
private:
|
private:
|
||||||
std::FILE* file;
|
std::FILE* file;
|
||||||
};
|
};
|
||||||
std::format_to(FileOutIterator(data.severity < Logger::MessageSeverity::Error ? stdout : stderr), "[Lucore/{}] [{}] {}\n",
|
std::format_to(
|
||||||
Logger::SeverityToString(data.severity), data.time,
|
FileOutIterator(data.severity < Logger::MessageSeverity::Error ? stdout : stderr),
|
||||||
std::vformat(data.format, data.args));
|
"[Lucore/{}] [{}] {}\n", Logger::SeverityToString(data.severity), data.time,
|
||||||
|
std::vformat(data.format, data.args));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoggerAttachStdout() {
|
void LoggerAttachStdout() {
|
||||||
|
|
|
@ -7,7 +7,7 @@ project(riscv_emu
|
||||||
|
|
||||||
add_library(riscv
|
add_library(riscv
|
||||||
src/Bus.cpp
|
src/Bus.cpp
|
||||||
src/MemoryDevice.cpp
|
src/Devices/RamDevice.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_features(riscv PUBLIC cxx_std_20)
|
target_compile_features(riscv PUBLIC cxx_std_20)
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
#include <riscv/Bus.hpp>
|
||||||
|
|
||||||
|
#include "riscv/Types.hpp"
|
||||||
|
|
||||||
|
namespace riscv::devices {
|
||||||
|
|
||||||
|
struct RamDevice : public Bus::Device {
|
||||||
|
RamDevice(AddressT size);
|
||||||
|
virtual ~RamDevice();
|
||||||
|
|
||||||
|
AddressT Size() const override;
|
||||||
|
|
||||||
|
// Implementation of Device interface
|
||||||
|
|
||||||
|
void Attached(Bus* bus, AddressT base) override;
|
||||||
|
|
||||||
|
u8 PeekByte(AddressT address) override;
|
||||||
|
u16 PeekShort(AddressT address) override;
|
||||||
|
u32 PeekWord(AddressT address) override;
|
||||||
|
|
||||||
|
void PokeByte(AddressT address, u8 value) override;
|
||||||
|
void PokeShort(AddressT address, u16 value) override;
|
||||||
|
void PokeWord(AddressT address, u32 value) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// helper used for implementing stuff
|
||||||
|
template <class T>
|
||||||
|
constexpr usize AddressToIndex(AddressT address) {
|
||||||
|
return ((address - baseAddress) % memorySize) / sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remember what we were attached to via "signal"
|
||||||
|
Bus* attachedBus {};
|
||||||
|
AddressT baseAddress {};
|
||||||
|
|
||||||
|
u8* memory {};
|
||||||
|
usize memorySize {};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace riscv::devices
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include <riscv/Devices/RamDevice.hpp>
|
||||||
|
|
||||||
|
#include "riscv/Types.hpp"
|
||||||
|
|
||||||
|
namespace riscv::devices {
|
||||||
|
|
||||||
|
RamDevice::RamDevice(AddressT size) : Bus::Device(), memorySize(size) {
|
||||||
|
memory = new u8[size];
|
||||||
|
LUCORE_CHECK(memory, "Could not allocate buffer for memory device with size 0x{:08x}.",
|
||||||
|
size);
|
||||||
|
}
|
||||||
|
|
||||||
|
RamDevice::~RamDevice() {
|
||||||
|
if(memory)
|
||||||
|
delete[] memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressT RamDevice::Size() const {
|
||||||
|
return memorySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementation of Device interface
|
||||||
|
|
||||||
|
void RamDevice::Attached(Bus* bus, AddressT base) {
|
||||||
|
attachedBus = bus;
|
||||||
|
baseAddress = base;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 RamDevice::PeekByte(AddressT address) {
|
||||||
|
return memory[AddressToIndex<u8>(address)];
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 RamDevice::PeekShort(AddressT address) {
|
||||||
|
return std::bit_cast<u16*>(memory)[AddressToIndex<u16>(address)];
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 RamDevice::PeekWord(AddressT address) {
|
||||||
|
return std::bit_cast<u32*>(memory)[AddressToIndex<u32>(address)];
|
||||||
|
}
|
||||||
|
|
||||||
|
void RamDevice::PokeByte(AddressT address, u8 value) {
|
||||||
|
memory[AddressToIndex<u8>(address)] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RamDevice::PokeShort(AddressT address, u16 value) {
|
||||||
|
std::bit_cast<u16*>(memory)[AddressToIndex<u16>(address)] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RamDevice::PokeWord(AddressT address, u32 value) {
|
||||||
|
std::bit_cast<u32*>(memory)[AddressToIndex<u32>(address)] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace riscv::devices
|
|
@ -1,84 +0,0 @@
|
||||||
#include <riscv/Bus.hpp>
|
|
||||||
|
|
||||||
namespace riscv {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
template <bool Rom>
|
|
||||||
struct BasicMemoryDevice : public Bus::Device {
|
|
||||||
BasicMemoryDevice(usize size) : Bus::Device(), memorySize(size) {
|
|
||||||
memory = new u8[size];
|
|
||||||
LUCORE_CHECK(memory, "Could not allocate buffer for memory device.");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~BasicMemoryDevice() {
|
|
||||||
if(memory)
|
|
||||||
delete[] memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddressT Size() const override {
|
|
||||||
return memorySize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementation of Device interface
|
|
||||||
|
|
||||||
void Attached(Bus* bus, AddressT base) override {
|
|
||||||
attachedBus = bus;
|
|
||||||
baseAddress = base;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 PeekByte(AddressT address) override {
|
|
||||||
return memory[AddressToIndex<u8>(address)];
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 PeekShort(AddressT address) override {
|
|
||||||
return std::bit_cast<u16*>(memory)[AddressToIndex<u16>(address)];
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 PeekWord(AddressT address) override {
|
|
||||||
return std::bit_cast<u32*>(memory)[AddressToIndex<u32>(address)];
|
|
||||||
}
|
|
||||||
|
|
||||||
void PokeByte(AddressT address, u8 value) override {
|
|
||||||
if constexpr(!Rom) {
|
|
||||||
memory[AddressToIndex<u8>(address)] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PokeShort(AddressT address, u16 value) override {
|
|
||||||
if constexpr(!Rom) {
|
|
||||||
std::bit_cast<u16*>(memory)[AddressToIndex<u16>(address)] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PokeWord(AddressT address, u32 value) override {
|
|
||||||
if constexpr(!Rom) {
|
|
||||||
std::bit_cast<u32*>(memory)[AddressToIndex<u32>(address)] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// helper used for implementing stuff
|
|
||||||
template <class T>
|
|
||||||
constexpr usize AddressToIndex(AddressT address) {
|
|
||||||
return ((address - baseAddress) % memorySize) / sizeof(T);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remember what we were attached to via "signal"
|
|
||||||
Bus* attachedBus {};
|
|
||||||
AddressT baseAddress {};
|
|
||||||
|
|
||||||
u8* memory {};
|
|
||||||
usize memorySize {};
|
|
||||||
};
|
|
||||||
|
|
||||||
using RamDevice = BasicMemoryDevice<false>;
|
|
||||||
using RomDevice = BasicMemoryDevice<true>;
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
Bus::Device* NewRam(usize size) {
|
|
||||||
return new RamDevice(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace riscv
|
|
Loading…
Reference in New Issue