Add .clang-format file
Using clang-format version 12.0.0
This commit is contained in:
parent
51b155df92
commit
53493b2024
315 changed files with 3178 additions and 2660 deletions
218
.clang-format
Normal file
218
.clang-format
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveMacros: None
|
||||||
|
AlignConsecutiveAssignments: None
|
||||||
|
AlignConsecutiveBitFields: None
|
||||||
|
AlignConsecutiveDeclarations: None
|
||||||
|
AlignConsecutiveMacros: None
|
||||||
|
AlignEscapedNewlines: Right
|
||||||
|
AlignOperands: AlignAfterOperator
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllArgumentsOnNextLine: true
|
||||||
|
AllowAllConstructorInitializersOnNextLine: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortEnumsOnASingleLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: Empty
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: Inline
|
||||||
|
AllowShortLambdasOnASingleLine: All
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: true
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
AttributeMacros:
|
||||||
|
- __capability
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: false
|
||||||
|
BitFieldColonSpacing: Both
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: false
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: Never
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
BeforeLambdaBody: false
|
||||||
|
BeforeWhile: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: false
|
||||||
|
SplitEmptyRecord: false
|
||||||
|
SplitEmptyNamespace: false
|
||||||
|
BreakBeforeBinaryOperators: All
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BreakBeforeConceptDeclarations: true
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakConstructorInitializersBeforeComma: true
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
BreakInheritanceList: BeforeComma
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 0
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ConstructorInitializerIndentWidth: 8
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DeriveLineEnding: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
# EmptyLineAfterAccessModifier: Leave
|
||||||
|
EmptyLineBeforeAccessModifier: Always
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros:
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
IncludeBlocks: Regroup
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^<mach/'
|
||||||
|
Priority: 1
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
- Regex: '^<windows.h>'
|
||||||
|
Priority: 1
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
- Regex: '(^<signal.h>)|(^<sys/ucontext.h>)|(^<ucontext.h>)'
|
||||||
|
Priority: 1
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
- Regex: '^<([^\.])*>$'
|
||||||
|
Priority: 2
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
- Regex: '^<.*\.'
|
||||||
|
Priority: 3
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 4
|
||||||
|
SortPriority: 0
|
||||||
|
CaseSensitive: false
|
||||||
|
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||||
|
IncludeIsMainSourceRegex: ''
|
||||||
|
# IndentAccessModifiers: false
|
||||||
|
IndentCaseBlocks: false
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentExternBlock: NoIndent
|
||||||
|
IndentGotoLabels: false
|
||||||
|
IndentPPDirectives: AfterHash
|
||||||
|
IndentRequires: false
|
||||||
|
IndentWidth: 4
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
# InsertTrailingCommas: None
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
NamespaceMacros:
|
||||||
|
ObjCBinPackProtocolList: Never
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCBreakBeforeNestedBlockParam: true
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 1
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 200
|
||||||
|
PenaltyIndentedWhitespace: 0
|
||||||
|
PointerAlignment: Left
|
||||||
|
RawStringFormats:
|
||||||
|
- Language: Cpp
|
||||||
|
Delimiters:
|
||||||
|
- cc
|
||||||
|
- CC
|
||||||
|
- cpp
|
||||||
|
- Cpp
|
||||||
|
- CPP
|
||||||
|
- 'c++'
|
||||||
|
- 'C++'
|
||||||
|
CanonicalDelimiter: ''
|
||||||
|
BasedOnStyle: google
|
||||||
|
- Language: TextProto
|
||||||
|
Delimiters:
|
||||||
|
- pb
|
||||||
|
- PB
|
||||||
|
- proto
|
||||||
|
- PROTO
|
||||||
|
EnclosingFunctions:
|
||||||
|
- EqualsProto
|
||||||
|
- EquivToProto
|
||||||
|
- PARSE_PARTIAL_TEXT_PROTO
|
||||||
|
- PARSE_TEST_PROTO
|
||||||
|
- PARSE_TEXT_PROTO
|
||||||
|
- ParseTextOrDie
|
||||||
|
- ParseTextProtoOrDie
|
||||||
|
- ParseTestProto
|
||||||
|
- ParsePartialTestProto
|
||||||
|
CanonicalDelimiter: ''
|
||||||
|
BasedOnStyle: google
|
||||||
|
ReflowComments: true
|
||||||
|
# ShortNamespaceLines: 5
|
||||||
|
SortIncludes: true
|
||||||
|
SortJavaStaticImport: Before
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterLogicalNot: false
|
||||||
|
SpaceAfterTemplateKeyword: false
|
||||||
|
SpaceAroundPointerQualifiers: Default
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCaseColon: false
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceAroundPointerQualifiers: Default
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceBeforeSquareBrackets: false
|
||||||
|
SpaceInEmptyBlock: false
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 2
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInConditionalStatement: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInConditionalStatement: false
|
||||||
|
SpacesInContainerLiterals: false
|
||||||
|
# SpacesInLineCommentPrefix: -1
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Latest
|
||||||
|
StatementAttributeLikeMacros:
|
||||||
|
- Q_EMIT
|
||||||
|
StatementMacros:
|
||||||
|
- Q_UNUSED
|
||||||
|
- QT_REQUIRE_VERSION
|
||||||
|
TabWidth: 4
|
||||||
|
TypenameMacros:
|
||||||
|
UseCRLF: false
|
||||||
|
UseTab: Never
|
||||||
|
WhitespaceSensitiveMacros:
|
||||||
|
- STRINGIZE
|
||||||
|
- PP_STRINGIZE
|
||||||
|
- BOOST_PP_STRINGIZE
|
||||||
|
- NS_SWIFT_NAME
|
||||||
|
- CF_SWIFT_NAME
|
||||||
|
- FCODE
|
||||||
|
- ICODE
|
||||||
|
...
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/backend/x64/a32_emit_x64.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
@ -11,7 +13,6 @@
|
||||||
#include <fmt/ostream.h>
|
#include <fmt/ostream.h>
|
||||||
#include <mp/traits/integer_of_size.h>
|
#include <mp/traits/integer_of_size.h>
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/a32_emit_x64.h"
|
|
||||||
#include "dynarmic/backend/x64/a32_jitstate.h"
|
#include "dynarmic/backend/x64/a32_jitstate.h"
|
||||||
#include "dynarmic/backend/x64/abi.h"
|
#include "dynarmic/backend/x64/abi.h"
|
||||||
#include "dynarmic/backend/x64/block_of_code.h"
|
#include "dynarmic/backend/x64/block_of_code.h"
|
||||||
|
@ -126,7 +127,6 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
|
||||||
|
|
||||||
// Call the relevant Emit* member function.
|
// Call the relevant Emit* member function.
|
||||||
switch (inst->GetOpcode()) {
|
switch (inst->GetOpcode()) {
|
||||||
|
|
||||||
#define OPCODE(name, type, ...) \
|
#define OPCODE(name, type, ...) \
|
||||||
case IR::Opcode::name: \
|
case IR::Opcode::name: \
|
||||||
A32EmitX64::Emit##name(ctx, inst); \
|
A32EmitX64::Emit##name(ctx, inst); \
|
||||||
|
@ -1048,8 +1048,7 @@ void A32EmitX64::ReadMemory(A32EmitContext& ctx, IR::Inst* inst) {
|
||||||
Common::BitCast<u64>(code.getCurr()),
|
Common::BitCast<u64>(code.getCurr()),
|
||||||
Common::BitCast<u64>(wrapped_fn),
|
Common::BitCast<u64>(wrapped_fn),
|
||||||
*marker,
|
*marker,
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(inst, value);
|
ctx.reg_alloc.DefineValue(inst, value);
|
||||||
return;
|
return;
|
||||||
|
@ -1095,8 +1094,7 @@ void A32EmitX64::WriteMemory(A32EmitContext& ctx, IR::Inst* inst) {
|
||||||
Common::BitCast<u64>(code.getCurr()),
|
Common::BitCast<u64>(code.getCurr()),
|
||||||
Common::BitCast<u64>(wrapped_fn),
|
Common::BitCast<u64>(wrapped_fn),
|
||||||
*marker,
|
*marker,
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1162,8 +1160,7 @@ void A32EmitX64::ExclusiveReadMemory(A32EmitContext& ctx, IR::Inst* inst) {
|
||||||
return conf.global_monitor->ReadAndMark<T>(conf.processor_id, vaddr, [&]() -> T {
|
return conf.global_monitor->ReadAndMark<T>(conf.processor_id, vaddr, [&]() -> T {
|
||||||
return (conf.callbacks->*callback)(vaddr);
|
return (conf.callbacks->*callback)(vaddr);
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t bitsize, auto callback>
|
template<size_t bitsize, auto callback>
|
||||||
|
@ -1187,9 +1184,10 @@ void A32EmitX64::ExclusiveWriteMemory(A32EmitContext& ctx, IR::Inst* inst) {
|
||||||
return conf.global_monitor->DoExclusiveOperation<T>(conf.processor_id, vaddr,
|
return conf.global_monitor->DoExclusiveOperation<T>(conf.processor_id, vaddr,
|
||||||
[&](T expected) -> bool {
|
[&](T expected) -> bool {
|
||||||
return (conf.callbacks->*callback)(vaddr, value, expected);
|
return (conf.callbacks->*callback)(vaddr, value, expected);
|
||||||
}) ? 0 : 1;
|
})
|
||||||
}
|
? 0
|
||||||
);
|
: 1;
|
||||||
|
});
|
||||||
code.L(end);
|
code.L(end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1229,10 +1227,7 @@ static void EmitCoprocessorException() {
|
||||||
ASSERT_FALSE("Should raise coproc exception here");
|
ASSERT_FALSE("Should raise coproc exception here");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CallCoprocCallback(BlockOfCode& code, RegAlloc& reg_alloc, A32::Jit* jit_interface,
|
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 = {}) {
|
||||||
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));
|
||||||
|
|
|
@ -55,8 +55,7 @@ struct Jit::Impl {
|
||||||
: block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this), JitStateInfo{jit_state}, conf.code_cache_size, conf.far_code_offset, GenRCP(conf))
|
: block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this), JitStateInfo{jit_state}, conf.code_cache_size, conf.far_code_offset, GenRCP(conf))
|
||||||
, emitter(block_of_code, conf, jit)
|
, emitter(block_of_code, conf, jit)
|
||||||
, conf(std::move(conf))
|
, conf(std::move(conf))
|
||||||
, jit_interface(jit)
|
, jit_interface(jit) {}
|
||||||
{}
|
|
||||||
|
|
||||||
A32JitState jit_state;
|
A32JitState jit_state;
|
||||||
BlockOfCode block_of_code;
|
BlockOfCode block_of_code;
|
||||||
|
@ -176,7 +175,8 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Jit::Jit(UserConfig conf) : impl(std::make_unique<Impl>(this, std::move(conf))) {}
|
Jit::Jit(UserConfig conf)
|
||||||
|
: impl(std::make_unique<Impl>(this, std::move(conf))) {}
|
||||||
|
|
||||||
Jit::~Jit() = default;
|
Jit::~Jit() = default;
|
||||||
|
|
||||||
|
@ -269,10 +269,15 @@ struct Context::Impl {
|
||||||
size_t invalid_cache_generation;
|
size_t invalid_cache_generation;
|
||||||
};
|
};
|
||||||
|
|
||||||
Context::Context() : impl(std::make_unique<Context::Impl>()) { impl->jit_state.ResetRSB(); }
|
Context::Context()
|
||||||
|
: impl(std::make_unique<Context::Impl>()) {
|
||||||
|
impl->jit_state.ResetRSB();
|
||||||
|
}
|
||||||
Context::~Context() = default;
|
Context::~Context() = default;
|
||||||
Context::Context(const Context& ctx) : impl(std::make_unique<Context::Impl>(*ctx.impl)) {}
|
Context::Context(const Context& ctx)
|
||||||
Context::Context(Context&& ctx) noexcept : impl(std::move(ctx.impl)) {}
|
: impl(std::make_unique<Context::Impl>(*ctx.impl)) {}
|
||||||
|
Context::Context(Context&& ctx) noexcept
|
||||||
|
: impl(std::move(ctx.impl)) {}
|
||||||
Context& Context::operator=(const Context& ctx) {
|
Context& Context::operator=(const Context& ctx) {
|
||||||
*impl = *ctx.impl;
|
*impl = *ctx.impl;
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/a32_jitstate.h"
|
#include "dynarmic/backend/x64/a32_jitstate.h"
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/block_of_code.h"
|
#include "dynarmic/backend/x64/block_of_code.h"
|
||||||
#include "dynarmic/backend/x64/nzcv_util.h"
|
#include "dynarmic/backend/x64/nzcv_util.h"
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/backend/x64/a64_emit_x64.h"
|
||||||
|
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <fmt/ostream.h>
|
#include <fmt/ostream.h>
|
||||||
#include <mp/traits/integer_of_size.h>
|
#include <mp/traits/integer_of_size.h>
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/a64_emit_x64.h"
|
|
||||||
#include "dynarmic/backend/x64/a64_jitstate.h"
|
#include "dynarmic/backend/x64/a64_jitstate.h"
|
||||||
#include "dynarmic/backend/x64/abi.h"
|
#include "dynarmic/backend/x64/abi.h"
|
||||||
#include "dynarmic/backend/x64/block_of_code.h"
|
#include "dynarmic/backend/x64/block_of_code.h"
|
||||||
|
@ -92,7 +93,6 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) {
|
||||||
|
|
||||||
// Call the relevant Emit* member function.
|
// Call the relevant Emit* member function.
|
||||||
switch (inst->GetOpcode()) {
|
switch (inst->GetOpcode()) {
|
||||||
|
|
||||||
#define OPCODE(name, type, ...) \
|
#define OPCODE(name, type, ...) \
|
||||||
case IR::Opcode::name: \
|
case IR::Opcode::name: \
|
||||||
A64EmitX64::Emit##name(ctx, inst); \
|
A64EmitX64::Emit##name(ctx, inst); \
|
||||||
|
@ -152,8 +152,7 @@ void A64EmitX64::GenMemory128Accessors() {
|
||||||
code.align();
|
code.align();
|
||||||
memory_read_128 = code.getCurr<void (*)()>();
|
memory_read_128 = code.getCurr<void (*)()>();
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
Devirtualize<&A64::UserCallbacks::MemoryRead128>(conf.callbacks).EmitCallWithReturnPointer(code,
|
Devirtualize<&A64::UserCallbacks::MemoryRead128>(conf.callbacks).EmitCallWithReturnPointer(code, [&](Xbyak::Reg64 return_value_ptr, [[maybe_unused]] RegList args) {
|
||||||
[&](Xbyak::Reg64 return_value_ptr, [[maybe_unused]] RegList args) {
|
|
||||||
code.mov(code.ABI_PARAM3, code.ABI_PARAM2);
|
code.mov(code.ABI_PARAM3, code.ABI_PARAM2);
|
||||||
code.sub(rsp, 8 + 16 + ABI_SHADOW_SPACE);
|
code.sub(rsp, 8 + 16 + ABI_SHADOW_SPACE);
|
||||||
code.lea(return_value_ptr, ptr[rsp + ABI_SHADOW_SPACE]);
|
code.lea(return_value_ptr, ptr[rsp + ABI_SHADOW_SPACE]);
|
||||||
|
@ -628,8 +627,7 @@ void A64EmitX64::EmitA64CallSupervisor(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
ASSERT(args[0].IsImmediate());
|
ASSERT(args[0].IsImmediate());
|
||||||
const u32 imm = args[0].GetImmediateU32();
|
const u32 imm = args[0].GetImmediateU32();
|
||||||
Devirtualize<&A64::UserCallbacks::CallSVC>(conf.callbacks).EmitCall(code,
|
Devirtualize<&A64::UserCallbacks::CallSVC>(conf.callbacks).EmitCall(code, [&](RegList param) {
|
||||||
[&](RegList param) {
|
|
||||||
code.mov(param[0], imm);
|
code.mov(param[0], imm);
|
||||||
});
|
});
|
||||||
// The kernel would have to execute ERET to get here, which would clear exclusive state.
|
// The kernel would have to execute ERET to get here, which would clear exclusive state.
|
||||||
|
@ -642,8 +640,7 @@ void A64EmitX64::EmitA64ExceptionRaised(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
ASSERT(args[0].IsImmediate() && args[1].IsImmediate());
|
ASSERT(args[0].IsImmediate() && args[1].IsImmediate());
|
||||||
const u64 pc = args[0].GetImmediateU64();
|
const u64 pc = args[0].GetImmediateU64();
|
||||||
const u64 exception = args[1].GetImmediateU64();
|
const u64 exception = args[1].GetImmediateU64();
|
||||||
Devirtualize<&A64::UserCallbacks::ExceptionRaised>(conf.callbacks).EmitCall(code,
|
Devirtualize<&A64::UserCallbacks::ExceptionRaised>(conf.callbacks).EmitCall(code, [&](RegList param) {
|
||||||
[&](RegList param) {
|
|
||||||
code.mov(param[0], pc);
|
code.mov(param[0], pc);
|
||||||
code.mov(param[1], exception);
|
code.mov(param[1], exception);
|
||||||
});
|
});
|
||||||
|
@ -881,7 +878,7 @@ void EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, const Xbya
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namepsace
|
} // namespace
|
||||||
|
|
||||||
template<std::size_t bitsize>
|
template<std::size_t bitsize>
|
||||||
void A64EmitX64::EmitDirectPageTableMemoryRead(A64EmitContext& ctx, IR::Inst* inst) {
|
void A64EmitX64::EmitDirectPageTableMemoryRead(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
@ -1090,8 +1087,7 @@ void A64EmitX64::EmitExclusiveReadMemory(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
return conf.global_monitor->ReadAndMark<T>(conf.processor_id, vaddr, [&]() -> T {
|
return conf.global_monitor->ReadAndMark<T>(conf.processor_id, vaddr, [&]() -> T {
|
||||||
return (conf.callbacks->*callback)(vaddr);
|
return (conf.callbacks->*callback)(vaddr);
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
|
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
|
||||||
ctx.reg_alloc.Use(args[0], ABI_PARAM2);
|
ctx.reg_alloc.Use(args[0], ABI_PARAM2);
|
||||||
|
@ -1107,8 +1103,7 @@ void A64EmitX64::EmitExclusiveReadMemory(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
ret = conf.global_monitor->ReadAndMark<A64::Vector>(conf.processor_id, vaddr, [&]() -> A64::Vector {
|
ret = conf.global_monitor->ReadAndMark<A64::Vector>(conf.processor_id, vaddr, [&]() -> A64::Vector {
|
||||||
return (conf.callbacks->*callback)(vaddr);
|
return (conf.callbacks->*callback)(vaddr);
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
);
|
|
||||||
code.movups(result, xword[rsp + ABI_SHADOW_SPACE]);
|
code.movups(result, xword[rsp + ABI_SHADOW_SPACE]);
|
||||||
ctx.reg_alloc.ReleaseStackSpace(16 + ABI_SHADOW_SPACE);
|
ctx.reg_alloc.ReleaseStackSpace(16 + ABI_SHADOW_SPACE);
|
||||||
|
|
||||||
|
@ -1165,9 +1160,10 @@ void A64EmitX64::EmitExclusiveWriteMemory(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
return conf.global_monitor->DoExclusiveOperation<T>(conf.processor_id, vaddr,
|
return conf.global_monitor->DoExclusiveOperation<T>(conf.processor_id, vaddr,
|
||||||
[&](T expected) -> bool {
|
[&](T expected) -> bool {
|
||||||
return (conf.callbacks->*callback)(vaddr, value, expected);
|
return (conf.callbacks->*callback)(vaddr, value, expected);
|
||||||
}) ? 0 : 1;
|
})
|
||||||
}
|
? 0
|
||||||
);
|
: 1;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
ctx.reg_alloc.AllocStackSpace(16 + ABI_SHADOW_SPACE);
|
ctx.reg_alloc.AllocStackSpace(16 + ABI_SHADOW_SPACE);
|
||||||
code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE]);
|
code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE]);
|
||||||
|
@ -1177,9 +1173,10 @@ void A64EmitX64::EmitExclusiveWriteMemory(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
return conf.global_monitor->DoExclusiveOperation<A64::Vector>(conf.processor_id, vaddr,
|
return conf.global_monitor->DoExclusiveOperation<A64::Vector>(conf.processor_id, vaddr,
|
||||||
[&](A64::Vector expected) -> bool {
|
[&](A64::Vector expected) -> bool {
|
||||||
return (conf.callbacks->*callback)(vaddr, value, expected);
|
return (conf.callbacks->*callback)(vaddr, value, expected);
|
||||||
}) ? 0 : 1;
|
})
|
||||||
}
|
? 0
|
||||||
);
|
: 1;
|
||||||
|
});
|
||||||
ctx.reg_alloc.ReleaseStackSpace(16 + ABI_SHADOW_SPACE);
|
ctx.reg_alloc.ReleaseStackSpace(16 + ABI_SHADOW_SPACE);
|
||||||
}
|
}
|
||||||
code.L(end);
|
code.L(end);
|
||||||
|
@ -1214,8 +1211,7 @@ std::string A64EmitX64::LocationDescriptorToFriendlyName(const IR::LocationDescr
|
||||||
|
|
||||||
void A64EmitX64::EmitTerminalImpl(IR::Term::Interpret terminal, IR::LocationDescriptor, bool) {
|
void A64EmitX64::EmitTerminalImpl(IR::Term::Interpret terminal, IR::LocationDescriptor, bool) {
|
||||||
code.SwitchMxcsrOnExit();
|
code.SwitchMxcsrOnExit();
|
||||||
Devirtualize<&A64::UserCallbacks::InterpreterFallback>(conf.callbacks).EmitCall(code,
|
Devirtualize<&A64::UserCallbacks::InterpreterFallback>(conf.callbacks).EmitCall(code, [&](RegList param) {
|
||||||
[&](RegList param) {
|
|
||||||
code.mov(param[0], A64::LocationDescriptor{terminal.next}.PC());
|
code.mov(param[0], A64::LocationDescriptor{terminal.next}.PC());
|
||||||
code.mov(qword[r15 + offsetof(A64JitState, pc)], param[0]);
|
code.mov(qword[r15 + offsetof(A64JitState, pc)], param[0]);
|
||||||
code.mov(param[1].cvt32(), terminal.num_instructions);
|
code.mov(param[1].cvt32(), terminal.num_instructions);
|
||||||
|
|
|
@ -46,8 +46,7 @@ public:
|
||||||
Impl(Jit* jit, UserConfig conf)
|
Impl(Jit* jit, UserConfig conf)
|
||||||
: conf(conf)
|
: conf(conf)
|
||||||
, block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this), JitStateInfo{jit_state}, conf.code_cache_size, conf.far_code_offset, GenRCP(conf))
|
, block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this), JitStateInfo{jit_state}, conf.code_cache_size, conf.far_code_offset, GenRCP(conf))
|
||||||
, emitter(block_of_code, conf, jit)
|
, emitter(block_of_code, conf, jit) {
|
||||||
{
|
|
||||||
ASSERT(conf.page_table_address_space_bits >= 12 && conf.page_table_address_space_bits <= 64);
|
ASSERT(conf.page_table_address_space_bits >= 12 && conf.page_table_address_space_bits <= 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/a64_jitstate.h"
|
#include "dynarmic/backend/x64/a64_jitstate.h"
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/frontend/A64/location_descriptor.h"
|
#include "dynarmic/frontend/A64/location_descriptor.h"
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/backend/x64/abi.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <xbyak.h>
|
#include <xbyak.h>
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/abi.h"
|
|
||||||
#include "dynarmic/backend/x64/block_of_code.h"
|
#include "dynarmic/backend/x64/block_of_code.h"
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/common/iterator_util.h"
|
#include "dynarmic/common/iterator_util.h"
|
||||||
|
|
|
@ -3,6 +3,15 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/backend/x64/block_of_code.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define WIN32_LEAN_AND_MEAN
|
||||||
|
# include <windows.h>
|
||||||
|
#else
|
||||||
|
# include <sys/mman.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
@ -10,19 +19,12 @@
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/a32_jitstate.h"
|
#include "dynarmic/backend/x64/a32_jitstate.h"
|
||||||
#include "dynarmic/backend/x64/abi.h"
|
#include "dynarmic/backend/x64/abi.h"
|
||||||
#include "dynarmic/backend/x64/block_of_code.h"
|
|
||||||
#include "dynarmic/backend/x64/hostloc.h"
|
#include "dynarmic/backend/x64/hostloc.h"
|
||||||
#include "dynarmic/backend/x64/perf_map.h"
|
#include "dynarmic/backend/x64/perf_map.h"
|
||||||
#include "dynarmic/backend/x64/stack_layout.h"
|
#include "dynarmic/backend/x64/stack_layout.h"
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#else
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Dynarmic::Backend::X64 {
|
namespace Dynarmic::Backend::X64 {
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -73,34 +75,53 @@ void ProtectMemory(const void* base, size_t size, bool is_executable) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HostFeature GetHostFeatures()
|
HostFeature GetHostFeatures() {
|
||||||
{
|
|
||||||
HostFeature features = {};
|
HostFeature features = {};
|
||||||
|
|
||||||
#ifdef DYNARMIC_ENABLE_CPU_FEATURE_DETECTION
|
#ifdef DYNARMIC_ENABLE_CPU_FEATURE_DETECTION
|
||||||
using Cpu = Xbyak::util::Cpu;
|
using Cpu = Xbyak::util::Cpu;
|
||||||
Xbyak::util::Cpu cpu_info;
|
Xbyak::util::Cpu cpu_info;
|
||||||
|
|
||||||
if (cpu_info.has(Cpu::tSSSE3)) features |= HostFeature::SSSE3;
|
if (cpu_info.has(Cpu::tSSSE3))
|
||||||
if (cpu_info.has(Cpu::tSSE41)) features |= HostFeature::SSE41;
|
features |= HostFeature::SSSE3;
|
||||||
if (cpu_info.has(Cpu::tSSE42)) features |= HostFeature::SSE42;
|
if (cpu_info.has(Cpu::tSSE41))
|
||||||
if (cpu_info.has(Cpu::tAVX)) features |= HostFeature::AVX;
|
features |= HostFeature::SSE41;
|
||||||
if (cpu_info.has(Cpu::tAVX2)) features |= HostFeature::AVX2;
|
if (cpu_info.has(Cpu::tSSE42))
|
||||||
if (cpu_info.has(Cpu::tAVX512F)) features |= HostFeature::AVX512F;
|
features |= HostFeature::SSE42;
|
||||||
if (cpu_info.has(Cpu::tAVX512CD)) features |= HostFeature::AVX512CD;
|
if (cpu_info.has(Cpu::tAVX))
|
||||||
if (cpu_info.has(Cpu::tAVX512VL)) features |= HostFeature::AVX512VL;
|
features |= HostFeature::AVX;
|
||||||
if (cpu_info.has(Cpu::tAVX512BW)) features |= HostFeature::AVX512BW;
|
if (cpu_info.has(Cpu::tAVX2))
|
||||||
if (cpu_info.has(Cpu::tAVX512DQ)) features |= HostFeature::AVX512DQ;
|
features |= HostFeature::AVX2;
|
||||||
if (cpu_info.has(Cpu::tAVX512_BITALG)) features |= HostFeature::AVX512BITALG;
|
if (cpu_info.has(Cpu::tAVX512F))
|
||||||
if (cpu_info.has(Cpu::tPCLMULQDQ)) features |= HostFeature::PCLMULQDQ;
|
features |= HostFeature::AVX512F;
|
||||||
if (cpu_info.has(Cpu::tF16C)) features |= HostFeature::F16C;
|
if (cpu_info.has(Cpu::tAVX512CD))
|
||||||
if (cpu_info.has(Cpu::tFMA)) features |= HostFeature::FMA;
|
features |= HostFeature::AVX512CD;
|
||||||
if (cpu_info.has(Cpu::tAESNI)) features |= HostFeature::AES;
|
if (cpu_info.has(Cpu::tAVX512VL))
|
||||||
if (cpu_info.has(Cpu::tPOPCNT)) features |= HostFeature::POPCNT;
|
features |= HostFeature::AVX512VL;
|
||||||
if (cpu_info.has(Cpu::tBMI1)) features |= HostFeature::BMI1;
|
if (cpu_info.has(Cpu::tAVX512BW))
|
||||||
if (cpu_info.has(Cpu::tBMI2)) features |= HostFeature::BMI2;
|
features |= HostFeature::AVX512BW;
|
||||||
if (cpu_info.has(Cpu::tLZCNT)) features |= HostFeature::LZCNT;
|
if (cpu_info.has(Cpu::tAVX512DQ))
|
||||||
if (cpu_info.has(Cpu::tGFNI)) features |= HostFeature::GFNI;
|
features |= HostFeature::AVX512DQ;
|
||||||
|
if (cpu_info.has(Cpu::tAVX512_BITALG))
|
||||||
|
features |= HostFeature::AVX512BITALG;
|
||||||
|
if (cpu_info.has(Cpu::tPCLMULQDQ))
|
||||||
|
features |= HostFeature::PCLMULQDQ;
|
||||||
|
if (cpu_info.has(Cpu::tF16C))
|
||||||
|
features |= HostFeature::F16C;
|
||||||
|
if (cpu_info.has(Cpu::tFMA))
|
||||||
|
features |= HostFeature::FMA;
|
||||||
|
if (cpu_info.has(Cpu::tAESNI))
|
||||||
|
features |= HostFeature::AES;
|
||||||
|
if (cpu_info.has(Cpu::tPOPCNT))
|
||||||
|
features |= HostFeature::POPCNT;
|
||||||
|
if (cpu_info.has(Cpu::tBMI1))
|
||||||
|
features |= HostFeature::BMI1;
|
||||||
|
if (cpu_info.has(Cpu::tBMI2))
|
||||||
|
features |= HostFeature::BMI2;
|
||||||
|
if (cpu_info.has(Cpu::tLZCNT))
|
||||||
|
features |= HostFeature::LZCNT;
|
||||||
|
if (cpu_info.has(Cpu::tGFNI))
|
||||||
|
features |= HostFeature::GFNI;
|
||||||
|
|
||||||
if (cpu_info.has(Cpu::tBMI2)) {
|
if (cpu_info.has(Cpu::tBMI2)) {
|
||||||
// BMI2 instructions such as pdep and pext have been very slow up until Zen 3.
|
// BMI2 instructions such as pdep and pext have been very slow up until Zen 3.
|
||||||
|
@ -131,8 +152,7 @@ BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, size_t total_cod
|
||||||
, jsi(jsi)
|
, jsi(jsi)
|
||||||
, far_code_offset(far_code_offset)
|
, far_code_offset(far_code_offset)
|
||||||
, constant_pool(*this, CONSTANT_POOL_SIZE)
|
, constant_pool(*this, CONSTANT_POOL_SIZE)
|
||||||
, host_features(GetHostFeatures())
|
, host_features(GetHostFeatures()) {
|
||||||
{
|
|
||||||
ASSERT(total_code_size > far_code_offset);
|
ASSERT(total_code_size > far_code_offset);
|
||||||
EnableWriting();
|
EnableWriting();
|
||||||
GenRunCode(rcp);
|
GenRunCode(rcp);
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/backend/x64/block_range_information.h"
|
||||||
|
|
||||||
#include <boost/icl/interval_map.hpp>
|
#include <boost/icl/interval_map.hpp>
|
||||||
#include <boost/icl/interval_set.hpp>
|
#include <boost/icl/interval_set.hpp>
|
||||||
#include <tsl/robin_set.h>
|
#include <tsl/robin_set.h>
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/block_range_information.h"
|
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
|
|
||||||
namespace Dynarmic::Backend::X64 {
|
namespace Dynarmic::Backend::X64 {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/callback.h"
|
#include "dynarmic/backend/x64/callback.h"
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/block_of_code.h"
|
#include "dynarmic/backend/x64/block_of_code.h"
|
||||||
|
|
||||||
namespace Dynarmic::Backend::X64 {
|
namespace Dynarmic::Backend::X64 {
|
||||||
|
|
|
@ -22,16 +22,23 @@ class Callback {
|
||||||
public:
|
public:
|
||||||
virtual ~Callback();
|
virtual ~Callback();
|
||||||
|
|
||||||
virtual void EmitCall(BlockOfCode& code, std::function<void(RegList)> fn = [](RegList){}) const = 0;
|
void EmitCall(BlockOfCode& code) const {
|
||||||
|
EmitCall(code, [](RegList) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void EmitCall(BlockOfCode& code, std::function<void(RegList)> fn) const = 0;
|
||||||
virtual void EmitCallWithReturnPointer(BlockOfCode& code, std::function<void(Xbyak::Reg64, RegList)> fn) const = 0;
|
virtual void EmitCallWithReturnPointer(BlockOfCode& code, std::function<void(Xbyak::Reg64, RegList)> fn) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SimpleCallback final : public Callback {
|
class SimpleCallback final : public Callback {
|
||||||
public:
|
public:
|
||||||
template<typename Function>
|
template<typename Function>
|
||||||
SimpleCallback(Function fn) : fn(reinterpret_cast<void(*)()>(fn)) {}
|
SimpleCallback(Function fn)
|
||||||
|
: fn(reinterpret_cast<void (*)()>(fn)) {}
|
||||||
|
|
||||||
void EmitCall(BlockOfCode& code, std::function<void(RegList)> fn = [](RegList){}) const override;
|
using Callback::EmitCall;
|
||||||
|
|
||||||
|
void EmitCall(BlockOfCode& code, std::function<void(RegList)> fn) const override;
|
||||||
void EmitCallWithReturnPointer(BlockOfCode& code, std::function<void(Xbyak::Reg64, RegList)> fn) const override;
|
void EmitCallWithReturnPointer(BlockOfCode& code, std::function<void(Xbyak::Reg64, RegList)> fn) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -41,9 +48,12 @@ private:
|
||||||
class ArgCallback final : public Callback {
|
class ArgCallback final : public Callback {
|
||||||
public:
|
public:
|
||||||
template<typename Function>
|
template<typename Function>
|
||||||
ArgCallback(Function fn, u64 arg) : fn(reinterpret_cast<void(*)()>(fn)), arg(arg) {}
|
ArgCallback(Function fn, u64 arg)
|
||||||
|
: fn(reinterpret_cast<void (*)()>(fn)), arg(arg) {}
|
||||||
|
|
||||||
void EmitCall(BlockOfCode& code, std::function<void(RegList)> fn = [](RegList){}) const override;
|
using Callback::EmitCall;
|
||||||
|
|
||||||
|
void EmitCall(BlockOfCode& code, std::function<void(RegList)> fn) const override;
|
||||||
void EmitCallWithReturnPointer(BlockOfCode& code, std::function<void(Xbyak::Reg64, RegList)> fn) const override;
|
void EmitCallWithReturnPointer(BlockOfCode& code, std::function<void(Xbyak::Reg64, RegList)> fn) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -3,15 +3,17 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/backend/x64/constant_pool.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/block_of_code.h"
|
#include "dynarmic/backend/x64/block_of_code.h"
|
||||||
#include "dynarmic/backend/x64/constant_pool.h"
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
|
|
||||||
namespace Dynarmic::Backend::X64 {
|
namespace Dynarmic::Backend::X64 {
|
||||||
|
|
||||||
ConstantPool::ConstantPool(BlockOfCode& code, size_t size) : code(code), pool_size(size) {
|
ConstantPool::ConstantPool(BlockOfCode& code, size_t size)
|
||||||
|
: code(code), pool_size(size) {
|
||||||
code.int3();
|
code.int3();
|
||||||
code.align(align_size);
|
code.align(align_size);
|
||||||
pool_begin = reinterpret_cast<u8*>(code.AllocateFromCodeSpace(size));
|
pool_begin = reinterpret_cast<u8*>(code.AllocateFromCodeSpace(size));
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/backend/x64/emit_x64.h"
|
||||||
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
#include <tsl/robin_set.h>
|
#include <tsl/robin_set.h>
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/block_of_code.h"
|
#include "dynarmic/backend/x64/block_of_code.h"
|
||||||
#include "dynarmic/backend/x64/emit_x64.h"
|
|
||||||
#include "dynarmic/backend/x64/nzcv_util.h"
|
#include "dynarmic/backend/x64/nzcv_util.h"
|
||||||
#include "dynarmic/backend/x64/perf_map.h"
|
#include "dynarmic/backend/x64/perf_map.h"
|
||||||
#include "dynarmic/backend/x64/stack_layout.h"
|
#include "dynarmic/backend/x64/stack_layout.h"
|
||||||
|
@ -40,7 +41,8 @@ void EmitContext::EraseInstruction(IR::Inst* inst) {
|
||||||
inst->ClearArgs();
|
inst->ClearArgs();
|
||||||
}
|
}
|
||||||
|
|
||||||
EmitX64::EmitX64(BlockOfCode& code) : code(code) {
|
EmitX64::EmitX64(BlockOfCode& code)
|
||||||
|
: code(code) {
|
||||||
exception_handler.Register(code);
|
exception_handler.Register(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
|
|
||||||
#include <tsl/robin_map.h>
|
#include <tsl/robin_map.h>
|
||||||
#include <tsl/robin_set.h>
|
#include <tsl/robin_set.h>
|
||||||
|
|
||||||
#include <xbyak_util.h>
|
#include <xbyak_util.h>
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/exception_handler.h"
|
#include "dynarmic/backend/x64/exception_handler.h"
|
||||||
|
|
|
@ -889,35 +889,43 @@ static void EmitMaskedShift64(BlockOfCode& code, EmitContext& ctx, IR::Inst* ins
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitLogicalShiftLeftMasked32(EmitContext& ctx, IR::Inst* inst) {
|
void EmitX64::EmitLogicalShiftLeftMasked32(EmitContext& ctx, IR::Inst* inst) {
|
||||||
EmitMaskedShift32(code, ctx, inst, [&](auto result, auto shift) { code.shl(result, shift); }, &Xbyak::CodeGenerator::shlx);
|
EmitMaskedShift32(
|
||||||
|
code, ctx, inst, [&](auto result, auto shift) { code.shl(result, shift); }, &Xbyak::CodeGenerator::shlx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitLogicalShiftLeftMasked64(EmitContext& ctx, IR::Inst* inst) {
|
void EmitX64::EmitLogicalShiftLeftMasked64(EmitContext& ctx, IR::Inst* inst) {
|
||||||
EmitMaskedShift64(code, ctx, inst, [&](auto result, auto shift) { code.shl(result, shift); }, &Xbyak::CodeGenerator::shlx);
|
EmitMaskedShift64(
|
||||||
|
code, ctx, inst, [&](auto result, auto shift) { code.shl(result, shift); }, &Xbyak::CodeGenerator::shlx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitLogicalShiftRightMasked32(EmitContext& ctx, IR::Inst* inst) {
|
void EmitX64::EmitLogicalShiftRightMasked32(EmitContext& ctx, IR::Inst* inst) {
|
||||||
EmitMaskedShift32(code, ctx, inst, [&](auto result, auto shift) { code.shr(result, shift); }, &Xbyak::CodeGenerator::shrx);
|
EmitMaskedShift32(
|
||||||
|
code, ctx, inst, [&](auto result, auto shift) { code.shr(result, shift); }, &Xbyak::CodeGenerator::shrx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitLogicalShiftRightMasked64(EmitContext& ctx, IR::Inst* inst) {
|
void EmitX64::EmitLogicalShiftRightMasked64(EmitContext& ctx, IR::Inst* inst) {
|
||||||
EmitMaskedShift64(code, ctx, inst, [&](auto result, auto shift) { code.shr(result, shift); }, &Xbyak::CodeGenerator::shrx);
|
EmitMaskedShift64(
|
||||||
|
code, ctx, inst, [&](auto result, auto shift) { code.shr(result, shift); }, &Xbyak::CodeGenerator::shrx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitArithmeticShiftRightMasked32(EmitContext& ctx, IR::Inst* inst) {
|
void EmitX64::EmitArithmeticShiftRightMasked32(EmitContext& ctx, IR::Inst* inst) {
|
||||||
EmitMaskedShift32(code, ctx, inst, [&](auto result, auto shift) { code.sar(result, shift); }, &Xbyak::CodeGenerator::sarx);
|
EmitMaskedShift32(
|
||||||
|
code, ctx, inst, [&](auto result, auto shift) { code.sar(result, shift); }, &Xbyak::CodeGenerator::sarx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitArithmeticShiftRightMasked64(EmitContext& ctx, IR::Inst* inst) {
|
void EmitX64::EmitArithmeticShiftRightMasked64(EmitContext& ctx, IR::Inst* inst) {
|
||||||
EmitMaskedShift64(code, ctx, inst, [&](auto result, auto shift) { code.sar(result, shift); }, &Xbyak::CodeGenerator::sarx);
|
EmitMaskedShift64(
|
||||||
|
code, ctx, inst, [&](auto result, auto shift) { code.sar(result, shift); }, &Xbyak::CodeGenerator::sarx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitRotateRightMasked32(EmitContext& ctx, IR::Inst* inst) {
|
void EmitX64::EmitRotateRightMasked32(EmitContext& ctx, IR::Inst* inst) {
|
||||||
EmitMaskedShift32(code, ctx, inst, [&](auto result, auto shift) { code.ror(result, shift); }, nullptr);
|
EmitMaskedShift32(
|
||||||
|
code, ctx, inst, [&](auto result, auto shift) { code.ror(result, shift); }, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitRotateRightMasked64(EmitContext& ctx, IR::Inst* inst) {
|
void EmitX64::EmitRotateRightMasked64(EmitContext& ctx, IR::Inst* inst) {
|
||||||
EmitMaskedShift64(code, ctx, inst, [&](auto result, auto shift) { code.ror(result, shift); }, nullptr);
|
EmitMaskedShift64(
|
||||||
|
code, ctx, inst, [&](auto result, auto shift) { code.ror(result, shift); }, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Xbyak::Reg8 DoCarry(RegAlloc& reg_alloc, Argument& carry_in, IR::Inst* carry_out) {
|
static Xbyak::Reg8 DoCarry(RegAlloc& reg_alloc, Argument& carry_in, IR::Inst* carry_out) {
|
||||||
|
|
|
@ -930,8 +930,7 @@ static void EmitFPRound(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, siz
|
||||||
mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
|
mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
|
||||||
mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
|
mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
|
||||||
mp::lift_value<FP::RoundingMode::TowardsZero>,
|
mp::lift_value<FP::RoundingMode::TowardsZero>,
|
||||||
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>
|
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>>;
|
||||||
>;
|
|
||||||
using exact_list = mp::list<std::true_type, std::false_type>;
|
using exact_list = mp::list<std::true_type, std::false_type>;
|
||||||
|
|
||||||
static const auto lut = Common::GenerateLookupTableFromList(
|
static const auto lut = Common::GenerateLookupTableFromList(
|
||||||
|
@ -947,12 +946,9 @@ static void EmitFPRound(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, siz
|
||||||
using InputSize = mp::unsigned_integer_of_size<fsize>;
|
using InputSize = mp::unsigned_integer_of_size<fsize>;
|
||||||
|
|
||||||
return FP::FPRoundInt<InputSize>(static_cast<InputSize>(input), fpcr, rounding_mode, exact, fpsr);
|
return FP::FPRoundInt<InputSize>(static_cast<InputSize>(input), fpcr, rounding_mode, exact, fpsr);
|
||||||
}
|
})};
|
||||||
)
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
mp::cartesian_product<fsize_list, rounding_list, exact_list>{}
|
mp::cartesian_product<fsize_list, rounding_list, exact_list>{});
|
||||||
);
|
|
||||||
|
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
ctx.reg_alloc.HostCall(inst, args[0]);
|
ctx.reg_alloc.HostCall(inst, args[0]);
|
||||||
|
@ -1546,8 +1542,7 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
|
mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
|
||||||
mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
|
mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
|
||||||
mp::lift_value<FP::RoundingMode::TowardsZero>,
|
mp::lift_value<FP::RoundingMode::TowardsZero>,
|
||||||
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>
|
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>>;
|
||||||
>;
|
|
||||||
|
|
||||||
static const auto lut = Common::GenerateLookupTableFromList(
|
static const auto lut = Common::GenerateLookupTableFromList(
|
||||||
[](auto args) {
|
[](auto args) {
|
||||||
|
@ -1561,12 +1556,9 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
using FPT = mp::unsigned_integer_of_size<fsize>;
|
using FPT = mp::unsigned_integer_of_size<fsize>;
|
||||||
|
|
||||||
return FP::FPToFixed<FPT>(isize, static_cast<FPT>(input), fbits, unsigned_, fpcr, rounding_mode, fpsr);
|
return FP::FPToFixed<FPT>(isize, static_cast<FPT>(input), fbits, unsigned_, fpcr, rounding_mode, fpsr);
|
||||||
}
|
})};
|
||||||
)
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
mp::cartesian_product<fbits_list, rounding_list>{}
|
mp::cartesian_product<fbits_list, rounding_list>{});
|
||||||
);
|
|
||||||
|
|
||||||
ctx.reg_alloc.HostCall(inst, args[0]);
|
ctx.reg_alloc.HostCall(inst, args[0]);
|
||||||
code.lea(code.ABI_PARAM2, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]);
|
code.lea(code.ABI_PARAM2, code.ptr[code.r15 + code.GetJitStateInfo().offsetof_fpsr_exc]);
|
||||||
|
|
|
@ -2947,8 +2947,7 @@ static void RoundingShiftLeft(VectorArray<T>& out, const VectorArray<T>& lhs, co
|
||||||
out[i] = static_cast<T>(static_cast<unsigned_type>(lhs[i]) << extended_shift);
|
out[i] = static_cast<T>(static_cast<unsigned_type>(lhs[i]) << extended_shift);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((std::is_unsigned_v<T> && extended_shift < -bit_size) ||
|
if ((std::is_unsigned_v<T> && extended_shift < -bit_size) || (std::is_signed_v<T> && extended_shift <= -bit_size)) {
|
||||||
(std::is_signed_v<T> && extended_shift <= -bit_size)) {
|
|
||||||
out[i] = 0;
|
out[i] = 0;
|
||||||
} else {
|
} else {
|
||||||
const s64 shift_value = -extended_shift - 1;
|
const s64 shift_value = -extended_shift - 1;
|
||||||
|
@ -3350,7 +3349,6 @@ static void EmitVectorSignedSaturatedAbs(size_t esize, BlockOfCode& code, EmitCo
|
||||||
ctx.reg_alloc.DefineValue(inst, data);
|
ctx.reg_alloc.DefineValue(inst, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EmitX64::EmitVectorSignedSaturatedAbs8(EmitContext& ctx, IR::Inst* inst) {
|
void EmitX64::EmitVectorSignedSaturatedAbs8(EmitContext& ctx, IR::Inst* inst) {
|
||||||
EmitVectorSignedSaturatedAbs(8, code, ctx, inst);
|
EmitVectorSignedSaturatedAbs(8, code, ctx, inst);
|
||||||
}
|
}
|
||||||
|
@ -4318,8 +4316,7 @@ void EmitX64::EmitVectorTableLookup64(EmitContext& ctx, IR::Inst* inst) {
|
||||||
result[i] = table[index][elem];
|
result[i] = table[index][elem];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
code.movq(result, qword[rsp + ABI_SHADOW_SPACE + 4 * 8]);
|
code.movq(result, qword[rsp + ABI_SHADOW_SPACE + 4 * 8]);
|
||||||
ctx.reg_alloc.ReleaseStackSpace(stack_space + ABI_SHADOW_SPACE);
|
ctx.reg_alloc.ReleaseStackSpace(stack_space + ABI_SHADOW_SPACE);
|
||||||
|
@ -4448,8 +4445,7 @@ void EmitX64::EmitVectorTableLookup128(EmitContext& ctx, IR::Inst* inst) {
|
||||||
result[i] = table[index][elem];
|
result[i] = table[index][elem];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
code.movaps(result, xword[rsp + ABI_SHADOW_SPACE + (table_size + 0) * 16]);
|
code.movaps(result, xword[rsp + ABI_SHADOW_SPACE + (table_size + 0) * 16]);
|
||||||
ctx.reg_alloc.ReleaseStackSpace(stack_space + ABI_SHADOW_SPACE);
|
ctx.reg_alloc.ReleaseStackSpace(stack_space + ABI_SHADOW_SPACE);
|
||||||
|
|
|
@ -337,7 +337,8 @@ void EmitTwoOpVectorOperation(BlockOfCode& code, EmitContext& ctx, IR::Inst* ins
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CheckInputNaN {
|
enum CheckInputNaN {
|
||||||
Yes, No,
|
Yes,
|
||||||
|
No,
|
||||||
};
|
};
|
||||||
|
|
||||||
template<size_t fsize, template<typename> class Indexer, typename Function>
|
template<size_t fsize, template<typename> class Indexer, typename Function>
|
||||||
|
@ -936,7 +937,8 @@ static void EmitFPVectorMinMax(BlockOfCode& code, EmitContext& ctx, IR::Inst* in
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
EmitThreeOpVectorOperation<fsize, DefaultIndexer>(code, ctx, inst, [&](const Xbyak::Xmm& result, Xbyak::Xmm xmm_b){
|
EmitThreeOpVectorOperation<fsize, DefaultIndexer>(
|
||||||
|
code, ctx, inst, [&](const Xbyak::Xmm& result, Xbyak::Xmm xmm_b) {
|
||||||
const Xbyak::Xmm mask = xmm0;
|
const Xbyak::Xmm mask = xmm0;
|
||||||
const Xbyak::Xmm eq = ctx.reg_alloc.ScratchXmm();
|
const Xbyak::Xmm eq = ctx.reg_alloc.ScratchXmm();
|
||||||
|
|
||||||
|
@ -978,7 +980,8 @@ static void EmitFPVectorMinMax(BlockOfCode& code, EmitContext& ctx, IR::Inst* in
|
||||||
code.andnps(mask, eq);
|
code.andnps(mask, eq);
|
||||||
code.orps(result, mask);
|
code.orps(result, mask);
|
||||||
}
|
}
|
||||||
}, CheckInputNaN::Yes);
|
},
|
||||||
|
CheckInputNaN::Yes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitFPVectorMax32(EmitContext& ctx, IR::Inst* inst) {
|
void EmitX64::EmitFPVectorMax32(EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
@ -1151,8 +1154,7 @@ static void EmitFPVectorMulX(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst
|
||||||
result[elementi] = sign | FP::FPValue<FPT, false, 0, 2>();
|
result[elementi] = sign | FP::FPValue<FPT, false, 0, 2>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
HandleNaNs<fsize, 2>(code, ctx, fpcr_controlled, {result, xmm_a, xmm_b}, nan_mask, nan_handler);
|
HandleNaNs<fsize, 2>(code, ctx, fpcr_controlled, {result, xmm_a, xmm_b}, nan_mask, nan_handler);
|
||||||
|
|
||||||
|
@ -1399,8 +1401,7 @@ void EmitFPVectorRoundInt(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
|
mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
|
||||||
mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
|
mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
|
||||||
mp::lift_value<FP::RoundingMode::TowardsZero>,
|
mp::lift_value<FP::RoundingMode::TowardsZero>,
|
||||||
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>
|
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>>;
|
||||||
>;
|
|
||||||
using exact_list = mp::list<std::true_type, std::false_type>;
|
using exact_list = mp::list<std::true_type, std::false_type>;
|
||||||
|
|
||||||
static const auto lut = Common::GenerateLookupTableFromList(
|
static const auto lut = Common::GenerateLookupTableFromList(
|
||||||
|
@ -1416,12 +1417,9 @@ void EmitFPVectorRoundInt(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
for (size_t i = 0; i < output.size(); ++i) {
|
for (size_t i = 0; i < output.size(); ++i) {
|
||||||
output[i] = static_cast<FPT>(FP::FPRoundInt<FPT>(input[i], fpcr, rounding_mode, exact, fpsr));
|
output[i] = static_cast<FPT>(FP::FPRoundInt<FPT>(input[i], fpcr, rounding_mode, exact, fpsr));
|
||||||
}
|
}
|
||||||
}
|
})};
|
||||||
)
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
mp::cartesian_product<rounding_list, exact_list>{}
|
mp::cartesian_product<rounding_list, exact_list>{});
|
||||||
);
|
|
||||||
|
|
||||||
EmitTwoOpFallback<3>(code, ctx, inst, lut.at(std::make_tuple(rounding, exact)));
|
EmitTwoOpFallback<3>(code, ctx, inst, lut.at(std::make_tuple(rounding, exact)));
|
||||||
}
|
}
|
||||||
|
@ -1528,7 +1526,7 @@ static void EmitRSqrtStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* in
|
||||||
FCODE(vfnmadd231p)(result, operand1, operand2);
|
FCODE(vfnmadd231p)(result, operand1, operand2);
|
||||||
|
|
||||||
// An explanation for this is given in EmitFPRSqrtStepFused.
|
// An explanation for this is given in EmitFPRSqrtStepFused.
|
||||||
code.vmovaps(mask, GetVectorOf<fsize, fsize == 32 ? 0x7f000000 : 0x7fe0000000000000>(code));
|
code.vmovaps(mask, GetVectorOf<fsize, (fsize == 32 ? 0x7f000000 : 0x7fe0000000000000)>(code));
|
||||||
FCODE(vandp)(tmp, result, mask);
|
FCODE(vandp)(tmp, result, mask);
|
||||||
ICODE(vpcmpeq)(tmp, tmp, mask);
|
ICODE(vpcmpeq)(tmp, tmp, mask);
|
||||||
code.ptest(tmp, tmp);
|
code.ptest(tmp, tmp);
|
||||||
|
@ -1621,7 +1619,6 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
const Xbyak::Xmm src = ctx.reg_alloc.UseScratchXmm(args[0]);
|
const Xbyak::Xmm src = ctx.reg_alloc.UseScratchXmm(args[0]);
|
||||||
|
|
||||||
MaybeStandardFPSCRValue(code, ctx, fpcr_controlled, [&] {
|
MaybeStandardFPSCRValue(code, ctx, fpcr_controlled, [&] {
|
||||||
|
|
||||||
const int round_imm = [&] {
|
const int round_imm = [&] {
|
||||||
switch (rounding) {
|
switch (rounding) {
|
||||||
case FP::RoundingMode::ToNearest_TieEven:
|
case FP::RoundingMode::ToNearest_TieEven:
|
||||||
|
@ -1702,7 +1699,6 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
perform_conversion(src);
|
perform_conversion(src);
|
||||||
FCODE(blendvp)(src, GetVectorOf<fsize, integer_max>(code));
|
FCODE(blendvp)(src, GetVectorOf<fsize, integer_max>(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(inst, src);
|
ctx.reg_alloc.DefineValue(inst, src);
|
||||||
|
@ -1716,8 +1712,7 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
|
mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
|
||||||
mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
|
mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
|
||||||
mp::lift_value<FP::RoundingMode::TowardsZero>,
|
mp::lift_value<FP::RoundingMode::TowardsZero>,
|
||||||
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>
|
mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>>;
|
||||||
>;
|
|
||||||
|
|
||||||
static const auto lut = Common::GenerateLookupTableFromList(
|
static const auto lut = Common::GenerateLookupTableFromList(
|
||||||
[](auto arg) {
|
[](auto arg) {
|
||||||
|
@ -1732,12 +1727,9 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
for (size_t i = 0; i < output.size(); ++i) {
|
for (size_t i = 0; i < output.size(); ++i) {
|
||||||
output[i] = static_cast<FPT>(FP::FPToFixed<FPT>(fsize, input[i], fbits, unsigned_, fpcr, rounding_mode, fpsr));
|
output[i] = static_cast<FPT>(FP::FPToFixed<FPT>(fsize, input[i], fbits, unsigned_, fpcr, rounding_mode, fpsr));
|
||||||
}
|
}
|
||||||
}
|
})};
|
||||||
)
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
mp::cartesian_product<fbits_list, rounding_list>{}
|
mp::cartesian_product<fbits_list, rounding_list>{});
|
||||||
);
|
|
||||||
|
|
||||||
EmitTwoOpFallback<3>(code, ctx, inst, lut.at(std::make_tuple(fbits, rounding)));
|
EmitTwoOpFallback<3>(code, ctx, inst, lut.at(std::make_tuple(fbits, rounding)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/exception_handler.h"
|
|
||||||
|
|
||||||
#include <mach/mach.h>
|
#include <mach/mach.h>
|
||||||
#include <mach/message.h>
|
#include <mach/message.h>
|
||||||
|
|
||||||
|
@ -18,6 +16,7 @@
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/block_of_code.h"
|
#include "dynarmic/backend/x64/block_of_code.h"
|
||||||
|
#include "dynarmic/backend/x64/exception_handler.h"
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/cast_util.h"
|
#include "dynarmic/common/cast_util.h"
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
|
@ -167,8 +166,7 @@ mig_external kern_return_t catch_mach_exception_raise_state(
|
||||||
const thread_state_t old_state,
|
const thread_state_t old_state,
|
||||||
mach_msg_type_number_t old_stateCnt,
|
mach_msg_type_number_t old_stateCnt,
|
||||||
thread_state_t new_state,
|
thread_state_t new_state,
|
||||||
mach_msg_type_number_t* new_stateCnt
|
mach_msg_type_number_t* new_stateCnt) {
|
||||||
) {
|
|
||||||
if (!flavor || !new_stateCnt) {
|
if (!flavor || !new_stateCnt) {
|
||||||
fmt::print(stderr, "dynarmic: catch_mach_exception_raise_state: Invalid arguments.\n");
|
fmt::print(stderr, "dynarmic: catch_mach_exception_raise_state: Invalid arguments.\n");
|
||||||
return KERN_INVALID_ARGUMENT;
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
@ -192,8 +190,7 @@ mig_external kern_return_t catch_mach_exception_raise_state(
|
||||||
struct ExceptionHandler::Impl final {
|
struct ExceptionHandler::Impl final {
|
||||||
Impl(BlockOfCode& code)
|
Impl(BlockOfCode& code)
|
||||||
: code_begin(Common::BitCast<u64>(code.getCode()))
|
: code_begin(Common::BitCast<u64>(code.getCode()))
|
||||||
, code_end(code_begin + code.GetTotalCodeSize())
|
, code_end(code_begin + code.GetTotalCodeSize()) {}
|
||||||
{}
|
|
||||||
|
|
||||||
void SetCallback(std::function<FakeCall(u64)> cb) {
|
void SetCallback(std::function<FakeCall(u64)> cb) {
|
||||||
CodeBlockInfo cbi;
|
CodeBlockInfo cbi;
|
||||||
|
|
|
@ -5,19 +5,20 @@
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/exception_handler.h"
|
#include "dynarmic/backend/x64/exception_handler.h"
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
# include <signal.h>
|
||||||
|
# include <sys/ucontext.h>
|
||||||
|
#else
|
||||||
|
# include <signal.h>
|
||||||
|
# include <ucontext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include <sys/ucontext.h>
|
|
||||||
#else
|
|
||||||
#include <ucontext.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/block_of_code.h"
|
#include "dynarmic/backend/x64/block_of_code.h"
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/cast_util.h"
|
#include "dynarmic/common/cast_util.h"
|
||||||
|
@ -170,8 +171,7 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
|
||||||
struct ExceptionHandler::Impl final {
|
struct ExceptionHandler::Impl final {
|
||||||
Impl(BlockOfCode& code)
|
Impl(BlockOfCode& code)
|
||||||
: code_begin(Common::BitCast<u64>(code.getCode()))
|
: code_begin(Common::BitCast<u64>(code.getCode()))
|
||||||
, code_end(code_begin + code.GetTotalCodeSize())
|
, code_end(code_begin + code.GetTotalCodeSize()) {}
|
||||||
{}
|
|
||||||
|
|
||||||
void SetCallback(std::function<FakeCall(u64)> cb) {
|
void SetCallback(std::function<FakeCall(u64)> cb) {
|
||||||
CodeBlockInfo cbi;
|
CodeBlockInfo cbi;
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/block_of_code.h"
|
#include "dynarmic/backend/x64/block_of_code.h"
|
||||||
#include "dynarmic/backend/x64/exception_handler.h"
|
#include "dynarmic/backend/x64/exception_handler.h"
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
|
@ -193,8 +193,7 @@ struct ExceptionHandler::Impl final {
|
||||||
ctx->Rsp -= sizeof(u64);
|
ctx->Rsp -= sizeof(u64);
|
||||||
*Common::BitCast<u64*>(ctx->Rsp) = fc.ret_rip;
|
*Common::BitCast<u64*>(ctx->Rsp) = fc.ret_rip;
|
||||||
ctx->Rip = fc.call_rip;
|
ctx->Rip = fc.call_rip;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
code.add(code.rsp, 8);
|
code.add(code.rsp, 8);
|
||||||
code.mov(code.eax, static_cast<u32>(ExceptionContinueExecution));
|
code.mov(code.eax, static_cast<u32>(ExceptionContinueExecution));
|
||||||
code.ret();
|
code.ret();
|
||||||
|
|
|
@ -3,15 +3,16 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/interface/exclusive_monitor.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/interface/exclusive_monitor.h"
|
|
||||||
|
|
||||||
namespace Dynarmic {
|
namespace Dynarmic {
|
||||||
|
|
||||||
ExclusiveMonitor::ExclusiveMonitor(size_t processor_count) :
|
ExclusiveMonitor::ExclusiveMonitor(size_t processor_count)
|
||||||
exclusive_addresses(processor_count, INVALID_EXCLUSIVE_ADDRESS), exclusive_values(processor_count) {
|
: exclusive_addresses(processor_count, INVALID_EXCLUSIVE_ADDRESS), exclusive_values(processor_count) {
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,4 +61,4 @@ constexpr HostFeature operator&=(HostFeature& result, HostFeature f) {
|
||||||
return result = (result & f);
|
return result = (result & f);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace Dynarmic::Backend::X64
|
||||||
|
|
|
@ -3,10 +3,11 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/backend/x64/hostloc.h"
|
||||||
|
|
||||||
#include <xbyak.h>
|
#include <xbyak.h>
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/abi.h"
|
#include "dynarmic/backend/x64/abi.h"
|
||||||
#include "dynarmic/backend/x64/hostloc.h"
|
|
||||||
#include "dynarmic/backend/x64/stack_layout.h"
|
#include "dynarmic/backend/x64/stack_layout.h"
|
||||||
|
|
||||||
namespace Dynarmic::Backend::X64 {
|
namespace Dynarmic::Backend::X64 {
|
||||||
|
|
|
@ -13,10 +13,44 @@ namespace Dynarmic::Backend::X64 {
|
||||||
|
|
||||||
enum class HostLoc {
|
enum class HostLoc {
|
||||||
// Ordering of the registers is intentional. See also: HostLocToX64.
|
// Ordering of the registers is intentional. See also: HostLocToX64.
|
||||||
RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15,
|
RAX,
|
||||||
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
|
RCX,
|
||||||
XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15,
|
RDX,
|
||||||
CF, PF, AF, ZF, SF, OF,
|
RBX,
|
||||||
|
RSP,
|
||||||
|
RBP,
|
||||||
|
RSI,
|
||||||
|
RDI,
|
||||||
|
R8,
|
||||||
|
R9,
|
||||||
|
R10,
|
||||||
|
R11,
|
||||||
|
R12,
|
||||||
|
R13,
|
||||||
|
R14,
|
||||||
|
R15,
|
||||||
|
XMM0,
|
||||||
|
XMM1,
|
||||||
|
XMM2,
|
||||||
|
XMM3,
|
||||||
|
XMM4,
|
||||||
|
XMM5,
|
||||||
|
XMM6,
|
||||||
|
XMM7,
|
||||||
|
XMM8,
|
||||||
|
XMM9,
|
||||||
|
XMM10,
|
||||||
|
XMM11,
|
||||||
|
XMM12,
|
||||||
|
XMM13,
|
||||||
|
XMM14,
|
||||||
|
XMM15,
|
||||||
|
CF,
|
||||||
|
PF,
|
||||||
|
AF,
|
||||||
|
ZF,
|
||||||
|
SF,
|
||||||
|
OF,
|
||||||
FirstSpill,
|
FirstSpill,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,7 @@ struct JitStateInfo {
|
||||||
, offsetof_rsb_codeptrs(offsetof(JitStateType, rsb_codeptrs))
|
, offsetof_rsb_codeptrs(offsetof(JitStateType, rsb_codeptrs))
|
||||||
, offsetof_cpsr_nzcv(offsetof(JitStateType, cpsr_nzcv))
|
, offsetof_cpsr_nzcv(offsetof(JitStateType, cpsr_nzcv))
|
||||||
, offsetof_fpsr_exc(offsetof(JitStateType, fpsr_exc))
|
, offsetof_fpsr_exc(offsetof(JitStateType, fpsr_exc))
|
||||||
, offsetof_fpsr_qc(offsetof(JitStateType, fpsr_qc))
|
, offsetof_fpsr_qc(offsetof(JitStateType, fpsr_qc)) {}
|
||||||
{}
|
|
||||||
|
|
||||||
const size_t offsetof_guest_MXCSR;
|
const size_t offsetof_guest_MXCSR;
|
||||||
const size_t offsetof_asimd_MXCSR;
|
const size_t offsetof_asimd_MXCSR;
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "dynarmic/common/common_types.h"
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/common/common_types.h"
|
||||||
|
|
||||||
namespace Dynarmic::Backend::X64::NZCV {
|
namespace Dynarmic::Backend::X64::NZCV {
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,12 @@
|
||||||
namespace Dynarmic::Backend::X64 {
|
namespace Dynarmic::Backend::X64 {
|
||||||
|
|
||||||
struct OpArg {
|
struct OpArg {
|
||||||
OpArg() : type(Type::Operand), inner_operand() {}
|
OpArg()
|
||||||
/* implicit */ OpArg(const Xbyak::Address& address) : type(Type::Address), inner_address(address) {}
|
: type(Type::Operand), inner_operand() {}
|
||||||
/* implicit */ OpArg(const Xbyak::Reg& reg) : type(Type::Reg), inner_reg(reg) {}
|
/* implicit */ OpArg(const Xbyak::Address& address)
|
||||||
|
: type(Type::Address), inner_address(address) {}
|
||||||
|
/* implicit */ OpArg(const Xbyak::Reg& reg)
|
||||||
|
: type(Type::Reg), inner_reg(reg) {}
|
||||||
|
|
||||||
Xbyak::Operand& operator*() {
|
Xbyak::Operand& operator*() {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
|
@ -3,20 +3,20 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/backend/x64/perf_map.h"
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/perf_map.h"
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
|
||||||
# include <cstdio>
|
# include <cstdio>
|
||||||
# include <cstdlib>
|
# include <cstdlib>
|
||||||
# include <mutex>
|
# include <mutex>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
# include <fmt/format.h>
|
# include <fmt/format.h>
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
|
||||||
# include "dynarmic/common/common_types.h"
|
# include "dynarmic/common/common_types.h"
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/backend/x64/reg_alloc.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
@ -11,7 +13,6 @@
|
||||||
#include <xbyak.h>
|
#include <xbyak.h>
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/abi.h"
|
#include "dynarmic/backend/x64/abi.h"
|
||||||
#include "dynarmic/backend/x64/reg_alloc.h"
|
|
||||||
#include "dynarmic/backend/x64/stack_layout.h"
|
#include "dynarmic/backend/x64/stack_layout.h"
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
|
|
||||||
|
@ -228,8 +229,7 @@ RegAlloc::RegAlloc(BlockOfCode& code, std::vector<HostLoc> gpr_order, std::vecto
|
||||||
: gpr_order(gpr_order)
|
: gpr_order(gpr_order)
|
||||||
, xmm_order(xmm_order)
|
, xmm_order(xmm_order)
|
||||||
, hostloc_info(NonSpillHostLocCount + SpillCount)
|
, hostloc_info(NonSpillHostLocCount + SpillCount)
|
||||||
, code(code)
|
, code(code) {}
|
||||||
{}
|
|
||||||
|
|
||||||
RegAlloc::ArgumentInfo RegAlloc::GetArgumentInfo(IR::Inst* inst) {
|
RegAlloc::ArgumentInfo RegAlloc::GetArgumentInfo(IR::Inst* inst) {
|
||||||
ArgumentInfo ret = {Argument{*this}, Argument{*this}, Argument{*this}, Argument{*this}};
|
ArgumentInfo ret = {Argument{*this}, Argument{*this}, Argument{*this}, Argument{*this}};
|
||||||
|
@ -382,7 +382,8 @@ HostLoc RegAlloc::ScratchImpl(const std::vector<HostLoc>& desired_locations) {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegAlloc::HostCall(IR::Inst* result_def, std::optional<Argument::copyable_reference> arg0,
|
void RegAlloc::HostCall(IR::Inst* result_def,
|
||||||
|
std::optional<Argument::copyable_reference> arg0,
|
||||||
std::optional<Argument::copyable_reference> arg1,
|
std::optional<Argument::copyable_reference> arg1,
|
||||||
std::optional<Argument::copyable_reference> arg2,
|
std::optional<Argument::copyable_reference> arg2,
|
||||||
std::optional<Argument::copyable_reference> arg3) {
|
std::optional<Argument::copyable_reference> arg3) {
|
||||||
|
|
|
@ -85,7 +85,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RegAlloc;
|
friend class RegAlloc;
|
||||||
explicit Argument(RegAlloc& reg_alloc) : reg_alloc(reg_alloc) {}
|
explicit Argument(RegAlloc& reg_alloc)
|
||||||
|
: reg_alloc(reg_alloc) {}
|
||||||
|
|
||||||
bool allocated = false;
|
bool allocated = false;
|
||||||
RegAlloc& reg_alloc;
|
RegAlloc& reg_alloc;
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/common/assert.h"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
|
||||||
|
|
||||||
namespace Dynarmic::Common {
|
namespace Dynarmic::Common {
|
||||||
|
|
||||||
[[noreturn]] void Terminate(fmt::string_view msg, fmt::format_args args) {
|
[[noreturn]] void Terminate(fmt::string_view msg, fmt::format_args args) {
|
||||||
|
|
|
@ -219,8 +219,8 @@ constexpr T RotateRight(T value, size_t amount) {
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr u32 SwapHalves32(u32 value) {
|
constexpr u32 SwapHalves32(u32 value) {
|
||||||
return ((value & 0xFFFF0000U) >> 16) |
|
return ((value & 0xFFFF0000U) >> 16)
|
||||||
((value & 0x0000FFFFU) << 16);
|
| ((value & 0x0000FFFFU) << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr u16 SwapBytes16(u16 value) {
|
constexpr u16 SwapBytes16(u16 value) {
|
||||||
|
@ -228,21 +228,21 @@ constexpr u16 SwapBytes16(u16 value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr u32 SwapBytes32(u32 value) {
|
constexpr u32 SwapBytes32(u32 value) {
|
||||||
return ((value & 0xFF000000U) >> 24) |
|
return ((value & 0xFF000000U) >> 24)
|
||||||
((value & 0x00FF0000U) >> 8) |
|
| ((value & 0x00FF0000U) >> 8)
|
||||||
((value & 0x0000FF00U) << 8) |
|
| ((value & 0x0000FF00U) << 8)
|
||||||
((value & 0x000000FFU) << 24);
|
| ((value & 0x000000FFU) << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr u64 SwapBytes64(u64 value) {
|
constexpr u64 SwapBytes64(u64 value) {
|
||||||
return ((value & 0xFF00000000000000ULL) >> 56) |
|
return ((value & 0xFF00000000000000ULL) >> 56)
|
||||||
((value & 0x00FF000000000000ULL) >> 40) |
|
| ((value & 0x00FF000000000000ULL) >> 40)
|
||||||
((value & 0x0000FF0000000000ULL) >> 24) |
|
| ((value & 0x0000FF0000000000ULL) >> 24)
|
||||||
((value & 0x000000FF00000000ULL) >> 8) |
|
| ((value & 0x000000FF00000000ULL) >> 8)
|
||||||
((value & 0x00000000FF000000ULL) << 8) |
|
| ((value & 0x00000000FF000000ULL) << 8)
|
||||||
((value & 0x0000000000FF0000ULL) << 24) |
|
| ((value & 0x0000000000FF0000ULL) << 24)
|
||||||
((value & 0x000000000000FF00ULL) << 40) |
|
| ((value & 0x000000000000FF00ULL) << 40)
|
||||||
((value & 0x00000000000000FFULL) << 56);
|
| ((value & 0x00000000000000FFULL) << 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Dynarmic::Common
|
} // namespace Dynarmic::Common
|
||||||
|
|
|
@ -3,18 +3,19 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/common/crypto/aes.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/common/crypto/aes.h"
|
|
||||||
|
|
||||||
namespace Dynarmic::Common::Crypto::AES {
|
namespace Dynarmic::Common::Crypto::AES {
|
||||||
|
|
||||||
using SubstitutionTable = std::array<u8, 256>;
|
using SubstitutionTable = std::array<u8, 256>;
|
||||||
|
|
||||||
// See section 5.1.1 Figure 7 in FIPS 197
|
// See section 5.1.1 Figure 7 in FIPS 197
|
||||||
constexpr SubstitutionTable substitution_box{{
|
constexpr SubstitutionTable substitution_box{
|
||||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
{// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||||
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
|
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
|
||||||
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
|
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
|
||||||
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
|
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
|
||||||
|
@ -30,12 +31,11 @@ constexpr SubstitutionTable substitution_box{{
|
||||||
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
|
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
|
||||||
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
|
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
|
||||||
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
|
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
|
||||||
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
|
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16}};
|
||||||
}};
|
|
||||||
|
|
||||||
// See section 5.3.2 Figure 14 in FIPS 197
|
// See section 5.3.2 Figure 14 in FIPS 197
|
||||||
constexpr SubstitutionTable inverse_substitution_box{{
|
constexpr SubstitutionTable inverse_substitution_box{
|
||||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
{// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||||
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
|
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
|
||||||
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
|
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
|
||||||
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
|
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
|
||||||
|
@ -51,8 +51,7 @@ constexpr SubstitutionTable inverse_substitution_box{{
|
||||||
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
|
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
|
||||||
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
|
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
|
||||||
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
|
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
|
||||||
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
|
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D}};
|
||||||
}};
|
|
||||||
|
|
||||||
// See section 4.2.1 in FIPS 197.
|
// See section 4.2.1 in FIPS 197.
|
||||||
static constexpr u8 xtime(u8 x) {
|
static constexpr u8 xtime(u8 x) {
|
||||||
|
@ -61,11 +60,11 @@ static constexpr u8 xtime(u8 x) {
|
||||||
|
|
||||||
// Galois Field multiplication.
|
// Galois Field multiplication.
|
||||||
static constexpr u8 Multiply(u8 x, u8 y) {
|
static constexpr u8 Multiply(u8 x, u8 y) {
|
||||||
return static_cast<u8>(((y & 1) * x) ^
|
return static_cast<u8>(((y & 1) * x)
|
||||||
((y >> 1 & 1) * xtime(x)) ^
|
^ ((y >> 1 & 1) * xtime(x))
|
||||||
((y >> 2 & 1) * xtime(xtime(x))) ^
|
^ ((y >> 2 & 1) * xtime(xtime(x)))
|
||||||
((y >> 3 & 1) * xtime(xtime(xtime(x)))) ^
|
^ ((y >> 3 & 1) * xtime(xtime(xtime(x))))
|
||||||
((y >> 4 & 1) * xtime(xtime(xtime(xtime(x))))));
|
^ ((y >> 4 & 1) * xtime(xtime(xtime(xtime(x))))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ShiftRows(State& out_state, const State& state) {
|
static void ShiftRows(State& out_state, const State& state) {
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
|
|
||||||
namespace Dynarmic::Common::Crypto::AES {
|
namespace Dynarmic::Common::Crypto::AES {
|
||||||
|
|
|
@ -3,18 +3,19 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/common/crypto/crc32.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/common/crypto/crc32.h"
|
|
||||||
|
|
||||||
namespace Dynarmic::Common::Crypto::CRC32 {
|
namespace Dynarmic::Common::Crypto::CRC32 {
|
||||||
|
|
||||||
using CRC32Table = std::array<u32, 256>;
|
using CRC32Table = std::array<u32, 256>;
|
||||||
|
|
||||||
// CRC32 algorithm that uses polynomial 0x1EDC6F41
|
// CRC32 algorithm that uses polynomial 0x1EDC6F41
|
||||||
constexpr CRC32Table castagnoli_table{{
|
constexpr CRC32Table castagnoli_table{
|
||||||
0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
|
{0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
|
||||||
0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
|
0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
|
||||||
0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
|
0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
|
||||||
0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
|
0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
|
||||||
|
@ -77,12 +78,11 @@ constexpr CRC32Table castagnoli_table{{
|
||||||
0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
|
0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
|
||||||
0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
|
0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
|
||||||
0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
|
0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
|
||||||
0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
|
0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351}};
|
||||||
}};
|
|
||||||
|
|
||||||
// CRC32 algorithm that uses polynomial 0x04C11DB7
|
// CRC32 algorithm that uses polynomial 0x04C11DB7
|
||||||
constexpr CRC32Table iso_table{{
|
constexpr CRC32Table iso_table{
|
||||||
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
|
{0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
|
||||||
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
||||||
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
|
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
|
||||||
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
||||||
|
@ -145,8 +145,7 @@ constexpr CRC32Table iso_table{{
|
||||||
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
|
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
|
||||||
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
|
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
|
||||||
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
|
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
|
||||||
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
|
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D}};
|
||||||
}};
|
|
||||||
|
|
||||||
static u32 ComputeCRC32(const CRC32Table& table, u32 crc, const u64 value, int length) {
|
static u32 ComputeCRC32(const CRC32Table& table, u32 crc, const u64 value, int length) {
|
||||||
const auto* data = reinterpret_cast<const unsigned char*>(&value);
|
const auto* data = reinterpret_cast<const unsigned char*>(&value);
|
||||||
|
|
|
@ -3,17 +3,18 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/common/crypto/sm4.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/common/crypto/sm4.h"
|
|
||||||
|
|
||||||
namespace Dynarmic::Common::Crypto::SM4 {
|
namespace Dynarmic::Common::Crypto::SM4 {
|
||||||
|
|
||||||
using SubstitutionTable = std::array<u8, 256>;
|
using SubstitutionTable = std::array<u8, 256>;
|
||||||
|
|
||||||
constexpr SubstitutionTable substitution_box{{
|
constexpr SubstitutionTable substitution_box{
|
||||||
0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7,
|
{0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7,
|
||||||
0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05,
|
0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05,
|
||||||
0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3,
|
0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3,
|
||||||
0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
|
0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
|
||||||
|
@ -44,8 +45,7 @@ constexpr SubstitutionTable substitution_box{{
|
||||||
0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E,
|
0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E,
|
||||||
0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84,
|
0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84,
|
||||||
0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20,
|
0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20,
|
||||||
0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48
|
0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48}};
|
||||||
}};
|
|
||||||
|
|
||||||
u8 AccessSubstitutionBox(u8 index) {
|
u8 AccessSubstitutionBox(u8 index) {
|
||||||
return substitution_box[index];
|
return substitution_box[index];
|
||||||
|
|
|
@ -22,7 +22,8 @@ public:
|
||||||
FPCR() = default;
|
FPCR() = default;
|
||||||
FPCR(const FPCR&) = default;
|
FPCR(const FPCR&) = default;
|
||||||
FPCR(FPCR&&) = default;
|
FPCR(FPCR&&) = default;
|
||||||
explicit FPCR(u32 data) : value{data & mask} {}
|
explicit FPCR(u32 data)
|
||||||
|
: value{data & mask} {}
|
||||||
|
|
||||||
FPCR& operator=(const FPCR&) = default;
|
FPCR& operator=(const FPCR&) = default;
|
||||||
FPCR& operator=(FPCR&&) = default;
|
FPCR& operator=(FPCR&&) = default;
|
||||||
|
|
|
@ -18,7 +18,8 @@ public:
|
||||||
FPSR() = default;
|
FPSR() = default;
|
||||||
FPSR(const FPSR&) = default;
|
FPSR(const FPSR&) = default;
|
||||||
FPSR(FPSR&&) = default;
|
FPSR(FPSR&&) = default;
|
||||||
explicit FPSR(u32 data) : value{data & mask} {}
|
explicit FPSR(u32 data)
|
||||||
|
: value{data & mask} {}
|
||||||
|
|
||||||
FPSR& operator=(const FPSR&) = default;
|
FPSR& operator=(const FPSR&) = default;
|
||||||
FPSR& operator=(FPSR&&) = default;
|
FPSR& operator=(FPSR&&) = default;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/common/fp/fused.h"
|
#include "dynarmic/common/fp/fused.h"
|
||||||
|
|
||||||
#include "dynarmic/common/fp/mantissa_util.h"
|
#include "dynarmic/common/fp/mantissa_util.h"
|
||||||
#include "dynarmic/common/fp/unpacked.h"
|
#include "dynarmic/common/fp/unpacked.h"
|
||||||
#include "dynarmic/common/u128.h"
|
#include "dynarmic/common/u128.h"
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
#include "dynarmic/common/fp/op/FPCompare.h"
|
#include "dynarmic/common/fp/op/FPCompare.h"
|
||||||
#include "dynarmic/common/fp/op/FPConvert.h"
|
#include "dynarmic/common/fp/op/FPConvert.h"
|
||||||
#include "dynarmic/common/fp/op/FPMulAdd.h"
|
#include "dynarmic/common/fp/op/FPMulAdd.h"
|
||||||
|
#include "dynarmic/common/fp/op/FPRSqrtEstimate.h"
|
||||||
|
#include "dynarmic/common/fp/op/FPRSqrtStepFused.h"
|
||||||
#include "dynarmic/common/fp/op/FPRecipEstimate.h"
|
#include "dynarmic/common/fp/op/FPRecipEstimate.h"
|
||||||
#include "dynarmic/common/fp/op/FPRecipExponent.h"
|
#include "dynarmic/common/fp/op/FPRecipExponent.h"
|
||||||
#include "dynarmic/common/fp/op/FPRecipStepFused.h"
|
#include "dynarmic/common/fp/op/FPRecipStepFused.h"
|
||||||
#include "dynarmic/common/fp/op/FPRoundInt.h"
|
#include "dynarmic/common/fp/op/FPRoundInt.h"
|
||||||
#include "dynarmic/common/fp/op/FPRSqrtEstimate.h"
|
|
||||||
#include "dynarmic/common/fp/op/FPRSqrtStepFused.h"
|
|
||||||
#include "dynarmic/common/fp/op/FPToFixed.h"
|
#include "dynarmic/common/fp/op/FPToFixed.h"
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/common/fp/op/FPCompare.h"
|
||||||
|
|
||||||
#include "dynarmic/common/fp/fpcr.h"
|
#include "dynarmic/common/fp/fpcr.h"
|
||||||
#include "dynarmic/common/fp/fpsr.h"
|
#include "dynarmic/common/fp/fpsr.h"
|
||||||
#include "dynarmic/common/fp/op/FPCompare.h"
|
|
||||||
#include "dynarmic/common/fp/process_exception.h"
|
#include "dynarmic/common/fp/process_exception.h"
|
||||||
#include "dynarmic/common/fp/unpacked.h"
|
#include "dynarmic/common/fp/unpacked.h"
|
||||||
|
|
||||||
|
@ -20,8 +21,7 @@ bool FPCompareEQ(FPT lhs, FPT rhs, FPCR fpcr, FPSR& fpsr) {
|
||||||
const auto& value1 = std::get<FPUnpacked>(unpacked1);
|
const auto& value1 = std::get<FPUnpacked>(unpacked1);
|
||||||
const auto& value2 = std::get<FPUnpacked>(unpacked2);
|
const auto& value2 = std::get<FPUnpacked>(unpacked2);
|
||||||
|
|
||||||
if (type1 == FPType::QNaN || type1 == FPType::SNaN ||
|
if (type1 == FPType::QNaN || type1 == FPType::SNaN || type2 == FPType::QNaN || type2 == FPType::SNaN) {
|
||||||
type2 == FPType::QNaN || type2 == FPType::SNaN) {
|
|
||||||
if (type1 == FPType::SNaN || type2 == FPType::SNaN) {
|
if (type1 == FPType::SNaN || type2 == FPType::SNaN) {
|
||||||
FPProcessException(FPExc::InvalidOp, fpcr, fpsr);
|
FPProcessException(FPExc::InvalidOp, fpcr, fpsr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/common/fp/op/FPConvert.h"
|
||||||
|
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/common/fp/fpcr.h"
|
#include "dynarmic/common/fp/fpcr.h"
|
||||||
#include "dynarmic/common/fp/fpsr.h"
|
#include "dynarmic/common/fp/fpsr.h"
|
||||||
#include "dynarmic/common/fp/info.h"
|
#include "dynarmic/common/fp/info.h"
|
||||||
#include "dynarmic/common/fp/op/FPConvert.h"
|
|
||||||
#include "dynarmic/common/fp/process_exception.h"
|
#include "dynarmic/common/fp/process_exception.h"
|
||||||
#include "dynarmic/common/fp/unpacked.h"
|
#include "dynarmic/common/fp/unpacked.h"
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/common/fp/op/FPMulAdd.h"
|
||||||
|
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/common/fp/fpcr.h"
|
#include "dynarmic/common/fp/fpcr.h"
|
||||||
#include "dynarmic/common/fp/fpsr.h"
|
#include "dynarmic/common/fp/fpsr.h"
|
||||||
#include "dynarmic/common/fp/info.h"
|
|
||||||
#include "dynarmic/common/fp/fused.h"
|
#include "dynarmic/common/fp/fused.h"
|
||||||
#include "dynarmic/common/fp/op/FPMulAdd.h"
|
#include "dynarmic/common/fp/info.h"
|
||||||
#include "dynarmic/common/fp/process_exception.h"
|
#include "dynarmic/common/fp/process_exception.h"
|
||||||
#include "dynarmic/common/fp/process_nan.h"
|
#include "dynarmic/common/fp/process_nan.h"
|
||||||
#include "dynarmic/common/fp/unpacked.h"
|
#include "dynarmic/common/fp/unpacked.h"
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/common/fp/op/FPRSqrtEstimate.h"
|
||||||
|
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/common/fp/fpcr.h"
|
#include "dynarmic/common/fp/fpcr.h"
|
||||||
#include "dynarmic/common/fp/fpsr.h"
|
#include "dynarmic/common/fp/fpsr.h"
|
||||||
#include "dynarmic/common/fp/info.h"
|
#include "dynarmic/common/fp/info.h"
|
||||||
#include "dynarmic/common/fp/op/FPRSqrtEstimate.h"
|
|
||||||
#include "dynarmic/common/fp/process_exception.h"
|
#include "dynarmic/common/fp/process_exception.h"
|
||||||
#include "dynarmic/common/fp/process_nan.h"
|
#include "dynarmic/common/fp/process_nan.h"
|
||||||
#include "dynarmic/common/fp/unpacked.h"
|
#include "dynarmic/common/fp/unpacked.h"
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/common/fp/op/FPRSqrtStepFused.h"
|
||||||
|
|
||||||
#include "dynarmic/common/fp/fpcr.h"
|
#include "dynarmic/common/fp/fpcr.h"
|
||||||
#include "dynarmic/common/fp/fpsr.h"
|
#include "dynarmic/common/fp/fpsr.h"
|
||||||
#include "dynarmic/common/fp/fused.h"
|
#include "dynarmic/common/fp/fused.h"
|
||||||
#include "dynarmic/common/fp/info.h"
|
#include "dynarmic/common/fp/info.h"
|
||||||
#include "dynarmic/common/fp/op/FPNeg.h"
|
#include "dynarmic/common/fp/op/FPNeg.h"
|
||||||
#include "dynarmic/common/fp/op/FPRSqrtStepFused.h"
|
|
||||||
#include "dynarmic/common/fp/process_nan.h"
|
#include "dynarmic/common/fp/process_nan.h"
|
||||||
#include "dynarmic/common/fp/unpacked.h"
|
#include "dynarmic/common/fp/unpacked.h"
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/common/fp/op/FPRecipEstimate.h"
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
|
@ -10,7 +12,6 @@
|
||||||
#include "dynarmic/common/fp/fpcr.h"
|
#include "dynarmic/common/fp/fpcr.h"
|
||||||
#include "dynarmic/common/fp/fpsr.h"
|
#include "dynarmic/common/fp/fpsr.h"
|
||||||
#include "dynarmic/common/fp/info.h"
|
#include "dynarmic/common/fp/info.h"
|
||||||
#include "dynarmic/common/fp/op/FPRecipEstimate.h"
|
|
||||||
#include "dynarmic/common/fp/process_exception.h"
|
#include "dynarmic/common/fp/process_exception.h"
|
||||||
#include "dynarmic/common/fp/process_nan.h"
|
#include "dynarmic/common/fp/process_nan.h"
|
||||||
#include "dynarmic/common/fp/unpacked.h"
|
#include "dynarmic/common/fp/unpacked.h"
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/fp/op/FPRecipExponent.h"
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/common/fp/fpcr.h"
|
#include "dynarmic/common/fp/fpcr.h"
|
||||||
#include "dynarmic/common/fp/fpsr.h"
|
#include "dynarmic/common/fp/fpsr.h"
|
||||||
#include "dynarmic/common/fp/info.h"
|
#include "dynarmic/common/fp/info.h"
|
||||||
#include "dynarmic/common/fp/op/FPRecipExponent.h"
|
|
||||||
#include "dynarmic/common/fp/process_nan.h"
|
#include "dynarmic/common/fp/process_nan.h"
|
||||||
#include "dynarmic/common/fp/unpacked.h"
|
#include "dynarmic/common/fp/unpacked.h"
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/common/fp/op/FPRecipStepFused.h"
|
||||||
|
|
||||||
#include "dynarmic/common/fp/fpcr.h"
|
#include "dynarmic/common/fp/fpcr.h"
|
||||||
#include "dynarmic/common/fp/fpsr.h"
|
#include "dynarmic/common/fp/fpsr.h"
|
||||||
#include "dynarmic/common/fp/fused.h"
|
#include "dynarmic/common/fp/fused.h"
|
||||||
#include "dynarmic/common/fp/info.h"
|
#include "dynarmic/common/fp/info.h"
|
||||||
#include "dynarmic/common/fp/op/FPNeg.h"
|
#include "dynarmic/common/fp/op/FPNeg.h"
|
||||||
#include "dynarmic/common/fp/op/FPRecipStepFused.h"
|
|
||||||
#include "dynarmic/common/fp/process_nan.h"
|
#include "dynarmic/common/fp/process_nan.h"
|
||||||
#include "dynarmic/common/fp/unpacked.h"
|
#include "dynarmic/common/fp/unpacked.h"
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/common/fp/op/FPRoundInt.h"
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
|
@ -10,7 +12,6 @@
|
||||||
#include "dynarmic/common/fp/fpsr.h"
|
#include "dynarmic/common/fp/fpsr.h"
|
||||||
#include "dynarmic/common/fp/info.h"
|
#include "dynarmic/common/fp/info.h"
|
||||||
#include "dynarmic/common/fp/mantissa_util.h"
|
#include "dynarmic/common/fp/mantissa_util.h"
|
||||||
#include "dynarmic/common/fp/op/FPRoundInt.h"
|
|
||||||
#include "dynarmic/common/fp/process_exception.h"
|
#include "dynarmic/common/fp/process_exception.h"
|
||||||
#include "dynarmic/common/fp/process_nan.h"
|
#include "dynarmic/common/fp/process_nan.h"
|
||||||
#include "dynarmic/common/fp/rounding_mode.h"
|
#include "dynarmic/common/fp/rounding_mode.h"
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/common/fp/op/FPToFixed.h"
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/common/fp/fpcr.h"
|
#include "dynarmic/common/fp/fpcr.h"
|
||||||
#include "dynarmic/common/fp/fpsr.h"
|
#include "dynarmic/common/fp/fpsr.h"
|
||||||
#include "dynarmic/common/fp/mantissa_util.h"
|
#include "dynarmic/common/fp/mantissa_util.h"
|
||||||
#include "dynarmic/common/fp/op/FPToFixed.h"
|
|
||||||
#include "dynarmic/common/fp/process_exception.h"
|
#include "dynarmic/common/fp/process_exception.h"
|
||||||
#include "dynarmic/common/fp/rounding_mode.h"
|
#include "dynarmic/common/fp/rounding_mode.h"
|
||||||
#include "dynarmic/common/fp/unpacked.h"
|
#include "dynarmic/common/fp/unpacked.h"
|
||||||
|
|
|
@ -3,10 +3,11 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/common/fp/process_exception.h"
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/fp/fpcr.h"
|
#include "dynarmic/common/fp/fpcr.h"
|
||||||
#include "dynarmic/common/fp/fpsr.h"
|
#include "dynarmic/common/fp/fpsr.h"
|
||||||
#include "dynarmic/common/fp/process_exception.h"
|
|
||||||
|
|
||||||
namespace Dynarmic::FP {
|
namespace Dynarmic::FP {
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/common/fp/process_nan.h"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
|
@ -11,7 +13,6 @@
|
||||||
#include "dynarmic/common/fp/fpsr.h"
|
#include "dynarmic/common/fp/fpsr.h"
|
||||||
#include "dynarmic/common/fp/info.h"
|
#include "dynarmic/common/fp/info.h"
|
||||||
#include "dynarmic/common/fp/process_exception.h"
|
#include "dynarmic/common/fp/process_exception.h"
|
||||||
#include "dynarmic/common/fp/process_nan.h"
|
|
||||||
#include "dynarmic/common/fp/unpacked.h"
|
#include "dynarmic/common/fp/unpacked.h"
|
||||||
|
|
||||||
namespace Dynarmic::FP {
|
namespace Dynarmic::FP {
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/common/fp/unpacked.h"
|
||||||
|
|
||||||
#include "dynarmic/common/fp/fpsr.h"
|
#include "dynarmic/common/fp/fpsr.h"
|
||||||
#include "dynarmic/common/fp/info.h"
|
#include "dynarmic/common/fp/info.h"
|
||||||
#include "dynarmic/common/fp/mantissa_util.h"
|
#include "dynarmic/common/fp/mantissa_util.h"
|
||||||
#include "dynarmic/common/fp/process_exception.h"
|
#include "dynarmic/common/fp/process_exception.h"
|
||||||
#include "dynarmic/common/fp/rounding_mode.h"
|
#include "dynarmic/common/fp/rounding_mode.h"
|
||||||
#include "dynarmic/common/fp/unpacked.h"
|
|
||||||
#include "dynarmic/common/safe_ops.h"
|
#include "dynarmic/common/safe_ops.h"
|
||||||
|
|
||||||
namespace Dynarmic::FP {
|
namespace Dynarmic::FP {
|
||||||
|
|
|
@ -14,8 +14,10 @@
|
||||||
|
|
||||||
namespace Dynarmic::Common {
|
namespace Dynarmic::Common {
|
||||||
|
|
||||||
template <typename T> class IntrusiveList;
|
template<typename T>
|
||||||
template <typename T> class IntrusiveListIterator;
|
class IntrusiveList;
|
||||||
|
template<typename T>
|
||||||
|
class IntrusiveListIterator;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class IntrusiveListNode {
|
class IntrusiveListNode {
|
||||||
|
@ -35,8 +37,7 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class IntrusiveListSentinel final : public IntrusiveListNode<T>
|
class IntrusiveListSentinel final : public IntrusiveListNode<T> {
|
||||||
{
|
|
||||||
using IntrusiveListNode<T>::next;
|
using IntrusiveListNode<T>::next;
|
||||||
using IntrusiveListNode<T>::prev;
|
using IntrusiveListNode<T>::prev;
|
||||||
using IntrusiveListNode<T>::is_sentinel;
|
using IntrusiveListNode<T>::is_sentinel;
|
||||||
|
@ -71,11 +72,14 @@ public:
|
||||||
IntrusiveListIterator(const IntrusiveListIterator& other) = default;
|
IntrusiveListIterator(const IntrusiveListIterator& other) = default;
|
||||||
IntrusiveListIterator& operator=(const IntrusiveListIterator& other) = default;
|
IntrusiveListIterator& operator=(const IntrusiveListIterator& other) = default;
|
||||||
|
|
||||||
explicit IntrusiveListIterator(node_pointer list_node) : node(list_node) {
|
explicit IntrusiveListIterator(node_pointer list_node)
|
||||||
|
: node(list_node) {
|
||||||
}
|
}
|
||||||
explicit IntrusiveListIterator(pointer data) : node(data) {
|
explicit IntrusiveListIterator(pointer data)
|
||||||
|
: node(data) {
|
||||||
}
|
}
|
||||||
explicit IntrusiveListIterator(reference data) : node(&data) {
|
explicit IntrusiveListIterator(reference data)
|
||||||
|
: node(&data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
IntrusiveListIterator& operator++() {
|
IntrusiveListIterator& operator++() {
|
||||||
|
|
|
@ -79,8 +79,10 @@ std::string DisassembleAArch32([[maybe_unused]] bool is_thumb, [[maybe_unused]]
|
||||||
result += inst_size > 0 ? buffer : "<invalid instruction>";
|
result += inst_size > 0 ? buffer : "<invalid instruction>";
|
||||||
result += '\n';
|
result += '\n';
|
||||||
|
|
||||||
if (inst_size == 0) inst_size = is_thumb ? 2 : 4;
|
if (inst_size == 0)
|
||||||
if (length <= inst_size) break;
|
inst_size = is_thumb ? 2 : 4;
|
||||||
|
if (length <= inst_size)
|
||||||
|
break;
|
||||||
|
|
||||||
pc += inst_size;
|
pc += inst_size;
|
||||||
instructions += inst_size;
|
instructions += inst_size;
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include "dynarmic/common/math_util.h"
|
#include "dynarmic/common/math_util.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace Dynarmic::Common {
|
namespace Dynarmic::Common {
|
||||||
|
|
||||||
u8 RecipEstimate(u64 a) {
|
u8 RecipEstimate(u64 a) {
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
#include "dynarmic/common/memory_pool.h"
|
#include "dynarmic/common/memory_pool.h"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
namespace Dynarmic::Common {
|
namespace Dynarmic::Common {
|
||||||
|
|
||||||
Pool::Pool(size_t object_size, size_t initial_pool_size) : object_size(object_size), slab_size(initial_pool_size) {
|
Pool::Pool(size_t object_size, size_t initial_pool_size)
|
||||||
|
: object_size(object_size), slab_size(initial_pool_size) {
|
||||||
AllocateNewSlab();
|
AllocateNewSlab();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,10 +13,14 @@
|
||||||
|
|
||||||
namespace Dynarmic::Safe {
|
namespace Dynarmic::Safe {
|
||||||
|
|
||||||
template<typename T> T LogicalShiftLeft(T value, int shift_amount);
|
template<typename T>
|
||||||
template<typename T> T LogicalShiftRight(T value, int shift_amount);
|
T LogicalShiftLeft(T value, int shift_amount);
|
||||||
template<typename T> T ArithmeticShiftLeft(T value, int shift_amount);
|
template<typename T>
|
||||||
template<typename T> T ArithmeticShiftRight(T value, int shift_amount);
|
T LogicalShiftRight(T value, int shift_amount);
|
||||||
|
template<typename T>
|
||||||
|
T ArithmeticShiftLeft(T value, int shift_amount);
|
||||||
|
template<typename T>
|
||||||
|
T ArithmeticShiftRight(T value, int shift_amount);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T LogicalShiftLeft(T value, int shift_amount) {
|
T LogicalShiftLeft(T value, int shift_amount) {
|
||||||
|
|
|
@ -20,10 +20,12 @@ struct ScopeSuccessTag {};
|
||||||
template<typename Function>
|
template<typename Function>
|
||||||
class ScopeExit final {
|
class ScopeExit final {
|
||||||
public:
|
public:
|
||||||
explicit ScopeExit(Function&& fn) : function(std::move(fn)) {}
|
explicit ScopeExit(Function&& fn)
|
||||||
|
: function(std::move(fn)) {}
|
||||||
~ScopeExit() noexcept {
|
~ScopeExit() noexcept {
|
||||||
function();
|
function();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Function function;
|
Function function;
|
||||||
};
|
};
|
||||||
|
@ -31,12 +33,14 @@ private:
|
||||||
template<typename Function>
|
template<typename Function>
|
||||||
class ScopeFail final {
|
class ScopeFail final {
|
||||||
public:
|
public:
|
||||||
explicit ScopeFail(Function&& fn) : function(std::move(fn)), exception_count(std::uncaught_exceptions()) {}
|
explicit ScopeFail(Function&& fn)
|
||||||
|
: function(std::move(fn)), exception_count(std::uncaught_exceptions()) {}
|
||||||
~ScopeFail() noexcept {
|
~ScopeFail() noexcept {
|
||||||
if (std::uncaught_exceptions() > exception_count) {
|
if (std::uncaught_exceptions() > exception_count) {
|
||||||
function();
|
function();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Function function;
|
Function function;
|
||||||
int exception_count;
|
int exception_count;
|
||||||
|
@ -45,12 +49,14 @@ private:
|
||||||
template<typename Function>
|
template<typename Function>
|
||||||
class ScopeSuccess final {
|
class ScopeSuccess final {
|
||||||
public:
|
public:
|
||||||
explicit ScopeSuccess(Function&& fn) : function(std::move(fn)), exception_count(std::uncaught_exceptions()) {}
|
explicit ScopeSuccess(Function&& fn)
|
||||||
|
: function(std::move(fn)), exception_count(std::uncaught_exceptions()) {}
|
||||||
~ScopeSuccess() {
|
~ScopeSuccess() {
|
||||||
if (std::uncaught_exceptions() <= exception_count) {
|
if (std::uncaught_exceptions() <= exception_count) {
|
||||||
function();
|
function();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Function function;
|
Function function;
|
||||||
int exception_count;
|
int exception_count;
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/common/common_types.h"
|
|
||||||
#include "dynarmic/common/u128.h"
|
#include "dynarmic/common/u128.h"
|
||||||
|
|
||||||
|
#include "dynarmic/common/common_types.h"
|
||||||
|
|
||||||
namespace Dynarmic {
|
namespace Dynarmic {
|
||||||
|
|
||||||
u128 Multiply64To128(u64 a, u64 b) {
|
u128 Multiply64To128(u64 a, u64 b) {
|
||||||
|
|
|
@ -20,10 +20,12 @@ struct u128 {
|
||||||
u128& operator=(const u128&) = default;
|
u128& operator=(const u128&) = default;
|
||||||
u128& operator=(u128&&) = default;
|
u128& operator=(u128&&) = default;
|
||||||
|
|
||||||
u128(u64 lower_, u64 upper_) : lower(lower_), upper(upper_) {}
|
u128(u64 lower_, u64 upper_)
|
||||||
|
: lower(lower_), upper(upper_) {}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
/* implicit */ u128(T value) : lower(value), upper(0) {
|
/* implicit */ u128(T value)
|
||||||
|
: lower(value), upper(0) {
|
||||||
static_assert(std::is_integral_v<T>);
|
static_assert(std::is_integral_v<T>);
|
||||||
static_assert(Common::BitSize<T>() <= Common::BitSize<u64>());
|
static_assert(Common::BitSize<T>() <= Common::BitSize<u64>());
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,10 @@ namespace Dynarmic::Common {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<typename ReturnT, typename Lambda>
|
template<typename ReturnT, typename Lambda>
|
||||||
struct VariantVisitor : boost::static_visitor<ReturnT>, Lambda {
|
struct VariantVisitor : boost::static_visitor<ReturnT>
|
||||||
|
, Lambda {
|
||||||
VariantVisitor(Lambda&& lambda)
|
VariantVisitor(Lambda&& lambda)
|
||||||
: Lambda(std::move(lambda))
|
: Lambda(std::move(lambda)) {}
|
||||||
{}
|
|
||||||
|
|
||||||
using Lambda::operator();
|
using Lambda::operator();
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,13 +16,13 @@ namespace Dynarmic::A32 {
|
||||||
/**
|
/**
|
||||||
* Representation of the Floating-Point Status and Control Register.
|
* Representation of the Floating-Point Status and Control Register.
|
||||||
*/
|
*/
|
||||||
class FPSCR final
|
class FPSCR final {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
FPSCR() = default;
|
FPSCR() = default;
|
||||||
FPSCR(const FPSCR&) = default;
|
FPSCR(const FPSCR&) = default;
|
||||||
FPSCR(FPSCR&&) = default;
|
FPSCR(FPSCR&&) = default;
|
||||||
explicit FPSCR(u32 data) : value{data & mask} {}
|
explicit FPSCR(u32 data)
|
||||||
|
: value{data & mask} {}
|
||||||
|
|
||||||
FPSCR& operator=(const FPSCR&) = default;
|
FPSCR& operator=(const FPSCR&) = default;
|
||||||
FPSCR& operator=(FPSCR&&) = default;
|
FPSCR& operator=(FPSCR&&) = default;
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "dynarmic/common/common_types.h"
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/ir/cond.h"
|
#include "dynarmic/ir/cond.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
@ -14,7 +14,8 @@ namespace Dynarmic::A32 {
|
||||||
class ITState final {
|
class ITState final {
|
||||||
public:
|
public:
|
||||||
ITState() = default;
|
ITState() = default;
|
||||||
explicit ITState(u8 data) : value(data) {}
|
explicit ITState(u8 data)
|
||||||
|
: value(data) {}
|
||||||
|
|
||||||
ITState& operator=(u8 data) {
|
ITState& operator=(u8 data) {
|
||||||
value = data;
|
value = data;
|
||||||
|
|
|
@ -56,7 +56,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
PSR() = default;
|
PSR() = default;
|
||||||
explicit PSR(u32 data) : value{data & mask} {}
|
explicit PSR(u32 data)
|
||||||
|
: value{data & mask} {}
|
||||||
|
|
||||||
PSR& operator=(u32 data) {
|
PSR& operator=(u32 data) {
|
||||||
value = data & mask;
|
value = data & mask;
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/frontend/decoder/decoder_detail.h"
|
#include "dynarmic/frontend/decoder/decoder_detail.h"
|
||||||
#include "dynarmic/frontend/decoder/matcher.h"
|
#include "dynarmic/frontend/decoder/matcher.h"
|
||||||
|
|
|
@ -11,11 +11,11 @@
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/common/string_util.h"
|
#include "dynarmic/common/string_util.h"
|
||||||
#include "dynarmic/frontend/imm.h"
|
|
||||||
#include "dynarmic/frontend/A32/decoder/arm.h"
|
#include "dynarmic/frontend/A32/decoder/arm.h"
|
||||||
#include "dynarmic/frontend/A32/decoder/vfp.h"
|
#include "dynarmic/frontend/A32/decoder/vfp.h"
|
||||||
#include "dynarmic/frontend/A32/disassembler/disassembler.h"
|
#include "dynarmic/frontend/A32/disassembler/disassembler.h"
|
||||||
#include "dynarmic/frontend/A32/types.h"
|
#include "dynarmic/frontend/A32/types.h"
|
||||||
|
#include "dynarmic/frontend/imm.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
@ -30,16 +30,20 @@ public:
|
||||||
static std::string ShiftStr(ShiftType shift, Imm<5> imm5) {
|
static std::string ShiftStr(ShiftType shift, Imm<5> imm5) {
|
||||||
switch (shift) {
|
switch (shift) {
|
||||||
case ShiftType::LSL:
|
case ShiftType::LSL:
|
||||||
if (imm5 == 0) return "";
|
if (imm5 == 0)
|
||||||
|
return "";
|
||||||
return fmt::format(", lsl #{}", imm5.ZeroExtend());
|
return fmt::format(", lsl #{}", imm5.ZeroExtend());
|
||||||
case ShiftType::LSR:
|
case ShiftType::LSR:
|
||||||
if (imm5 == 0) return ", lsr #32";
|
if (imm5 == 0)
|
||||||
|
return ", lsr #32";
|
||||||
return fmt::format(", lsr #{}", imm5.ZeroExtend());
|
return fmt::format(", lsr #{}", imm5.ZeroExtend());
|
||||||
case ShiftType::ASR:
|
case ShiftType::ASR:
|
||||||
if (imm5 == 0) return ", asr #32";
|
if (imm5 == 0)
|
||||||
|
return ", asr #32";
|
||||||
return fmt::format(", asr #{}", imm5.ZeroExtend());
|
return fmt::format(", asr #{}", imm5.ZeroExtend());
|
||||||
case ShiftType::ROR:
|
case ShiftType::ROR:
|
||||||
if (imm5 == 0) return ", rrx";
|
if (imm5 == 0)
|
||||||
|
return ", rrx";
|
||||||
return fmt::format(", ror #{}", imm5.ZeroExtend());
|
return fmt::format(", ror #{}", imm5.ZeroExtend());
|
||||||
}
|
}
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
|
@ -234,14 +238,20 @@ public:
|
||||||
// CRC32 instructions
|
// CRC32 instructions
|
||||||
std::string arm_CRC32([[maybe_unused]] Cond cond, Imm<2> sz, Reg n, Reg d, Reg m) {
|
std::string arm_CRC32([[maybe_unused]] Cond cond, Imm<2> sz, Reg n, Reg d, Reg m) {
|
||||||
static constexpr std::array data_type{
|
static constexpr std::array data_type{
|
||||||
"b", "h", "w", "invalid",
|
"b",
|
||||||
|
"h",
|
||||||
|
"w",
|
||||||
|
"invalid",
|
||||||
};
|
};
|
||||||
|
|
||||||
return fmt::format("crc32{} {}, {}, {}", data_type[sz.ZeroExtend()], d, n, m);
|
return fmt::format("crc32{} {}, {}, {}", data_type[sz.ZeroExtend()], d, n, m);
|
||||||
}
|
}
|
||||||
std::string arm_CRC32C([[maybe_unused]] Cond cond, Imm<2> sz, Reg n, Reg d, Reg m) {
|
std::string arm_CRC32C([[maybe_unused]] Cond cond, Imm<2> sz, Reg n, Reg d, Reg m) {
|
||||||
static constexpr std::array data_type{
|
static constexpr std::array data_type{
|
||||||
"b", "h", "w", "invalid",
|
"b",
|
||||||
|
"h",
|
||||||
|
"w",
|
||||||
|
"invalid",
|
||||||
};
|
};
|
||||||
|
|
||||||
return fmt::format("crc32c{} {}, {}, {}", data_type[sz.ZeroExtend()], d, n, m);
|
return fmt::format("crc32c{} {}, {}, {}", data_type[sz.ZeroExtend()], d, n, m);
|
||||||
|
|
|
@ -11,10 +11,10 @@
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/common/string_util.h"
|
#include "dynarmic/common/string_util.h"
|
||||||
#include "dynarmic/frontend/imm.h"
|
|
||||||
#include "dynarmic/frontend/A32/decoder/thumb16.h"
|
#include "dynarmic/frontend/A32/decoder/thumb16.h"
|
||||||
#include "dynarmic/frontend/A32/disassembler/disassembler.h"
|
#include "dynarmic/frontend/A32/disassembler/disassembler.h"
|
||||||
#include "dynarmic/frontend/A32/types.h"
|
#include "dynarmic/frontend/A32/types.h"
|
||||||
|
#include "dynarmic/frontend/imm.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
@ -305,12 +305,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_PUSH(bool M, RegList reg_list) {
|
std::string thumb16_PUSH(bool M, RegList reg_list) {
|
||||||
if (M) reg_list |= 1 << 14;
|
if (M)
|
||||||
|
reg_list |= 1 << 14;
|
||||||
return fmt::format("push {{{}}}", RegListToString(reg_list));
|
return fmt::format("push {{{}}}", RegListToString(reg_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb16_POP(bool P, RegList reg_list) {
|
std::string thumb16_POP(bool P, RegList reg_list) {
|
||||||
if (P) reg_list |= 1 << 15;
|
if (P)
|
||||||
|
reg_list |= 1 << 15;
|
||||||
return fmt::format("pop {{{}}}", RegListToString(reg_list));
|
return fmt::format("pop {{{}}}", RegListToString(reg_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
|
||||||
#include "dynarmic/frontend/A32/ir_emitter.h"
|
#include "dynarmic/frontend/A32/ir_emitter.h"
|
||||||
|
|
||||||
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/frontend/A32/types.h"
|
#include "dynarmic/frontend/A32/types.h"
|
||||||
#include "dynarmic/interface/A32/arch_version.h"
|
#include "dynarmic/interface/A32/arch_version.h"
|
||||||
#include "dynarmic/ir/opcodes.h"
|
#include "dynarmic/ir/opcodes.h"
|
||||||
|
|
|
@ -27,7 +27,8 @@ enum class Reg;
|
||||||
*/
|
*/
|
||||||
class IREmitter : public IR::IREmitter {
|
class IREmitter : public IR::IREmitter {
|
||||||
public:
|
public:
|
||||||
IREmitter(IR::Block& block, LocationDescriptor descriptor, ArchVersion arch_version) : IR::IREmitter(block), current_location(descriptor), arch_version(arch_version) {}
|
IREmitter(IR::Block& block, LocationDescriptor descriptor, ArchVersion arch_version)
|
||||||
|
: IR::IREmitter(block), current_location(descriptor), arch_version(arch_version) {}
|
||||||
|
|
||||||
LocationDescriptor current_location;
|
LocationDescriptor current_location;
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ostream>
|
|
||||||
#include <fmt/format.h>
|
|
||||||
#include "dynarmic/frontend/A32/location_descriptor.h"
|
#include "dynarmic/frontend/A32/location_descriptor.h"
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& o, const LocationDescriptor& descriptor) {
|
std::ostream& operator<<(std::ostream& o, const LocationDescriptor& descriptor) {
|
||||||
|
|
|
@ -8,10 +8,11 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/frontend/A32/FPSCR.h"
|
#include "dynarmic/frontend/A32/FPSCR.h"
|
||||||
#include "dynarmic/frontend/A32/PSR.h"
|
|
||||||
#include "dynarmic/frontend/A32/ITState.h"
|
#include "dynarmic/frontend/A32/ITState.h"
|
||||||
|
#include "dynarmic/frontend/A32/PSR.h"
|
||||||
#include "dynarmic/ir/location_descriptor.h"
|
#include "dynarmic/ir/location_descriptor.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
@ -32,8 +33,7 @@ public:
|
||||||
: arm_pc(arm_pc)
|
: arm_pc(arm_pc)
|
||||||
, cpsr(cpsr.Value() & CPSR_MODE_MASK)
|
, cpsr(cpsr.Value() & CPSR_MODE_MASK)
|
||||||
, fpscr(fpscr.Value() & FPSCR_MODE_MASK)
|
, fpscr(fpscr.Value() & FPSCR_MODE_MASK)
|
||||||
, single_stepping(single_stepping)
|
, single_stepping(single_stepping) {}
|
||||||
{}
|
|
||||||
|
|
||||||
explicit LocationDescriptor(const IR::LocationDescriptor& o) {
|
explicit LocationDescriptor(const IR::LocationDescriptor& o) {
|
||||||
arm_pc = static_cast<u32>(o.Value());
|
arm_pc = static_cast<u32>(o.Value());
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/frontend/A32/translate/conditional_state.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/frontend/A32/ir_emitter.h"
|
#include "dynarmic/frontend/A32/ir_emitter.h"
|
||||||
#include "dynarmic/frontend/A32/translate/conditional_state.h"
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
#include "dynarmic/interface/A32/config.h"
|
#include "dynarmic/interface/A32/config.h"
|
||||||
#include "dynarmic/ir/cond.h"
|
#include "dynarmic/ir/cond.h"
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ std::optional<std::tuple<size_t, size_t, size_t>> DecodeType(Imm<4> type, size_t
|
||||||
}
|
}
|
||||||
ASSERT_FALSE("Decode error");
|
ASSERT_FALSE("Decode error");
|
||||||
}
|
}
|
||||||
} // anoynmous namespace
|
} // namespace
|
||||||
|
|
||||||
bool TranslatorVisitor::v8_VST_multiple(bool D, Reg n, size_t Vd, Imm<4> type, size_t size, size_t align, Reg m) {
|
bool TranslatorVisitor::v8_VST_multiple(bool D, Reg n, size_t Vd, Imm<4> type, size_t size, size_t align, Reg m) {
|
||||||
if (type == 0b1011 || type.Bits<2, 3>() == 0b11) {
|
if (type == 0b1011 || type.Bits<2, 3>() == 0b11) {
|
||||||
|
|
|
@ -3,10 +3,9 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,15 +3,13 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
bool TranslatorVisitor::asimd_VMOV_imm(Imm<1> a, bool D, Imm<1> b, Imm<1> c, Imm<1> d, size_t Vd,
|
bool TranslatorVisitor::asimd_VMOV_imm(Imm<1> a, bool D, Imm<1> b, Imm<1> c, Imm<1> d, size_t Vd, Imm<4> cmode, bool Q, bool op, Imm<1> e, Imm<1> f, Imm<1> g, Imm<1> h) {
|
||||||
Imm<4> cmode, bool Q, bool op, Imm<1> e, Imm<1> f, Imm<1> g, Imm<1> h) {
|
|
||||||
if (Q && Common::Bit<0>(Vd)) {
|
if (Q && Common::Bit<0>(Vd)) {
|
||||||
return UndefinedInstruction();
|
return UndefinedInstruction();
|
||||||
}
|
}
|
||||||
|
@ -68,27 +66,42 @@ bool TranslatorVisitor::asimd_VMOV_imm(Imm<1> a, bool D, Imm<1> b, Imm<1> c, Imm
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (concatenate(cmode, Imm<1>{op}).ZeroExtend()) {
|
switch (concatenate(cmode, Imm<1>{op}).ZeroExtend()) {
|
||||||
case 0b00000: case 0b00100:
|
case 0b00000:
|
||||||
case 0b01000: case 0b01100:
|
case 0b00100:
|
||||||
case 0b10000: case 0b10100:
|
case 0b01000:
|
||||||
case 0b11000: case 0b11010:
|
case 0b01100:
|
||||||
case 0b11100: case 0b11101:
|
case 0b10000:
|
||||||
|
case 0b10100:
|
||||||
|
case 0b11000:
|
||||||
|
case 0b11010:
|
||||||
|
case 0b11100:
|
||||||
|
case 0b11101:
|
||||||
case 0b11110:
|
case 0b11110:
|
||||||
return mov();
|
return mov();
|
||||||
case 0b11111:
|
case 0b11111:
|
||||||
return UndefinedInstruction();
|
return UndefinedInstruction();
|
||||||
case 0b00001: case 0b00101:
|
case 0b00001:
|
||||||
case 0b01001: case 0b01101:
|
case 0b00101:
|
||||||
case 0b10001: case 0b10101:
|
case 0b01001:
|
||||||
case 0b11001: case 0b11011:
|
case 0b01101:
|
||||||
|
case 0b10001:
|
||||||
|
case 0b10101:
|
||||||
|
case 0b11001:
|
||||||
|
case 0b11011:
|
||||||
return mvn();
|
return mvn();
|
||||||
case 0b00010: case 0b00110:
|
case 0b00010:
|
||||||
case 0b01010: case 0b01110:
|
case 0b00110:
|
||||||
case 0b10010: case 0b10110:
|
case 0b01010:
|
||||||
|
case 0b01110:
|
||||||
|
case 0b10010:
|
||||||
|
case 0b10110:
|
||||||
return orr();
|
return orr();
|
||||||
case 0b00011: case 0b00111:
|
case 0b00011:
|
||||||
case 0b01011: case 0b01111:
|
case 0b00111:
|
||||||
case 0b10011: case 0b10111:
|
case 0b01011:
|
||||||
|
case 0b01111:
|
||||||
|
case 0b10011:
|
||||||
|
case 0b10111:
|
||||||
return bic();
|
return bic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -76,8 +75,7 @@ bool FloatingPointInstruction(TranslatorVisitor& v, bool D, bool sz, size_t Vn,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IntegerComparison(TranslatorVisitor& v, bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm,
|
bool IntegerComparison(TranslatorVisitor& v, bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm, Comparison comparison) {
|
||||||
Comparison comparison) {
|
|
||||||
if (sz == 0b11) {
|
if (sz == 0b11) {
|
||||||
return v.UndefinedInstruction();
|
return v.UndefinedInstruction();
|
||||||
}
|
}
|
||||||
|
@ -112,8 +110,7 @@ bool IntegerComparison(TranslatorVisitor& v, bool U, bool D, size_t sz, size_t V
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FloatComparison(TranslatorVisitor& v, bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm,
|
bool FloatComparison(TranslatorVisitor& v, bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm, Comparison comparison) {
|
||||||
Comparison comparison) {
|
|
||||||
if (sz) {
|
if (sz) {
|
||||||
return v.UndefinedInstruction();
|
return v.UndefinedInstruction();
|
||||||
}
|
}
|
||||||
|
@ -149,8 +146,7 @@ bool FloatComparison(TranslatorVisitor& v, bool D, bool sz, size_t Vn, size_t Vd
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AbsoluteDifference(TranslatorVisitor& v, bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm,
|
bool AbsoluteDifference(TranslatorVisitor& v, bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm, AccumulateBehavior accumulate) {
|
||||||
AccumulateBehavior accumulate) {
|
|
||||||
if (sz == 0b11) {
|
if (sz == 0b11) {
|
||||||
return v.UndefinedInstruction();
|
return v.UndefinedInstruction();
|
||||||
}
|
}
|
||||||
|
@ -182,8 +178,7 @@ bool AbsoluteDifference(TranslatorVisitor& v, bool U, bool D, size_t sz, size_t
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AbsoluteDifferenceLong(TranslatorVisitor& v, bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool M, size_t Vm,
|
bool AbsoluteDifferenceLong(TranslatorVisitor& v, bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool M, size_t Vm, AccumulateBehavior accumulate) {
|
||||||
AccumulateBehavior accumulate) {
|
|
||||||
if (sz == 0b11) {
|
if (sz == 0b11) {
|
||||||
return v.DecodeError();
|
return v.DecodeError();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,10 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -19,8 +18,7 @@ enum class Comparison {
|
||||||
LT,
|
LT,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool CompareWithZero(TranslatorVisitor& v, bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm,
|
bool CompareWithZero(TranslatorVisitor& v, bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm, Comparison type) {
|
||||||
Comparison type) {
|
|
||||||
if (sz == 0b11 || (F && sz != 0b10)) {
|
if (sz == 0b11 || (F && sz != 0b10)) {
|
||||||
return v.UndefinedInstruction();
|
return v.UndefinedInstruction();
|
||||||
}
|
}
|
||||||
|
@ -73,8 +71,7 @@ enum class AccumulateBehavior {
|
||||||
Accumulate,
|
Accumulate,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool PairedAddOperation(TranslatorVisitor& v, bool D, size_t sz, size_t Vd, bool op, bool Q, bool M, size_t Vm,
|
bool PairedAddOperation(TranslatorVisitor& v, bool D, size_t sz, size_t Vd, bool op, bool Q, bool M, size_t Vm, AccumulateBehavior accumulate) {
|
||||||
AccumulateBehavior accumulate) {
|
|
||||||
if (sz == 0b11) {
|
if (sz == 0b11) {
|
||||||
return v.UndefinedInstruction();
|
return v.UndefinedInstruction();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,11 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -29,8 +28,7 @@ enum class Rounding {
|
||||||
Round,
|
Round,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ScalarMultiply(TranslatorVisitor& v, bool Q, bool D, size_t sz, size_t Vn, size_t Vd, bool F, bool N, bool M, size_t Vm,
|
bool ScalarMultiply(TranslatorVisitor& v, bool Q, bool D, size_t sz, size_t Vn, size_t Vd, bool F, bool N, bool M, size_t Vm, MultiplyBehavior multiply) {
|
||||||
MultiplyBehavior multiply) {
|
|
||||||
if (sz == 0b11) {
|
if (sz == 0b11) {
|
||||||
return v.DecodeError();
|
return v.DecodeError();
|
||||||
}
|
}
|
||||||
|
@ -72,8 +70,7 @@ bool ScalarMultiply(TranslatorVisitor& v, bool Q, bool D, size_t sz, size_t Vn,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScalarMultiplyLong(TranslatorVisitor& v, bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool M, size_t Vm,
|
bool ScalarMultiplyLong(TranslatorVisitor& v, bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool M, size_t Vm, MultiplyBehavior multiply) {
|
||||||
MultiplyBehavior multiply) {
|
|
||||||
if (sz == 0b11) {
|
if (sz == 0b11) {
|
||||||
return v.DecodeError();
|
return v.DecodeError();
|
||||||
}
|
}
|
||||||
|
@ -110,8 +107,7 @@ bool ScalarMultiplyLong(TranslatorVisitor& v, bool U, bool D, size_t sz, size_t
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScalarMultiplyReturnHigh(TranslatorVisitor& v, bool Q, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool M, size_t Vm,
|
bool ScalarMultiplyReturnHigh(TranslatorVisitor& v, bool Q, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool M, size_t Vm, Rounding round) {
|
||||||
Rounding round) {
|
|
||||||
if (sz == 0b11) {
|
if (sz == 0b11) {
|
||||||
return v.DecodeError();
|
return v.DecodeError();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,9 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -57,8 +56,7 @@ std::pair<size_t, size_t> ElementSizeAndShiftAmount(bool right_shift, bool L, si
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShiftRight(TranslatorVisitor& v, bool U, bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm,
|
bool ShiftRight(TranslatorVisitor& v, bool U, bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm, Accumulating accumulate, Rounding rounding) {
|
||||||
Accumulating accumulate, Rounding rounding) {
|
|
||||||
if (!L && Common::Bits<3, 5>(imm6) == 0) {
|
if (!L && Common::Bits<3, 5>(imm6) == 0) {
|
||||||
return v.DecodeError();
|
return v.DecodeError();
|
||||||
}
|
}
|
||||||
|
@ -89,8 +87,7 @@ bool ShiftRight(TranslatorVisitor& v, bool U, bool D, size_t imm6, size_t Vd, bo
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShiftRightNarrowing(TranslatorVisitor& v, bool D, size_t imm6, size_t Vd, bool M, size_t Vm,
|
bool ShiftRightNarrowing(TranslatorVisitor& v, bool D, size_t imm6, size_t Vd, bool M, size_t Vm, Rounding rounding, Narrowing narrowing, Signedness signedness) {
|
||||||
Rounding rounding, Narrowing narrowing, Signedness signedness) {
|
|
||||||
if (Common::Bits<3, 5>(imm6) == 0) {
|
if (Common::Bits<3, 5>(imm6) == 0) {
|
||||||
return v.DecodeError();
|
return v.DecodeError();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,7 @@ namespace Dynarmic::A32 {
|
||||||
namespace {
|
namespace {
|
||||||
using DivideFunction = IR::U32U64 (IREmitter::*)(const IR::U32U64&, const IR::U32U64&);
|
using DivideFunction = IR::U32U64 (IREmitter::*)(const IR::U32U64&, const IR::U32U64&);
|
||||||
|
|
||||||
bool DivideOperation(TranslatorVisitor& v, Cond cond, Reg d, Reg m, Reg n,
|
bool DivideOperation(TranslatorVisitor& v, Cond cond, Reg d, Reg m, Reg n, DivideFunction fn) {
|
||||||
DivideFunction fn) {
|
|
||||||
if (d == Reg::PC || m == Reg::PC || n == Reg::PC) {
|
if (d == Reg::PC || m == Reg::PC || n == Reg::PC) {
|
||||||
return v.UnpredictableInstruction();
|
return v.UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
#include "dynarmic/interface/A32/config.h"
|
#include "dynarmic/interface/A32/config.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
#include "dynarmic/interface/A32/config.h"
|
#include "dynarmic/interface/A32/config.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,6 @@ bool TranslatorVisitor::arm_MUL(Cond cond, bool S, Reg d, Reg m, Reg n) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// SMLAL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
|
// SMLAL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
|
||||||
bool TranslatorVisitor::arm_SMLAL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n) {
|
bool TranslatorVisitor::arm_SMLAL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n) {
|
||||||
if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) {
|
if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) {
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
#include "dynarmic/interface/A32/config.h"
|
#include "dynarmic/interface/A32/config.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
|
@ -3,10 +3,9 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
static IR::U32 Pack2x16To1x32(A32::IREmitter& ir, IR::U32 lo, IR::U32 hi) {
|
static IR::U32 Pack2x16To1x32(A32::IREmitter& ir, IR::U32 lo, IR::U32 hi) {
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
#include "dynarmic/interface/A32/config.h"
|
#include "dynarmic/interface/A32/config.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
@ -28,8 +27,7 @@ static bool PLIHandler(TranslatorVisitor& v) {
|
||||||
|
|
||||||
using ExtensionFunction = IR::U32 (IREmitter::*)(const IR::U8&);
|
using ExtensionFunction = IR::U32 (IREmitter::*)(const IR::U8&);
|
||||||
|
|
||||||
static bool LoadByteLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12,
|
static bool LoadByteLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12, ExtensionFunction ext_fn) {
|
||||||
ExtensionFunction ext_fn) {
|
|
||||||
const u32 imm32 = imm12.ZeroExtend();
|
const u32 imm32 = imm12.ZeroExtend();
|
||||||
const u32 base = v.ir.AlignPC(4);
|
const u32 base = v.ir.AlignPC(4);
|
||||||
const u32 address = U ? (base + imm32) : (base - imm32);
|
const u32 address = U ? (base + imm32) : (base - imm32);
|
||||||
|
@ -39,8 +37,7 @@ static bool LoadByteLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool LoadByteRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Reg m,
|
static bool LoadByteRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Reg m, ExtensionFunction ext_fn) {
|
||||||
ExtensionFunction ext_fn) {
|
|
||||||
if (m == Reg::PC) {
|
if (m == Reg::PC) {
|
||||||
return v.UnpredictableInstruction();
|
return v.UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -55,8 +52,7 @@ static bool LoadByteRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Re
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool LoadByteImmediate(TranslatorVisitor& v, Reg n, Reg t, bool P, bool U, bool W, Imm<12> imm12,
|
static bool LoadByteImmediate(TranslatorVisitor& v, Reg n, Reg t, bool P, bool U, bool W, Imm<12> imm12, ExtensionFunction ext_fn) {
|
||||||
ExtensionFunction ext_fn) {
|
|
||||||
const u32 imm32 = imm12.ZeroExtend();
|
const u32 imm32 = imm12.ZeroExtend();
|
||||||
const IR::U32 reg_n = v.ir.GetRegister(n);
|
const IR::U32 reg_n = v.ir.GetRegister(n);
|
||||||
const IR::U32 offset_address = U ? v.ir.Add(reg_n, v.ir.Imm32(imm32))
|
const IR::U32 offset_address = U ? v.ir.Add(reg_n, v.ir.Imm32(imm32))
|
||||||
|
|
|
@ -9,8 +9,7 @@ namespace Dynarmic::A32 {
|
||||||
|
|
||||||
using ExtensionFunction = IR::U32 (IREmitter::*)(const IR::U16&);
|
using ExtensionFunction = IR::U32 (IREmitter::*)(const IR::U16&);
|
||||||
|
|
||||||
static bool LoadHalfLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12,
|
static bool LoadHalfLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12, ExtensionFunction ext_fn) {
|
||||||
ExtensionFunction ext_fn) {
|
|
||||||
const auto imm32 = imm12.ZeroExtend();
|
const auto imm32 = imm12.ZeroExtend();
|
||||||
const auto base = v.ir.AlignPC(4);
|
const auto base = v.ir.AlignPC(4);
|
||||||
const auto address = U ? (base + imm32) : (base - imm32);
|
const auto address = U ? (base + imm32) : (base - imm32);
|
||||||
|
@ -20,8 +19,7 @@ static bool LoadHalfLiteral(TranslatorVisitor& v, bool U, Reg t, Imm<12> imm12,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool LoadHalfRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Reg m,
|
static bool LoadHalfRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Reg m, ExtensionFunction ext_fn) {
|
||||||
ExtensionFunction ext_fn) {
|
|
||||||
if (m == Reg::PC) {
|
if (m == Reg::PC) {
|
||||||
return v.UnpredictableInstruction();
|
return v.UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
@ -36,8 +34,7 @@ static bool LoadHalfRegister(TranslatorVisitor& v, Reg n, Reg t, Imm<2> imm2, Re
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool LoadHalfImmediate(TranslatorVisitor& v, Reg n, Reg t, bool P, bool U, bool W,
|
static bool LoadHalfImmediate(TranslatorVisitor& v, Reg n, Reg t, bool P, bool U, bool W, Imm<12> imm12, ExtensionFunction ext_fn) {
|
||||||
Imm<12> imm12, ExtensionFunction ext_fn) {
|
|
||||||
const u32 imm32 = imm12.ZeroExtend();
|
const u32 imm32 = imm12.ZeroExtend();
|
||||||
const IR::U32 reg_n = v.ir.GetRegister(n);
|
const IR::U32 reg_n = v.ir.GetRegister(n);
|
||||||
const IR::U32 offset_address = U ? v.ir.Add(reg_n, v.ir.Imm32(imm32))
|
const IR::U32 offset_address = U ? v.ir.Add(reg_n, v.ir.Imm32(imm32))
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
static bool ITBlockCheck(const A32::IREmitter& ir) {
|
static bool ITBlockCheck(const A32::IREmitter& ir) {
|
||||||
|
@ -40,8 +39,7 @@ static bool TableBranch(TranslatorVisitor& v, Reg n, Reg m, bool half) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool LoadDualImmediate(TranslatorVisitor& v, bool P, bool U, bool W,
|
static bool LoadDualImmediate(TranslatorVisitor& v, bool P, bool U, bool W, Reg n, Reg t, Reg t2, Imm<8> imm8) {
|
||||||
Reg n, Reg t, Reg t2, Imm<8> imm8) {
|
|
||||||
if (W && (n == t || n == t2)) {
|
if (W && (n == t || n == t2)) {
|
||||||
return v.UnpredictableInstruction();
|
return v.UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,15 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
static bool ITBlockCheck(const A32::IREmitter& ir) {
|
static bool ITBlockCheck(const A32::IREmitter& ir) {
|
||||||
return ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock();
|
return ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, u32 list,
|
static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, u32 list, const IR::U32& start_address, const IR::U32& writeback_address) {
|
||||||
const IR::U32& start_address, const IR::U32& writeback_address) {
|
|
||||||
auto address = start_address;
|
auto address = start_address;
|
||||||
for (size_t i = 0; i <= 14; i++) {
|
for (size_t i = 0; i <= 14; i++) {
|
||||||
if (Common::Bit(i, list)) {
|
if (Common::Bit(i, list)) {
|
||||||
|
@ -37,8 +35,7 @@ static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, u32 list,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool STMHelper(A32::IREmitter& ir, bool W, Reg n, u32 list,
|
static bool STMHelper(A32::IREmitter& ir, bool W, Reg n, u32 list, const IR::U32& start_address, const IR::U32& writeback_address) {
|
||||||
const IR::U32& start_address, const IR::U32& writeback_address) {
|
|
||||||
auto address = start_address;
|
auto address = start_address;
|
||||||
for (size_t i = 0; i <= 14; i++) {
|
for (size_t i = 0; i <= 14; i++) {
|
||||||
if (Common::Bit(i, list)) {
|
if (Common::Bit(i, list)) {
|
||||||
|
|
|
@ -43,8 +43,7 @@ static void StoreImmWordFn(TranslatorVisitor& v, const IR::U32& address, const I
|
||||||
v.ir.WriteMemory32(address, data);
|
v.ir.WriteMemory32(address, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool StoreImmediate(TranslatorVisitor& v, Reg n, Reg t, bool P, bool U, bool W, Imm<12> imm12,
|
static bool StoreImmediate(TranslatorVisitor& v, Reg n, Reg t, bool P, bool U, bool W, Imm<12> imm12, StoreImmFn store_fn) {
|
||||||
StoreImmFn store_fn) {
|
|
||||||
const auto imm32 = imm12.ZeroExtend();
|
const auto imm32 = imm12.ZeroExtend();
|
||||||
const auto reg_n = v.ir.GetRegister(n);
|
const auto reg_n = v.ir.GetRegister(n);
|
||||||
const auto reg_t = v.ir.GetRegister(t);
|
const auto reg_t = v.ir.GetRegister(t);
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/frontend/imm.h"
|
|
||||||
#include "dynarmic/frontend/A32/ir_emitter.h"
|
#include "dynarmic/frontend/A32/ir_emitter.h"
|
||||||
#include "dynarmic/frontend/A32/location_descriptor.h"
|
#include "dynarmic/frontend/A32/location_descriptor.h"
|
||||||
#include "dynarmic/frontend/A32/translate/conditional_state.h"
|
#include "dynarmic/frontend/A32/translate/conditional_state.h"
|
||||||
#include "dynarmic/frontend/A32/translate/translate.h"
|
#include "dynarmic/frontend/A32/translate/translate.h"
|
||||||
#include "dynarmic/frontend/A32/types.h"
|
#include "dynarmic/frontend/A32/types.h"
|
||||||
|
#include "dynarmic/frontend/imm.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
@ -22,8 +22,7 @@ struct TranslatorVisitor final {
|
||||||
using instruction_return_type = bool;
|
using instruction_return_type = bool;
|
||||||
|
|
||||||
explicit TranslatorVisitor(IR::Block& block, LocationDescriptor descriptor, const TranslationOptions& options)
|
explicit TranslatorVisitor(IR::Block& block, LocationDescriptor descriptor, const TranslationOptions& options)
|
||||||
: ir(block, descriptor, options.arch_version), options(options)
|
: ir(block, descriptor, options.arch_version), options(options) {}
|
||||||
{}
|
|
||||||
|
|
||||||
A32::IREmitter ir;
|
A32::IREmitter ir;
|
||||||
ConditionalState cond_state = ConditionalState::None;
|
ConditionalState cond_state = ConditionalState::None;
|
||||||
|
@ -93,8 +92,10 @@ struct TranslatorVisitor final {
|
||||||
IR::ResultAndCarry<IR::U32> EmitImmShift(IR::U32 value, ShiftType type, Imm<3> imm3, Imm<2> imm2, IR::U1 carry_in);
|
IR::ResultAndCarry<IR::U32> EmitImmShift(IR::U32 value, ShiftType type, Imm<3> imm3, Imm<2> imm2, IR::U1 carry_in);
|
||||||
IR::ResultAndCarry<IR::U32> EmitImmShift(IR::U32 value, ShiftType type, Imm<5> imm5, IR::U1 carry_in);
|
IR::ResultAndCarry<IR::U32> EmitImmShift(IR::U32 value, ShiftType type, Imm<5> imm5, IR::U1 carry_in);
|
||||||
IR::ResultAndCarry<IR::U32> EmitRegShift(IR::U32 value, ShiftType type, IR::U8 amount, IR::U1 carry_in);
|
IR::ResultAndCarry<IR::U32> EmitRegShift(IR::U32 value, ShiftType type, IR::U8 amount, IR::U1 carry_in);
|
||||||
template <typename FnT> bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg n, ExtReg m, const FnT& fn);
|
template<typename FnT>
|
||||||
template <typename FnT> bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg m, const FnT& fn);
|
bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg n, ExtReg m, const FnT& fn);
|
||||||
|
template<typename FnT>
|
||||||
|
bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg m, const FnT& fn);
|
||||||
|
|
||||||
// Barrier instructions
|
// Barrier instructions
|
||||||
bool arm_DMB(Imm<4> option);
|
bool arm_DMB(Imm<4> option);
|
||||||
|
@ -821,8 +822,7 @@ struct TranslatorVisitor final {
|
||||||
bool vfp_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8);
|
bool vfp_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8);
|
||||||
|
|
||||||
// Advanced SIMD one register, modified immediate
|
// Advanced SIMD one register, modified immediate
|
||||||
bool asimd_VMOV_imm(Imm<1> a, bool D, Imm<1> b, Imm<1> c, Imm<1> d, size_t Vd,
|
bool asimd_VMOV_imm(Imm<1> a, bool D, Imm<1> b, Imm<1> c, Imm<1> d, size_t Vd, Imm<4> cmode, bool Q, bool op, Imm<1> e, Imm<1> f, Imm<1> g, Imm<1> h);
|
||||||
Imm<4> cmode, bool Q, bool op, Imm<1> e, Imm<1> f, Imm<1> g, Imm<1> h);
|
|
||||||
|
|
||||||
// Advanced SIMD three register with same length
|
// Advanced SIMD three register with same length
|
||||||
bool asimd_VHADD(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
bool asimd_VHADD(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
template<typename FnT>
|
template<typename FnT>
|
||||||
|
@ -1230,7 +1230,8 @@ bool TranslatorVisitor::vfp_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm<8>
|
||||||
const auto reg_d = ir.GetExtendedRegister(d + i);
|
const auto reg_d = ir.GetExtendedRegister(d + i);
|
||||||
auto lo = ir.LeastSignificantWord(reg_d);
|
auto lo = ir.LeastSignificantWord(reg_d);
|
||||||
auto hi = ir.MostSignificantWord(reg_d).result;
|
auto hi = ir.MostSignificantWord(reg_d).result;
|
||||||
if (ir.current_location.EFlag()) std::swap(lo, hi);
|
if (ir.current_location.EFlag())
|
||||||
|
std::swap(lo, hi);
|
||||||
ir.WriteMemory32(address, lo);
|
ir.WriteMemory32(address, lo);
|
||||||
address = ir.Add(address, ir.Imm32(4));
|
address = ir.Add(address, ir.Imm32(4));
|
||||||
ir.WriteMemory32(address, hi);
|
ir.WriteMemory32(address, hi);
|
||||||
|
|
|
@ -16,8 +16,6 @@ namespace Dynarmic::A32 {
|
||||||
class LocationDescriptor;
|
class LocationDescriptor;
|
||||||
struct TranslateCallbacks;
|
struct TranslateCallbacks;
|
||||||
|
|
||||||
using MemoryReadCodeFuncType = std::function<u32(u32 vaddr)>;
|
|
||||||
|
|
||||||
struct TranslationOptions {
|
struct TranslationOptions {
|
||||||
ArchVersion arch_version;
|
ArchVersion arch_version;
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,8 @@ namespace Dynarmic::A32 {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
enum class ThumbInstSize {
|
enum class ThumbInstSize {
|
||||||
Thumb16, Thumb32
|
Thumb16,
|
||||||
|
Thumb32
|
||||||
};
|
};
|
||||||
|
|
||||||
bool IsThumb16(u16 first_part) {
|
bool IsThumb16(u16 first_part) {
|
||||||
|
@ -83,7 +84,7 @@ bool MaybeVFPOrASIMDInstruction(u32 thumb_instruction) {
|
||||||
return (thumb_instruction & 0xEC000000) == 0xEC000000 || (thumb_instruction & 0xFF100000) == 0xF9000000;
|
return (thumb_instruction & 0xEC000000) == 0xEC000000 || (thumb_instruction & 0xFF100000) == 0xF9000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // local namespace
|
} // namespace
|
||||||
|
|
||||||
IR::Block TranslateThumb(LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options) {
|
IR::Block TranslateThumb(LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options) {
|
||||||
const bool single_step = descriptor.SingleStepping();
|
const bool single_step = descriptor.SingleStepping();
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue