MMU: Replace TryReadResult and TryWriteResult with std::optional

This commit is contained in:
Pokechu22 2021-09-04 11:05:35 -07:00
parent 673f886a7e
commit 525e6b2194
3 changed files with 129 additions and 129 deletions

View File

@ -101,87 +101,87 @@ std::vector<u8> Cheats::GetValueAsByteVector(const Cheats::SearchValue& value)
namespace
{
template <typename T>
static PowerPC::TryReadResult<T>
static std::optional<PowerPC::ReadResult<T>>
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space);
template <>
PowerPC::TryReadResult<u8> TryReadValueFromEmulatedMemory(u32 addr,
PowerPC::RequestedAddressSpace space)
std::optional<PowerPC::ReadResult<u8>>
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
{
return PowerPC::HostTryReadU8(addr, space);
}
template <>
PowerPC::TryReadResult<u16> TryReadValueFromEmulatedMemory(u32 addr,
PowerPC::RequestedAddressSpace space)
std::optional<PowerPC::ReadResult<u16>>
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
{
return PowerPC::HostTryReadU16(addr, space);
}
template <>
PowerPC::TryReadResult<u32> TryReadValueFromEmulatedMemory(u32 addr,
PowerPC::RequestedAddressSpace space)
std::optional<PowerPC::ReadResult<u32>>
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
{
return PowerPC::HostTryReadU32(addr, space);
}
template <>
PowerPC::TryReadResult<u64> TryReadValueFromEmulatedMemory(u32 addr,
PowerPC::RequestedAddressSpace space)
std::optional<PowerPC::ReadResult<u64>>
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
{
return PowerPC::HostTryReadU64(addr, space);
}
template <>
PowerPC::TryReadResult<s8> TryReadValueFromEmulatedMemory(u32 addr,
PowerPC::RequestedAddressSpace space)
std::optional<PowerPC::ReadResult<s8>>
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
{
auto tmp = PowerPC::HostTryReadU8(addr, space);
if (!tmp)
return PowerPC::TryReadResult<s8>();
return PowerPC::TryReadResult<s8>(tmp.translated, Common::BitCast<s8>(tmp.value));
return std::nullopt;
return PowerPC::ReadResult<s8>(tmp->translated, Common::BitCast<s8>(tmp->value));
}
template <>
PowerPC::TryReadResult<s16> TryReadValueFromEmulatedMemory(u32 addr,
PowerPC::RequestedAddressSpace space)
std::optional<PowerPC::ReadResult<s16>>
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
{
auto tmp = PowerPC::HostTryReadU16(addr, space);
if (!tmp)
return PowerPC::TryReadResult<s16>();
return PowerPC::TryReadResult<s16>(tmp.translated, Common::BitCast<s16>(tmp.value));
return std::nullopt;
return PowerPC::ReadResult<s16>(tmp->translated, Common::BitCast<s16>(tmp->value));
}
template <>
PowerPC::TryReadResult<s32> TryReadValueFromEmulatedMemory(u32 addr,
PowerPC::RequestedAddressSpace space)
std::optional<PowerPC::ReadResult<s32>>
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
{
auto tmp = PowerPC::HostTryReadU32(addr, space);
if (!tmp)
return PowerPC::TryReadResult<s32>();
return PowerPC::TryReadResult<s32>(tmp.translated, Common::BitCast<s32>(tmp.value));
return std::nullopt;
return PowerPC::ReadResult<s32>(tmp->translated, Common::BitCast<s32>(tmp->value));
}
template <>
PowerPC::TryReadResult<s64> TryReadValueFromEmulatedMemory(u32 addr,
PowerPC::RequestedAddressSpace space)
std::optional<PowerPC::ReadResult<s64>>
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
{
auto tmp = PowerPC::HostTryReadU64(addr, space);
if (!tmp)
return PowerPC::TryReadResult<s64>();
return PowerPC::TryReadResult<s64>(tmp.translated, Common::BitCast<s64>(tmp.value));
return std::nullopt;
return PowerPC::ReadResult<s64>(tmp->translated, Common::BitCast<s64>(tmp->value));
}
template <>
PowerPC::TryReadResult<float> TryReadValueFromEmulatedMemory(u32 addr,
PowerPC::RequestedAddressSpace space)
std::optional<PowerPC::ReadResult<float>>
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
{
return PowerPC::HostTryReadF32(addr, space);
}
template <>
PowerPC::TryReadResult<double> TryReadValueFromEmulatedMemory(u32 addr,
PowerPC::RequestedAddressSpace space)
std::optional<PowerPC::ReadResult<double>>
TryReadValueFromEmulatedMemory(u32 addr, PowerPC::RequestedAddressSpace space)
{
return PowerPC::HostTryReadF64(addr, space);
}
@ -230,11 +230,11 @@ Cheats::NewSearch(const std::vector<Cheats::MemoryRange>& memory_ranges,
if (!current_value)
continue;
if (validator(current_value.value))
if (validator(current_value->value))
{
auto& r = results.emplace_back();
r.m_value = current_value.value;
r.m_value_state = current_value.translated ?
r.m_value = current_value->value;
r.m_value_state = current_value->translated ?
Cheats::SearchResultValueState::ValueFromVirtualMemory :
Cheats::SearchResultValueState::ValueFromPhysicalMemory;
r.m_address = addr;
@ -284,11 +284,11 @@ Cheats::NextSearch(const std::vector<Cheats::SearchResult<T>>& previous_results,
// if the previous state was invalid we always update the value to avoid getting stuck in an
// invalid state
if (!previous_result.IsValueValid() ||
validator(current_value.value, previous_result.m_value))
validator(current_value->value, previous_result.m_value))
{
auto& r = results.emplace_back();
r.m_value = current_value.value;
r.m_value_state = current_value.translated ?
r.m_value = current_value->value;
r.m_value_state = current_value->translated ?
Cheats::SearchResultValueState::ValueFromVirtualMemory :
Cheats::SearchResultValueState::ValueFromPhysicalMemory;
r.m_address = addr;

View File

@ -468,34 +468,35 @@ u32 HostRead_Instruction(const u32 address)
return ReadFromHardware<XCheckTLBFlag::OpcodeNoException, u32>(address);
}
TryReadResult<u32> HostTryReadInstruction(const u32 address, RequestedAddressSpace space)
std::optional<ReadResult<u32>> HostTryReadInstruction(const u32 address,
RequestedAddressSpace space)
{
if (!HostIsInstructionRAMAddress(address, space))
return TryReadResult<u32>();
return std::nullopt;
switch (space)
{
case RequestedAddressSpace::Effective:
{
const u32 value = ReadFromHardware<XCheckTLBFlag::OpcodeNoException, u32>(address);
return TryReadResult<u32>(!!MSR.DR, value);
return ReadResult<u32>(!!MSR.DR, value);
}
case RequestedAddressSpace::Physical:
{
const u32 value = ReadFromHardware<XCheckTLBFlag::OpcodeNoException, u32, true>(address);
return TryReadResult<u32>(false, value);
return ReadResult<u32>(false, value);
}
case RequestedAddressSpace::Virtual:
{
if (!MSR.DR)
return TryReadResult<u32>();
return std::nullopt;
const u32 value = ReadFromHardware<XCheckTLBFlag::OpcodeNoException, u32>(address);
return TryReadResult<u32>(true, value);
return ReadResult<u32>(true, value);
}
}
ASSERT(0);
return TryReadResult<u32>();
return std::nullopt;
}
static void Memcheck(u32 address, u64 var, bool write, size_t size)
@ -574,70 +575,70 @@ float Read_F32(const u32 address)
}
template <typename T>
static TryReadResult<T> HostTryReadUX(const u32 address, RequestedAddressSpace space)
static std::optional<ReadResult<T>> HostTryReadUX(const u32 address, RequestedAddressSpace space)
{
if (!HostIsRAMAddress(address, space))
return TryReadResult<T>();
return std::nullopt;
switch (space)
{
case RequestedAddressSpace::Effective:
{
T value = ReadFromHardware<XCheckTLBFlag::NoException, T>(address);
return TryReadResult<T>(!!MSR.DR, std::move(value));
return ReadResult<T>(!!MSR.DR, std::move(value));
}
case RequestedAddressSpace::Physical:
{
T value = ReadFromHardware<XCheckTLBFlag::NoException, T, true>(address);
return TryReadResult<T>(false, std::move(value));
return ReadResult<T>(false, std::move(value));
}
case RequestedAddressSpace::Virtual:
{
if (!MSR.DR)
return TryReadResult<T>();
return std::nullopt;
T value = ReadFromHardware<XCheckTLBFlag::NoException, T>(address);
return TryReadResult<T>(true, std::move(value));
return ReadResult<T>(true, std::move(value));
}
}
ASSERT(0);
return TryReadResult<T>();
return std::nullopt;
}
TryReadResult<u8> HostTryReadU8(u32 address, RequestedAddressSpace space)
std::optional<ReadResult<u8>> HostTryReadU8(u32 address, RequestedAddressSpace space)
{
return HostTryReadUX<u8>(address, space);
}
TryReadResult<u16> HostTryReadU16(u32 address, RequestedAddressSpace space)
std::optional<ReadResult<u16>> HostTryReadU16(u32 address, RequestedAddressSpace space)
{
return HostTryReadUX<u16>(address, space);
}
TryReadResult<u32> HostTryReadU32(u32 address, RequestedAddressSpace space)
std::optional<ReadResult<u32>> HostTryReadU32(u32 address, RequestedAddressSpace space)
{
return HostTryReadUX<u32>(address, space);
}
TryReadResult<u64> HostTryReadU64(u32 address, RequestedAddressSpace space)
std::optional<ReadResult<u64>> HostTryReadU64(u32 address, RequestedAddressSpace space)
{
return HostTryReadUX<u64>(address, space);
}
TryReadResult<float> HostTryReadF32(u32 address, RequestedAddressSpace space)
std::optional<ReadResult<float>> HostTryReadF32(u32 address, RequestedAddressSpace space)
{
const auto result = HostTryReadUX<u32>(address, space);
if (!result)
return TryReadResult<float>();
return TryReadResult<float>(result.translated, Common::BitCast<float>(result.value));
return std::nullopt;
return ReadResult<float>(result->translated, Common::BitCast<float>(result->value));
}
TryReadResult<double> HostTryReadF64(u32 address, RequestedAddressSpace space)
std::optional<ReadResult<double>> HostTryReadF64(u32 address, RequestedAddressSpace space)
{
const auto result = HostTryReadUX<u64>(address, space);
if (!result)
return TryReadResult<double>();
return TryReadResult<double>(result.translated, Common::BitCast<double>(result.value));
return std::nullopt;
return ReadResult<double>(result->translated, Common::BitCast<double>(result->value));
}
u32 Read_U8_ZX(const u32 address)
@ -763,62 +764,68 @@ void HostWrite_F64(const double var, const u32 address)
HostWrite_U64(integral, address);
}
static TryWriteResult HostTryWriteUX(const u32 var, const u32 address, const u32 size,
RequestedAddressSpace space)
static std::optional<WriteResult> HostTryWriteUX(const u32 var, const u32 address, const u32 size,
RequestedAddressSpace space)
{
if (!HostIsRAMAddress(address, space))
return TryWriteResult();
return std::nullopt;
switch (space)
{
case RequestedAddressSpace::Effective:
WriteToHardware<XCheckTLBFlag::NoException>(address, var, size);
return TryWriteResult(!!MSR.DR);
return WriteResult(!!MSR.DR);
case RequestedAddressSpace::Physical:
WriteToHardware<XCheckTLBFlag::NoException, true>(address, var, size);
return TryWriteResult(false);
return WriteResult(false);
case RequestedAddressSpace::Virtual:
if (!MSR.DR)
return TryWriteResult();
return std::nullopt;
WriteToHardware<XCheckTLBFlag::NoException>(address, var, size);
return TryWriteResult(true);
return WriteResult(true);
}
ASSERT(0);
return TryWriteResult();
return std::nullopt;
}
TryWriteResult HostTryWriteU8(const u32 var, const u32 address, RequestedAddressSpace space)
std::optional<WriteResult> HostTryWriteU8(const u32 var, const u32 address,
RequestedAddressSpace space)
{
return HostTryWriteUX(var, address, 1, space);
}
TryWriteResult HostTryWriteU16(const u32 var, const u32 address, RequestedAddressSpace space)
std::optional<WriteResult> HostTryWriteU16(const u32 var, const u32 address,
RequestedAddressSpace space)
{
return HostTryWriteUX(var, address, 2, space);
}
TryWriteResult HostTryWriteU32(const u32 var, const u32 address, RequestedAddressSpace space)
std::optional<WriteResult> HostTryWriteU32(const u32 var, const u32 address,
RequestedAddressSpace space)
{
return HostTryWriteUX(var, address, 4, space);
}
TryWriteResult HostTryWriteU64(const u64 var, const u32 address, RequestedAddressSpace space)
std::optional<WriteResult> HostTryWriteU64(const u64 var, const u32 address,
RequestedAddressSpace space)
{
const TryWriteResult result = HostTryWriteUX(static_cast<u32>(var >> 32), address, 4, space);
const auto result = HostTryWriteUX(static_cast<u32>(var >> 32), address, 4, space);
if (!result)
return result;
return HostTryWriteUX(static_cast<u32>(var), address + 4, 4, space);
}
TryWriteResult HostTryWriteF32(const float var, const u32 address, RequestedAddressSpace space)
std::optional<WriteResult> HostTryWriteF32(const float var, const u32 address,
RequestedAddressSpace space)
{
const u32 integral = Common::BitCast<u32>(var);
return HostTryWriteU32(integral, address, space);
}
TryWriteResult HostTryWriteF64(const double var, const u32 address, RequestedAddressSpace space)
std::optional<WriteResult> HostTryWriteF64(const double var, const u32 address,
RequestedAddressSpace space)
{
const u64 integral = Common::BitCast<u64>(var);
return HostTryWriteU64(integral, address, space);
@ -840,25 +847,26 @@ std::string HostGetString(u32 address, size_t size)
return s;
}
TryReadResult<std::string> HostTryReadString(u32 address, size_t size, RequestedAddressSpace space)
std::optional<ReadResult<std::string>> HostTryReadString(u32 address, size_t size,
RequestedAddressSpace space)
{
auto c = HostTryReadU8(address, space);
if (!c)
return TryReadResult<std::string>();
if (c.value == 0)
return TryReadResult<std::string>(c.translated, "");
return std::nullopt;
if (c->value == 0)
return ReadResult<std::string>(c->translated, "");
std::string s;
s += static_cast<char>(c.value);
s += static_cast<char>(c->value);
while (size == 0 || s.length() < size)
{
++address;
const auto res = HostTryReadU8(address, space);
if (!res || res.value == 0)
if (!res || res->value == 0)
break;
s += static_cast<char>(res.value);
s += static_cast<char>(res->value);
}
return TryReadResult<std::string>(c.translated, std::move(s));
return ReadResult<std::string>(c->translated, std::move(s));
}
bool IsOptimizableRAMAddress(const u32 address)

