Switch boost::optional to std::optional
This commit is contained in:
parent
85bc96a61c
commit
764a93bf5a
42 changed files with 137 additions and 125 deletions
|
@ -7,8 +7,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include <boost/variant.hpp>
|
#include <boost/variant.hpp>
|
||||||
|
|
||||||
#include <dynarmic/A32/coprocessor_util.h>
|
#include <dynarmic/A32/coprocessor_util.h>
|
||||||
|
@ -31,8 +31,8 @@ public:
|
||||||
* @return Purpose of return value depends on type of callback.
|
* @return Purpose of return value depends on type of callback.
|
||||||
*/
|
*/
|
||||||
std::uint64_t (*function)(Jit* jit, void* user_arg, std::uint32_t arg0, std::uint32_t arg1);
|
std::uint64_t (*function)(Jit* jit, void* user_arg, std::uint32_t arg0, std::uint32_t arg1);
|
||||||
/// If boost::none, function will be called with a user_arg parameter containing garbage.
|
/// If std::nullopt, function will be called with a user_arg parameter containing garbage.
|
||||||
boost::optional<void*> user_arg;
|
std::optional<void*> user_arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,10 +51,10 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when compiling CDP or CDP2 for this coprocessor.
|
* Called when compiling CDP or CDP2 for this coprocessor.
|
||||||
* A return value of boost::none will cause a coprocessor exception to be compiled.
|
* A return value of std::nullopt will cause a coprocessor exception to be compiled.
|
||||||
* arg0, arg1 and return value of callback are ignored.
|
* arg0, arg1 and return value of callback are ignored.
|
||||||
*/
|
*/
|
||||||
virtual boost::optional<Callback> CompileInternalOperation(bool two, unsigned opc1, CoprocReg CRd, CoprocReg CRn, CoprocReg CRm, unsigned opc2) = 0;
|
virtual std::optional<Callback> CompileInternalOperation(bool two, unsigned opc1, CoprocReg CRd, CoprocReg CRn, CoprocReg CRm, unsigned opc2) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when compiling MCR or MCR2 for this coprocessor.
|
* Called when compiling MCR or MCR2 for this coprocessor.
|
||||||
|
@ -93,19 +93,19 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when compiling LDC or LDC2 for this coprocessor.
|
* Called when compiling LDC or LDC2 for this coprocessor.
|
||||||
* A return value of boost::none will cause a coprocessor exception to be compiled.
|
* A return value of std::nullopt will cause a coprocessor exception to be compiled.
|
||||||
* arg0 of the callback will contain the start address.
|
* arg0 of the callback will contain the start address.
|
||||||
* arg1 and return value of the callback are ignored.
|
* arg1 and return value of the callback are ignored.
|
||||||
*/
|
*/
|
||||||
virtual boost::optional<Callback> CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd, boost::optional<std::uint8_t> option) = 0;
|
virtual std::optional<Callback> CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd, std::optional<std::uint8_t> option) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when compiling STC or STC2 for this coprocessor.
|
* Called when compiling STC or STC2 for this coprocessor.
|
||||||
* A return value of boost::none will cause a coprocessor exception to be compiled.
|
* A return value of std::nullopt will cause a coprocessor exception to be compiled.
|
||||||
* arg0 of the callback will contain the start address.
|
* arg0 of the callback will contain the start address.
|
||||||
* arg1 and return value of the callback are ignored.
|
* arg1 and return value of the callback are ignored.
|
||||||
*/
|
*/
|
||||||
virtual boost::optional<Callback> CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd, boost::optional<std::uint8_t> option) = 0;
|
virtual std::optional<Callback> CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd, std::optional<std::uint8_t> option) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace A32
|
} // namespace A32
|
||||||
|
|
|
@ -954,7 +954,10 @@ static void EmitCoprocessorException() {
|
||||||
ASSERT_MSG(false, "Should raise coproc exception here");
|
ASSERT_MSG(false, "Should raise coproc exception here");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CallCoprocCallback(BlockOfCode& code, RegAlloc& reg_alloc, A32::Jit* jit_interface, A32::Coprocessor::Callback callback, IR::Inst* inst = nullptr, boost::optional<Argument&> arg0 = {}, boost::optional<Argument&> arg1 = {}) {
|
static void CallCoprocCallback(BlockOfCode& code, RegAlloc& reg_alloc, A32::Jit* jit_interface,
|
||||||
|
A32::Coprocessor::Callback callback, IR::Inst* inst = nullptr,
|
||||||
|
std::optional<Argument::copyable_reference> arg0 = {},
|
||||||
|
std::optional<Argument::copyable_reference> arg1 = {}) {
|
||||||
reg_alloc.HostCall(inst, {}, {}, arg0, arg1);
|
reg_alloc.HostCall(inst, {}, {}, arg0, arg1);
|
||||||
|
|
||||||
code.mov(code.ABI_PARAM1, reinterpret_cast<u64>(jit_interface));
|
code.mov(code.ABI_PARAM1, reinterpret_cast<u64>(jit_interface));
|
||||||
|
@ -1170,7 +1173,10 @@ void A32EmitX64::EmitA32CoprocLoadWords(A32EmitContext& ctx, IR::Inst* inst) {
|
||||||
bool long_transfer = coproc_info[2] != 0;
|
bool long_transfer = coproc_info[2] != 0;
|
||||||
A32::CoprocReg CRd = static_cast<A32::CoprocReg>(coproc_info[3]);
|
A32::CoprocReg CRd = static_cast<A32::CoprocReg>(coproc_info[3]);
|
||||||
bool has_option = coproc_info[4] != 0;
|
bool has_option = coproc_info[4] != 0;
|
||||||
boost::optional<u8> option{has_option, coproc_info[5]};
|
std::optional<u8> option = std::nullopt;
|
||||||
|
if (has_option) {
|
||||||
|
option = coproc_info[5];
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<A32::Coprocessor> coproc = config.coprocessors[coproc_num];
|
std::shared_ptr<A32::Coprocessor> coproc = config.coprocessors[coproc_num];
|
||||||
if (!coproc) {
|
if (!coproc) {
|
||||||
|
@ -1196,7 +1202,10 @@ void A32EmitX64::EmitA32CoprocStoreWords(A32EmitContext& ctx, IR::Inst* inst) {
|
||||||
bool long_transfer = coproc_info[2] != 0;
|
bool long_transfer = coproc_info[2] != 0;
|
||||||
A32::CoprocReg CRd = static_cast<A32::CoprocReg>(coproc_info[3]);
|
A32::CoprocReg CRd = static_cast<A32::CoprocReg>(coproc_info[3]);
|
||||||
bool has_option = coproc_info[4] != 0;
|
bool has_option = coproc_info[4] != 0;
|
||||||
boost::optional<u8> option{has_option, coproc_info[5]};
|
std::optional<u8> option = std::nullopt;
|
||||||
|
if (has_option) {
|
||||||
|
option = coproc_info[5];
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<A32::Coprocessor> coproc = config.coprocessors[coproc_num];
|
std::shared_ptr<A32::Coprocessor> coproc = config.coprocessors[coproc_num];
|
||||||
if (!coproc) {
|
if (!coproc) {
|
||||||
|
|
|
@ -7,8 +7,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <optional>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include "backend/x64/a32_jitstate.h"
|
#include "backend/x64/a32_jitstate.h"
|
||||||
#include "backend/x64/block_range_information.h"
|
#include "backend/x64/block_range_information.h"
|
||||||
|
|
|
@ -706,13 +706,13 @@ void A64EmitX64::EmitA64SetExclusive(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.mov(qword[r15 + offsetof(A64JitState, exclusive_address)], address);
|
code.mov(qword[r15 + offsetof(A64JitState, exclusive_address)], address);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Xbyak::RegExp EmitVAddrLookup(BlockOfCode& code, A64EmitContext& ctx, Xbyak::Label& abort, Xbyak::Reg64 vaddr, boost::optional<Xbyak::Reg64> arg_scratch = {}) {
|
static Xbyak::RegExp EmitVAddrLookup(BlockOfCode& code, A64EmitContext& ctx, Xbyak::Label& abort, Xbyak::Reg64 vaddr, std::optional<Xbyak::Reg64> arg_scratch = {}) {
|
||||||
constexpr size_t page_bits = 12;
|
constexpr size_t page_bits = 12;
|
||||||
constexpr size_t page_size = 1 << page_bits;
|
constexpr size_t page_size = 1 << page_bits;
|
||||||
const size_t valid_page_index_bits = ctx.conf.page_table_address_space_bits - page_bits;
|
const size_t valid_page_index_bits = ctx.conf.page_table_address_space_bits - page_bits;
|
||||||
const size_t unused_top_bits = 64 - ctx.conf.page_table_address_space_bits;
|
const size_t unused_top_bits = 64 - ctx.conf.page_table_address_space_bits;
|
||||||
|
|
||||||
Xbyak::Reg64 page_table = arg_scratch.value_or_eval([&]{ return ctx.reg_alloc.ScratchGpr(); });
|
Xbyak::Reg64 page_table = arg_scratch ? *arg_scratch : ctx.reg_alloc.ScratchGpr();
|
||||||
Xbyak::Reg64 tmp = ctx.reg_alloc.ScratchGpr();
|
Xbyak::Reg64 tmp = ctx.reg_alloc.ScratchGpr();
|
||||||
code.mov(page_table, reinterpret_cast<u64>(ctx.conf.page_table));
|
code.mov(page_table, reinterpret_cast<u64>(ctx.conf.page_table));
|
||||||
code.mov(tmp, vaddr);
|
code.mov(tmp, vaddr);
|
||||||
|
|
|
@ -38,10 +38,10 @@ EmitX64::EmitX64(BlockOfCode& code)
|
||||||
|
|
||||||
EmitX64::~EmitX64() = default;
|
EmitX64::~EmitX64() = default;
|
||||||
|
|
||||||
boost::optional<typename EmitX64::BlockDescriptor> EmitX64::GetBasicBlock(IR::LocationDescriptor descriptor) const {
|
std::optional<typename EmitX64::BlockDescriptor> EmitX64::GetBasicBlock(IR::LocationDescriptor descriptor) const {
|
||||||
auto iter = block_descriptors.find(descriptor);
|
auto iter = block_descriptors.find(descriptor);
|
||||||
if (iter == block_descriptors.end())
|
if (iter == block_descriptors.end())
|
||||||
return boost::none;
|
return std::nullopt;
|
||||||
return iter->second;
|
return iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include <xbyak_util.h>
|
#include <xbyak_util.h>
|
||||||
|
|
||||||
#include "backend/x64/reg_alloc.h"
|
#include "backend/x64/reg_alloc.h"
|
||||||
|
@ -67,7 +66,7 @@ public:
|
||||||
virtual ~EmitX64();
|
virtual ~EmitX64();
|
||||||
|
|
||||||
/// Looks up an emitted host block in the cache.
|
/// Looks up an emitted host block in the cache.
|
||||||
boost::optional<BlockDescriptor> GetBasicBlock(IR::LocationDescriptor descriptor) const;
|
std::optional<BlockDescriptor> GetBasicBlock(IR::LocationDescriptor descriptor) const;
|
||||||
|
|
||||||
/// Empties the entire cache.
|
/// Empties the entire cache.
|
||||||
virtual void ClearCache();
|
virtual void ClearCache();
|
||||||
|
|
|
@ -370,10 +370,13 @@ HostLoc RegAlloc::ScratchImpl(HostLocList desired_locations) {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegAlloc::HostCall(IR::Inst* result_def, boost::optional<Argument&> arg0, boost::optional<Argument&> arg1, boost::optional<Argument&> arg2, boost::optional<Argument&> arg3) {
|
void RegAlloc::HostCall(IR::Inst* result_def, std::optional<Argument::copyable_reference> arg0,
|
||||||
|
std::optional<Argument::copyable_reference> arg1,
|
||||||
|
std::optional<Argument::copyable_reference> arg2,
|
||||||
|
std::optional<Argument::copyable_reference> arg3) {
|
||||||
constexpr size_t args_count = 4;
|
constexpr size_t args_count = 4;
|
||||||
constexpr std::array<HostLoc, args_count> args_hostloc = { ABI_PARAM1, ABI_PARAM2, ABI_PARAM3, ABI_PARAM4 };
|
constexpr std::array<HostLoc, args_count> args_hostloc = { ABI_PARAM1, ABI_PARAM2, ABI_PARAM3, ABI_PARAM4 };
|
||||||
const std::array<boost::optional<Argument&>, args_count> args = { arg0, arg1, arg2, arg3 };
|
const std::array<std::optional<Argument::copyable_reference>, args_count> args = { arg0, arg1, arg2, arg3 };
|
||||||
|
|
||||||
static const std::vector<HostLoc> other_caller_save = [args_hostloc]() {
|
static const std::vector<HostLoc> other_caller_save = [args_hostloc]() {
|
||||||
std::vector<HostLoc> ret(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end());
|
std::vector<HostLoc> ret(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end());
|
||||||
|
@ -396,7 +399,7 @@ void RegAlloc::HostCall(IR::Inst* result_def, boost::optional<Argument&> arg0, b
|
||||||
#if defined(__llvm__) && !defined(_WIN32)
|
#if defined(__llvm__) && !defined(_WIN32)
|
||||||
// LLVM puts the burden of zero-extension of 8 and 16 bit values on the caller instead of the callee
|
// LLVM puts the burden of zero-extension of 8 and 16 bit values on the caller instead of the callee
|
||||||
Xbyak::Reg64 reg = HostLocToReg64(args_hostloc[i]);
|
Xbyak::Reg64 reg = HostLocToReg64(args_hostloc[i]);
|
||||||
switch (args[i]->GetType()) {
|
switch (args[i]->get().GetType()) {
|
||||||
case IR::Type::U8:
|
case IR::Type::U8:
|
||||||
code.movzx(reg.cvt32(), reg.cvt8());
|
code.movzx(reg.cvt32(), reg.cvt8());
|
||||||
break;
|
break;
|
||||||
|
@ -452,12 +455,12 @@ HostLoc RegAlloc::SelectARegister(HostLocList desired_locations) const {
|
||||||
return candidates.front();
|
return candidates.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<HostLoc> RegAlloc::ValueLocation(const IR::Inst* value) const {
|
std::optional<HostLoc> RegAlloc::ValueLocation(const IR::Inst* value) const {
|
||||||
for (size_t i = 0; i < hostloc_info.size(); i++)
|
for (size_t i = 0; i < hostloc_info.size(); i++)
|
||||||
if (hostloc_info[i].ContainsValue(value))
|
if (hostloc_info[i].ContainsValue(value))
|
||||||
return static_cast<HostLoc>(i);
|
return static_cast<HostLoc>(i);
|
||||||
|
|
||||||
return boost::none;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegAlloc::DefineValueImpl(IR::Inst* def_inst, HostLoc host_loc) {
|
void RegAlloc::DefineValueImpl(IR::Inst* def_inst, HostLoc host_loc) {
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <optional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include <xbyak.h>
|
#include <xbyak.h>
|
||||||
|
|
||||||
#include "backend/x64/block_of_code.h"
|
#include "backend/x64/block_of_code.h"
|
||||||
|
@ -60,6 +60,8 @@ private:
|
||||||
|
|
||||||
struct Argument {
|
struct Argument {
|
||||||
public:
|
public:
|
||||||
|
using copyable_reference = std::reference_wrapper<Argument>;
|
||||||
|
|
||||||
IR::Type GetType() const;
|
IR::Type GetType() const;
|
||||||
bool IsImmediate() const;
|
bool IsImmediate() const;
|
||||||
bool IsVoid() const;
|
bool IsVoid() const;
|
||||||
|
@ -117,7 +119,11 @@ public:
|
||||||
Xbyak::Reg64 ScratchGpr(HostLocList desired_locations = any_gpr);
|
Xbyak::Reg64 ScratchGpr(HostLocList desired_locations = any_gpr);
|
||||||
Xbyak::Xmm ScratchXmm(HostLocList desired_locations = any_xmm);
|
Xbyak::Xmm ScratchXmm(HostLocList desired_locations = any_xmm);
|
||||||
|
|
||||||
void HostCall(IR::Inst* result_def = nullptr, boost::optional<Argument&> arg0 = {}, boost::optional<Argument&> arg1 = {}, boost::optional<Argument&> arg2 = {}, boost::optional<Argument&> arg3 = {});
|
void HostCall(IR::Inst* result_def = nullptr,
|
||||||
|
std::optional<Argument::copyable_reference> arg0 = {},
|
||||||
|
std::optional<Argument::copyable_reference> arg1 = {},
|
||||||
|
std::optional<Argument::copyable_reference> arg2 = {},
|
||||||
|
std::optional<Argument::copyable_reference> arg3 = {});
|
||||||
|
|
||||||
// TODO: Values in host flags
|
// TODO: Values in host flags
|
||||||
|
|
||||||
|
@ -129,7 +135,7 @@ private:
|
||||||
friend struct Argument;
|
friend struct Argument;
|
||||||
|
|
||||||
HostLoc SelectARegister(HostLocList desired_locations) const;
|
HostLoc SelectARegister(HostLocList desired_locations) const;
|
||||||
boost::optional<HostLoc> ValueLocation(const IR::Inst* value) const;
|
std::optional<HostLoc> ValueLocation(const IR::Inst* value) const;
|
||||||
|
|
||||||
HostLoc UseImpl(IR::Value use_value, HostLocList desired_locations);
|
HostLoc UseImpl(IR::Value use_value, HostLocList desired_locations);
|
||||||
HostLoc UseScratchImpl(IR::Value use_value, HostLocList desired_locations);
|
HostLoc UseScratchImpl(IR::Value use_value, HostLocList desired_locations);
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
|
@ -75,14 +75,14 @@ public:
|
||||||
|
|
||||||
/// Get the stride of a vector when executing AArch32 VFP instructions.
|
/// Get the stride of a vector when executing AArch32 VFP instructions.
|
||||||
/// This field has no function in AArch64 state.
|
/// This field has no function in AArch64 state.
|
||||||
boost::optional<size_t> Stride() const {
|
std::optional<size_t> Stride() const {
|
||||||
switch (Common::Bits<20, 21>(value)) {
|
switch (Common::Bits<20, 21>(value)) {
|
||||||
case 0b00:
|
case 0b00:
|
||||||
return 1;
|
return 1;
|
||||||
case 0b11:
|
case 0b11:
|
||||||
return 2;
|
return 2;
|
||||||
default:
|
default:
|
||||||
return boost::none;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* General Public License version 2 or any later version.
|
* General Public License version 2 or any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
|
@ -41,7 +41,7 @@ template u32 FPProcessNaN<u32>(FPType type, u32 op, FPCR fpcr, FPSR& fpsr);
|
||||||
template u64 FPProcessNaN<u64>(FPType type, u64 op, FPCR fpcr, FPSR& fpsr);
|
template u64 FPProcessNaN<u64>(FPType type, u64 op, FPCR fpcr, FPSR& fpsr);
|
||||||
|
|
||||||
template<typename FPT>
|
template<typename FPT>
|
||||||
boost::optional<FPT> FPProcessNaNs(FPType type1, FPType type2, FPT op1, FPT op2, FPCR fpcr, FPSR& fpsr) {
|
std::optional<FPT> FPProcessNaNs(FPType type1, FPType type2, FPT op1, FPT op2, FPCR fpcr, FPSR& fpsr) {
|
||||||
if (type1 == FPType::SNaN) {
|
if (type1 == FPType::SNaN) {
|
||||||
return FPProcessNaN<FPT>(type1, op1, fpcr, fpsr);
|
return FPProcessNaN<FPT>(type1, op1, fpcr, fpsr);
|
||||||
}
|
}
|
||||||
|
@ -54,14 +54,14 @@ boost::optional<FPT> FPProcessNaNs(FPType type1, FPType type2, FPT op1, FPT op2,
|
||||||
if (type2 == FPType::QNaN) {
|
if (type2 == FPType::QNaN) {
|
||||||
return FPProcessNaN<FPT>(type2, op2, fpcr, fpsr);
|
return FPProcessNaN<FPT>(type2, op2, fpcr, fpsr);
|
||||||
}
|
}
|
||||||
return boost::none;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
template boost::optional<u32> FPProcessNaNs<u32>(FPType type1, FPType type2, u32 op1, u32 op2, FPCR fpcr, FPSR& fpsr);
|
template std::optional<u32> FPProcessNaNs<u32>(FPType type1, FPType type2, u32 op1, u32 op2, FPCR fpcr, FPSR& fpsr);
|
||||||
template boost::optional<u64> FPProcessNaNs<u64>(FPType type1, FPType type2, u64 op1, u64 op2, FPCR fpcr, FPSR& fpsr);
|
template std::optional<u64> FPProcessNaNs<u64>(FPType type1, FPType type2, u64 op1, u64 op2, FPCR fpcr, FPSR& fpsr);
|
||||||
|
|
||||||
template<typename FPT>
|
template<typename FPT>
|
||||||
boost::optional<FPT> FPProcessNaNs3(FPType type1, FPType type2, FPType type3, FPT op1, FPT op2, FPT op3, FPCR fpcr, FPSR& fpsr) {
|
std::optional<FPT> FPProcessNaNs3(FPType type1, FPType type2, FPType type3, FPT op1, FPT op2, FPT op3, FPCR fpcr, FPSR& fpsr) {
|
||||||
if (type1 == FPType::SNaN) {
|
if (type1 == FPType::SNaN) {
|
||||||
return FPProcessNaN<FPT>(type1, op1, fpcr, fpsr);
|
return FPProcessNaN<FPT>(type1, op1, fpcr, fpsr);
|
||||||
}
|
}
|
||||||
|
@ -80,10 +80,10 @@ boost::optional<FPT> FPProcessNaNs3(FPType type1, FPType type2, FPType type3, FP
|
||||||
if (type3 == FPType::QNaN) {
|
if (type3 == FPType::QNaN) {
|
||||||
return FPProcessNaN<FPT>(type3, op3, fpcr, fpsr);
|
return FPProcessNaN<FPT>(type3, op3, fpcr, fpsr);
|
||||||
}
|
}
|
||||||
return boost::none;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
template boost::optional<u32> FPProcessNaNs3<u32>(FPType type1, FPType type2, FPType type3, u32 op1, u32 op2, u32 op3, FPCR fpcr, FPSR& fpsr);
|
template std::optional<u32> FPProcessNaNs3<u32>(FPType type1, FPType type2, FPType type3, u32 op1, u32 op2, u32 op3, FPCR fpcr, FPSR& fpsr);
|
||||||
template boost::optional<u64> FPProcessNaNs3<u64>(FPType type1, FPType type2, FPType type3, u64 op1, u64 op2, u64 op3, FPCR fpcr, FPSR& fpsr);
|
template std::optional<u64> FPProcessNaNs3<u64>(FPType type1, FPType type2, FPType type3, u64 op1, u64 op2, u64 op3, FPCR fpcr, FPSR& fpsr);
|
||||||
|
|
||||||
} // namespace Dynarmic::FP
|
} // namespace Dynarmic::FP
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
namespace Dynarmic::FP {
|
namespace Dynarmic::FP {
|
||||||
|
|
||||||
|
@ -18,9 +18,9 @@ template<typename FPT>
|
||||||
FPT FPProcessNaN(FPType type, FPT op, FPCR fpcr, FPSR& fpsr);
|
FPT FPProcessNaN(FPType type, FPT op, FPCR fpcr, FPSR& fpsr);
|
||||||
|
|
||||||
template<typename FPT>
|
template<typename FPT>
|
||||||
boost::optional<FPT> FPProcessNaNs(FPType type1, FPType type2, FPT op1, FPT op2, FPCR fpcr, FPSR& fpsr);
|
std::optional<FPT> FPProcessNaNs(FPType type1, FPType type2, FPT op1, FPT op2, FPCR fpcr, FPSR& fpsr);
|
||||||
|
|
||||||
template<typename FPT>
|
template<typename FPT>
|
||||||
boost::optional<FPT> FPProcessNaNs3(FPType type1, FPType type2, FPType type3, FPT op1, FPT op2, FPT op3, FPCR fpcr, FPSR& fpsr);
|
std::optional<FPT> FPProcessNaNs3(FPType type1, FPType type2, FPType type3, FPT op1, FPT op2, FPT op3, FPCR fpcr, FPSR& fpsr);
|
||||||
|
|
||||||
} // namespace Dynarmic::FP
|
} // namespace Dynarmic::FP
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/fp/fpcr.h"
|
#include "common/fp/fpcr.h"
|
||||||
|
@ -51,21 +51,21 @@ constexpr bool IsNaN(FPT value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a single argument, return the NaN value which would be returned by an ARM processor.
|
/// Given a single argument, return the NaN value which would be returned by an ARM processor.
|
||||||
/// If the argument isn't a NaN, returns boost::none.
|
/// If the argument isn't a NaN, returns std::nullopt.
|
||||||
template<typename FPT>
|
template<typename FPT>
|
||||||
inline boost::optional<FPT> ProcessNaNs(FPT a) {
|
inline std::optional<FPT> ProcessNaNs(FPT a) {
|
||||||
if (IsSNaN(a)) {
|
if (IsSNaN(a)) {
|
||||||
return a | FPInfo<FPT>::mantissa_msb;
|
return a | FPInfo<FPT>::mantissa_msb;
|
||||||
} else if (IsQNaN(a)) {
|
} else if (IsQNaN(a)) {
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
return boost::none;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a pair of arguments, return the NaN value which would be returned by an ARM processor.
|
/// Given a pair of arguments, return the NaN value which would be returned by an ARM processor.
|
||||||
/// If neither argument is a NaN, returns boost::none.
|
/// If neither argument is a NaN, returns std::nullopt.
|
||||||
template<typename FPT>
|
template<typename FPT>
|
||||||
inline boost::optional<FPT> ProcessNaNs(FPT a, FPT b) {
|
inline std::optional<FPT> ProcessNaNs(FPT a, FPT b) {
|
||||||
if (IsSNaN(a)) {
|
if (IsSNaN(a)) {
|
||||||
return a | FPInfo<FPT>::mantissa_msb;
|
return a | FPInfo<FPT>::mantissa_msb;
|
||||||
} else if (IsSNaN(b)) {
|
} else if (IsSNaN(b)) {
|
||||||
|
@ -75,13 +75,13 @@ inline boost::optional<FPT> ProcessNaNs(FPT a, FPT b) {
|
||||||
} else if (IsQNaN(b)) {
|
} else if (IsQNaN(b)) {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
return boost::none;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given three arguments, return the NaN value which would be returned by an ARM processor.
|
/// Given three arguments, return the NaN value which would be returned by an ARM processor.
|
||||||
/// If none of the arguments is a NaN, returns boost::none.
|
/// If none of the arguments is a NaN, returns std::nullopt.
|
||||||
template<typename FPT>
|
template<typename FPT>
|
||||||
inline boost::optional<FPT> ProcessNaNs(FPT a, FPT b, FPT c) {
|
inline std::optional<FPT> ProcessNaNs(FPT a, FPT b, FPT c) {
|
||||||
if (IsSNaN(a)) {
|
if (IsSNaN(a)) {
|
||||||
return a | FPInfo<FPT>::mantissa_msb;
|
return a | FPInfo<FPT>::mantissa_msb;
|
||||||
} else if (IsSNaN(b)) {
|
} else if (IsSNaN(b)) {
|
||||||
|
@ -95,7 +95,7 @@ inline boost::optional<FPT> ProcessNaNs(FPT a, FPT b, FPT c) {
|
||||||
} else if (IsQNaN(c)) {
|
} else if (IsQNaN(c)) {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
return boost::none;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Dynarmic::FP
|
} // namespace Dynarmic::FP
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
@ -78,14 +78,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicates the stride of a vector.
|
/// Indicates the stride of a vector.
|
||||||
boost::optional<size_t> Stride() const {
|
std::optional<size_t> Stride() const {
|
||||||
switch (Common::Bits<20, 21>(value)) {
|
switch (Common::Bits<20, 21>(value)) {
|
||||||
case 0b00:
|
case 0b00:
|
||||||
return 1;
|
return 1;
|
||||||
case 0b11:
|
case 0b11:
|
||||||
return 2;
|
return 2;
|
||||||
default:
|
default:
|
||||||
return boost::none;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,9 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "frontend/decoder/decoder_detail.h"
|
#include "frontend/decoder/decoder_detail.h"
|
||||||
|
@ -43,13 +42,13 @@ std::vector<ArmMatcher<V>> GetArmDecodeTable() {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
|
std::optional<std::reference_wrapper<const ArmMatcher<V>>> DecodeArm(u32 instruction) {
|
||||||
static const auto table = GetArmDecodeTable<V>();
|
static const auto table = GetArmDecodeTable<V>();
|
||||||
|
|
||||||
const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); };
|
const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); };
|
||||||
|
|
||||||
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
||||||
return iter != table.end() ? boost::optional<const ArmMatcher<V>&>(*iter) : boost::none;
|
return iter != table.end() ? std::optional<std::reference_wrapper<const ArmMatcher<V>>>(*iter) : std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Dynarmic::A32
|
} // namespace Dynarmic::A32
|
||||||
|
|
|
@ -7,10 +7,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "frontend/decoder/decoder_detail.h"
|
#include "frontend/decoder/decoder_detail.h"
|
||||||
#include "frontend/decoder/matcher.h"
|
#include "frontend/decoder/matcher.h"
|
||||||
|
@ -21,7 +21,7 @@ template <typename Visitor>
|
||||||
using Thumb16Matcher = Decoder::Matcher<Visitor, u16>;
|
using Thumb16Matcher = Decoder::Matcher<Visitor, u16>;
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
boost::optional<const Thumb16Matcher<V>&> DecodeThumb16(u16 instruction) {
|
std::optional<std::reference_wrapper<const Thumb16Matcher<V>>> DecodeThumb16(u16 instruction) {
|
||||||
static const std::vector<Thumb16Matcher<V>> table = {
|
static const std::vector<Thumb16Matcher<V>> table = {
|
||||||
|
|
||||||
#define INST(fn, name, bitstring) Decoder::detail::detail<Thumb16Matcher<V>>::GetMatcher(fn, name, bitstring)
|
#define INST(fn, name, bitstring) Decoder::detail::detail<Thumb16Matcher<V>>::GetMatcher(fn, name, bitstring)
|
||||||
|
@ -120,7 +120,7 @@ boost::optional<const Thumb16Matcher<V>&> DecodeThumb16(u16 instruction) {
|
||||||
const auto matches_instruction = [instruction](const auto& matcher){ return matcher.Matches(instruction); };
|
const auto matches_instruction = [instruction](const auto& matcher){ return matcher.Matches(instruction); };
|
||||||
|
|
||||||
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
||||||
return iter != table.end() ? boost::optional<const Thumb16Matcher<V>&>(*iter) : boost::none;
|
return iter != table.end() ? std::optional<std::reference_wrapper<const Thumb16Matcher<V>>>(*iter) : std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Dynarmic::A32
|
} // namespace Dynarmic::A32
|
||||||
|
|
|
@ -7,10 +7,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "frontend/decoder/decoder_detail.h"
|
#include "frontend/decoder/decoder_detail.h"
|
||||||
#include "frontend/decoder/matcher.h"
|
#include "frontend/decoder/matcher.h"
|
||||||
|
@ -21,7 +20,7 @@ template <typename Visitor>
|
||||||
using Thumb32Matcher = Decoder::Matcher<Visitor, u32>;
|
using Thumb32Matcher = Decoder::Matcher<Visitor, u32>;
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
boost::optional<const Thumb32Matcher<V>&> DecodeThumb32(u32 instruction) {
|
std::optional<std::reference_wrapper<const Thumb32Matcher<V>>> DecodeThumb32(u32 instruction) {
|
||||||
static const std::vector<Thumb32Matcher<V>> table = {
|
static const std::vector<Thumb32Matcher<V>> table = {
|
||||||
|
|
||||||
#define INST(fn, name, bitstring) Decoder::detail::detail<Thumb32Matcher<V>>::GetMatcher(fn, name, bitstring)
|
#define INST(fn, name, bitstring) Decoder::detail::detail<Thumb32Matcher<V>>::GetMatcher(fn, name, bitstring)
|
||||||
|
@ -349,7 +348,7 @@ boost::optional<const Thumb32Matcher<V>&> DecodeThumb32(u32 instruction) {
|
||||||
const auto matches_instruction = [instruction](const auto& matcher){ return matcher.Matches(instruction); };
|
const auto matches_instruction = [instruction](const auto& matcher){ return matcher.Matches(instruction); };
|
||||||
|
|
||||||
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
||||||
return iter != table.end() ? boost::optional<const Thumb32Matcher<V>&>(*iter) : boost::none;
|
return iter != table.end() ? std::optional<std::reference_wrapper<const Thumb32Matcher<V>>>(*iter) : std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Dynarmic::A32
|
} // namespace Dynarmic::A32
|
||||||
|
|
|
@ -7,9 +7,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "frontend/decoder/decoder_detail.h"
|
#include "frontend/decoder/decoder_detail.h"
|
||||||
|
@ -21,7 +22,7 @@ template <typename Visitor>
|
||||||
using VFP2Matcher = Decoder::Matcher<Visitor, u32>;
|
using VFP2Matcher = Decoder::Matcher<Visitor, u32>;
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
boost::optional<const VFP2Matcher<V>&> DecodeVFP2(u32 instruction) {
|
std::optional<std::reference_wrapper<const VFP2Matcher<V>>> DecodeVFP2(u32 instruction) {
|
||||||
static const std::vector<VFP2Matcher<V>> table = {
|
static const std::vector<VFP2Matcher<V>> table = {
|
||||||
|
|
||||||
#define INST(fn, name, bitstring) Decoder::detail::detail<VFP2Matcher<V>>::GetMatcher(&V::fn, name, bitstring),
|
#define INST(fn, name, bitstring) Decoder::detail::detail<VFP2Matcher<V>>::GetMatcher(&V::fn, name, bitstring),
|
||||||
|
@ -31,12 +32,12 @@ boost::optional<const VFP2Matcher<V>&> DecodeVFP2(u32 instruction) {
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((instruction & 0xF0000000) == 0xF0000000)
|
if ((instruction & 0xF0000000) == 0xF0000000)
|
||||||
return boost::none; // Don't try matching any unconditional instructions.
|
return std::nullopt; // Don't try matching any unconditional instructions.
|
||||||
|
|
||||||
const auto matches_instruction = [instruction](const auto& matcher){ return matcher.Matches(instruction); };
|
const auto matches_instruction = [instruction](const auto& matcher){ return matcher.Matches(instruction); };
|
||||||
|
|
||||||
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
||||||
return iter != table.end() ? boost::optional<const VFP2Matcher<V>&>(*iter) : boost::none;
|
return iter != table.end() ? std::optional<std::reference_wrapper<const VFP2Matcher<V>>>(*iter) : std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Dynarmic::A32
|
} // namespace Dynarmic::A32
|
||||||
|
|
|
@ -1068,9 +1068,9 @@ public:
|
||||||
std::string DisassembleArm(u32 instruction) {
|
std::string DisassembleArm(u32 instruction) {
|
||||||
DisassemblerVisitor visitor;
|
DisassemblerVisitor visitor;
|
||||||
if (auto vfp_decoder = DecodeVFP2<DisassemblerVisitor>(instruction)) {
|
if (auto vfp_decoder = DecodeVFP2<DisassemblerVisitor>(instruction)) {
|
||||||
return vfp_decoder->call(visitor, instruction);
|
return vfp_decoder->get().call(visitor, instruction);
|
||||||
} else if (auto decoder = DecodeArm<DisassemblerVisitor>(instruction)) {
|
} else if (auto decoder = DecodeArm<DisassemblerVisitor>(instruction)) {
|
||||||
return decoder->call(visitor, instruction);
|
return decoder->get().call(visitor, instruction);
|
||||||
} else {
|
} else {
|
||||||
return fmt::format("UNKNOWN: {:x}", instruction);
|
return fmt::format("UNKNOWN: {:x}", instruction);
|
||||||
}
|
}
|
||||||
|
|
|
@ -328,7 +328,7 @@ public:
|
||||||
std::string DisassembleThumb16(u16 instruction) {
|
std::string DisassembleThumb16(u16 instruction) {
|
||||||
DisassemblerVisitor visitor;
|
DisassemblerVisitor visitor;
|
||||||
auto decoder = DecodeThumb16<DisassemblerVisitor>(instruction);
|
auto decoder = DecodeThumb16<DisassemblerVisitor>(instruction);
|
||||||
return !decoder ? fmt::format("UNKNOWN: {:x}", instruction) : decoder->call(visitor, instruction);
|
return !decoder ? fmt::format("UNKNOWN: {:x}", instruction) : decoder->get().call(visitor, instruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Dynarmic::A32
|
} // namespace Dynarmic::A32
|
||||||
|
|
|
@ -38,9 +38,9 @@ IR::Block TranslateArm(LocationDescriptor descriptor, MemoryReadCodeFuncType mem
|
||||||
const u32 arm_instruction = memory_read_code(arm_pc);
|
const u32 arm_instruction = memory_read_code(arm_pc);
|
||||||
|
|
||||||
if (const auto vfp_decoder = DecodeVFP2<ArmTranslatorVisitor>(arm_instruction)) {
|
if (const auto vfp_decoder = DecodeVFP2<ArmTranslatorVisitor>(arm_instruction)) {
|
||||||
should_continue = vfp_decoder->call(visitor, arm_instruction);
|
should_continue = vfp_decoder->get().call(visitor, arm_instruction);
|
||||||
} else if (const auto decoder = DecodeArm<ArmTranslatorVisitor>(arm_instruction)) {
|
} else if (const auto decoder = DecodeArm<ArmTranslatorVisitor>(arm_instruction)) {
|
||||||
should_continue = decoder->call(visitor, arm_instruction);
|
should_continue = decoder->get().call(visitor, arm_instruction);
|
||||||
} else {
|
} else {
|
||||||
should_continue = visitor.arm_UDF();
|
should_continue = visitor.arm_UDF();
|
||||||
}
|
}
|
||||||
|
@ -73,9 +73,9 @@ bool TranslateSingleArmInstruction(IR::Block& block, LocationDescriptor descript
|
||||||
|
|
||||||
bool should_continue = true;
|
bool should_continue = true;
|
||||||
if (const auto vfp_decoder = DecodeVFP2<ArmTranslatorVisitor>(arm_instruction)) {
|
if (const auto vfp_decoder = DecodeVFP2<ArmTranslatorVisitor>(arm_instruction)) {
|
||||||
should_continue = vfp_decoder->call(visitor, arm_instruction);
|
should_continue = vfp_decoder->get().call(visitor, arm_instruction);
|
||||||
} else if (const auto decoder = DecodeArm<ArmTranslatorVisitor>(arm_instruction)) {
|
} else if (const auto decoder = DecodeArm<ArmTranslatorVisitor>(arm_instruction)) {
|
||||||
should_continue = decoder->call(visitor, arm_instruction);
|
should_continue = decoder->get().call(visitor, arm_instruction);
|
||||||
} else {
|
} else {
|
||||||
should_continue = visitor.arm_UDF();
|
should_continue = visitor.arm_UDF();
|
||||||
}
|
}
|
||||||
|
|
|
@ -891,13 +891,13 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryReadCodeFuncType m
|
||||||
|
|
||||||
if (inst_size == ThumbInstSize::Thumb16) {
|
if (inst_size == ThumbInstSize::Thumb16) {
|
||||||
if (const auto decoder = DecodeThumb16<ThumbTranslatorVisitor>(static_cast<u16>(thumb_instruction))) {
|
if (const auto decoder = DecodeThumb16<ThumbTranslatorVisitor>(static_cast<u16>(thumb_instruction))) {
|
||||||
should_continue = decoder->call(visitor, static_cast<u16>(thumb_instruction));
|
should_continue = decoder->get().call(visitor, static_cast<u16>(thumb_instruction));
|
||||||
} else {
|
} else {
|
||||||
should_continue = visitor.thumb16_UDF();
|
should_continue = visitor.thumb16_UDF();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (const auto decoder = DecodeThumb32<ThumbTranslatorVisitor>(thumb_instruction)) {
|
if (const auto decoder = DecodeThumb32<ThumbTranslatorVisitor>(thumb_instruction)) {
|
||||||
should_continue = decoder->call(visitor, thumb_instruction);
|
should_continue = decoder->get().call(visitor, thumb_instruction);
|
||||||
} else {
|
} else {
|
||||||
should_continue = visitor.thumb32_UDF();
|
should_continue = visitor.thumb32_UDF();
|
||||||
}
|
}
|
||||||
|
@ -920,13 +920,13 @@ bool TranslateSingleThumbInstruction(IR::Block& block, LocationDescriptor descri
|
||||||
bool should_continue = true;
|
bool should_continue = true;
|
||||||
if (is_thumb_16) {
|
if (is_thumb_16) {
|
||||||
if (const auto decoder = DecodeThumb16<ThumbTranslatorVisitor>(static_cast<u16>(thumb_instruction))) {
|
if (const auto decoder = DecodeThumb16<ThumbTranslatorVisitor>(static_cast<u16>(thumb_instruction))) {
|
||||||
should_continue = decoder->call(visitor, static_cast<u16>(thumb_instruction));
|
should_continue = decoder->get().call(visitor, static_cast<u16>(thumb_instruction));
|
||||||
} else {
|
} else {
|
||||||
should_continue = visitor.thumb16_UDF();
|
should_continue = visitor.thumb16_UDF();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (const auto decoder = DecodeThumb32<ThumbTranslatorVisitor>(thumb_instruction)) {
|
if (const auto decoder = DecodeThumb32<ThumbTranslatorVisitor>(thumb_instruction)) {
|
||||||
should_continue = decoder->call(visitor, thumb_instruction);
|
should_continue = decoder->get().call(visitor, thumb_instruction);
|
||||||
} else {
|
} else {
|
||||||
should_continue = visitor.thumb32_UDF();
|
should_continue = visitor.thumb32_UDF();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,10 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "frontend/decoder/decoder_detail.h"
|
#include "frontend/decoder/decoder_detail.h"
|
||||||
|
@ -51,13 +50,13 @@ std::vector<Matcher<Visitor>> GetDecodeTable() {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Visitor>
|
template<typename Visitor>
|
||||||
boost::optional<const Matcher<Visitor>&> Decode(u32 instruction) {
|
std::optional<std::reference_wrapper<const Matcher<Visitor>>> Decode(u32 instruction) {
|
||||||
static const auto table = GetDecodeTable<Visitor>();
|
static const auto table = GetDecodeTable<Visitor>();
|
||||||
|
|
||||||
const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); };
|
const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); };
|
||||||
|
|
||||||
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
||||||
return iter != table.end() ? boost::optional<const Matcher<Visitor>&>(*iter) : boost::none;
|
return iter != table.end() ? std::optional<std::reference_wrapper<const Matcher<Visitor>>>(*iter) : std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Dynarmic::A64
|
} // namespace Dynarmic::A64
|
||||||
|
|
|
@ -7,8 +7,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
#include <optional>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include <dynarmic/A64/config.h>
|
#include <dynarmic/A64/config.h>
|
||||||
|
|
||||||
|
@ -30,7 +29,7 @@ public:
|
||||||
explicit IREmitter(IR::Block& block) : IR::IREmitter(block) {}
|
explicit IREmitter(IR::Block& block) : IR::IREmitter(block) {}
|
||||||
explicit IREmitter(IR::Block& block, LocationDescriptor descriptor) : IR::IREmitter(block), current_location(descriptor) {}
|
explicit IREmitter(IR::Block& block, LocationDescriptor descriptor) : IR::IREmitter(block), current_location(descriptor) {}
|
||||||
|
|
||||||
boost::optional<LocationDescriptor> current_location;
|
std::optional<LocationDescriptor> current_location;
|
||||||
|
|
||||||
u64 PC();
|
u64 PC();
|
||||||
u64 AlignPC(size_t alignment);
|
u64 AlignPC(size_t alignment);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* General Public License version 2 or any later version.
|
* General Public License version 2 or any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "frontend/A64/translate/impl/impl.h"
|
#include "frontend/A64/translate/impl/impl.h"
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* General Public License version 2 or any later version.
|
* General Public License version 2 or any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "frontend/A64/translate/impl/impl.h"
|
#include "frontend/A64/translate/impl/impl.h"
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* General Public License version 2 or any later version.
|
* General Public License version 2 or any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "frontend/A64/translate/impl/impl.h"
|
#include "frontend/A64/translate/impl/impl.h"
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* General Public License version 2 or any later version.
|
* General Public License version 2 or any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "frontend/A64/translate/impl/impl.h"
|
#include "frontend/A64/translate/impl/impl.h"
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* General Public License version 2 or any later version.
|
* General Public License version 2 or any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "common/fp/rounding_mode.h"
|
#include "common/fp/rounding_mode.h"
|
||||||
#include "frontend/A64/translate/impl/impl.h"
|
#include "frontend/A64/translate/impl/impl.h"
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* General Public License version 2 or any later version.
|
* General Public License version 2 or any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "frontend/A64/translate/impl/impl.h"
|
#include "frontend/A64/translate/impl/impl.h"
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* General Public License version 2 or any later version.
|
* General Public License version 2 or any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "frontend/A64/translate/impl/impl.h"
|
#include "frontend/A64/translate/impl/impl.h"
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* General Public License version 2 or any later version.
|
* General Public License version 2 or any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "frontend/A64/translate/impl/impl.h"
|
#include "frontend/A64/translate/impl/impl.h"
|
||||||
|
|
||||||
|
|
|
@ -39,15 +39,15 @@ bool TranslatorVisitor::RaiseException(Exception exception) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<TranslatorVisitor::BitMasks> TranslatorVisitor::DecodeBitMasks(bool immN, Imm<6> imms, Imm<6> immr, bool immediate) {
|
std::optional<TranslatorVisitor::BitMasks> TranslatorVisitor::DecodeBitMasks(bool immN, Imm<6> imms, Imm<6> immr, bool immediate) {
|
||||||
int len = Common::HighestSetBit((immN ? 1 << 6 : 0) | (imms.ZeroExtend() ^ 0b111111));
|
int len = Common::HighestSetBit((immN ? 1 << 6 : 0) | (imms.ZeroExtend() ^ 0b111111));
|
||||||
if (len < 1)
|
if (len < 1)
|
||||||
return boost::none;
|
return std::nullopt;
|
||||||
|
|
||||||
size_t levels = Common::Ones<size_t>(len);
|
size_t levels = Common::Ones<size_t>(len);
|
||||||
|
|
||||||
if (immediate && (imms.ZeroExtend() & levels) == levels)
|
if (immediate && (imms.ZeroExtend() & levels) == levels)
|
||||||
return boost::none;
|
return std::nullopt;
|
||||||
|
|
||||||
s32 S = s32(imms.ZeroExtend() & levels);
|
s32 S = s32(imms.ZeroExtend() & levels);
|
||||||
s32 R = s32(immr.ZeroExtend() & levels);
|
s32 R = s32(immr.ZeroExtend() & levels);
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "frontend/A64/imm.h"
|
#include "frontend/A64/imm.h"
|
||||||
#include "frontend/A64/ir_emitter.h"
|
#include "frontend/A64/ir_emitter.h"
|
||||||
|
@ -43,7 +43,7 @@ struct TranslatorVisitor final {
|
||||||
u64 wmask, tmask;
|
u64 wmask, tmask;
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::optional<BitMasks> DecodeBitMasks(bool N, Imm<6> immr, Imm<6> imms, bool immediate);
|
std::optional<BitMasks> DecodeBitMasks(bool N, Imm<6> immr, Imm<6> imms, bool immediate);
|
||||||
u64 AdvSIMDExpandImm(bool op, Imm<4> cmode, Imm<8> imm8);
|
u64 AdvSIMDExpandImm(bool op, Imm<4> cmode, Imm<8> imm8);
|
||||||
|
|
||||||
IR::UAny I(size_t bitsize, u64 value);
|
IR::UAny I(size_t bitsize, u64 value);
|
||||||
|
@ -1069,7 +1069,7 @@ struct TranslatorVisitor final {
|
||||||
bool FNMSUB_float(Imm<2> type, Vec Vm, Vec Va, Vec Vn, Vec Vd);
|
bool FNMSUB_float(Imm<2> type, Vec Vm, Vec Va, Vec Vn, Vec Vd);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline boost::optional<size_t> FPGetDataSize(Imm<2> type) {
|
inline std::optional<size_t> FPGetDataSize(Imm<2> type) {
|
||||||
switch (type.ZeroExtend()) {
|
switch (type.ZeroExtend()) {
|
||||||
case 0b00:
|
case 0b00:
|
||||||
return 32;
|
return 32;
|
||||||
|
@ -1078,7 +1078,7 @@ inline boost::optional<size_t> FPGetDataSize(Imm<2> type) {
|
||||||
case 0b11:
|
case 0b11:
|
||||||
return 16;
|
return 16;
|
||||||
}
|
}
|
||||||
return boost::none;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Dynarmic::A64
|
} // namespace Dynarmic::A64
|
||||||
|
|
|
@ -4,13 +4,13 @@
|
||||||
* General Public License version 2 or any later version.
|
* General Public License version 2 or any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "frontend/A64/translate/impl/impl.h"
|
#include "frontend/A64/translate/impl/impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A64 {
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
static bool ExclusiveSharedDecodeAndOperation(TranslatorVisitor& v, bool pair, size_t size, bool L, bool o0, boost::optional<Reg> Rs, boost::optional<Reg> Rt2, Reg Rn, Reg Rt) {
|
static bool ExclusiveSharedDecodeAndOperation(TranslatorVisitor& v, bool pair, size_t size, bool L, bool o0, std::optional<Reg> Rs, std::optional<Reg> Rt2, Reg Rn, Reg Rt) {
|
||||||
// Shared Decode
|
// Shared Decode
|
||||||
|
|
||||||
const AccType acctype = o0 ? AccType::ORDERED : AccType::ATOMIC;
|
const AccType acctype = o0 ? AccType::ORDERED : AccType::ATOMIC;
|
||||||
|
|
|
@ -5,14 +5,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <optional>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include "frontend/A64/translate/impl/impl.h"
|
#include "frontend/A64/translate/impl/impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A64 {
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
static bool SharedDecodeAndOperation(TranslatorVisitor& v, bool wback, MemOp memop, bool Q, boost::optional<Reg> Rm, Imm<4> opcode, Imm<2> size, Reg Rn, Vec Vt) {
|
static bool SharedDecodeAndOperation(TranslatorVisitor& v, bool wback, MemOp memop, bool Q, std::optional<Reg> Rm, Imm<4> opcode, Imm<2> size, Reg Rn, Vec Vt) {
|
||||||
const size_t datasize = Q ? 128 : 64;
|
const size_t datasize = Q ? 128 : 64;
|
||||||
const size_t esize = 8 << size.ZeroExtend<size_t>();
|
const size_t esize = 8 << size.ZeroExtend<size_t>();
|
||||||
const size_t elements = datasize / esize;
|
const size_t elements = datasize / esize;
|
||||||
|
|
|
@ -4,14 +4,14 @@
|
||||||
* General Public License version 2 or any later version.
|
* General Public License version 2 or any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "frontend/A64/translate/impl/impl.h"
|
#include "frontend/A64/translate/impl/impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A64 {
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
static bool SharedDecodeAndOperation(TranslatorVisitor& v, bool wback, MemOp memop,
|
static bool SharedDecodeAndOperation(TranslatorVisitor& v, bool wback, MemOp memop,
|
||||||
bool Q, bool S, bool R, bool replicate, boost::optional<Reg> Rm,
|
bool Q, bool S, bool R, bool replicate, std::optional<Reg> Rm,
|
||||||
Imm<3> opcode, Imm<2> size, Reg Rn, Vec Vt) {
|
Imm<3> opcode, Imm<2> size, Reg Rn, Vec Vt) {
|
||||||
const size_t selem = (opcode.Bit<0>() << 1 | u32{R}) + 1;
|
const size_t selem = (opcode.Bit<0>() << 1 | u32{R}) + 1;
|
||||||
size_t scale = opcode.Bits<1, 2>();
|
size_t scale = opcode.Bits<1, 2>();
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
* General Public License version 2 or any later version.
|
* General Public License version 2 or any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "frontend/A64/translate/impl/impl.h"
|
#include "frontend/A64/translate/impl/impl.h"
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ bool RoundingShiftLeft(TranslatorVisitor& v, Imm<2> size, Vec Vm, Vec Vn, Vec Vd
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScalarCompare(TranslatorVisitor& v, Imm<2> size, boost::optional<Vec> Vm, Vec Vn, Vec Vd,
|
bool ScalarCompare(TranslatorVisitor& v, Imm<2> size, std::optional<Vec> Vm, Vec Vn, Vec Vd,
|
||||||
ComparisonType type, ComparisonVariant variant) {
|
ComparisonType type, ComparisonVariant variant) {
|
||||||
if (size != 0b11) {
|
if (size != 0b11) {
|
||||||
return v.ReservedValue();
|
return v.ReservedValue();
|
||||||
|
@ -59,7 +60,7 @@ bool ScalarCompare(TranslatorVisitor& v, Imm<2> size, boost::optional<Vec> Vm, V
|
||||||
const size_t datasize = 64;
|
const size_t datasize = 64;
|
||||||
|
|
||||||
const IR::U128 operand1 = v.V(datasize, Vn);
|
const IR::U128 operand1 = v.V(datasize, Vn);
|
||||||
const IR::U128 operand2 = variant == ComparisonVariant::Register ? v.V(datasize, Vm.get()) : v.ir.ZeroVector();
|
const IR::U128 operand2 = variant == ComparisonVariant::Register ? v.V(datasize, *Vm) : v.ir.ZeroVector();
|
||||||
|
|
||||||
const IR::U128 result = [&] {
|
const IR::U128 result = [&] {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory
|
||||||
const u32 instruction = memory_read_code(pc);
|
const u32 instruction = memory_read_code(pc);
|
||||||
|
|
||||||
if (auto decoder = Decode<TranslatorVisitor>(instruction)) {
|
if (auto decoder = Decode<TranslatorVisitor>(instruction)) {
|
||||||
should_continue = decoder->call(visitor, instruction);
|
should_continue = decoder->get().call(visitor, instruction);
|
||||||
} else {
|
} else {
|
||||||
should_continue = visitor.InterpretThisInstruction();
|
should_continue = visitor.InterpretThisInstruction();
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ bool TranslateSingleInstruction(IR::Block& block, LocationDescriptor descriptor,
|
||||||
|
|
||||||
bool should_continue = true;
|
bool should_continue = true;
|
||||||
if (auto decoder = Decode<TranslatorVisitor>(instruction)) {
|
if (auto decoder = Decode<TranslatorVisitor>(instruction)) {
|
||||||
should_continue = decoder->call(visitor, instruction);
|
should_continue = decoder->get().call(visitor, instruction);
|
||||||
} else {
|
} else {
|
||||||
should_continue = visitor.InterpretThisInstruction();
|
should_continue = visitor.InterpretThisInstruction();
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ void Block::SetCondition(Cond condition) {
|
||||||
}
|
}
|
||||||
|
|
||||||
LocationDescriptor Block::ConditionFailedLocation() const {
|
LocationDescriptor Block::ConditionFailedLocation() const {
|
||||||
return cond_failed.get();
|
return *cond_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Block::SetConditionFailedLocation(LocationDescriptor fail_location) {
|
void Block::SetConditionFailedLocation(LocationDescriptor fail_location) {
|
||||||
|
@ -73,7 +73,7 @@ const size_t& Block::ConditionFailedCycleCount() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Block::HasConditionFailedLocation() const {
|
bool Block::HasConditionFailedLocation() const {
|
||||||
return cond_failed.is_initialized();
|
return cond_failed.has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
Block::InstructionList& Block::Instructions() {
|
Block::InstructionList& Block::Instructions() {
|
||||||
|
|
|
@ -8,10 +8,9 @@
|
||||||
|
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/intrusive_list.h"
|
#include "common/intrusive_list.h"
|
||||||
#include "common/memory_pool.h"
|
#include "common/memory_pool.h"
|
||||||
|
@ -139,7 +138,7 @@ private:
|
||||||
/// Conditional to pass in order to execute this block
|
/// Conditional to pass in order to execute this block
|
||||||
Cond cond = Cond::AL;
|
Cond cond = Cond::AL;
|
||||||
/// Block to execute next if `cond` did not pass.
|
/// Block to execute next if `cond` did not pass.
|
||||||
boost::optional<LocationDescriptor> cond_failed = {};
|
std::optional<LocationDescriptor> cond_failed = {};
|
||||||
/// Number of cycles this block takes to execute if the conditional fails.
|
/// Number of cycles this block takes to execute if the conditional fails.
|
||||||
size_t cond_failed_cycle_count = 0;
|
size_t cond_failed_cycle_count = 0;
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ using namespace Dynarmic;
|
||||||
|
|
||||||
const char* GetNameOfInstruction(u32 instruction) {
|
const char* GetNameOfInstruction(u32 instruction) {
|
||||||
if (auto decoder = A64::Decode<A64::TranslatorVisitor>(instruction)) {
|
if (auto decoder = A64::Decode<A64::TranslatorVisitor>(instruction)) {
|
||||||
return decoder->GetName();
|
return decoder->get().GetName();
|
||||||
}
|
}
|
||||||
return "<null>";
|
return "<null>";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue