Skip to content

Commit dab988c

Browse files
committed
Update memory controller to use concepts
1 parent bc17fdf commit dab988c

2 files changed

Lines changed: 54 additions & 164 deletions

File tree

src/Emulator/Core/MemoryController/IMemoryController.hpp

Lines changed: 0 additions & 96 deletions
This file was deleted.

src/Emulator/Core/MemoryController/MemoryControllerST.hpp

Lines changed: 54 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -3,103 +3,89 @@
33
#include "PCH/CStd.hpp"
44

55
#include "Emulator/Core/CPU/CPU.hpp"
6-
#include "Emulator/Core/MemoryController/IMemoryController.hpp"
6+
7+
#include "spdlog/spdlog.h"
8+
9+
// TODO: позор партии, убрать и переделать в функцию
10+
#define mem_ctlr_assert(expr) \
11+
do { \
12+
if (!(expr) && (!cpu || !cpu->CanExecuteInterrupts())) [[unlikely]] { \
13+
spdlog::error("Assertion failed: {}", #expr); \
14+
std::abort(); \
15+
} else if (!(expr) && cpu && cpu->CanExecuteInterrupts()) { \
16+
cpu->TriggerInterrupt(HyperCPU::cpu_exceptions::SEGF); \
17+
} else [[likely]] { \
18+
} \
19+
} while (false)
720

821
namespace HyperCPU {
9-
class MemoryControllerST final : public IMemoryController {
22+
class CPU;
23+
24+
template <bool, typename T>
25+
struct LoadTypeChooser;
26+
27+
template <typename T>
28+
struct LoadTypeChooser<false, T> {
29+
using type = T;
30+
};
31+
32+
template <typename T>
33+
struct LoadTypeChooser<true, T> {
34+
using type = std::underlying_type_t<T>;
35+
};
36+
37+
template<typename T>
38+
concept IntConvertable =
39+
(sizeof(T) == 1 && std::is_convertible_v<LoadTypeChooser<std::is_enum_v<T>, T>, std::uint8_t>) ||
40+
(sizeof(T) == 2 && std::is_convertible_v<LoadTypeChooser<std::is_enum_v<T>, T>, std::uint16_t>) ||
41+
(sizeof(T) == 4 && std::is_convertible_v<LoadTypeChooser<std::is_enum_v<T>, T>, std::uint32_t>) ||
42+
(sizeof(T) == 8 && std::is_convertible_v<LoadTypeChooser<std::is_enum_v<T>, T>, std::uint64_t>);
43+
44+
class MemoryControllerST final {
1045
private:
1146
char* memory;
1247
class CPU* cpu;
1348
std::size_t total_mem;
1449

50+
51+
1552
public:
1653
explicit MemoryControllerST(std::size_t mem_size, class CPU* cpu = nullptr)
1754
: cpu(cpu), total_mem(mem_size) {
1855
memory = static_cast<char*>(calloc(total_mem, 1));
1956
if (!memory)
2057
throw std::runtime_error("Failed to allocate memory!");
2158
}
22-
inline std::uint8_t Fetch8(std::uint64_t& ptr) override {
23-
mem_ctlr_assert(ptr + sizeof(std::uint8_t) - 1 < total_mem);
24-
std::uint8_t data;
25-
memcpy(&data, &memory[ptr], sizeof(std::uint8_t));
26-
ptr += sizeof(std::uint8_t);
27-
return data;
28-
}
2959

30-
inline std::uint16_t Fetch16(std::uint64_t& ptr) override {
31-
mem_ctlr_assert(ptr + sizeof(std::uint16_t) - 1 < total_mem);
32-
std::uint16_t data;
33-
memcpy(&data, &memory[ptr], sizeof(std::uint16_t));
34-
ptr += sizeof(std::uint16_t);
35-
return data;
36-
}
60+
template<IntConvertable T>
61+
inline T Fetch(std::uint64_t& ptr) {
62+
mem_ctlr_assert(ptr + sizeof(T) - 1 < total_mem);
3763

38-
inline std::uint32_t Fetch32(std::uint64_t& ptr) override {
39-
mem_ctlr_assert(ptr + sizeof(std::uint32_t) - 1 < total_mem);
40-
std::uint32_t data;
41-
memcpy(&data, &memory[ptr], sizeof(std::uint32_t));
42-
ptr += sizeof(std::uint32_t);
43-
return data;
44-
}
64+
T data;
65+
std::memcpy(&data, &memory[ptr], sizeof(T));
66+
ptr += sizeof(T);
4567

46-
inline std::uint64_t Fetch64(std::uint64_t& ptr) override {
47-
mem_ctlr_assert(ptr + sizeof(std::uint64_t) - 1 < total_mem);
48-
std::uint64_t data;
49-
memcpy(&data, &memory[ptr], sizeof(std::uint64_t));
50-
ptr += sizeof(std::uint64_t);
5168
return data;
5269
}
5370

54-
inline std::uint8_t Read8(std::uint64_t ptr) override {
55-
mem_ctlr_assert(ptr + sizeof(std::uint8_t) - 1 < total_mem);
56-
std::uint8_t data;
57-
memcpy(&data, &memory[ptr], sizeof(std::uint8_t));
58-
return data;
59-
}
71+
template<IntConvertable T>
72+
inline T Read(std::uint64_t ptr) {
73+
mem_ctlr_assert(ptr + sizeof(T) - 1 < total_mem);
6074

61-
inline std::uint16_t Read16(std::uint64_t ptr) override {
62-
mem_ctlr_assert(ptr + sizeof(std::uint16_t) - 1 < total_mem);
63-
std::uint16_t data;
64-
memcpy(&data, &memory[ptr], sizeof(std::uint16_t));
65-
return data;
66-
}
75+
T data;
76+
std::memcpy(&data, &memory[ptr], sizeof(T));
6777

68-
inline std::uint32_t Read32(std::uint64_t ptr) override {
69-
mem_ctlr_assert(ptr + sizeof(std::uint32_t) - 1 < total_mem);
70-
std::uint32_t data;
71-
memcpy(&data, &memory[ptr], sizeof(std::uint32_t));
7278
return data;
7379
}
7480

75-
inline std::uint64_t Read64(std::uint64_t ptr) override {
76-
mem_ctlr_assert(ptr + sizeof(std::uint64_t) - 1 < total_mem);
77-
std::uint64_t data;
78-
memcpy(&data, &memory[ptr], sizeof(std::uint64_t));
79-
return data;
80-
}
81+
template<IntConvertable T>
82+
inline void Load(std::uint64_t ptr, T data) {
83+
mem_ctlr_assert(ptr + sizeof(T) - 1 < total_mem);
8184

82-
inline void load8(std::uint64_t ptr, std::uint8_t data) override {
83-
mem_ctlr_assert(ptr + sizeof(std::uint8_t) - 1 < total_mem);
8485
memcpy(&memory[ptr], &data, sizeof(std::uint8_t));
8586
}
8687

87-
inline void load16(std::uint64_t ptr, std::uint16_t data) override {
88-
mem_ctlr_assert(ptr + sizeof(std::uint16_t) - 1 < total_mem);
89-
memcpy(&memory[ptr], &data, sizeof(std::uint16_t));
90-
}
91-
92-
inline void load32(std::uint64_t ptr, std::uint32_t data) override {
93-
mem_ctlr_assert(ptr + sizeof(std::uint32_t) - 1 < total_mem);
94-
memcpy(&memory[ptr], &data, sizeof(std::uint32_t));
95-
}
96-
97-
inline void load64(std::uint64_t ptr, std::uint64_t data) override {
98-
mem_ctlr_assert(ptr + sizeof(std::uint64_t) - 1 < total_mem);
99-
memcpy(&memory[ptr], &data, sizeof(std::uint64_t));
100-
}
101-
102-
std::uint8_t* get_ptr() const noexcept override {
88+
std::uint8_t* get_ptr() const noexcept {
10389
return reinterpret_cast<std::uint8_t*>(memory);
10490
}
10591

0 commit comments

Comments
 (0)