View File

@ -37,11 +37,8 @@ u32 HostRead_Instruction(u32 address);
std::string HostGetString(u32 address, size_t size = 0);
template <typename T>
struct TryReadResult
struct ReadResult
{
// whether the read succeeded; if false, the other fields should not be touched
bool success;
// whether the address had to be translated (given address was treated as virtual) or not (given
// address was treated as physical)
bool translated;
@ -49,37 +46,31 @@ struct TryReadResult
// the actual value that was read
T value;
TryReadResult() : success(false) {}
TryReadResult(bool translated_, T&& value_)
: success(true), translated(translated_), value(std::move(value_))
ReadResult(bool translated_, T&& value_) : translated(translated_), value(std::forward<T>(value_))
{
}
TryReadResult(bool translated_, const T& value_)
: success(true), translated(translated_), value(value_)
{
}
explicit operator bool() const { return success; }
ReadResult(bool translated_, const T& value_) : translated(translated_), value(value_) {}
};
// Try to read a value from emulated memory at the given address in the given memory space.
// If the read succeeds, the returned TryReadResult contains the read value and information on
// whether the given address had to be translated or not. Unlike the HostRead functions, this does
// not raise a user-visible alert on failure.
TryReadResult<u8> HostTryReadU8(u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
TryReadResult<u16> HostTryReadU16(u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
TryReadResult<u32> HostTryReadU32(u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
TryReadResult<u64> HostTryReadU64(u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
TryReadResult<float> HostTryReadF32(u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
TryReadResult<double>
// If the read succeeds, the returned value will be present and the ReadResult contains the read
// value and information on whether the given address had to be translated or not. Unlike the
// HostRead functions, this does not raise a user-visible alert on failure.
std::optional<ReadResult<u8>>
HostTryReadU8(u32 address, RequestedAddressSpace space = RequestedAddressSpace::Effective);
std::optional<ReadResult<u16>>
HostTryReadU16(u32 address, RequestedAddressSpace space = RequestedAddressSpace::Effective);
std::optional<ReadResult<u32>>
HostTryReadU32(u32 address, RequestedAddressSpace space = RequestedAddressSpace::Effective);
std::optional<ReadResult<u64>>
HostTryReadU64(u32 address, RequestedAddressSpace space = RequestedAddressSpace::Effective);
std::optional<ReadResult<float>>
HostTryReadF32(u32 address, RequestedAddressSpace space = RequestedAddressSpace::Effective);
std::optional<ReadResult<double>>
HostTryReadF64(u32 address, RequestedAddressSpace space = RequestedAddressSpace::Effective);
TryReadResult<u32>
std::optional<ReadResult<u32>>
HostTryReadInstruction(u32 address, RequestedAddressSpace space = RequestedAddressSpace::Effective);
TryReadResult<std::string>
std::optional<ReadResult<std::string>>
HostTryReadString(u32 address, size_t size = 0,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
@ -93,36 +84,37 @@ void HostWrite_U64(u64 var, u32 address);
void HostWrite_F32(float var, u32 address);
void HostWrite_F64(double var, u32 address);
struct TryWriteResult
struct WriteResult
{
// whether the write succeeded; if false, the other fields should not be touched
bool success;
// whether the address had to be translated (given address was treated as virtual) or not (given
// address was treated as physical)
bool translated;
TryWriteResult() : success(false) {}
TryWriteResult(bool translated_) : success(true), translated(translated_) {}
explicit operator bool() const { return success; }
explicit WriteResult(bool translated_) : translated(translated_) {}
};
// Try to a write a value to memory at the given address in the given memory space.
// If the write succeeds, the returned TryWriteResult contains information on whether the given
// address had to be translated or not. Unlike the HostWrite functions, this does not raise a
// user-visible alert on failure.
TryWriteResult HostTryWriteU8(u32 var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
TryWriteResult HostTryWriteU16(u32 var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
TryWriteResult HostTryWriteU32(u32 var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
TryWriteResult HostTryWriteU64(u64 var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
TryWriteResult HostTryWriteF32(float var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
TryWriteResult HostTryWriteF64(double var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
std::optional<WriteResult>
HostTryWriteU8(u32 var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
std::optional<WriteResult>
HostTryWriteU16(u32 var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
std::optional<WriteResult>
HostTryWriteU32(u32 var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
std::optional<WriteResult>
HostTryWriteU64(u64 var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
std::optional<WriteResult>
HostTryWriteF32(float var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
std::optional<WriteResult>
HostTryWriteF64(double var, const u32 address,
RequestedAddressSpace space = RequestedAddressSpace::Effective);
// Returns whether a read or write to the given address will resolve to a RAM access in the given
// address space.