clang-format
This commit is contained in:
parent
d459cb6f59
commit
1f302f397f
@ -4,21 +4,21 @@
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#include "dynarmic/backend/A64/a32_emit_a64.h"
|
||||
|
||||
#include <iterator>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
#include <dynarmic/interface/A32/coprocessor.h>
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ostream.h>
|
||||
#include <mcl/assert.hpp>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include <mcl/stdint.hpp>
|
||||
#include <mcl/scope_exit.hpp>
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
#include <dynarmic/interface/A32/coprocessor.h>
|
||||
|
||||
#include "dynarmic/backend/A64/a32_emit_a64.h"
|
||||
#include "dynarmic/backend/A64/a32_jitstate.h"
|
||||
#include "dynarmic/backend/A64/abi.h"
|
||||
#include "dynarmic/backend/A64/block_of_code.h"
|
||||
@ -56,7 +56,8 @@ static size_t MJitStateExtReg(A32::ExtReg reg) {
|
||||
ASSERT_FALSE("Should never happen.");
|
||||
}
|
||||
|
||||
A32EmitContext::A32EmitContext(RegAlloc& reg_alloc, IR::Block& block) : EmitContext(reg_alloc, block) {}
|
||||
A32EmitContext::A32EmitContext(RegAlloc& reg_alloc, IR::Block& block)
|
||||
: EmitContext(reg_alloc, block) {}
|
||||
|
||||
A32::LocationDescriptor A32EmitContext::Location() const {
|
||||
return A32::LocationDescriptor{block.Location()};
|
||||
@ -121,7 +122,6 @@ A32EmitA64::BlockDescriptor A32EmitA64::Emit(IR::Block& block) {
|
||||
|
||||
// Call the relevant Emit* member function.
|
||||
switch (inst->GetOpcode()) {
|
||||
|
||||
#define OPCODE(name, type, ...) \
|
||||
case IR::Opcode::name: \
|
||||
A32EmitA64::Emit##name(ctx, inst); \
|
||||
@ -359,7 +359,6 @@ void A32EmitA64::GenTerminalHandlers() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void A32EmitA64::EmitA32GetRegister(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
A32::Reg reg = inst->GetArg(0).GetA32RegRef();
|
||||
|
||||
@ -418,8 +417,7 @@ void A32EmitA64::EmitA32SetExtendedRegister64(A32EmitContext& ctx, IR::Inst* ins
|
||||
if (args[1].IsInFpr()) {
|
||||
ARM64Reg to_store = ctx.reg_alloc.UseFpr(args[1]);
|
||||
code.fp_emitter.STR(64, INDEX_UNSIGNED, to_store, X28, MJitStateExtReg(reg));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ARM64Reg to_store = ctx.reg_alloc.UseGpr(args[1]);
|
||||
code.STR(INDEX_UNSIGNED, to_store, X28, MJitStateExtReg(reg));
|
||||
}
|
||||
@ -858,7 +856,6 @@ void A32EmitA64::ReadMemory(A32EmitContext& ctx, IR::Inst* inst, const CodePtr c
|
||||
code.MOV(result, code.ABI_RETURN);
|
||||
};
|
||||
|
||||
|
||||
if (ShouldFastmem(do_not_fastmem_marker)) {
|
||||
const CodePtr patch_location = code.GetCodePtr();
|
||||
switch (bit_size) {
|
||||
@ -904,8 +901,7 @@ void A32EmitA64::ReadMemory(A32EmitContext& ctx, IR::Inst* inst, const CodePtr c
|
||||
code.SwitchToNearCode();
|
||||
|
||||
DoNotFastmem(do_not_fastmem_marker);
|
||||
}
|
||||
});
|
||||
}});
|
||||
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
return;
|
||||
@ -957,7 +953,8 @@ void A32EmitA64::WriteMemory(A32EmitContext& ctx, IR::Inst* inst, const CodePtr
|
||||
code.STRH(DecodeReg(value), addr, vaddr);
|
||||
break;
|
||||
case 32:
|
||||
code.STR(DecodeReg(value), addr, vaddr);;
|
||||
code.STR(DecodeReg(value), addr, vaddr);
|
||||
;
|
||||
break;
|
||||
case 64:
|
||||
code.STR(value, addr, vaddr);
|
||||
@ -1015,8 +1012,7 @@ void A32EmitA64::WriteMemory(A32EmitContext& ctx, IR::Inst* inst, const CodePtr
|
||||
code.SwitchToNearCode();
|
||||
|
||||
DoNotFastmem(do_not_fastmem_marker);
|
||||
}
|
||||
});
|
||||
}});
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1112,8 +1108,7 @@ static void EmitCoprocessorException() {
|
||||
ASSERT_FALSE("Should raise coproc exception here");
|
||||
}
|
||||
|
||||
static void CallCoprocCallback(BlockOfCode& code, RegAlloc& reg_alloc, A32::Jit* jit_interface, A32::Coprocessor::Callback callback,
|
||||
IR::Inst* inst = nullptr, std::optional<Argument::copyable_reference> arg0 = {}, std::optional<Argument::copyable_reference> arg1 = {}) {
|
||||
static void CallCoprocCallback(BlockOfCode& code, RegAlloc& reg_alloc, A32::Jit* jit_interface, A32::Coprocessor::Callback callback, IR::Inst* inst = nullptr, std::optional<Argument::copyable_reference> arg0 = {}, std::optional<Argument::copyable_reference> arg1 = {}) {
|
||||
reg_alloc.HostCall(inst, {}, {}, arg0, arg1);
|
||||
|
||||
code.MOVP2R(code.ABI_PARAM1, jit_interface);
|
||||
@ -1331,7 +1326,6 @@ void A32EmitA64::EmitA32CoprocLoadWords(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
option = coproc_info[5];
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<A32::Coprocessor> coproc = config.coprocessors[coproc_num];
|
||||
if (!coproc) {
|
||||
EmitCoprocessorException();
|
||||
@ -1376,7 +1370,6 @@ void A32EmitA64::EmitA32CoprocStoreWords(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
CallCoprocCallback(code, ctx.reg_alloc, jit_interface, *action, nullptr, args[1]);
|
||||
}
|
||||
|
||||
|
||||
std::string A32EmitA64::LocationDescriptorToFriendlyName(const IR::LocationDescriptor& ir_descriptor) const {
|
||||
const A32::LocationDescriptor descriptor{ir_descriptor};
|
||||
return fmt::format("a32_{}{:08X}_{}_fpcr{:08X}", descriptor.TFlag() ? "t" : "a", descriptor.PC(), descriptor.EFlag() ? "be" : "le",
|
||||
|
@ -17,9 +17,9 @@
|
||||
#include "dynarmic/backend/A64/block_range_information.h"
|
||||
#include "dynarmic/backend/A64/emit_a64.h"
|
||||
#include "dynarmic/backend/A64/exception_handler.h"
|
||||
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||
#include "dynarmic/interface/A32/a32.h"
|
||||
#include "dynarmic/interface/A32/config.h"
|
||||
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||
#include "dynarmic/ir/terminal.h"
|
||||
|
||||
namespace Dynarmic::BackendA64 {
|
||||
|
@ -7,13 +7,12 @@
|
||||
#include <memory>
|
||||
|
||||
#include <boost/icl/interval_set.hpp>
|
||||
#include <fmt/format.h>
|
||||
#include <mcl/assert.hpp>
|
||||
#include <mcl/stdint.hpp>
|
||||
#include <mcl/scope_exit.hpp>
|
||||
|
||||
#include <dynarmic/interface/A32/a32.h>
|
||||
#include <dynarmic/interface/A32/context.h>
|
||||
#include <fmt/format.h>
|
||||
#include <mcl/assert.hpp>
|
||||
#include <mcl/scope_exit.hpp>
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
#include "dynarmic/backend/A64/a32_emit_a64.h"
|
||||
#include "dynarmic/backend/A64/a32_jitstate.h"
|
||||
@ -21,12 +20,12 @@
|
||||
#include "dynarmic/backend/A64/callback.h"
|
||||
#include "dynarmic/backend/A64/devirtualize.h"
|
||||
#include "dynarmic/backend/A64/jitstate_info.h"
|
||||
#include "dynarmic/common/atomic.h"
|
||||
#include "dynarmic/common/llvm_disassemble.h"
|
||||
#include "dynarmic/frontend/A32/translate/a32_translate.h"
|
||||
#include "dynarmic/ir/basic_block.h"
|
||||
#include "dynarmic/ir/location_descriptor.h"
|
||||
#include "dynarmic/ir/opt/passes.h"
|
||||
#include "dynarmic/common/atomic.h"
|
||||
|
||||
namespace Dynarmic::A32 {
|
||||
|
||||
@ -46,8 +45,7 @@ struct Jit::Impl {
|
||||
: block_of_code(GenRunCodeCallbacks(config, &GetCurrentBlockThunk, this), JitStateInfo{jit_state})
|
||||
, emitter(block_of_code, config, jit)
|
||||
, config(std::move(config))
|
||||
, jit_interface(jit)
|
||||
{}
|
||||
, jit_interface(jit) {}
|
||||
|
||||
A32JitState jit_state;
|
||||
BlockOfCode block_of_code;
|
||||
@ -174,7 +172,8 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
Jit::Jit(UserConfig config) : impl(std::make_unique<Impl>(this, std::move(config))) {}
|
||||
Jit::Jit(UserConfig config)
|
||||
: impl(std::make_unique<Impl>(this, std::move(config))) {}
|
||||
|
||||
Jit::~Jit() = default;
|
||||
|
||||
@ -263,10 +262,15 @@ struct Context::Impl {
|
||||
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(const Context& ctx) : impl(std::make_unique<Context::Impl>(*ctx.impl)) {}
|
||||
Context::Context(Context&& ctx) noexcept : impl(std::move(ctx.impl)) {}
|
||||
Context::Context(const Context& ctx)
|
||||
: impl(std::make_unique<Context::Impl>(*ctx.impl)) {}
|
||||
Context::Context(Context&& ctx) noexcept
|
||||
: impl(std::move(ctx.impl)) {}
|
||||
Context& Context::operator=(const Context& ctx) {
|
||||
*impl = *ctx.impl;
|
||||
return *this;
|
||||
|
@ -4,11 +4,12 @@
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#include "dynarmic/backend/A64/a32_jitstate.h"
|
||||
|
||||
#include <mcl/assert.hpp>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
#include "dynarmic/backend/A64/a32_jitstate.h"
|
||||
#include "dynarmic/backend/A64/block_of_code.h"
|
||||
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
namespace Dynarmic::BackendA64 {
|
||||
|
@ -14,13 +14,13 @@
|
||||
|
||||
// 20th Sep 2018: This code was modified for Dynarmic.
|
||||
|
||||
#include "dynarmic/backend/A64/abi.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
#include "dynarmic/backend/A64/abi.h"
|
||||
|
||||
namespace Dynarmic::BackendA64 {
|
||||
|
||||
template<typename RegisterArrayT>
|
||||
@ -83,4 +83,4 @@ void ABI_PopCallerSaveRegistersAndAdjustStackExcept(BlockOfCode& code, HostLoc e
|
||||
ABI_PopRegistersAndAdjustStack(code, regs);
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::BackendX64
|
||||
} // namespace Dynarmic::BackendA64
|
||||
|
@ -107,4 +107,4 @@ void ABI_PopCallerSaveRegistersAndAdjustStack(BlockOfCode& code);
|
||||
void ABI_PushCallerSaveRegistersAndAdjustStackExcept(BlockOfCode& code, HostLoc exception);
|
||||
void ABI_PopCallerSaveRegistersAndAdjustStackExcept(BlockOfCode& code, HostLoc exception);
|
||||
|
||||
} // namespace Dynarmic::BackendX64
|
||||
} // namespace Dynarmic::BackendA64
|
||||
|
@ -4,6 +4,8 @@
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#include "dynarmic/backend/A64/block_of_code.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
@ -12,9 +14,8 @@
|
||||
|
||||
#include "dynarmic/backend/A64/a32_jitstate.h"
|
||||
#include "dynarmic/backend/A64/abi.h"
|
||||
#include "dynarmic/interface/halt_reason.h"
|
||||
#include "dynarmic/backend/A64/block_of_code.h"
|
||||
#include "dynarmic/backend/A64/perf_map.h"
|
||||
#include "dynarmic/interface/halt_reason.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
|
@ -14,8 +14,8 @@
|
||||
|
||||
#include "dynarmic/backend/A64/callback.h"
|
||||
#include "dynarmic/backend/A64/constant_pool.h"
|
||||
#include "dynarmic/backend/A64/jitstate_info.h"
|
||||
#include "dynarmic/backend/A64/emitter/a64_emitter.h"
|
||||
#include "dynarmic/backend/A64/jitstate_info.h"
|
||||
#include "dynarmic/interface/halt_reason.h"
|
||||
|
||||
namespace Dynarmic::BackendA64 {
|
||||
@ -34,7 +34,6 @@ public:
|
||||
BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi);
|
||||
BlockOfCode(const BlockOfCode&) = delete;
|
||||
|
||||
|
||||
/// Call when external emitters have finished emitting their preludes.
|
||||
void PreludeComplete();
|
||||
|
||||
|
@ -4,16 +4,14 @@
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#include "dynarmic/backend/A64/block_range_information.h"
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
#include <boost/icl/interval_map.hpp>
|
||||
#include <boost/icl/interval_set.hpp>
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
#include "dynarmic/backend/A64/block_range_information.h"
|
||||
|
||||
namespace Dynarmic::BackendA64 {
|
||||
|
||||
template<typename ProgramCounterType>
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "dynarmic/backend/A64/callback.h"
|
||||
|
||||
#include "dynarmic/backend/A64/block_of_code.h"
|
||||
|
||||
namespace Dynarmic::BackendA64 {
|
||||
@ -38,4 +39,4 @@ void ArgCallback::EmitCallWithReturnPointer(BlockOfCode& code, std::function<voi
|
||||
code.QuickCallFunction(fn);
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::BackendX64
|
||||
} // namespace Dynarmic::BackendA64
|
||||
|
@ -23,16 +23,19 @@ class Callback {
|
||||
public:
|
||||
virtual ~Callback();
|
||||
|
||||
virtual void EmitCall(BlockOfCode& code, std::function<void(RegList)> fn = [](RegList) {}) const = 0;
|
||||
virtual void EmitCall(
|
||||
BlockOfCode& code, std::function<void(RegList)> fn = [](RegList) {}) const = 0;
|
||||
virtual void EmitCallWithReturnPointer(BlockOfCode& code, std::function<void(Arm64Gen::ARM64Reg, RegList)> fn) const = 0;
|
||||
};
|
||||
|
||||
class SimpleCallback final : public Callback {
|
||||
public:
|
||||
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;
|
||||
void EmitCall(
|
||||
BlockOfCode& code, std::function<void(RegList)> fn = [](RegList) {}) const override;
|
||||
void EmitCallWithReturnPointer(BlockOfCode& code, std::function<void(Arm64Gen::ARM64Reg, RegList)> fn) const override;
|
||||
|
||||
private:
|
||||
@ -42,9 +45,11 @@ private:
|
||||
class ArgCallback final : public Callback {
|
||||
public:
|
||||
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;
|
||||
void EmitCall(
|
||||
BlockOfCode& code, std::function<void(RegList)> fn = [](RegList) {}) const override;
|
||||
void EmitCallWithReturnPointer(BlockOfCode& code, std::function<void(Arm64Gen::ARM64Reg, RegList)> fn) const override;
|
||||
|
||||
private:
|
||||
|
@ -4,16 +4,18 @@
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#include "dynarmic/backend/A64/constant_pool.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <mcl/assert.hpp>
|
||||
|
||||
#include "dynarmic/backend/A64/block_of_code.h"
|
||||
#include "dynarmic/backend/A64/constant_pool.h"
|
||||
|
||||
namespace Dynarmic::BackendA64 {
|
||||
|
||||
ConstantPool::ConstantPool(BlockOfCode& code) : code(code) {}
|
||||
ConstantPool::ConstantPool(BlockOfCode& code)
|
||||
: code(code) {}
|
||||
|
||||
void ConstantPool::EmitPatchLDR(Arm64Gen::ARM64Reg Rt, u64 lower, u64 upper) {
|
||||
const auto constant = std::make_tuple(lower, upper);
|
||||
|
@ -9,10 +9,10 @@
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include <mcl/type_traits/function_info.hpp>
|
||||
#include <mcl/stdint.hpp>
|
||||
#include <mcl/assert.hpp>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include <mcl/stdint.hpp>
|
||||
#include <mcl/type_traits/function_info.hpp>
|
||||
|
||||
#include "dynarmic/backend/A64/callback.h"
|
||||
|
||||
|
@ -4,16 +4,17 @@
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#include "dynarmic/backend/A64/emit_a64.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <mcl/assert.hpp>
|
||||
#include <mcl/bit/bit_field.hpp>
|
||||
#include <mcl/stdint.hpp>
|
||||
#include <mcl/scope_exit.hpp>
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
#include "dynarmic/backend/A64/block_of_code.h"
|
||||
#include "dynarmic/backend/A64/emit_a64.h"
|
||||
#include "dynarmic/backend/A64/hostloc.h"
|
||||
#include "dynarmic/backend/A64/perf_map.h"
|
||||
#include "dynarmic/backend/A64/reg_alloc.h"
|
||||
|
@ -124,4 +124,4 @@ protected:
|
||||
std::unordered_map<IR::LocationDescriptor, PatchInformation> patch_information;
|
||||
};
|
||||
|
||||
} // namespace Dynarmic::BackendX64
|
||||
} // namespace Dynarmic::BackendA64
|
||||
|
@ -8,8 +8,8 @@
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
#include "dynarmic/backend/A64/block_of_code.h"
|
||||
#include "dynarmic/backend/A64/reg_alloc.h"
|
||||
#include "dynarmic/backend/A64/emit_a64.h"
|
||||
#include "dynarmic/backend/A64/reg_alloc.h"
|
||||
#include "dynarmic/ir/basic_block.h"
|
||||
#include "dynarmic/ir/microinstruction.h"
|
||||
#include "dynarmic/ir/opcodes.h"
|
||||
@ -839,7 +839,6 @@ void EmitA64::EmitMul64(EmitContext& ctx, IR::Inst* inst) {
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
|
||||
void EmitA64::EmitUnsignedDiv32(EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
@ -880,7 +879,6 @@ void EmitA64::EmitSignedDiv64(EmitContext& ctx, IR::Inst* inst) {
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
|
||||
void EmitA64::EmitAnd32(EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
@ -905,8 +903,7 @@ void EmitA64::EmitAnd64(EmitContext& ctx, IR::Inst* inst) {
|
||||
if (args[1].IsImmediate()) {
|
||||
u32 op_arg = args[1].GetImmediateU32();
|
||||
code.ANDI2R(result, result, op_arg, ctx.reg_alloc.ScratchGpr());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Arm64Gen::ARM64Reg op_arg = ctx.reg_alloc.UseGpr(args[1]);
|
||||
code.AND(result, result, op_arg);
|
||||
}
|
||||
@ -938,8 +935,7 @@ void EmitA64::EmitEor64(EmitContext& ctx, IR::Inst* inst) {
|
||||
if (args[1].IsImmediate()) {
|
||||
u32 op_arg = args[1].GetImmediateU32();
|
||||
code.EORI2R(result, result, op_arg, ctx.reg_alloc.ScratchGpr());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Arm64Gen::ARM64Reg op_arg = ctx.reg_alloc.UseGpr(args[1]);
|
||||
code.EOR(result, result, op_arg);
|
||||
}
|
||||
@ -971,8 +967,7 @@ void EmitA64::EmitOr64(EmitContext& ctx, IR::Inst* inst) {
|
||||
if (args[1].IsImmediate()) {
|
||||
u32 op_arg = args[1].GetImmediateU32();
|
||||
code.ORRI2R(result, result, op_arg, ctx.reg_alloc.ScratchGpr());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Arm64Gen::ARM64Reg op_arg = ctx.reg_alloc.UseGpr(args[1]);
|
||||
code.ORR(result, result, op_arg);
|
||||
}
|
||||
@ -1001,8 +996,7 @@ void EmitA64::EmitNot64(EmitContext& ctx, IR::Inst* inst) {
|
||||
if (args[0].IsImmediate()) {
|
||||
result = ctx.reg_alloc.ScratchGpr();
|
||||
code.MOVI2R(result, u32(~args[0].GetImmediateU32()));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
result = ctx.reg_alloc.UseScratchGpr(args[0]);
|
||||
code.MVN(result, result);
|
||||
}
|
||||
|
@ -72,8 +72,7 @@ void FPThreeOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn)
|
||||
|
||||
if constexpr (std::is_member_function_pointer_v<Function>) {
|
||||
(code.fp_emitter.*fn)(result, result, operand);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
fn(result, result, operand);
|
||||
}
|
||||
|
||||
@ -276,13 +275,11 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
|
||||
if constexpr (unsigned_) {
|
||||
code.fp_emitter.FCVTU(result, src, round_imm);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
code.fp_emitter.FCVTS(result, src, round_imm);
|
||||
}
|
||||
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
|
||||
}
|
||||
|
||||
void EmitA64::EmitFPDoubleToFixedS32(EmitContext& ctx, IR::Inst* inst) {
|
||||
@ -328,8 +325,7 @@ void EmitA64::EmitFPFixedS32ToSingle(EmitContext& ctx, IR::Inst* inst) {
|
||||
|
||||
if (fbits != 0) {
|
||||
code.fp_emitter.SCVTF(result, from, fbits);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
code.fp_emitter.SCVTF(result, from);
|
||||
}
|
||||
|
||||
@ -347,8 +343,7 @@ void EmitA64::EmitFPFixedU32ToSingle(EmitContext& ctx, IR::Inst* inst) {
|
||||
|
||||
if (fbits != 0) {
|
||||
code.fp_emitter.UCVTF(result, from, fbits);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
code.fp_emitter.UCVTF(result, from);
|
||||
}
|
||||
|
||||
@ -366,8 +361,7 @@ void EmitA64::EmitFPFixedS32ToDouble(EmitContext& ctx, IR::Inst* inst) {
|
||||
|
||||
if (fbits != 0) {
|
||||
code.fp_emitter.SCVTF(result, from, fbits);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
code.fp_emitter.SCVTF(result, from);
|
||||
}
|
||||
|
||||
@ -385,8 +379,7 @@ void EmitA64::EmitFPFixedS64ToDouble(EmitContext& ctx, IR::Inst* inst) {
|
||||
|
||||
if (fbits != 0) {
|
||||
code.fp_emitter.SCVTF(result, from, fbits);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
code.fp_emitter.SCVTF(result, from);
|
||||
}
|
||||
|
||||
@ -404,8 +397,7 @@ void EmitA64::EmitFPFixedS64ToSingle(EmitContext& ctx, IR::Inst* inst) {
|
||||
|
||||
if (fbits != 0) {
|
||||
code.fp_emitter.SCVTF(result, from, fbits);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
code.fp_emitter.SCVTF(result, from);
|
||||
}
|
||||
|
||||
@ -423,8 +415,7 @@ void EmitA64::EmitFPFixedU32ToDouble(EmitContext& ctx, IR::Inst* inst) {
|
||||
|
||||
if (fbits != 0) {
|
||||
code.fp_emitter.UCVTF(result, from, fbits);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
code.fp_emitter.UCVTF(result, from);
|
||||
}
|
||||
|
||||
@ -434,7 +425,6 @@ void EmitA64::EmitFPFixedU32ToDouble(EmitContext& ctx, IR::Inst* inst) {
|
||||
void EmitA64::EmitFPFixedU64ToDouble(EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
|
||||
const ARM64Reg from = ctx.reg_alloc.UseGpr(args[0]);
|
||||
const ARM64Reg result = EncodeRegToDouble(ctx.reg_alloc.ScratchFpr());
|
||||
const size_t fbits = args[1].GetImmediateU8();
|
||||
@ -443,8 +433,7 @@ void EmitA64::EmitFPFixedU64ToDouble(EmitContext& ctx, IR::Inst* inst) {
|
||||
|
||||
if (fbits != 0) {
|
||||
code.fp_emitter.UCVTF(result, from, fbits);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
code.fp_emitter.UCVTF(result, from);
|
||||
}
|
||||
|
||||
@ -454,7 +443,6 @@ void EmitA64::EmitFPFixedU64ToDouble(EmitContext& ctx, IR::Inst* inst) {
|
||||
void EmitA64::EmitFPFixedU64ToSingle(EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
|
||||
const ARM64Reg from = ctx.reg_alloc.UseGpr(args[0]);
|
||||
const ARM64Reg result = EncodeRegToSingle(ctx.reg_alloc.ScratchFpr());
|
||||
const size_t fbits = args[1].GetImmediateU8();
|
||||
@ -463,8 +451,7 @@ void EmitA64::EmitFPFixedU64ToSingle(EmitContext& ctx, IR::Inst* inst) {
|
||||
|
||||
if (fbits != 0) {
|
||||
code.fp_emitter.UCVTF(result, from, fbits);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
code.fp_emitter.UCVTF(result, from);
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,7 @@ void EmitSignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst)
|
||||
|
||||
if constexpr (op == Op::Add) {
|
||||
code.fp_emitter.SQADD(size, result, result, addend);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
code.fp_emitter.SQSUB(size, result, result, addend);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "a64_emitter.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cinttypes>
|
||||
@ -9,11 +11,10 @@
|
||||
#include <vector>
|
||||
|
||||
#include <mcl/assert.hpp>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include <mcl/bit/bit_count.hpp>
|
||||
#include <mcl/bit/bit_field.hpp>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
|
||||
#include "a64_emitter.h"
|
||||
#include "dynarmic/common/math_util.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -70,8 +71,7 @@ bool IsImmArithmetic(uint64_t input, u32* val, bool* shift) {
|
||||
}
|
||||
|
||||
// For AND/TST/ORR/EOR etc
|
||||
bool IsImmLogical(uint64_t value, unsigned int width, unsigned int* n, unsigned int* imm_s,
|
||||
unsigned int* imm_r) {
|
||||
bool IsImmLogical(uint64_t value, unsigned int width, unsigned int* n, unsigned int* imm_s, unsigned int* imm_r) {
|
||||
bool negate = false;
|
||||
|
||||
// Logical immediates are encoded using parameters n, imm_s and imm_r using
|
||||
@ -211,8 +211,7 @@ bool IsImmLogical(uint64_t value, unsigned int width, unsigned int* n, unsigned
|
||||
int multiplier_idx = CountLeadingZeros(d, kXRegSizeInBits) - 57;
|
||||
|
||||
// Ensure that the index to the multipliers array is within bounds.
|
||||
DEBUG_ASSERT((multiplier_idx >= 0) &&
|
||||
(static_cast<size_t>(multiplier_idx) < multipliers.size()));
|
||||
DEBUG_ASSERT((multiplier_idx >= 0) && (static_cast<size_t>(multiplier_idx) < multipliers.size()));
|
||||
|
||||
uint64_t multiplier = multipliers[multiplier_idx];
|
||||
uint64_t candidate = (b - a) * multiplier;
|
||||
@ -284,8 +283,7 @@ bool FPImm8FromFloat(float value, u8* imm_out) {
|
||||
if ((exponent >> 7) == ((exponent >> 6) & 1))
|
||||
return false;
|
||||
|
||||
const u8 imm8 = static_cast<u8>((sign << 7) | ((!(exponent >> 7)) << 6) |
|
||||
((exponent & 3) << 4) | mantissa4);
|
||||
const u8 imm8 = static_cast<u8>((sign << 7) | ((!(exponent >> 7)) << 6) | ((exponent & 3) << 4) | mantissa4);
|
||||
const float new_float = FPImm8ToFloat(imm8);
|
||||
if (new_float == value)
|
||||
*imm_out = imm8;
|
||||
@ -384,7 +382,8 @@ void ARM64XEmitter::FlushIcacheSection(const u8* start, const u8* end) {
|
||||
static size_t icache_line_size = 0xffff, dcache_line_size = 0xffff;
|
||||
size_t isize, dsize;
|
||||
|
||||
__asm__ volatile("mrs %0, ctr_el0" : "=r"(ctr_el0));
|
||||
__asm__ volatile("mrs %0, ctr_el0"
|
||||
: "=r"(ctr_el0));
|
||||
isize = 4 << ((ctr_el0 >> 0) & 0xf);
|
||||
dsize = 4 << ((ctr_el0 >> 16) & 0xf);
|
||||
|
||||
@ -396,15 +395,30 @@ void ARM64XEmitter::FlushIcacheSection(const u8* start, const u8* end) {
|
||||
for (; addr < reinterpret_cast<u64>(end); addr += dsize)
|
||||
// use "civac" instead of "cvau", as this is the suggested workaround for
|
||||
// Cortex-A53 errata 819472, 826319, 827319 and 824069.
|
||||
__asm__ volatile("dc civac, %0" : : "r"(addr) : "memory");
|
||||
__asm__ volatile("dsb ish" : : : "memory");
|
||||
__asm__ volatile("dc civac, %0"
|
||||
:
|
||||
: "r"(addr)
|
||||
: "memory");
|
||||
__asm__ volatile("dsb ish"
|
||||
:
|
||||
:
|
||||
: "memory");
|
||||
|
||||
addr = reinterpret_cast<u64>(start) & ~static_cast<u64>(isize - 1);
|
||||
for (; addr < reinterpret_cast<u64>(end); addr += isize)
|
||||
__asm__ volatile("ic ivau, %0" : : "r"(addr) : "memory");
|
||||
__asm__ volatile("ic ivau, %0"
|
||||
:
|
||||
: "r"(addr)
|
||||
: "memory");
|
||||
|
||||
__asm__ volatile("dsb ish" : : : "memory");
|
||||
__asm__ volatile("isb" : : : "memory");
|
||||
__asm__ volatile("dsb ish"
|
||||
:
|
||||
:
|
||||
: "memory");
|
||||
__asm__ volatile("isb"
|
||||
:
|
||||
:
|
||||
: "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -535,8 +549,7 @@ void ARM64XEmitter::EncodeCompareBranchInst(u32 op, ARM64Reg Rt, const void* ptr
|
||||
"{}: Received too large distance: {:X}", __func__, distance);
|
||||
|
||||
Rt = DecodeReg(Rt);
|
||||
Write32((b64Bit << 31) | (0x34 << 24) | (op << 24) |
|
||||
((static_cast<u32>(distance) << 5) & 0xFFFFE0) | Rt);
|
||||
Write32((b64Bit << 31) | (0x34 << 24) | (op << 24) | ((static_cast<u32>(distance) << 5) & 0xFFFFE0) | Rt);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeTestBranchInst(u32 op, ARM64Reg Rt, u8 bits, const void* ptr) {
|
||||
@ -552,8 +565,7 @@ void ARM64XEmitter::EncodeTestBranchInst(u32 op, ARM64Reg Rt, u8 bits, const voi
|
||||
"{}: Received too large distance: {:X}", __func__, distance);
|
||||
|
||||
Rt = DecodeReg(Rt);
|
||||
Write32((b64Bit << 31) | (0x36 << 24) | (op << 24) | (bits << 19) |
|
||||
((static_cast<u32>(distance) << 5) & 0x7FFE0) | Rt);
|
||||
Write32((b64Bit << 31) | (0x36 << 24) | (op << 24) | (bits << 19) | ((static_cast<u32>(distance) << 5) & 0x7FFE0) | Rt);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeUnconditionalBranchInst(u32 op, const void* ptr) {
|
||||
@ -579,35 +591,29 @@ void ARM64XEmitter::EncodeExceptionInst(u32 instenc, u32 imm) {
|
||||
ASSERT_MSG(!(imm & ~0xFFFF), "{}: Exception instruction too large immediate: {}", __func__,
|
||||
imm);
|
||||
|
||||
Write32((0xD4 << 24) | (ExcEnc[instenc][0] << 21) | (imm << 5) | (ExcEnc[instenc][1] << 2) |
|
||||
ExcEnc[instenc][2]);
|
||||
Write32((0xD4 << 24) | (ExcEnc[instenc][0] << 21) | (imm << 5) | (ExcEnc[instenc][1] << 2) | ExcEnc[instenc][2]);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeSystemInst(u32 op0, u32 op1, u32 CRn, u32 CRm, u32 op2, ARM64Reg Rt) {
|
||||
Write32((0x354 << 22) | (op0 << 19) | (op1 << 16) | (CRn << 12) | (CRm << 8) | (op2 << 5) | Rt);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeArithmeticInst(u32 instenc, bool flags, ARM64Reg Rd, ARM64Reg Rn,
|
||||
ARM64Reg Rm, ArithOption Option) {
|
||||
void ARM64XEmitter::EncodeArithmeticInst(u32 instenc, bool flags, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Option) {
|
||||
bool b64Bit = Is64Bit(Rd);
|
||||
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
Rm = DecodeReg(Rm);
|
||||
Write32((b64Bit << 31) | (flags << 29) | (ArithEnc[instenc] << 21) |
|
||||
(Option.GetType() == ArithOption::TYPE_EXTENDEDREG ? (1 << 21) : 0) | (Rm << 16) |
|
||||
Option.GetData() | (Rn << 5) | Rd);
|
||||
Write32((b64Bit << 31) | (flags << 29) | (ArithEnc[instenc] << 21) | (Option.GetType() == ArithOption::TYPE_EXTENDEDREG ? (1 << 21) : 0) | (Rm << 16) | Option.GetData() | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeArithmeticCarryInst(u32 op, bool flags, ARM64Reg Rd, ARM64Reg Rn,
|
||||
ARM64Reg Rm) {
|
||||
void ARM64XEmitter::EncodeArithmeticCarryInst(u32 op, bool flags, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
|
||||
bool b64Bit = Is64Bit(Rd);
|
||||
|
||||
Rd = DecodeReg(Rd);
|
||||
Rm = DecodeReg(Rm);
|
||||
Rn = DecodeReg(Rn);
|
||||
Write32((b64Bit << 31) | (op << 30) | (flags << 29) | (0xD0 << 21) | (Rm << 16) | (Rn << 5) |
|
||||
Rd);
|
||||
Write32((b64Bit << 31) | (op << 30) | (flags << 29) | (0xD0 << 21) | (Rm << 16) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeCondCompareImmInst(u32 op, ARM64Reg Rn, u32 imm, u32 nzcv, CCFlags cond) {
|
||||
@ -617,31 +623,26 @@ void ARM64XEmitter::EncodeCondCompareImmInst(u32 op, ARM64Reg Rn, u32 imm, u32 n
|
||||
ASSERT_MSG(!(nzcv & ~0xF), "{}: Flags out of range: {}", __func__, nzcv);
|
||||
|
||||
Rn = DecodeReg(Rn);
|
||||
Write32((b64Bit << 31) | (op << 30) | (1 << 29) | (0xD2 << 21) | (imm << 16) | (cond << 12) |
|
||||
(1 << 11) | (Rn << 5) | nzcv);
|
||||
Write32((b64Bit << 31) | (op << 30) | (1 << 29) | (0xD2 << 21) | (imm << 16) | (cond << 12) | (1 << 11) | (Rn << 5) | nzcv);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeCondCompareRegInst(u32 op, ARM64Reg Rn, ARM64Reg Rm, u32 nzcv,
|
||||
CCFlags cond) {
|
||||
void ARM64XEmitter::EncodeCondCompareRegInst(u32 op, ARM64Reg Rn, ARM64Reg Rm, u32 nzcv, CCFlags cond) {
|
||||
bool b64Bit = Is64Bit(Rm);
|
||||
|
||||
ASSERT_MSG(!(nzcv & ~0xF), "{}: Flags out of range: {}", __func__, nzcv);
|
||||
|
||||
Rm = DecodeReg(Rm);
|
||||
Rn = DecodeReg(Rn);
|
||||
Write32((b64Bit << 31) | (op << 30) | (1 << 29) | (0xD2 << 21) | (Rm << 16) | (cond << 12) |
|
||||
(Rn << 5) | nzcv);
|
||||
Write32((b64Bit << 31) | (op << 30) | (1 << 29) | (0xD2 << 21) | (Rm << 16) | (cond << 12) | (Rn << 5) | nzcv);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeCondSelectInst(u32 instenc, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm,
|
||||
CCFlags cond) {
|
||||
void ARM64XEmitter::EncodeCondSelectInst(u32 instenc, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, CCFlags cond) {
|
||||
bool b64Bit = Is64Bit(Rd);
|
||||
|
||||
Rd = DecodeReg(Rd);
|
||||
Rm = DecodeReg(Rm);
|
||||
Rn = DecodeReg(Rn);
|
||||
Write32((b64Bit << 31) | (CondSelectEnc[instenc][0] << 30) | (0xD4 << 21) | (Rm << 16) |
|
||||
(cond << 12) | (CondSelectEnc[instenc][1] << 10) | (Rn << 5) | Rd);
|
||||
Write32((b64Bit << 31) | (CondSelectEnc[instenc][0] << 30) | (0xD4 << 21) | (Rm << 16) | (cond << 12) | (CondSelectEnc[instenc][1] << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeData1SrcInst(u32 instenc, ARM64Reg Rd, ARM64Reg Rn) {
|
||||
@ -649,8 +650,7 @@ void ARM64XEmitter::EncodeData1SrcInst(u32 instenc, ARM64Reg Rd, ARM64Reg Rn) {
|
||||
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
Write32((b64Bit << 31) | (0x2D6 << 21) | (Data1SrcEnc[instenc][0] << 16) |
|
||||
(Data1SrcEnc[instenc][1] << 10) | (Rn << 5) | Rd);
|
||||
Write32((b64Bit << 31) | (0x2D6 << 21) | (Data1SrcEnc[instenc][0] << 16) | (Data1SrcEnc[instenc][1] << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeData2SrcInst(u32 instenc, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
|
||||
@ -659,31 +659,26 @@ void ARM64XEmitter::EncodeData2SrcInst(u32 instenc, ARM64Reg Rd, ARM64Reg Rn, AR
|
||||
Rd = DecodeReg(Rd);
|
||||
Rm = DecodeReg(Rm);
|
||||
Rn = DecodeReg(Rn);
|
||||
Write32((b64Bit << 31) | (0x0D6 << 21) | (Rm << 16) | (Data2SrcEnc[instenc] << 10) | (Rn << 5) |
|
||||
Rd);
|
||||
Write32((b64Bit << 31) | (0x0D6 << 21) | (Rm << 16) | (Data2SrcEnc[instenc] << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeData3SrcInst(u32 instenc, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm,
|
||||
ARM64Reg Ra) {
|
||||
void ARM64XEmitter::EncodeData3SrcInst(u32 instenc, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra) {
|
||||
bool b64Bit = Is64Bit(Rd);
|
||||
|
||||
Rd = DecodeReg(Rd);
|
||||
Rm = DecodeReg(Rm);
|
||||
Rn = DecodeReg(Rn);
|
||||
Ra = DecodeReg(Ra);
|
||||
Write32((b64Bit << 31) | (0xD8 << 21) | (Data3SrcEnc[instenc][0] << 21) | (Rm << 16) |
|
||||
(Data3SrcEnc[instenc][1] << 15) | (Ra << 10) | (Rn << 5) | Rd);
|
||||
Write32((b64Bit << 31) | (0xD8 << 21) | (Data3SrcEnc[instenc][0] << 21) | (Rm << 16) | (Data3SrcEnc[instenc][1] << 15) | (Ra << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeLogicalInst(u32 instenc, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm,
|
||||
ArithOption Shift) {
|
||||
void ARM64XEmitter::EncodeLogicalInst(u32 instenc, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Shift) {
|
||||
bool b64Bit = Is64Bit(Rd);
|
||||
|
||||
Rd = DecodeReg(Rd);
|
||||
Rm = DecodeReg(Rm);
|
||||
Rn = DecodeReg(Rn);
|
||||
Write32((b64Bit << 31) | (LogicalEnc[instenc][0] << 29) | (0x5 << 25) |
|
||||
(LogicalEnc[instenc][1] << 21) | Shift.GetData() | (Rm << 16) | (Rn << 5) | Rd);
|
||||
Write32((b64Bit << 31) | (LogicalEnc[instenc][0] << 29) | (0x5 << 25) | (LogicalEnc[instenc][1] << 21) | Shift.GetData() | (Rm << 16) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeLoadRegisterInst(u32 bitop, ARM64Reg Rt, s32 imm) {
|
||||
@ -698,20 +693,15 @@ void ARM64XEmitter::EncodeLoadRegisterInst(u32 bitop, ARM64Reg Rt, s32 imm) {
|
||||
Write32((bitop << 30) | (bVec << 26) | (0x18 << 24) | (MaskImm19(imm) << 5) | Rt);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeLoadStoreExcInst(u32 instenc, ARM64Reg Rs, ARM64Reg Rt2, ARM64Reg Rn,
|
||||
ARM64Reg Rt) {
|
||||
void ARM64XEmitter::EncodeLoadStoreExcInst(u32 instenc, ARM64Reg Rs, ARM64Reg Rt2, ARM64Reg Rn, ARM64Reg Rt) {
|
||||
Rs = DecodeReg(Rs);
|
||||
Rt2 = DecodeReg(Rt2);
|
||||
Rn = DecodeReg(Rn);
|
||||
Rt = DecodeReg(Rt);
|
||||
Write32((LoadStoreExcEnc[instenc][0] << 30) | (0x8 << 24) |
|
||||
(LoadStoreExcEnc[instenc][1] << 23) | (LoadStoreExcEnc[instenc][2] << 22) |
|
||||
(LoadStoreExcEnc[instenc][3] << 21) | (Rs << 16) | (LoadStoreExcEnc[instenc][4] << 15) |
|
||||
(Rt2 << 10) | (Rn << 5) | Rt);
|
||||
Write32((LoadStoreExcEnc[instenc][0] << 30) | (0x8 << 24) | (LoadStoreExcEnc[instenc][1] << 23) | (LoadStoreExcEnc[instenc][2] << 22) | (LoadStoreExcEnc[instenc][3] << 21) | (Rs << 16) | (LoadStoreExcEnc[instenc][4] << 15) | (Rt2 << 10) | (Rn << 5) | Rt);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeLoadStorePairedInst(u32 op, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn,
|
||||
u32 imm) {
|
||||
void ARM64XEmitter::EncodeLoadStorePairedInst(u32 op, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, u32 imm) {
|
||||
bool b64Bit = Is64Bit(Rt);
|
||||
bool b128Bit = IsQuad(Rt);
|
||||
bool bVec = IsVector(Rt);
|
||||
@ -749,8 +739,7 @@ void ARM64XEmitter::EncodeLoadStoreIndexedInst(u32 op, u32 op2, ARM64Reg Rt, ARM
|
||||
|
||||
Rt = DecodeReg(Rt);
|
||||
Rn = DecodeReg(Rn);
|
||||
Write32((b64Bit << 30) | (op << 22) | (bVec << 26) | (offset << 12) | (op2 << 10) | (Rn << 5) |
|
||||
Rt);
|
||||
Write32((b64Bit << 30) | (op << 22) | (bVec << 26) | (offset << 12) | (op2 << 10) | (Rn << 5) | Rt);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeLoadStoreIndexedInst(u32 op, ARM64Reg Rt, ARM64Reg Rn, s32 imm, u8 size) {
|
||||
@ -786,36 +775,30 @@ void ARM64XEmitter::EncodeBitfieldMOVInst(u32 op, ARM64Reg Rd, ARM64Reg Rn, u32
|
||||
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
Write32((b64Bit << 31) | (op << 29) | (0x26 << 23) | (b64Bit << 22) | (immr << 16) |
|
||||
(imms << 10) | (Rn << 5) | Rd);
|
||||
Write32((b64Bit << 31) | (op << 29) | (0x26 << 23) | (b64Bit << 22) | (immr << 16) | (imms << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeLoadStoreRegisterOffset(u32 size, u32 opc, ARM64Reg Rt, ARM64Reg Rn,
|
||||
ArithOption Rm) {
|
||||
void ARM64XEmitter::EncodeLoadStoreRegisterOffset(u32 size, u32 opc, ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm) {
|
||||
ASSERT_MSG(Rm.GetType() == ArithOption::TYPE_EXTENDEDREG, "Shifted registers are not supported used Indexed registers");
|
||||
|
||||
Rt = DecodeReg(Rt);
|
||||
Rn = DecodeReg(Rn);
|
||||
ARM64Reg decoded_Rm = DecodeReg(Rm.GetReg());
|
||||
|
||||
Write32((size << 30) | (opc << 22) | (0x1C1 << 21) | (decoded_Rm << 16) | Rm.GetData() |
|
||||
(1 << 11) | (Rn << 5) | Rt);
|
||||
Write32((size << 30) | (opc << 22) | (0x1C1 << 21) | (decoded_Rm << 16) | Rm.GetData() | (1 << 11) | (Rn << 5) | Rt);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeAddSubImmInst(u32 op, bool flags, u32 shift, u32 imm, ARM64Reg Rn,
|
||||
ARM64Reg Rd) {
|
||||
void ARM64XEmitter::EncodeAddSubImmInst(u32 op, bool flags, u32 shift, u32 imm, ARM64Reg Rn, ARM64Reg Rd) {
|
||||
bool b64Bit = Is64Bit(Rd);
|
||||
|
||||
ASSERT_MSG(!(imm & ~0xFFF), "{}: immediate too large: {:X}", __func__, imm);
|
||||
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
Write32((b64Bit << 31) | (op << 30) | (flags << 29) | (0x11 << 24) | (shift << 22) |
|
||||
(imm << 10) | (Rn << 5) | Rd);
|
||||
Write32((b64Bit << 31) | (op << 30) | (flags << 29) | (0x11 << 24) | (shift << 22) | (imm << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeLogicalImmInst(u32 op, ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms,
|
||||
int n) {
|
||||
void ARM64XEmitter::EncodeLogicalImmInst(u32 op, ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms, int n) {
|
||||
// Sometimes Rd is fixed to SP, but can still be 32bit or 64bit.
|
||||
// Use Rn to determine bitness here.
|
||||
bool b64Bit = Is64Bit(Rn);
|
||||
@ -823,12 +806,10 @@ void ARM64XEmitter::EncodeLogicalImmInst(u32 op, ARM64Reg Rd, ARM64Reg Rn, u32 i
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
|
||||
Write32((b64Bit << 31) | (op << 29) | (0x24 << 23) | (n << 22) | (immr << 16) | (imms << 10) |
|
||||
(Rn << 5) | Rd);
|
||||
Write32((b64Bit << 31) | (op << 29) | (0x24 << 23) | (n << 22) | (immr << 16) | (imms << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeLoadStorePair(u32 op, u32 load, IndexType type, ARM64Reg Rt, ARM64Reg Rt2,
|
||||
ARM64Reg Rn, s32 imm) {
|
||||
void ARM64XEmitter::EncodeLoadStorePair(u32 op, u32 load, IndexType type, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, s32 imm) {
|
||||
bool b64Bit = Is64Bit(Rt);
|
||||
u32 type_encode = 0;
|
||||
|
||||
@ -858,8 +839,7 @@ void ARM64XEmitter::EncodeLoadStorePair(u32 op, u32 load, IndexType type, ARM64R
|
||||
Rt2 = DecodeReg(Rt2);
|
||||
Rn = DecodeReg(Rn);
|
||||
|
||||
Write32((op << 30) | (0b101 << 27) | (type_encode << 23) | (load << 22) | ((imm & 0x7F) << 15) |
|
||||
(Rt2 << 10) | (Rn << 5) | Rt);
|
||||
Write32((op << 30) | (0b101 << 27) | (type_encode << 23) | (load << 22) | ((imm & 0x7F) << 15) | (Rt2 << 10) | (Rn << 5) | Rt);
|
||||
}
|
||||
void ARM64XEmitter::EncodeAddressInst(u32 op, ARM64Reg Rd, s32 imm) {
|
||||
Rd = DecodeReg(Rd);
|
||||
@ -909,8 +889,7 @@ void ARM64XEmitter::SetJumpTarget(FixupBranch const& branch, u8* target) {
|
||||
ASSERT_MSG(IsInRangeImm14(distance), "{}({}): Received too large distance: {:X}",
|
||||
__func__, branch.type, distance);
|
||||
ARM64Reg reg = DecodeReg(branch.reg);
|
||||
inst = ((branch.bit & 0x20) << 26) | (0x1B << 25) | (Not << 24) |
|
||||
((branch.bit & 0x1F) << 19) | (MaskImm14(distance) << 5) | reg;
|
||||
inst = ((branch.bit & 0x20) << 26) | (0x1B << 25) | (Not << 24) | ((branch.bit & 0x1F) << 19) | (MaskImm14(distance) << 5) | reg;
|
||||
} break;
|
||||
case 5: // B (unconditional)
|
||||
ASSERT_MSG(IsInRangeImm26(distance), "{}({}): Received too large distance: {:X}",
|
||||
@ -1778,8 +1757,7 @@ void ARM64XEmitter::MOVI2R(ARM64Reg Rd, u64 imm, bool optimize) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((Is64Bit(Rd) && imm == std::numeric_limits<u64>::max()) ||
|
||||
(!Is64Bit(Rd) && imm == std::numeric_limits<u32>::max())) {
|
||||
if ((Is64Bit(Rd) && imm == std::numeric_limits<u64>::max()) || (!Is64Bit(Rd) && imm == std::numeric_limits<u32>::max())) {
|
||||
// Max unsigned value (or if signed, -1)
|
||||
// Set to ~ZR
|
||||
ARM64Reg ZR = Is64Bit(Rd) ? SP : WSP;
|
||||
@ -1943,8 +1921,7 @@ void ARM64XEmitter::ABI_PopRegisters(u32 registers) {
|
||||
}
|
||||
|
||||
// Float Emitter
|
||||
void ARM64FloatEmitter::EmitLoadStoreImmediate(u8 size, u32 opc, IndexType type, ARM64Reg Rt,
|
||||
ARM64Reg Rn, s32 imm) {
|
||||
void ARM64FloatEmitter::EmitLoadStoreImmediate(u8 size, u32 opc, IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm) {
|
||||
Rt = DecodeReg(Rt);
|
||||
Rn = DecodeReg(Rn);
|
||||
u32 encoded_size = 0;
|
||||
@ -1986,35 +1963,29 @@ void ARM64FloatEmitter::EmitLoadStoreImmediate(u8 size, u32 opc, IndexType type,
|
||||
encoded_imm |= 3;
|
||||
}
|
||||
|
||||
Write32((encoded_size << 30) | (0xF << 26) | (type == INDEX_UNSIGNED ? (1 << 24) : 0) |
|
||||
(size == 128 ? (1 << 23) : 0) | (opc << 22) | (encoded_imm << 10) | (Rn << 5) | Rt);
|
||||
Write32((encoded_size << 30) | (0xF << 26) | (type == INDEX_UNSIGNED ? (1 << 24) : 0) | (size == 128 ? (1 << 23) : 0) | (opc << 22) | (encoded_imm << 10) | (Rn << 5) | Rt);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitScalar2Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd,
|
||||
ARM64Reg Rn, ARM64Reg Rm) {
|
||||
void ARM64FloatEmitter::EmitScalar2Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
|
||||
ASSERT_MSG(!IsQuad(Rd), "{} only supports double and single registers!", __func__);
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
Rm = DecodeReg(Rm);
|
||||
|
||||
Write32((M << 31) | (S << 29) | (0b11110001 << 21) | (type << 22) | (Rm << 16) |
|
||||
(opcode << 12) | (1 << 11) | (Rn << 5) | Rd);
|
||||
Write32((M << 31) | (S << 29) | (0b11110001 << 21) | (type << 22) | (Rm << 16) | (opcode << 12) | (1 << 11) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitThreeSame(bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn,
|
||||
ARM64Reg Rm) {
|
||||
void ARM64FloatEmitter::EmitThreeSame(bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
|
||||
ASSERT_MSG(!IsSingle(Rd), "{} doesn't support singles!", __func__);
|
||||
bool quad = IsQuad(Rd);
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
Rm = DecodeReg(Rm);
|
||||
|
||||
Write32((quad << 30) | (U << 29) | (0b1110001 << 21) | (size << 22) | (Rm << 16) |
|
||||
(opcode << 11) | (1 << 10) | (Rn << 5) | Rd);
|
||||
Write32((quad << 30) | (U << 29) | (0b1110001 << 21) | (size << 22) | (Rm << 16) | (opcode << 11) | (1 << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitScalarThreeSame(bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn,
|
||||
ARM64Reg Rm) {
|
||||
void ARM64FloatEmitter::EmitScalarThreeSame(bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
|
||||
ASSERT_MSG(!IsQuad(Rd), "{} doesn't support quads!", __func__);
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
@ -2038,74 +2009,60 @@ void ARM64FloatEmitter::EmitScalarThreeSame(bool U, u32 size, u32 opcode, ARM64R
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Write32((U << 29) | (0b1011110001 << 21) | (esize << 22) | (Rm << 16) |
|
||||
(opcode << 11) | (1 << 10) | (Rn << 5) | Rd);
|
||||
Write32((U << 29) | (0b1011110001 << 21) | (esize << 22) | (Rm << 16) | (opcode << 11) | (1 << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitCopy(bool Q, u32 op, u32 imm5, u32 imm4, ARM64Reg Rd, ARM64Reg Rn) {
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
|
||||
Write32((Q << 30) | (op << 29) | (0b111 << 25) | (imm5 << 16) | (imm4 << 11) | (1 << 10) |
|
||||
(Rn << 5) | Rd);
|
||||
Write32((Q << 30) | (op << 29) | (0b111 << 25) | (imm5 << 16) | (imm4 << 11) | (1 << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::Emit2RegMisc(bool Q, bool U, u32 size, u32 opcode, ARM64Reg Rd,
|
||||
ARM64Reg Rn) {
|
||||
void ARM64FloatEmitter::Emit2RegMisc(bool Q, bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn) {
|
||||
ASSERT_MSG(!IsSingle(Rd), "{} doesn't support singles!", __func__);
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
|
||||
Write32((Q << 30) | (U << 29) | (0b1110001 << 21) | (size << 22) | (opcode << 12) | (1 << 11) |
|
||||
(Rn << 5) | Rd);
|
||||
Write32((Q << 30) | (U << 29) | (0b1110001 << 21) | (size << 22) | (opcode << 12) | (1 << 11) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size,
|
||||
ARM64Reg Rt, ARM64Reg Rn) {
|
||||
void ARM64FloatEmitter::EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size, ARM64Reg Rt, ARM64Reg Rn) {
|
||||
ASSERT_MSG(!IsSingle(Rt), "{} doesn't support singles!", __func__);
|
||||
bool quad = IsQuad(Rt);
|
||||
Rt = DecodeReg(Rt);
|
||||
Rn = DecodeReg(Rn);
|
||||
|
||||
Write32((quad << 30) | (0b1101 << 24) | (L << 22) | (R << 21) | (opcode << 13) | (S << 12) |
|
||||
(size << 10) | (Rn << 5) | Rt);
|
||||
Write32((quad << 30) | (0b1101 << 24) | (L << 22) | (R << 21) | (opcode << 13) | (S << 12) | (size << 10) | (Rn << 5) | Rt);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size,
|
||||
ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm) {
|
||||
void ARM64FloatEmitter::EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size, ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm) {
|
||||
ASSERT_MSG(!IsSingle(Rt), "{} doesn't support singles!", __func__);
|
||||
bool quad = IsQuad(Rt);
|
||||
Rt = DecodeReg(Rt);
|
||||
Rn = DecodeReg(Rn);
|
||||
Rm = DecodeReg(Rm);
|
||||
|
||||
Write32((quad << 30) | (0x1B << 23) | (L << 22) | (R << 21) | (Rm << 16) | (opcode << 13) |
|
||||
(S << 12) | (size << 10) | (Rn << 5) | Rt);
|
||||
Write32((quad << 30) | (0x1B << 23) | (L << 22) | (R << 21) | (Rm << 16) | (opcode << 13) | (S << 12) | (size << 10) | (Rn << 5) | Rt);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::Emit1Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd,
|
||||
ARM64Reg Rn) {
|
||||
void ARM64FloatEmitter::Emit1Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd, ARM64Reg Rn) {
|
||||
ASSERT_MSG(!IsQuad(Rd), "{} doesn't support vector!", __func__);
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
|
||||
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (type << 22) | (opcode << 15) | (1 << 14) |
|
||||
(Rn << 5) | Rd);
|
||||
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (type << 22) | (opcode << 15) | (1 << 14) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitConversion(bool sf, bool S, u32 type, u32 rmode, u32 opcode,
|
||||
ARM64Reg Rd, ARM64Reg Rn) {
|
||||
void ARM64FloatEmitter::EmitConversion(bool sf, bool S, u32 type, u32 rmode, u32 opcode, ARM64Reg Rd, ARM64Reg Rn) {
|
||||
ASSERT_MSG(Rn <= SP, "{} only supports GPR as source!", __func__);
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
|
||||
Write32((sf << 31) | (S << 29) | (0xF1 << 21) | (type << 22) | (rmode << 19) | (opcode << 16) |
|
||||
(Rn << 5) | Rd);
|
||||
Write32((sf << 31) | (S << 29) | (0xF1 << 21) | (type << 22) | (rmode << 19) | (opcode << 16) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitConvertScalarToInt(ARM64Reg Rd, ARM64Reg Rn, RoundingMode round,
|
||||
bool sign) {
|
||||
void ARM64FloatEmitter::EmitConvertScalarToInt(ARM64Reg Rd, ARM64Reg Rn, RoundingMode round, bool sign) {
|
||||
DEBUG_ASSERT_MSG(IsScalar(Rn), "fcvts: Rn must be floating point");
|
||||
if (IsGPR(Rd)) {
|
||||
// Use the encoding that transfers the result to a GPR.
|
||||
@ -2160,8 +2117,7 @@ void ARM64FloatEmitter::EmitConvertScalarToInt(ARM64Reg Rd, ARM64Reg Rn, Roundin
|
||||
sz |= 2;
|
||||
break;
|
||||
}
|
||||
Write32((0x5E << 24) | (sign << 29) | (sz << 22) | (1 << 21) | (opcode << 12) | (2 << 10) |
|
||||
(Rn << 5) | Rd);
|
||||
Write32((0x5E << 24) | (sign << 29) | (sz << 22) | (1 << 21) | (opcode << 12) | (2 << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2173,13 +2129,11 @@ void ARM64FloatEmitter::FCVTU(ARM64Reg Rd, ARM64Reg Rn, RoundingMode round) {
|
||||
EmitConvertScalarToInt(Rd, Rn, round, true);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitConversion2(bool sf, bool S, bool direction, u32 type, u32 rmode,
|
||||
u32 opcode, int scale, ARM64Reg Rd, ARM64Reg Rn) {
|
||||
void ARM64FloatEmitter::EmitConversion2(bool sf, bool S, bool direction, u32 type, u32 rmode, u32 opcode, int scale, ARM64Reg Rd, ARM64Reg Rn) {
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
|
||||
Write32((sf << 31) | (S << 29) | (0xF0 << 21) | (direction << 21) | (type << 22) |
|
||||
(rmode << 19) | (opcode << 16) | (scale << 10) | (Rn << 5) | Rd);
|
||||
Write32((sf << 31) | (S << 29) | (0xF0 << 21) | (direction << 21) | (type << 22) | (rmode << 19) | (opcode << 16) | (scale << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitCompare(bool M, bool S, u32 op, u32 opcode2, ARM64Reg Rn, ARM64Reg Rm) {
|
||||
@ -2189,12 +2143,10 @@ void ARM64FloatEmitter::EmitCompare(bool M, bool S, u32 op, u32 opcode2, ARM64Re
|
||||
Rn = DecodeReg(Rn);
|
||||
Rm = DecodeReg(Rm);
|
||||
|
||||
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (is_double << 22) | (Rm << 16) | (op << 14) |
|
||||
(1 << 13) | (Rn << 5) | opcode2);
|
||||
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (is_double << 22) | (Rm << 16) | (op << 14) | (1 << 13) | (Rn << 5) | opcode2);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitCondSelect(bool M, bool S, CCFlags cond, ARM64Reg Rd, ARM64Reg Rn,
|
||||
ARM64Reg Rm) {
|
||||
void ARM64FloatEmitter::EmitCondSelect(bool M, bool S, CCFlags cond, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
|
||||
ASSERT_MSG(!IsQuad(Rd), "{} doesn't support vector!", __func__);
|
||||
bool is_double = IsDouble(Rd);
|
||||
|
||||
@ -2202,8 +2154,7 @@ void ARM64FloatEmitter::EmitCondSelect(bool M, bool S, CCFlags cond, ARM64Reg Rd
|
||||
Rn = DecodeReg(Rn);
|
||||
Rm = DecodeReg(Rm);
|
||||
|
||||
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (is_double << 22) | (Rm << 16) | (cond << 12) |
|
||||
(3 << 10) | (Rn << 5) | Rd);
|
||||
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (is_double << 22) | (Rm << 16) | (cond << 12) | (3 << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitPermute(u32 size, u32 op, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
|
||||
@ -2223,8 +2174,7 @@ void ARM64FloatEmitter::EmitPermute(u32 size, u32 op, ARM64Reg Rd, ARM64Reg Rn,
|
||||
Rn = DecodeReg(Rn);
|
||||
Rm = DecodeReg(Rm);
|
||||
|
||||
Write32((quad << 30) | (7 << 25) | (encoded_size << 22) | (Rm << 16) | (op << 12) | (1 << 11) |
|
||||
(Rn << 5) | Rd);
|
||||
Write32((quad << 30) | (7 << 25) | (encoded_size << 22) | (Rm << 16) | (op << 12) | (1 << 11) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitScalarImm(bool M, bool S, u32 type, u32 imm5, ARM64Reg Rd, u32 imm8) {
|
||||
@ -2234,32 +2184,26 @@ void ARM64FloatEmitter::EmitScalarImm(bool M, bool S, u32 type, u32 imm5, ARM64R
|
||||
|
||||
Rd = DecodeReg(Rd);
|
||||
|
||||
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (is_double << 22) | (type << 22) | (imm8 << 13) |
|
||||
(1 << 12) | (imm5 << 5) | Rd);
|
||||
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (is_double << 22) | (type << 22) | (imm8 << 13) | (1 << 12) | (imm5 << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitShiftImm(bool Q, bool U, u32 immh, u32 immb, u32 opcode, ARM64Reg Rd,
|
||||
ARM64Reg Rn) {
|
||||
void ARM64FloatEmitter::EmitShiftImm(bool Q, bool U, u32 immh, u32 immb, u32 opcode, ARM64Reg Rd, ARM64Reg Rn) {
|
||||
ASSERT_MSG(immh, "{} bad encoding! Can't have zero immh", __func__);
|
||||
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
|
||||
Write32((Q << 30) | (U << 29) | (0xF << 24) | (immh << 19) | (immb << 16) | (opcode << 11) |
|
||||
(1 << 10) | (Rn << 5) | Rd);
|
||||
Write32((Q << 30) | (U << 29) | (0xF << 24) | (immh << 19) | (immb << 16) | (opcode << 11) | (1 << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitScalarShiftImm(bool U, u32 immh, u32 immb, u32 opcode, ARM64Reg Rd,
|
||||
ARM64Reg Rn) {
|
||||
void ARM64FloatEmitter::EmitScalarShiftImm(bool U, u32 immh, u32 immb, u32 opcode, ARM64Reg Rd, ARM64Reg Rn) {
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
|
||||
Write32((2 << 30) | (U << 29) | (0x3E << 23) | (immh << 19) | (immb << 16) | (opcode << 11) |
|
||||
(1 << 10) | (Rn << 5) | Rd);
|
||||
Write32((2 << 30) | (U << 29) | (0x3E << 23) | (immh << 19) | (immb << 16) | (opcode << 11) | (1 << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitLoadStoreMultipleStructure(u32 size, bool L, u32 opcode, ARM64Reg Rt,
|
||||
ARM64Reg Rn) {
|
||||
void ARM64FloatEmitter::EmitLoadStoreMultipleStructure(u32 size, bool L, u32 opcode, ARM64Reg Rt, ARM64Reg Rn) {
|
||||
bool quad = IsQuad(Rt);
|
||||
u32 encoded_size = 0;
|
||||
|
||||
@ -2273,12 +2217,10 @@ void ARM64FloatEmitter::EmitLoadStoreMultipleStructure(u32 size, bool L, u32 opc
|
||||
Rt = DecodeReg(Rt);
|
||||
Rn = DecodeReg(Rn);
|
||||
|
||||
Write32((quad << 30) | (3 << 26) | (L << 22) | (opcode << 12) | (encoded_size << 10) |
|
||||
(Rn << 5) | Rt);
|
||||
Write32((quad << 30) | (3 << 26) | (L << 22) | (opcode << 12) | (encoded_size << 10) | (Rn << 5) | Rt);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitLoadStoreMultipleStructurePost(u32 size, bool L, u32 opcode,
|
||||
ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm) {
|
||||
void ARM64FloatEmitter::EmitLoadStoreMultipleStructurePost(u32 size, bool L, u32 opcode, ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm) {
|
||||
bool quad = IsQuad(Rt);
|
||||
u32 encoded_size = 0;
|
||||
|
||||
@ -2293,31 +2235,26 @@ void ARM64FloatEmitter::EmitLoadStoreMultipleStructurePost(u32 size, bool L, u32
|
||||
Rn = DecodeReg(Rn);
|
||||
Rm = DecodeReg(Rm);
|
||||
|
||||
Write32((quad << 30) | (0b11001 << 23) | (L << 22) | (Rm << 16) | (opcode << 12) |
|
||||
(encoded_size << 10) | (Rn << 5) | Rt);
|
||||
Write32((quad << 30) | (0b11001 << 23) | (L << 22) | (Rm << 16) | (opcode << 12) | (encoded_size << 10) | (Rn << 5) | Rt);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitScalar1Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd,
|
||||
ARM64Reg Rn) {
|
||||
void ARM64FloatEmitter::EmitScalar1Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd, ARM64Reg Rn) {
|
||||
ASSERT_MSG(!IsQuad(Rd), "{} doesn't support vector!", __func__);
|
||||
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
|
||||
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (type << 22) | (opcode << 15) | (1 << 14) |
|
||||
(Rn << 5) | Rd);
|
||||
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (type << 22) | (opcode << 15) | (1 << 14) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitVectorxElement(bool U, u32 size, bool L, u32 opcode, bool H,
|
||||
ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
|
||||
void ARM64FloatEmitter::EmitVectorxElement(bool U, u32 size, bool L, u32 opcode, bool H, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
|
||||
bool quad = IsQuad(Rd);
|
||||
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
Rm = DecodeReg(Rm);
|
||||
|
||||
Write32((quad << 30) | (U << 29) | (0xF << 24) | (size << 22) | (L << 21) | (Rm << 16) |
|
||||
(opcode << 12) | (H << 11) | (Rn << 5) | Rd);
|
||||
Write32((quad << 30) | (U << 29) | (0xF << 24) | (size << 22) | (L << 21) | (Rm << 16) | (opcode << 12) | (H << 11) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitLoadStoreUnscaled(u32 size, u32 op, ARM64Reg Rt, ARM64Reg Rn, s32 imm) {
|
||||
@ -2328,8 +2265,7 @@ void ARM64FloatEmitter::EmitLoadStoreUnscaled(u32 size, u32 op, ARM64Reg Rt, ARM
|
||||
Write32((size << 30) | (0xF << 26) | (op << 22) | ((imm & 0x1FF) << 12) | (Rn << 5) | Rt);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EncodeLoadStorePair(u32 size, bool load, IndexType type, ARM64Reg Rt,
|
||||
ARM64Reg Rt2, ARM64Reg Rn, s32 imm) {
|
||||
void ARM64FloatEmitter::EncodeLoadStorePair(u32 size, bool load, IndexType type, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, s32 imm) {
|
||||
u32 type_encode = 0;
|
||||
u32 opc = 0;
|
||||
|
||||
@ -2366,12 +2302,10 @@ void ARM64FloatEmitter::EncodeLoadStorePair(u32 size, bool load, IndexType type,
|
||||
Rt2 = DecodeReg(Rt2);
|
||||
Rn = DecodeReg(Rn);
|
||||
|
||||
Write32((opc << 30) | (0b1011 << 26) | (type_encode << 23) | (load << 22) |
|
||||
((imm & 0x7F) << 15) | (Rt2 << 10) | (Rn << 5) | Rt);
|
||||
Write32((opc << 30) | (0b1011 << 26) | (type_encode << 23) | (load << 22) | ((imm & 0x7F) << 15) | (Rt2 << 10) | (Rn << 5) | Rt);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EncodeLoadStoreRegisterOffset(u32 size, bool load, ARM64Reg Rt, ARM64Reg Rn,
|
||||
ArithOption Rm) {
|
||||
void ARM64FloatEmitter::EncodeLoadStoreRegisterOffset(u32 size, bool load, ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm) {
|
||||
ASSERT_MSG(Rm.GetType() == ArithOption::TYPE_EXTENDEDREG,
|
||||
"{} must contain an extended reg as Rm!", __func__);
|
||||
|
||||
@ -2402,8 +2336,7 @@ void ARM64FloatEmitter::EncodeLoadStoreRegisterOffset(u32 size, bool load, ARM64
|
||||
Rn = DecodeReg(Rn);
|
||||
ARM64Reg decoded_Rm = DecodeReg(Rm.GetReg());
|
||||
|
||||
Write32((encoded_size << 30) | (encoded_op << 22) | (0b111100001 << 21) | (decoded_Rm << 16) |
|
||||
Rm.GetData() | (1 << 11) | (Rn << 5) | Rt);
|
||||
Write32((encoded_size << 30) | (encoded_op << 22) | (0b111100001 << 21) | (decoded_Rm << 16) | Rm.GetData() | (1 << 11) | (Rn << 5) | Rt);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EncodeModImm(bool Q, u8 op, u8 cmode, u8 o2, ARM64Reg Rd, u8 abcdefgh) {
|
||||
@ -2416,8 +2349,7 @@ void ARM64FloatEmitter::EncodeModImm(bool Q, u8 op, u8 cmode, u8 o2, ARM64Reg Rd
|
||||
} v;
|
||||
v.hex = abcdefgh;
|
||||
Rd = DecodeReg(Rd);
|
||||
Write32((Q << 30) | (op << 29) | (0xF << 24) | (v.in.abc << 16) | (cmode << 12) | (o2 << 11) |
|
||||
(1 << 10) | (v.in.defgh << 5) | Rd);
|
||||
Write32((Q << 30) | (op << 29) | (0xF << 24) | (v.in.abc << 16) | (cmode << 12) | (o2 << 11) | (1 << 10) | (v.in.defgh << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::LDR(u8 size, IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm) {
|
||||
@ -2675,8 +2607,7 @@ void ARM64FloatEmitter::LD1(u8 size, u8 count, ARM64Reg Rt, ARM64Reg Rn) {
|
||||
opcode = 0b0010;
|
||||
EmitLoadStoreMultipleStructure(size, 1, opcode, Rt, Rn);
|
||||
}
|
||||
void ARM64FloatEmitter::LD1(u8 size, u8 count, IndexType type, ARM64Reg Rt, ARM64Reg Rn,
|
||||
ARM64Reg Rm) {
|
||||
void ARM64FloatEmitter::LD1(u8 size, u8 count, IndexType type, ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm) {
|
||||
ASSERT_MSG(!(count == 0 || count > 4), "{} must have a count of 1 to 4 registers!", __func__);
|
||||
ASSERT_MSG(type == INDEX_POST, "{} only supports post indexing!", __func__);
|
||||
|
||||
@ -2704,8 +2635,7 @@ void ARM64FloatEmitter::ST1(u8 size, u8 count, ARM64Reg Rt, ARM64Reg Rn) {
|
||||
opcode = 0b0010;
|
||||
EmitLoadStoreMultipleStructure(size, 0, opcode, Rt, Rn);
|
||||
}
|
||||
void ARM64FloatEmitter::ST1(u8 size, u8 count, IndexType type, ARM64Reg Rt, ARM64Reg Rn,
|
||||
ARM64Reg Rm) {
|
||||
void ARM64FloatEmitter::ST1(u8 size, u8 count, IndexType type, ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm) {
|
||||
ASSERT_MSG(!(count == 0 || count > 4), "{} must have a count of 1 to 4 registers!", __func__);
|
||||
ASSERT_MSG(type == INDEX_POST, "{} only supports post indexing!", __func__);
|
||||
|
||||
@ -2756,12 +2686,10 @@ void ARM64FloatEmitter::FMOV(ARM64Reg Rd, ARM64Reg Rn, bool top) {
|
||||
}
|
||||
|
||||
// Loadstore paired
|
||||
void ARM64FloatEmitter::LDP(u8 size, IndexType type, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn,
|
||||
s32 imm) {
|
||||
void ARM64FloatEmitter::LDP(u8 size, IndexType type, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, s32 imm) {
|
||||
EncodeLoadStorePair(size, true, type, Rt, Rt2, Rn, imm);
|
||||
}
|
||||
void ARM64FloatEmitter::STP(u8 size, IndexType type, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn,
|
||||
s32 imm) {
|
||||
void ARM64FloatEmitter::STP(u8 size, IndexType type, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, s32 imm) {
|
||||
EncodeLoadStorePair(size, false, type, Rt, Rt2, Rn, imm);
|
||||
}
|
||||
|
||||
@ -2825,8 +2753,7 @@ void ARM64FloatEmitter::FNMSUB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg R
|
||||
EmitScalar3Source(IsDouble(Rd), Rd, Rn, Rm, Ra, 3);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitScalar3Source(bool isDouble, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm,
|
||||
ARM64Reg Ra, int opcode) {
|
||||
void ARM64FloatEmitter::EmitScalar3Source(bool isDouble, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra, int opcode) {
|
||||
int type = isDouble ? 1 : 0;
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
@ -2834,8 +2761,7 @@ void ARM64FloatEmitter::EmitScalar3Source(bool isDouble, ARM64Reg Rd, ARM64Reg R
|
||||
Ra = DecodeReg(Ra);
|
||||
int o1 = opcode >> 1;
|
||||
int o0 = opcode & 1;
|
||||
m_emit->Write32((0x1F << 24) | (type << 22) | (o1 << 21) | (Rm << 16) | (o0 << 15) |
|
||||
(Ra << 10) | (Rn << 5) | Rd);
|
||||
m_emit->Write32((0x1F << 24) | (type << 22) | (o1 << 21) | (Rm << 16) | (o0 << 15) | (Ra << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
// Scalar three same
|
||||
@ -3706,8 +3632,7 @@ void ARM64XEmitter::ANDSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
|
||||
}
|
||||
}
|
||||
|
||||
void ARM64XEmitter::AddImmediate(ARM64Reg Rd, ARM64Reg Rn, u64 imm, bool shift, bool negative,
|
||||
bool flags) {
|
||||
void ARM64XEmitter::AddImmediate(ARM64Reg Rd, ARM64Reg Rn, u64 imm, bool shift, bool negative, bool flags) {
|
||||
switch ((negative << 1) | static_cast<unsigned int>(flags)) {
|
||||
case 0:
|
||||
ADD(Rd, Rn, static_cast<u32>(imm), shift);
|
||||
@ -3724,8 +3649,7 @@ void ARM64XEmitter::AddImmediate(ARM64Reg Rd, ARM64Reg Rn, u64 imm, bool shift,
|
||||
}
|
||||
}
|
||||
|
||||
void ARM64XEmitter::ADDI2R_internal(ARM64Reg Rd, ARM64Reg Rn, u64 imm, bool negative, bool flags,
|
||||
ARM64Reg scratch) {
|
||||
void ARM64XEmitter::ADDI2R_internal(ARM64Reg Rd, ARM64Reg Rn, u64 imm, bool negative, bool flags, ARM64Reg scratch) {
|
||||
bool has_scratch = scratch != INVALID_REG;
|
||||
u64 imm_neg = Is64Bit(Rd) ? ~imm + 1 : (~imm + 1) & 0xFFFFFFFFuLL;
|
||||
bool neg_neg = negative ? false : true;
|
||||
|
@ -265,7 +265,11 @@ constexpr ARM64Reg EncodeRegToQuad(ARM64Reg reg) {
|
||||
return static_cast<ARM64Reg>(reg | 0xC0);
|
||||
}
|
||||
|
||||
enum OpType { TYPE_IMM = 0, TYPE_REG, TYPE_IMMSREG, TYPE_RSR, TYPE_MEM };
|
||||
enum OpType { TYPE_IMM = 0,
|
||||
TYPE_REG,
|
||||
TYPE_IMMSREG,
|
||||
TYPE_RSR,
|
||||
TYPE_MEM };
|
||||
|
||||
enum ShiftType {
|
||||
ST_LSL = 0,
|
||||
@ -474,8 +478,7 @@ private:
|
||||
void EncodeUnconditionalBranchInst(u32 opc, u32 op2, u32 op3, u32 op4, ARM64Reg Rn);
|
||||
void EncodeExceptionInst(u32 instenc, u32 imm);
|
||||
void EncodeSystemInst(u32 op0, u32 op1, u32 CRn, u32 CRm, u32 op2, ARM64Reg Rt);
|
||||
void EncodeArithmeticInst(u32 instenc, bool flags, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm,
|
||||
ArithOption Option);
|
||||
void EncodeArithmeticInst(u32 instenc, bool flags, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Option);
|
||||
void EncodeArithmeticCarryInst(u32 op, bool flags, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void EncodeCondCompareImmInst(u32 op, ARM64Reg Rn, u32 imm, u32 nzcv, CCFlags cond);
|
||||
void EncodeCondCompareRegInst(u32 op, ARM64Reg Rn, ARM64Reg Rm, u32 nzcv, CCFlags cond);
|
||||
@ -494,8 +497,7 @@ private:
|
||||
void EncodeLoadStoreRegisterOffset(u32 size, u32 opc, ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm);
|
||||
void EncodeAddSubImmInst(u32 op, bool flags, u32 shift, u32 imm, ARM64Reg Rn, ARM64Reg Rd);
|
||||
void EncodeLogicalImmInst(u32 op, ARM64Reg Rd, ARM64Reg Rn, u32 immr, u32 imms, int n);
|
||||
void EncodeLoadStorePair(u32 op, u32 load, IndexType type, ARM64Reg Rt, ARM64Reg Rt2,
|
||||
ARM64Reg Rn, s32 imm);
|
||||
void EncodeLoadStorePair(u32 op, u32 load, IndexType type, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, s32 imm);
|
||||
void EncodeAddressInst(u32 op, ARM64Reg Rd, s32 imm);
|
||||
void EncodeLoadStoreUnscaled(u32 size, u32 op, ARM64Reg Rt, ARM64Reg Rn, s32 imm);
|
||||
|
||||
@ -503,7 +505,8 @@ protected:
|
||||
void Write32(u32 value);
|
||||
|
||||
public:
|
||||
ARM64XEmitter() : m_code(nullptr), m_lastCacheFlushEnd(nullptr) {
|
||||
ARM64XEmitter()
|
||||
: m_code(nullptr), m_lastCacheFlushEnd(nullptr) {
|
||||
}
|
||||
|
||||
ARM64XEmitter(u8* code_ptr) {
|
||||
@ -848,8 +851,7 @@ public:
|
||||
void EORI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch = INVALID_REG);
|
||||
void CMPI2R(ARM64Reg Rn, u64 imm, ARM64Reg scratch = INVALID_REG);
|
||||
|
||||
void ADDI2R_internal(ARM64Reg Rd, ARM64Reg Rn, u64 imm, bool negative, bool flags,
|
||||
ARM64Reg scratch);
|
||||
void ADDI2R_internal(ARM64Reg Rd, ARM64Reg Rn, u64 imm, bool negative, bool flags, ARM64Reg scratch);
|
||||
void ADDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch = INVALID_REG);
|
||||
void ADDSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch = INVALID_REG);
|
||||
void SUBI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch = INVALID_REG);
|
||||
@ -897,7 +899,8 @@ public:
|
||||
|
||||
class ARM64FloatEmitter {
|
||||
public:
|
||||
ARM64FloatEmitter(ARM64XEmitter* emit) : m_emit(emit) {
|
||||
ARM64FloatEmitter(ARM64XEmitter* emit)
|
||||
: m_emit(emit) {
|
||||
}
|
||||
|
||||
void LDR(u8 size, IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm);
|
||||
@ -1110,22 +1113,17 @@ private:
|
||||
}
|
||||
|
||||
// Emitting functions
|
||||
void EmitLoadStoreImmediate(u8 size, u32 opc, IndexType type, ARM64Reg Rt, ARM64Reg Rn,
|
||||
s32 imm);
|
||||
void EmitScalar2Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd, ARM64Reg Rn,
|
||||
ARM64Reg Rm);
|
||||
void EmitLoadStoreImmediate(u8 size, u32 opc, IndexType type, ARM64Reg Rt, ARM64Reg Rn, s32 imm);
|
||||
void EmitScalar2Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void EmitThreeSame(bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void EmitScalarThreeSame(bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void EmitCopy(bool Q, u32 op, u32 imm5, u32 imm4, ARM64Reg Rd, ARM64Reg Rn);
|
||||
void Emit2RegMisc(bool Q, bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn);
|
||||
void EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size, ARM64Reg Rt,
|
||||
ARM64Reg Rn);
|
||||
void EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size, ARM64Reg Rt,
|
||||
ARM64Reg Rn, ARM64Reg Rm);
|
||||
void EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size, ARM64Reg Rt, ARM64Reg Rn);
|
||||
void EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size, ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void Emit1Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd, ARM64Reg Rn);
|
||||
void EmitConversion(bool sf, bool S, u32 type, u32 rmode, u32 opcode, ARM64Reg Rd, ARM64Reg Rn);
|
||||
void EmitConversion2(bool sf, bool S, bool direction, u32 type, u32 rmode, u32 opcode,
|
||||
int scale, ARM64Reg Rd, ARM64Reg Rn);
|
||||
void EmitConversion2(bool sf, bool S, bool direction, u32 type, u32 rmode, u32 opcode, int scale, ARM64Reg Rd, ARM64Reg Rn);
|
||||
void EmitCompare(bool M, bool S, u32 op, u32 opcode2, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void EmitCondSelect(bool M, bool S, CCFlags cond, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void EmitPermute(u32 size, u32 op, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
@ -1133,19 +1131,14 @@ private:
|
||||
void EmitShiftImm(bool Q, bool U, u32 immh, u32 immb, u32 opcode, ARM64Reg Rd, ARM64Reg Rn);
|
||||
void EmitScalarShiftImm(bool U, u32 immh, u32 immb, u32 opcode, ARM64Reg Rd, ARM64Reg Rn);
|
||||
void EmitLoadStoreMultipleStructure(u32 size, bool L, u32 opcode, ARM64Reg Rt, ARM64Reg Rn);
|
||||
void EmitLoadStoreMultipleStructurePost(u32 size, bool L, u32 opcode, ARM64Reg Rt, ARM64Reg Rn,
|
||||
ARM64Reg Rm);
|
||||
void EmitLoadStoreMultipleStructurePost(u32 size, bool L, u32 opcode, ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void EmitScalar1Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd, ARM64Reg Rn);
|
||||
void EmitVectorxElement(bool U, u32 size, bool L, u32 opcode, bool H, ARM64Reg Rd, ARM64Reg Rn,
|
||||
ARM64Reg Rm);
|
||||
void EmitVectorxElement(bool U, u32 size, bool L, u32 opcode, bool H, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void EmitLoadStoreUnscaled(u32 size, u32 op, ARM64Reg Rt, ARM64Reg Rn, s32 imm);
|
||||
void EmitConvertScalarToInt(ARM64Reg Rd, ARM64Reg Rn, RoundingMode round, bool sign);
|
||||
void EmitScalar3Source(bool isDouble, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra,
|
||||
int opcode);
|
||||
void EncodeLoadStorePair(u32 size, bool load, IndexType type, ARM64Reg Rt, ARM64Reg Rt2,
|
||||
ARM64Reg Rn, s32 imm);
|
||||
void EncodeLoadStoreRegisterOffset(u32 size, bool load, ARM64Reg Rt, ARM64Reg Rn,
|
||||
ArithOption Rm);
|
||||
void EmitScalar3Source(bool isDouble, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ARM64Reg Ra, int opcode);
|
||||
void EncodeLoadStorePair(u32 size, bool load, IndexType type, ARM64Reg Rt, ARM64Reg Rt2, ARM64Reg Rn, s32 imm);
|
||||
void EncodeLoadStoreRegisterOffset(u32 size, bool load, ARM64Reg Rt, ARM64Reg Rn, ArithOption Rm);
|
||||
void EncodeModImm(bool Q, u8 op, u8 cmode, u8 o2, ARM64Reg Rd, u8 abcdefgh);
|
||||
|
||||
void SSHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper);
|
||||
|
@ -7,8 +7,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
@ -32,6 +32,7 @@ public:
|
||||
void Register(BlockOfCode& code, std::function<void(CodePtr)> segv_callback = nullptr);
|
||||
|
||||
bool SupportsFastmem() const;
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
|
@ -8,10 +8,9 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <csignal>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include <csignal>
|
||||
#ifdef __APPLE__
|
||||
# include <sys/ucontext.h>
|
||||
#else
|
||||
@ -117,8 +116,7 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) {
|
||||
"dynarmic: POSIX SigHandler: Exception was not in registered code blocks (PC {})\n",
|
||||
PC);
|
||||
|
||||
struct sigaction* retry_sa =
|
||||
sig == SIGSEGV ? &sig_handler.old_sa_segv : &sig_handler.old_sa_bus;
|
||||
struct sigaction* retry_sa = sig == SIGSEGV ? &sig_handler.old_sa_segv : &sig_handler.old_sa_bus;
|
||||
if (retry_sa->sa_flags & SA_SIGINFO) {
|
||||
retry_sa->sa_sigaction(sig, info, raw_context);
|
||||
return;
|
||||
|
@ -18,4 +18,4 @@ Arm64Gen::ARM64Reg HostLocToFpr(HostLoc loc) {
|
||||
return EncodeRegToQuad(static_cast<Arm64Gen::ARM64Reg>(static_cast<int>(loc) - static_cast<int>(HostLoc::Q0)));
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::BackendX64
|
||||
} // namespace Dynarmic::BackendA64
|
||||
|
@ -138,26 +138,70 @@ using HostLocList = std::initializer_list<HostLoc>;
|
||||
// X30 is the link register.
|
||||
// In order of desireablity based first on ABI
|
||||
constexpr HostLocList any_gpr = {
|
||||
HostLoc::X19, HostLoc::X20, HostLoc::X21, HostLoc::X22, HostLoc::X23,
|
||||
HostLoc::X24, HostLoc::X25,
|
||||
HostLoc::X19,
|
||||
HostLoc::X20,
|
||||
HostLoc::X21,
|
||||
HostLoc::X22,
|
||||
HostLoc::X23,
|
||||
HostLoc::X24,
|
||||
HostLoc::X25,
|
||||
|
||||
HostLoc::X8, HostLoc::X9, HostLoc::X10, HostLoc::X11, HostLoc::X12,
|
||||
HostLoc::X13, HostLoc::X14, HostLoc::X15, HostLoc::X16, HostLoc::X17,
|
||||
HostLoc::X8,
|
||||
HostLoc::X9,
|
||||
HostLoc::X10,
|
||||
HostLoc::X11,
|
||||
HostLoc::X12,
|
||||
HostLoc::X13,
|
||||
HostLoc::X14,
|
||||
HostLoc::X15,
|
||||
HostLoc::X16,
|
||||
HostLoc::X17,
|
||||
|
||||
HostLoc::X7, HostLoc::X6, HostLoc::X5, HostLoc::X4, HostLoc::X3,
|
||||
HostLoc::X2, HostLoc::X1, HostLoc::X0,
|
||||
HostLoc::X7,
|
||||
HostLoc::X6,
|
||||
HostLoc::X5,
|
||||
HostLoc::X4,
|
||||
HostLoc::X3,
|
||||
HostLoc::X2,
|
||||
HostLoc::X1,
|
||||
HostLoc::X0,
|
||||
};
|
||||
|
||||
constexpr HostLocList any_fpr = {
|
||||
HostLoc::Q8, HostLoc::Q9, HostLoc::Q10, HostLoc::Q11, HostLoc::Q12, HostLoc::Q13,
|
||||
HostLoc::Q14, HostLoc::Q15,
|
||||
HostLoc::Q8,
|
||||
HostLoc::Q9,
|
||||
HostLoc::Q10,
|
||||
HostLoc::Q11,
|
||||
HostLoc::Q12,
|
||||
HostLoc::Q13,
|
||||
HostLoc::Q14,
|
||||
HostLoc::Q15,
|
||||
|
||||
HostLoc::Q16, HostLoc::Q17, HostLoc::Q18, HostLoc::Q19, HostLoc::Q20, HostLoc::Q21,
|
||||
HostLoc::Q22, HostLoc::Q23, HostLoc::Q24, HostLoc::Q25, HostLoc::Q26, HostLoc::Q27,
|
||||
HostLoc::Q28, HostLoc::Q29, HostLoc::Q30, HostLoc::Q31,
|
||||
HostLoc::Q16,
|
||||
HostLoc::Q17,
|
||||
HostLoc::Q18,
|
||||
HostLoc::Q19,
|
||||
HostLoc::Q20,
|
||||
HostLoc::Q21,
|
||||
HostLoc::Q22,
|
||||
HostLoc::Q23,
|
||||
HostLoc::Q24,
|
||||
HostLoc::Q25,
|
||||
HostLoc::Q26,
|
||||
HostLoc::Q27,
|
||||
HostLoc::Q28,
|
||||
HostLoc::Q29,
|
||||
HostLoc::Q30,
|
||||
HostLoc::Q31,
|
||||
|
||||
HostLoc::Q7, HostLoc::Q6, HostLoc::Q5, HostLoc::Q4, HostLoc::Q3, HostLoc::Q2,
|
||||
HostLoc::Q1, HostLoc::Q0,
|
||||
HostLoc::Q7,
|
||||
HostLoc::Q6,
|
||||
HostLoc::Q5,
|
||||
HostLoc::Q4,
|
||||
HostLoc::Q3,
|
||||
HostLoc::Q2,
|
||||
HostLoc::Q1,
|
||||
HostLoc::Q0,
|
||||
};
|
||||
|
||||
Arm64Gen::ARM64Reg HostLocToReg64(HostLoc loc);
|
||||
|
@ -25,8 +25,7 @@ struct JitStateInfo {
|
||||
, offsetof_cpsr_nzcv(offsetof(JitStateType, cpsr_nzcv))
|
||||
, offsetof_fpsr_exc(offsetof(JitStateType, fpsr_exc))
|
||||
, offsetof_fpsr_qc(offsetof(JitStateType, fpsr_qc))
|
||||
, offsetof_halt_reason(offsetof(JitStateType, halt_reason))
|
||||
{}
|
||||
, offsetof_halt_reason(offsetof(JitStateType, halt_reason)) {}
|
||||
|
||||
const size_t offsetof_cycles_remaining;
|
||||
const size_t offsetof_cycles_to_run;
|
||||
|
@ -12,11 +12,11 @@
|
||||
# include <cstdio>
|
||||
# include <cstdlib>
|
||||
# include <mutex>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
# include <fmt/format.h>
|
||||
# include <mcl/stdint.hpp>
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
|
||||
namespace Dynarmic::BackendA64 {
|
||||
|
||||
@ -71,7 +71,7 @@ void PerfMapClear() {
|
||||
OpenFile();
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::BackendX64
|
||||
} // namespace Dynarmic::BackendA64
|
||||
|
||||
#else
|
||||
|
||||
@ -83,6 +83,6 @@ void PerfMapRegister(const void*, const void*, const std::string&) {}
|
||||
|
||||
void PerfMapClear() {}
|
||||
|
||||
} // namespace Dynarmic::BackendX64
|
||||
} // namespace Dynarmic::BackendA64
|
||||
|
||||
#endif
|
||||
|
@ -24,4 +24,4 @@ void PerfMapRegister(T start, const void* end, const std::string& friendly_name)
|
||||
|
||||
void PerfMapClear();
|
||||
|
||||
} // namespace Dynarmic::BackendX64
|
||||
} // namespace Dynarmic::BackendA64
|
||||
|
@ -4,6 +4,8 @@
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#include "dynarmic/backend/A64/reg_alloc.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
@ -12,7 +14,6 @@
|
||||
#include <mcl/assert.hpp>
|
||||
|
||||
#include "dynarmic/backend/A64/abi.h"
|
||||
#include "dynarmic/backend/A64/reg_alloc.h"
|
||||
|
||||
namespace Dynarmic::BackendA64 {
|
||||
|
||||
@ -379,14 +380,7 @@ HostLoc RegAlloc::ScratchImpl(HostLocList desired_locations) {
|
||||
return location;
|
||||
}
|
||||
|
||||
void RegAlloc::HostCall(IR::Inst* result_def, std::optional<Argument::copyable_reference> arg0,
|
||||
std::optional<Argument::copyable_reference> arg1,
|
||||
std::optional<Argument::copyable_reference> arg2,
|
||||
std::optional<Argument::copyable_reference> arg3,
|
||||
std::optional<Argument::copyable_reference> arg4,
|
||||
std::optional<Argument::copyable_reference> arg5,
|
||||
std::optional<Argument::copyable_reference> arg6,
|
||||
std::optional<Argument::copyable_reference> arg7) {
|
||||
void RegAlloc::HostCall(IR::Inst* result_def, std::optional<Argument::copyable_reference> arg0, std::optional<Argument::copyable_reference> arg1, std::optional<Argument::copyable_reference> arg2, std::optional<Argument::copyable_reference> arg3, std::optional<Argument::copyable_reference> arg4, std::optional<Argument::copyable_reference> arg5, std::optional<Argument::copyable_reference> arg6, std::optional<Argument::copyable_reference> arg7) {
|
||||
constexpr size_t args_count = 8;
|
||||
constexpr std::array<HostLoc, args_count> args_hostloc = {ABI_PARAM1, ABI_PARAM2, ABI_PARAM3, ABI_PARAM4, ABI_PARAM5, ABI_PARAM6, ABI_PARAM7, ABI_PARAM8};
|
||||
const std::array<std::optional<Argument::copyable_reference>, args_count> args = {arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7};
|
||||
|
@ -8,9 +8,9 @@
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
@ -84,7 +84,8 @@ public:
|
||||
|
||||
private:
|
||||
friend class RegAlloc;
|
||||
explicit Argument(RegAlloc& reg_alloc) : reg_alloc(reg_alloc) {}
|
||||
explicit Argument(RegAlloc& reg_alloc)
|
||||
: reg_alloc(reg_alloc) {}
|
||||
|
||||
bool allocated = false;
|
||||
RegAlloc& reg_alloc;
|
||||
@ -117,14 +118,7 @@ public:
|
||||
Arm64Gen::ARM64Reg ScratchGpr(HostLocList desired_locations = any_gpr);
|
||||
Arm64Gen::ARM64Reg ScratchFpr(HostLocList desired_locations = any_fpr);
|
||||
|
||||
void HostCall(IR::Inst* result_def = nullptr, std::optional<Argument::copyable_reference> arg0 = {},
|
||||
std::optional<Argument::copyable_reference> arg1 = {},
|
||||
std::optional<Argument::copyable_reference> arg2 = {},
|
||||
std::optional<Argument::copyable_reference> arg3 = {},
|
||||
std::optional<Argument::copyable_reference> arg4 = {},
|
||||
std::optional<Argument::copyable_reference> arg5 = {},
|
||||
std::optional<Argument::copyable_reference> arg6 = {},
|
||||
std::optional<Argument::copyable_reference> arg7 = {});
|
||||
void HostCall(IR::Inst* result_def = nullptr, std::optional<Argument::copyable_reference> arg0 = {}, std::optional<Argument::copyable_reference> arg1 = {}, std::optional<Argument::copyable_reference> arg2 = {}, std::optional<Argument::copyable_reference> arg3 = {}, std::optional<Argument::copyable_reference> arg4 = {}, std::optional<Argument::copyable_reference> arg5 = {}, std::optional<Argument::copyable_reference> arg6 = {}, std::optional<Argument::copyable_reference> arg7 = {});
|
||||
|
||||
// TODO: Values in host flags
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user