mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-08-01 05:38:50 +00:00
Merge branch 'master' of https://github.com/dolphin-emu/dolphin into dolphin-emu-master
This commit is contained in:
commit
4bd7d38a77
1243 changed files with 15939 additions and 15402 deletions
|
@ -28,6 +28,7 @@
|
|||
#endif
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ranges.h>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/FileUtil.h"
|
||||
|
@ -332,5 +333,5 @@ std::string CPUInfo::Summarize()
|
|||
if (bSHA2)
|
||||
sum.push_back("SHA2");
|
||||
|
||||
return JoinStrings(sum, ",");
|
||||
return fmt::to_string(fmt::join(sum, ","));
|
||||
}
|
||||
|
|
|
@ -75,6 +75,8 @@ add_library(common
|
|||
Hash.cpp
|
||||
Hash.h
|
||||
HookableEvent.h
|
||||
HostDisassembler.cpp
|
||||
HostDisassembler.h
|
||||
HttpRequest.cpp
|
||||
HttpRequest.h
|
||||
Image.cpp
|
||||
|
@ -180,6 +182,11 @@ PRIVATE
|
|||
${VTUNE_LIBRARIES}
|
||||
)
|
||||
|
||||
if ((DEFINED CMAKE_ANDROID_ARCH_ABI AND CMAKE_ANDROID_ARCH_ABI MATCHES "x86|x86_64") OR
|
||||
(NOT DEFINED CMAKE_ANDROID_ARCH_ABI AND _M_X86_64))
|
||||
target_link_libraries(common PRIVATE bdisasm)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
target_link_libraries(common
|
||||
PRIVATE
|
||||
|
@ -330,6 +337,28 @@ if(OPROFILE_FOUND)
|
|||
target_link_libraries(common PRIVATE OProfile::OProfile)
|
||||
endif()
|
||||
|
||||
if(ENABLE_LLVM)
|
||||
find_package(LLVM CONFIG)
|
||||
if(LLVM_FOUND)
|
||||
message(STATUS "LLVM found, enabling LLVM support in disassembler")
|
||||
target_compile_definitions(common PRIVATE HAVE_LLVM)
|
||||
# Minimal documentation about LLVM's CMake functions is available here:
|
||||
# https://releases.llvm.org/16.0.0/docs/CMake.html#embedding-llvm-in-your-project
|
||||
# https://groups.google.com/g/llvm-dev/c/YeEVe7HTasQ?pli=1
|
||||
#
|
||||
# However, you have to read the source code in any case.
|
||||
# Look for LLVM-Config.cmake in your (Unix) system:
|
||||
# $ find /usr -name LLVM-Config\\.cmake 2>/dev/null
|
||||
llvm_expand_pseudo_components(LLVM_EXPAND_COMPONENTS
|
||||
AllTargetsInfos AllTargetsDisassemblers AllTargetsCodeGens
|
||||
)
|
||||
llvm_config(common USE_SHARED
|
||||
mcdisassembler target ${LLVM_EXPAND_COMPONENTS}
|
||||
)
|
||||
target_include_directories(common PRIVATE ${LLVM_INCLUDE_DIRS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
# Posix networking code needs to be fixed for Windows
|
||||
add_executable(traversal_server TraversalServer.cpp)
|
||||
|
|
|
@ -20,7 +20,6 @@ struct ConfigChangedCallbackID
|
|||
size_t id = -1;
|
||||
|
||||
bool operator==(const ConfigChangedCallbackID&) const = default;
|
||||
bool operator!=(const ConfigChangedCallbackID&) const = default;
|
||||
};
|
||||
|
||||
using ConfigChangedCallback = std::function<void()>;
|
||||
|
|
|
@ -15,11 +15,6 @@ bool Location::operator==(const Location& other) const
|
|||
strcasecmp(key.c_str(), other.key.c_str()) == 0;
|
||||
}
|
||||
|
||||
bool Location::operator!=(const Location& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool Location::operator<(const Location& other) const
|
||||
{
|
||||
if (system != other.system)
|
||||
|
|
|
@ -28,7 +28,6 @@ struct Location
|
|||
std::string key;
|
||||
|
||||
bool operator==(const Location& other) const;
|
||||
bool operator!=(const Location& other) const;
|
||||
bool operator<(const Location& other) const;
|
||||
};
|
||||
|
||||
|
|
|
@ -252,8 +252,8 @@ Signature Sign(const u8* key, const u8* hash)
|
|||
bn_mul(s.data.data(), minv, kk, ec_N, 30);
|
||||
|
||||
Signature signature;
|
||||
std::copy(r.data.cbegin(), r.data.cend(), signature.begin());
|
||||
std::copy(s.data.cbegin(), s.data.cend(), signature.begin() + 30);
|
||||
std::ranges::copy(r.data, signature.begin());
|
||||
std::ranges::copy(s.data, signature.begin() + 30);
|
||||
return signature;
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ std::vector<std::string> DoFileSearch(const std::vector<std::string>& directorie
|
|||
// Remove duplicates (occurring because caller gave e.g. duplicate or overlapping directories -
|
||||
// not because std::filesystem returns duplicates). Also note that this pathname-based uniqueness
|
||||
// isn't as thorough as std::filesystem::equivalent.
|
||||
std::sort(result.begin(), result.end());
|
||||
std::ranges::sort(result);
|
||||
result.erase(std::unique(result.begin(), result.end()), result.end());
|
||||
|
||||
// Dolphin expects to be able to use "/" (DIR_SEP) everywhere.
|
||||
|
@ -107,7 +107,7 @@ std::vector<std::string> DoFileSearch(const std::vector<std::string>& directorie
|
|||
if constexpr (os_separator != DIR_SEP_CHR)
|
||||
{
|
||||
for (auto& path : result)
|
||||
std::replace(path.begin(), path.end(), '\\', DIR_SEP_CHR);
|
||||
std::ranges::replace(path, '\\', DIR_SEP_CHR);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -446,7 +446,7 @@ FSTEntry ScanDirectoryTree(std::string directory, bool recursive)
|
|||
// about with directory separators (for host paths - emulated paths may require it) and instead
|
||||
// use fs::path to interact with them.
|
||||
auto wpath = path.wstring();
|
||||
std::replace(wpath.begin(), wpath.end(), L'\\', L'/');
|
||||
std::ranges::replace(wpath, L'\\', L'/');
|
||||
return WStringToUTF8(wpath);
|
||||
#else
|
||||
return PathToString(path);
|
||||
|
|
158
Source/Core/Common/HostDisassembler.cpp
Normal file
158
Source/Core/Common/HostDisassembler.cpp
Normal file
|
@ -0,0 +1,158 @@
|
|||
// Copyright 2008 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "Common/HostDisassembler.h"
|
||||
|
||||
#include <span>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ostream.h>
|
||||
#include <fmt/ranges.h>
|
||||
|
||||
#if defined(HAVE_LLVM)
|
||||
#include <llvm-c/Disassembler.h>
|
||||
#include <llvm-c/Target.h>
|
||||
#elif defined(_M_X86_64)
|
||||
#include <disasm.h> // Bochs
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LLVM)
|
||||
class HostDisassemblerLLVM final : public HostDisassembler
|
||||
{
|
||||
public:
|
||||
explicit HostDisassemblerLLVM(const char* host_disasm, const char* cpu = "",
|
||||
std::size_t inst_size = 0);
|
||||
~HostDisassemblerLLVM();
|
||||
|
||||
private:
|
||||
LLVMDisasmContextRef m_llvm_context;
|
||||
std::size_t m_instruction_size;
|
||||
|
||||
std::size_t Disassemble(const u8* begin, const u8* end, std::ostream& stream) override;
|
||||
};
|
||||
|
||||
HostDisassemblerLLVM::HostDisassemblerLLVM(const char* host_disasm, const char* cpu,
|
||||
std::size_t inst_size)
|
||||
: m_instruction_size(inst_size)
|
||||
{
|
||||
LLVMInitializeAllTargetInfos();
|
||||
LLVMInitializeAllTargetMCs();
|
||||
LLVMInitializeAllDisassemblers();
|
||||
|
||||
m_llvm_context = LLVMCreateDisasmCPU(host_disasm, cpu, nullptr, 0, nullptr, nullptr);
|
||||
|
||||
// Couldn't create llvm context
|
||||
if (!m_llvm_context)
|
||||
return;
|
||||
|
||||
LLVMSetDisasmOptions(m_llvm_context, LLVMDisassembler_Option_AsmPrinterVariant |
|
||||
LLVMDisassembler_Option_PrintLatency);
|
||||
}
|
||||
|
||||
HostDisassemblerLLVM::~HostDisassemblerLLVM()
|
||||
{
|
||||
if (m_llvm_context)
|
||||
LLVMDisasmDispose(m_llvm_context);
|
||||
}
|
||||
|
||||
std::size_t HostDisassemblerLLVM::Disassemble(const u8* begin, const u8* end, std::ostream& stream)
|
||||
{
|
||||
std::size_t instruction_count = 0;
|
||||
if (!m_llvm_context)
|
||||
return instruction_count;
|
||||
|
||||
while (begin < end)
|
||||
{
|
||||
char inst_disasm[256];
|
||||
|
||||
const auto inst_size =
|
||||
LLVMDisasmInstruction(m_llvm_context, const_cast<u8*>(begin), static_cast<u64>(end - begin),
|
||||
reinterpret_cast<u64>(begin), inst_disasm, sizeof(inst_disasm));
|
||||
if (inst_size == 0)
|
||||
{
|
||||
if (m_instruction_size != 0)
|
||||
{
|
||||
// If we are on an architecture that has a fixed instruction
|
||||
// size, we can continue onward past this bad instruction.
|
||||
fmt::println(stream, "{}\tInvalid inst: {:02x}", fmt::ptr(begin),
|
||||
fmt::join(std::span{begin, m_instruction_size}, ""));
|
||||
begin += m_instruction_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We can't continue if we are on an architecture that has flexible
|
||||
// instruction sizes. Dump the rest of the block instead.
|
||||
fmt::println(stream, "{}\tInvalid inst: {:02x}", fmt::ptr(begin),
|
||||
fmt::join(std::span{begin, end}, ""));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::println(stream, "{}{}", fmt::ptr(begin), inst_disasm);
|
||||
begin += inst_size;
|
||||
}
|
||||
++instruction_count;
|
||||
}
|
||||
return instruction_count;
|
||||
}
|
||||
#elif defined(_M_X86_64)
|
||||
class HostDisassemblerBochs final : public HostDisassembler
|
||||
{
|
||||
public:
|
||||
explicit HostDisassemblerBochs();
|
||||
~HostDisassemblerBochs() = default;
|
||||
|
||||
private:
|
||||
disassembler m_disasm;
|
||||
|
||||
std::size_t Disassemble(const u8* begin, const u8* end, std::ostream& stream) override;
|
||||
};
|
||||
|
||||
HostDisassemblerBochs::HostDisassemblerBochs()
|
||||
{
|
||||
m_disasm.set_syntax_intel();
|
||||
}
|
||||
|
||||
std::size_t HostDisassemblerBochs::Disassemble(const u8* begin, const u8* end, std::ostream& stream)
|
||||
{
|
||||
std::size_t instruction_count = 0;
|
||||
while (begin < end)
|
||||
{
|
||||
char inst_disasm[256];
|
||||
|
||||
const auto inst_size =
|
||||
m_disasm.disasm64(0, reinterpret_cast<bx_address>(begin), begin, inst_disasm);
|
||||
fmt::println(stream, "{}\t{}", fmt::ptr(begin), inst_disasm);
|
||||
begin += inst_size;
|
||||
++instruction_count;
|
||||
}
|
||||
return instruction_count;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<HostDisassembler> HostDisassembler::Factory(Platform arch)
|
||||
{
|
||||
switch (arch)
|
||||
{
|
||||
#if defined(HAVE_LLVM)
|
||||
case Platform::x86_64:
|
||||
return std::make_unique<HostDisassemblerLLVM>("x86_64-none-unknown");
|
||||
case Platform::aarch64:
|
||||
return std::make_unique<HostDisassemblerLLVM>("aarch64-none-unknown", "cortex-a57", 4);
|
||||
#elif defined(_M_X86_64)
|
||||
case Platform::x86_64:
|
||||
return std::make_unique<HostDisassemblerBochs>();
|
||||
#else
|
||||
case Platform{}: // warning C4065: "switch statement contains 'default' but no 'case' labels"
|
||||
#endif
|
||||
default:
|
||||
return std::make_unique<HostDisassembler>();
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t HostDisassembler::Disassemble(const u8* begin, const u8* end, std::ostream& stream)
|
||||
{
|
||||
fmt::println(stream, "{}\t{:02x}", fmt::ptr(begin), fmt::join(std::span{begin, end}, ""));
|
||||
return 0;
|
||||
}
|
26
Source/Core/Common/HostDisassembler.h
Normal file
26
Source/Core/Common/HostDisassembler.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2008 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
class HostDisassembler
|
||||
{
|
||||
public:
|
||||
enum class Platform
|
||||
{
|
||||
x86_64,
|
||||
aarch64,
|
||||
};
|
||||
|
||||
virtual ~HostDisassembler() = default;
|
||||
|
||||
static std::unique_ptr<HostDisassembler> Factory(Platform arch);
|
||||
|
||||
virtual std::size_t Disassemble(const u8* begin, const u8* end, std::ostream& stream);
|
||||
};
|
|
@ -85,7 +85,7 @@ bool IniFile::Section::Delete(std::string_view key)
|
|||
return false;
|
||||
|
||||
values.erase(it);
|
||||
keys_order.erase(std::find(keys_order.begin(), keys_order.end(), key));
|
||||
keys_order.erase(std::ranges::find(keys_order, key));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,7 @@ const IniFile::Section* IniFile::GetSection(std::string_view section_name) const
|
|||
{
|
||||
for (const Section& sect : sections)
|
||||
{
|
||||
if (CaseInsensitiveStringCompare::IsEqual(sect.name, section_name))
|
||||
if (CaseInsensitiveEquals(sect.name, section_name))
|
||||
return §
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,7 @@ IniFile::Section* IniFile::GetSection(std::string_view section_name)
|
|||
{
|
||||
for (Section& sect : sections)
|
||||
{
|
||||
if (CaseInsensitiveStringCompare::IsEqual(sect.name, section_name))
|
||||
if (CaseInsensitiveEquals(sect.name, section_name))
|
||||
return §
|
||||
}
|
||||
|
||||
|
|
|
@ -15,29 +15,6 @@
|
|||
|
||||
namespace Common
|
||||
{
|
||||
struct CaseInsensitiveStringCompare
|
||||
{
|
||||
// Allow heterogenous lookup.
|
||||
using is_transparent = void;
|
||||
|
||||
bool operator()(std::string_view a, std::string_view b) const
|
||||
{
|
||||
return std::lexicographical_compare(
|
||||
a.begin(), a.end(), b.begin(), b.end(),
|
||||
[](char lhs, char rhs) { return Common::ToLower(lhs) < Common::ToLower(rhs); });
|
||||
}
|
||||
|
||||
static bool IsEqual(std::string_view a, std::string_view b)
|
||||
{
|
||||
if (a.size() != b.size())
|
||||
return false;
|
||||
|
||||
return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char lhs, char rhs) {
|
||||
return Common::ToLower(lhs) == Common::ToLower(rhs);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class IniFile
|
||||
{
|
||||
public:
|
||||
|
@ -86,7 +63,7 @@ public:
|
|||
bool GetLines(std::vector<std::string>* lines, const bool remove_comments = true) const;
|
||||
|
||||
bool operator<(const Section& other) const { return name < other.name; }
|
||||
using SectionMap = std::map<std::string, std::string, CaseInsensitiveStringCompare>;
|
||||
using SectionMap = std::map<std::string, std::string, CaseInsensitiveLess>;
|
||||
|
||||
const std::string& GetName() const { return name; }
|
||||
const SectionMap& GetValues() const { return values; }
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ranges.h>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/FileUtil.h"
|
||||
|
@ -141,7 +142,7 @@ std::string EscapePath(const std::string& path)
|
|||
for (const std::string& split_string : split_strings)
|
||||
escaped_split_strings.push_back(EscapeFileName(split_string));
|
||||
|
||||
return JoinStrings(escaped_split_strings, "/");
|
||||
return fmt::to_string(fmt::join(escaped_split_strings, "/"));
|
||||
}
|
||||
|
||||
std::string UnescapeFileName(const std::string& filename)
|
||||
|
|
|
@ -36,10 +36,10 @@ MACAddress GenerateMacAddress(const MACConsumer type)
|
|||
switch (type)
|
||||
{
|
||||
case MACConsumer::BBA:
|
||||
std::copy(oui_bba.begin(), oui_bba.end(), mac.begin());
|
||||
std::ranges::copy(oui_bba, mac.begin());
|
||||
break;
|
||||
case MACConsumer::IOS:
|
||||
std::copy(oui_ios.begin(), oui_ios.end(), mac.begin());
|
||||
std::ranges::copy(oui_ios, mac.begin());
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ranges.h>
|
||||
|
||||
#include "Common/CommonFuncs.h"
|
||||
#include "Common/CommonPaths.h"
|
||||
|
@ -233,8 +234,8 @@ std::string_view StripQuotes(std::string_view s)
|
|||
// Turns "\n\rhello" into " hello".
|
||||
void ReplaceBreaksWithSpaces(std::string& str)
|
||||
{
|
||||
std::replace(str.begin(), str.end(), '\r', ' ');
|
||||
std::replace(str.begin(), str.end(), '\n', ' ');
|
||||
std::ranges::replace(str, '\r', ' ');
|
||||
std::ranges::replace(str, '\n', ' ');
|
||||
}
|
||||
|
||||
void TruncateToCString(std::string* s)
|
||||
|
@ -367,21 +368,6 @@ std::vector<std::string> SplitString(const std::string& str, const char delim)
|
|||
return output;
|
||||
}
|
||||
|
||||
std::string JoinStrings(const std::vector<std::string>& strings, const std::string& delimiter)
|
||||
{
|
||||
// Check if we can return early, just for speed
|
||||
if (strings.empty())
|
||||
return "";
|
||||
|
||||
std::ostringstream res;
|
||||
std::copy(strings.begin(), strings.end(),
|
||||
std::ostream_iterator<std::string>(res, delimiter.c_str()));
|
||||
|
||||
// Drop the trailing delimiter.
|
||||
std::string joined = res.str();
|
||||
return joined.substr(0, joined.length() - delimiter.length());
|
||||
}
|
||||
|
||||
std::string TabsToSpaces(int tab_size, std::string str)
|
||||
{
|
||||
const std::string spaces(tab_size, ' ');
|
||||
|
@ -417,8 +403,7 @@ void StringPopBackIf(std::string* s, char c)
|
|||
|
||||
size_t StringUTF8CodePointCount(std::string_view str)
|
||||
{
|
||||
return str.size() -
|
||||
std::count_if(str.begin(), str.end(), [](char c) -> bool { return (c & 0xC0) == 0x80; });
|
||||
return str.size() - std::ranges::count_if(str, [](char c) -> bool { return (c & 0xC0) == 0x80; });
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -670,20 +655,24 @@ std::string GetEscapedHtml(std::string html)
|
|||
|
||||
void ToLower(std::string* str)
|
||||
{
|
||||
std::transform(str->begin(), str->end(), str->begin(), [](char c) { return Common::ToLower(c); });
|
||||
std::ranges::transform(*str, str->begin(), static_cast<char (&)(char)>(Common::ToLower));
|
||||
}
|
||||
|
||||
void ToUpper(std::string* str)
|
||||
{
|
||||
std::transform(str->begin(), str->end(), str->begin(), [](char c) { return Common::ToUpper(c); });
|
||||
std::ranges::transform(*str, str->begin(), static_cast<char (&)(char)>(Common::ToUpper));
|
||||
}
|
||||
|
||||
bool CaseInsensitiveEquals(std::string_view a, std::string_view b)
|
||||
{
|
||||
if (a.size() != b.size())
|
||||
return false;
|
||||
return std::equal(a.begin(), a.end(), b.begin(),
|
||||
[](char ca, char cb) { return Common::ToLower(ca) == Common::ToLower(cb); });
|
||||
return std::ranges::equal(
|
||||
a, b, [](char ca, char cb) { return Common::ToLower(ca) == Common::ToLower(cb); });
|
||||
}
|
||||
|
||||
bool CaseInsensitiveLess::operator()(std::string_view a, std::string_view b) const
|
||||
{
|
||||
return std::ranges::lexicographical_compare(
|
||||
a, b, [](char ca, char cb) { return Common::ToLower(ca) < Common::ToLower(cb); });
|
||||
}
|
||||
|
||||
std::string BytesToHexString(std::span<const u8> bytes)
|
||||
|
|
|
@ -200,7 +200,6 @@ std::from_chars_result FromChars(std::string_view sv, T& value,
|
|||
std::string TabsToSpaces(int tab_size, std::string str);
|
||||
|
||||
std::vector<std::string> SplitString(const std::string& str, char delim);
|
||||
std::string JoinStrings(const std::vector<std::string>& strings, const std::string& delimiter);
|
||||
|
||||
// "C:/Windows/winhelp.exe" to "C:/Windows/", "winhelp", ".exe"
|
||||
// This requires forward slashes to be used for the path separators, even on Windows.
|
||||
|
@ -314,5 +313,13 @@ std::string GetEscapedHtml(std::string html);
|
|||
void ToLower(std::string* str);
|
||||
void ToUpper(std::string* str);
|
||||
bool CaseInsensitiveEquals(std::string_view a, std::string_view b);
|
||||
|
||||
// 'std::less'-like comparison function object type for case-insensitive strings.
|
||||
struct CaseInsensitiveLess
|
||||
{
|
||||
using is_transparent = void; // Allow heterogenous lookup.
|
||||
bool operator()(std::string_view a, std::string_view b) const;
|
||||
};
|
||||
|
||||
std::string BytesToHexString(std::span<const u8> bytes);
|
||||
} // namespace Common
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <thread>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ranges.h>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Intrinsics.h"
|
||||
|
@ -275,5 +276,5 @@ std::string CPUInfo::Summarize()
|
|||
if (bSHA2)
|
||||
sum.push_back("SHA2");
|
||||
|
||||
return JoinStrings(sum, ",");
|
||||
return fmt::to_string(fmt::join(sum, ","));
|
||||
}
|
||||
|
|
|
@ -122,7 +122,6 @@ struct OpArg
|
|||
return std::tie(scale, offsetOrBaseReg, indexReg, offset, operandReg) ==
|
||||
std::tie(b.scale, b.offsetOrBaseReg, b.indexReg, b.offset, b.operandReg);
|
||||
}
|
||||
constexpr bool operator!=(const OpArg& b) const { return !operator==(b); }
|
||||
u64 Imm64() const
|
||||
{
|
||||
DEBUG_ASSERT(scale == SCALE_IMM64);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue