Skip to content

Commit

Permalink
[PPU] Implement new instruction decoder. (#35)
Browse files Browse the repository at this point in the history
* Interpreter: Implement experimental code

Implement a few instrs, change to full jump-table, skipping decoding.

* Fix debug message

* [Formatting]: Fix build & formatting errors

* [Config]: Fix option var for ODD

* [Interpreter] Add mtmsr instruction.

---------

Co-authored-by: Vali <[email protected]>
  • Loading branch information
bitsh1ft3r and Vali0004 authored Feb 10, 2025
1 parent 3e34f3a commit e9b3f2c
Show file tree
Hide file tree
Showing 30 changed files with 2,506 additions and 2,336 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ set(RootBus
)

set(XCPU
Xenon/Core/XCPU/Bitfield.h
Xenon/Core/XCPU/Xenon.cpp
Xenon/Core/XCPU/Xenon.h
Xenon/Core/XCPU/XenonReservations.cpp
Expand All @@ -141,6 +142,7 @@ set(XCPU
Xenon/Core/XCPU/Interpreter/PPCInterpreter.cpp
Xenon/Core/XCPU/Interpreter/PPCInterpreter.h
Xenon/Core/XCPU/Interpreter/PPCInternal.h
Xenon/Core/XCPU/Interpreter/PPCOpcodes.h
Xenon/Core/XCPU/PostBus/PostBus.cpp
Xenon/Core/XCPU/PostBus/PostBus.h
Xenon/Core/XCPU/PPU/PPU.cpp
Expand Down
4 changes: 2 additions & 2 deletions Xenon/Base/Assert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void assert_fail_impl() {
throw std::runtime_error("Unreachable code");
}

void assert_fail_debug_msg(const char* msg) {
LOG_CRITICAL(Debug, "Assertion Failed!\n{}", msg);
void assert_fail_debug_msg(const std::string& msg) {
LOG_CRITICAL(Debug, "Assertion Failed!\n{}", msg.data());
assert_fail_impl();
}
1 change: 1 addition & 0 deletions Xenon/Base/Assert.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

void assert_fail_impl();
[[noreturn]] void unreachable_impl();
void assert_fail_debug_msg(const std::string& msg);

#ifdef _MSC_VER
#define XENON_NO_INLINE __declspec(noinline)
Expand Down
2 changes: 1 addition & 1 deletion Xenon/Base/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ void saveConfig(const std::filesystem::path &path) {
data["Paths"]["Fuses"] = fusesTxtPath;
data["Paths"]["OneBL"] = oneBlBinPath;
data["Paths"]["Nand"] = nandBinPath;
data["Paths"]["ISO"] = oddDiscImagePath;
data["Paths"]["ODDImage"] = oddDiscImagePath;

// HighlyExperimental.
data["HighlyExperimental"].comments().push_back("# Do not touch these options unless you know what you're doing!");
Expand Down
106 changes: 95 additions & 11 deletions Xenon/Base/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,113 @@
#pragma once

#include <cstdint>
#include <type_traits>
#include <format>

// Signed
using s8 = std::int8_t;
using s16 = std::int16_t;
using s32 = std::int32_t;
using s64 = std::int64_t;
using s8 = signed char;
using s16 = short;
using s32 = int;
using sl32 = long;
using s64 = long long;

// Unsigned
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using u8 = unsigned char;
using u16 = unsigned short;
using u32 = unsigned int;
using ul32 = unsigned long;
using u64 = unsigned long long;

// Floating point
using f32 = float;
using f64 = double;

// UDLs for memory size values
constexpr u64 operator""_KB(const u64 x) {
[[nodiscard]] inline constexpr u64 operator""_KB(const u64 x) {
return 1024ULL * x;
}
constexpr u64 operator""_MB(const u64 x) {
[[nodiscard]] inline constexpr u64 operator""_MB(const u64 x) {
return 1024_KB * x;
}
constexpr u64 operator""_GB(const u64 x) {
[[nodiscard]] inline constexpr u64 operator""_GB(const u64 x) {
return 1024_MB * x;
}

// Min/max value of a typetemplate <typename T>
template <typename T>
static consteval T min_t() {
if constexpr (std::is_unsigned_v<T>) {
return 0;
} else if constexpr (std::is_same_v<T, s64>) {
return (-0x7FFFFFFFFFFFFFFF - 1);
} else if constexpr (std::is_same_v<T, s32> || std::is_same_v<T, sl32>) {
return (-0x7FFFFFFF - 1);
} else if constexpr (std::is_same_v<T, s16>) {
return (-0x7FFF - 1);
} else if constexpr (std::is_same_v<T, s8>) {
return (-0x7F - 1);
}
}
template <typename T>
class min {
public:
static constexpr T value = min_t<T>();
};
template <typename T>
constexpr T min_v = min<T>::value;
template <typename T>
static consteval T max_t() {
if constexpr (std::is_same_v<T, u64>) {
return 0xFFFFFFFFFFFFFFFFu;
} else if constexpr (std::is_same_v<T, s64>) {
return 0x7FFFFFFFFFFFFFFF;
} else if constexpr (std::is_same_v<T, u32> || std::is_same_v<T, ul32>) {
return 0xFFFFFFFF;
} else if constexpr (std::is_same_v<T, s32> || std::is_same_v<T, sl32>) {
return 0x7FFFFFFF;
} else if constexpr (std::is_same_v<T, u16>) {
return 0xFFFF;
} else if constexpr (std::is_same_v<T, s16>) {
return 0x7FFF;
} else if constexpr (std::is_same_v<T, u8>) {
return 0xFF;
} else if constexpr (std::is_same_v<T, s8>) {
return 0x7F;
}
}
template <typename T>
class max {
public:
static constexpr T value = max_t<T>();
};
template <typename T>
constexpr T max_v = max<T>::value;

extern void assert_fail_debug_msg(const std::string& msg);

// Array accessors
template <typename cT, typename T>
requires requires (cT&& x) { std::size(x); std::data(x); } || requires (cT && x) { std::size(x); x.front(); }
[[nodiscard]] constexpr auto& c_at(cT&& c, T&& idx) {
// Associative container
size_t cSize = c.size();
if (cSize <= idx) [[unlikely]] {
assert_fail_debug_msg(std::format("Range check failed! (index: {}{})", idx, cSize != max_v<size_t> ? std::format(", size: {}", cSize) : ""));
}
auto it = std::begin(std::forward<cT>(c));
std::advance(it, idx);
return *it;
}
template <typename cT, typename T>
requires requires(cT&& x, T&& y) { x.count(y); x.find(y); }
[[nodiscard]] static constexpr auto& c_at(cT&& c, T&& idx) {
// Associative container
const auto found = c.find(std::forward<T>(idx));
size_t cSize = max_v<size_t>;
if constexpr ((requires() { c.size(); }))
cSize = c.size();
if (found == c.end()) [[unlikely]] {
assert_fail_debug_msg(std::format("Range check failed! (index: {}{})", idx, cSize != max_v<size_t> ? std::format(", size: {}", cSize) : ""));
}
return found->second;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,26 @@ void Xe::PCIDev::AUDIOCTRLR::AUDIOCTRLR::Write(u64 writeAddress, u64 data,

void Xe::PCIDev::AUDIOCTRLR::AUDIOCTRLR::ConfigWrite(u64 writeAddress, u64 data,
u8 byteCount) {
// Check if we're being scanned.
if (static_cast<u8>(writeAddress) >= 0x10 && static_cast<u8>(writeAddress) < 0x34) {
const u32 regOffset = (static_cast<u8>(writeAddress) - 0x10) >> 2;
if (pciDevSizes[regOffset] != 0) {
if (data == 0xFFFFFFFF) { // PCI BAR Size discovery.
u32 x = 2;
for (int idx = 2; idx < 31; idx++) {
data &= ~x;
x <<= 1;
if (x >= pciDevSizes[regOffset]) {
break;
}
}
data &= ~0x3;
}
}
if (static_cast<u8>(writeAddress) == 0x30) { // Expansion ROM Base Address.
data = 0; // Register not implemented.
// Check if we're being scanned.
if (static_cast<u8>(writeAddress) >= 0x10 && static_cast<u8>(writeAddress) < 0x34) {
const u32 regOffset = (static_cast<u8>(writeAddress) - 0x10) >> 2;
if (pciDevSizes[regOffset] != 0) {
if (data == 0xFFFFFFFF) { // PCI BAR Size discovery.
u64 x = 2;
for (int idx = 2; idx < 31; idx++) {
data &= ~x;
x <<= 1;
if (x >= pciDevSizes[regOffset]) {
break;
}
}
data &= ~0x3;
}
}
if (static_cast<u8>(writeAddress) == 0x30) { // Expansion ROM Base Address.
data = 0; // Register not implemented.
}
}

memcpy(&pciConfigSpace.data[static_cast<u8>(writeAddress)], &data, byteCount);
}
37 changes: 19 additions & 18 deletions Xenon/Core/RootBus/HostBridge/PCIBridge/EHCI0/EHCI0.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,26 @@ void Xe::PCIDev::EHCI0::EHCI0::Write(u64 writeAddress, u64 data, u8 byteCount) {

void Xe::PCIDev::EHCI0::EHCI0::ConfigWrite(u64 writeAddress, u64 data,
u8 byteCount) {
// Check if we're being scanned.
if (static_cast<u8>(writeAddress) >= 0x10 && static_cast<u8>(writeAddress) < 0x34) {
const u32 regOffset = (static_cast<u8>(writeAddress) - 0x10) >> 2;
if (pciDevSizes[regOffset] != 0) {
if (data == 0xFFFFFFFF) { // PCI BAR Size discovery.
u32 x = 2;
for (int idx = 2; idx < 31; idx++) {
data &= ~x;
x <<= 1;
if (x >= pciDevSizes[regOffset]) {
break;
}
}
data &= ~0x3;
}
}
if (static_cast<u8>(writeAddress) == 0x30) { // Expansion ROM Base Address.
data = 0; // Register not implemented.
// Check if we're being scanned.
if (static_cast<u8>(writeAddress) >= 0x10 && static_cast<u8>(writeAddress) < 0x34) {
const u32 regOffset = (static_cast<u8>(writeAddress) - 0x10) >> 2;
if (pciDevSizes[regOffset] != 0) {
if (data == 0xFFFFFFFF) { // PCI BAR Size discovery.
u64 x = 2;
for (int idx = 2; idx < 31; idx++) {
data &= ~x;
x <<= 1;
if (x >= pciDevSizes[regOffset]) {
break;
}
}
data &= ~0x3;
}
}
if (static_cast<u8>(writeAddress) == 0x30) { // Expansion ROM Base Address.
data = 0; // Register not implemented.
}
}

memcpy(&pciConfigSpace.data[static_cast<u8>(writeAddress)], &data, byteCount);
}
37 changes: 19 additions & 18 deletions Xenon/Core/RootBus/HostBridge/PCIBridge/EHCI1/EHCI1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,26 @@ void Xe::PCIDev::EHCI1::EHCI1::Write(u64 writeAddress, u64 data, u8 byteCount) {

void Xe::PCIDev::EHCI1::EHCI1::ConfigWrite(u64 writeAddress, u64 data,
u8 byteCount) {
// Check if we're being scanned.
if (static_cast<u8>(writeAddress) >= 0x10 && static_cast<u8>(writeAddress) < 0x34) {
const u32 regOffset = (static_cast<u8>(writeAddress) - 0x10) >> 2;
if (pciDevSizes[regOffset] != 0) {
if (data == 0xFFFFFFFF) { // PCI BAR Size discovery.
u32 x = 2;
for (int idx = 2; idx < 31; idx++) {
data &= ~x;
x <<= 1;
if (x >= pciDevSizes[regOffset]) {
break;
}
}
data &= ~0x3;
}
}
if (static_cast<u8>(writeAddress) == 0x30) { // Expansion ROM Base Address.
data = 0; // Register not implemented.
// Check if we're being scanned.
if (static_cast<u8>(writeAddress) >= 0x10 && static_cast<u8>(writeAddress) < 0x34) {
const u32 regOffset = (static_cast<u8>(writeAddress) - 0x10) >> 2;
if (pciDevSizes[regOffset] != 0) {
if (data == 0xFFFFFFFF) { // PCI BAR Size discovery.
u64 x = 2;
for (int idx = 2; idx < 31; idx++) {
data &= ~x;
x <<= 1;
if (x >= pciDevSizes[regOffset]) {
break;
}
}
data &= ~0x3;
}
}
if (static_cast<u8>(writeAddress) == 0x30) { // Expansion ROM Base Address.
data = 0; // Register not implemented.
}
}

memcpy(&pciConfigSpace.data[static_cast<u8>(writeAddress)], &data, byteCount);
}
37 changes: 19 additions & 18 deletions Xenon/Core/RootBus/HostBridge/PCIBridge/ETHERNET/Ethernet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,25 +154,26 @@ void Xe::PCIDev::ETHERNET::ETHERNET::Write(u64 writeAddress, u64 data,

void Xe::PCIDev::ETHERNET::ETHERNET::ConfigWrite(u64 writeAddress, u64 data,
u8 byteCount) {
// Check if we're being scanned.
if (static_cast<u8>(writeAddress) >= 0x10 && static_cast<u8>(writeAddress) < 0x34) {
const u32 regOffset = (static_cast<u8>(writeAddress) - 0x10) >> 2;
if (pciDevSizes[regOffset] != 0) {
if (data == 0xFFFFFFFF) { // PCI BAR Size discovery.
u32 x = 2;
for (int idx = 2; idx < 31; idx++) {
data &= ~x;
x <<= 1;
if (x >= pciDevSizes[regOffset]) {
break;
}
}
data &= ~0x3;
}
}
if (static_cast<u8>(writeAddress) == 0x30) { // Expansion ROM Base Address.
data = 0; // Register not implemented.
// Check if we're being scanned.
if (static_cast<u8>(writeAddress) >= 0x10 && static_cast<u8>(writeAddress) < 0x34) {
const u32 regOffset = (static_cast<u8>(writeAddress) - 0x10) >> 2;
if (pciDevSizes[regOffset] != 0) {
if (data == 0xFFFFFFFF) { // PCI BAR Size discovery.
u64 x = 2;
for (int idx = 2; idx < 31; idx++) {
data &= ~x;
x <<= 1;
if (x >= pciDevSizes[regOffset]) {
break;
}
}
data &= ~0x3;
}
}
if (static_cast<u8>(writeAddress) == 0x30) { // Expansion ROM Base Address.
data = 0; // Register not implemented.
}
}

memcpy(&pciConfigSpace.data[static_cast<u8>(writeAddress)], &data, byteCount);
}
36 changes: 18 additions & 18 deletions Xenon/Core/RootBus/HostBridge/PCIBridge/HDD/HDD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,26 +136,26 @@ void HDD::ConfigRead(u64 readAddress, u64 *data, u8 byteCount) {
}

void HDD::ConfigWrite(u64 writeAddress, u64 data, u8 byteCount) {
// Check if we're being scanned.
if (static_cast<u8>(writeAddress) >= 0x10 && static_cast<u8>(writeAddress) < 0x34) {
const u32 regOffset = (static_cast<u8>(writeAddress) - 0x10) >> 2;
if (pciDevSizes[regOffset] != 0) {
if (data == 0xFFFFFFFF) { // PCI BAR Size discovery.
u32 x = 2;
for (int idx = 2; idx < 31; idx++) {
data &= ~x;
x <<= 1;
if (x >= pciDevSizes[regOffset]) {
break;
}
}
data &= ~0x3;
}
}
if (static_cast<u8>(writeAddress) == 0x30) { // Expansion ROM Base Address.
data = 0; // Register not implemented.
// Check if we're being scanned.
if (static_cast<u8>(writeAddress) >= 0x10 && static_cast<u8>(writeAddress) < 0x34) {
const u32 regOffset = (static_cast<u8>(writeAddress) - 0x10) >> 2;
if (pciDevSizes[regOffset] != 0) {
if (data == 0xFFFFFFFF) { // PCI BAR Size discovery.
u64 x = 2;
for (int idx = 2; idx < 31; idx++) {
data &= ~x;
x <<= 1;
if (x >= pciDevSizes[regOffset]) {
break;
}
}
data &= ~0x3;
}
}
if (static_cast<u8>(writeAddress) == 0x30) { // Expansion ROM Base Address.
data = 0; // Register not implemented.
}
}
memcpy(&pciConfigSpace.data[static_cast<u8>(writeAddress)], &data, byteCount);
}

Expand Down
Loading

0 comments on commit e9b3f2c

Please sign in to comment.