emit_x64: Extract BlockRangeInformation, remove template parameter

This commit is contained in:
MerryMage 2018-01-23 19:16:39 +00:00
parent 58c4a25527
commit db30e02ac8
14 changed files with 308 additions and 398 deletions

View file

@ -121,6 +121,8 @@ if (ARCHITECTURE_x86_64)
backend_x64/abi.h backend_x64/abi.h
backend_x64/block_of_code.cpp backend_x64/block_of_code.cpp
backend_x64/block_of_code.h backend_x64/block_of_code.h
backend_x64/block_range_information.cpp
backend_x64/block_range_information.h
backend_x64/callback.cpp backend_x64/callback.cpp
backend_x64/callback.h backend_x64/callback.h
backend_x64/constant_pool.cpp backend_x64/constant_pool.cpp

View file

@ -127,13 +127,22 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
const size_t size = static_cast<size_t>(code->getCurr() - entrypoint); const size_t size = static_cast<size_t>(code->getCurr() - entrypoint);
const A32::LocationDescriptor end_location{block.EndLocation()}; const A32::LocationDescriptor end_location{block.EndLocation()};
const auto range = boost::icl::discrete_interval<u32>::closed(descriptor.PC(), end_location.PC() - 1); const auto range = boost::icl::discrete_interval<u32>::closed(descriptor.PC(), end_location.PC() - 1);
A32EmitX64::BlockDescriptor block_desc{entrypoint, size, block.Location(), range}; A32EmitX64::BlockDescriptor block_desc{entrypoint, size};
block_descriptors.emplace(descriptor.UniqueHash(), block_desc); block_descriptors.emplace(descriptor.UniqueHash(), block_desc);
block_ranges.add(std::make_pair(range, std::set<IR::LocationDescriptor>{descriptor})); block_ranges.AddRange(range, descriptor);
return block_desc; return block_desc;
} }
void A32EmitX64::ClearCache() {
EmitX64::ClearCache();
block_ranges.ClearCache();
}
void A32EmitX64::InvalidateCacheRanges(const boost::icl::interval_set<u32>& ranges) {
InvalidateBasicBlocks(block_ranges.InvalidateRanges(ranges));
}
void A32EmitX64::GenMemoryAccessors() { void A32EmitX64::GenMemoryAccessors() {
code->align(); code->align();
read_memory_8 = code->getCurr<const void*>(); read_memory_8 = code->getCurr<const void*>();

View file

@ -9,6 +9,7 @@
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include "backend_x64/a32_jitstate.h" #include "backend_x64/a32_jitstate.h"
#include "backend_x64/block_range_information.h"
#include "backend_x64/emit_x64.h" #include "backend_x64/emit_x64.h"
#include "dynarmic/A32/a32.h" #include "dynarmic/A32/a32.h"
#include "dynarmic/A32/callbacks.h" #include "dynarmic/A32/callbacks.h"
@ -28,7 +29,7 @@ struct A32EmitContext final : public EmitContext {
bool FPSCR_DN() const override; bool FPSCR_DN() const override;
}; };
class A32EmitX64 final : public EmitX64<A32JitState> { class A32EmitX64 final : public EmitX64 {
public: public:
A32EmitX64(BlockOfCode* code, A32::UserCallbacks cb, A32::Jit* jit_interface); A32EmitX64(BlockOfCode* code, A32::UserCallbacks cb, A32::Jit* jit_interface);
~A32EmitX64(); ~A32EmitX64();
@ -39,9 +40,14 @@ public:
*/ */
BlockDescriptor Emit(IR::Block& ir); BlockDescriptor Emit(IR::Block& ir);
void ClearCache() override;
void InvalidateCacheRanges(const boost::icl::interval_set<u32>& ranges);
protected: protected:
const A32::UserCallbacks cb; const A32::UserCallbacks cb;
A32::Jit* jit_interface; A32::Jit* jit_interface;
BlockRangeInformation<u32> block_ranges;
const void* read_memory_8; const void* read_memory_8;
const void* read_memory_16; const void* read_memory_16;

View file

@ -109,13 +109,22 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) {
const size_t size = static_cast<size_t>(code->getCurr() - entrypoint); const size_t size = static_cast<size_t>(code->getCurr() - entrypoint);
const A64::LocationDescriptor end_location{block.EndLocation()}; const A64::LocationDescriptor end_location{block.EndLocation()};
const auto range = boost::icl::discrete_interval<u64>::closed(descriptor.PC(), end_location.PC() - 1); const auto range = boost::icl::discrete_interval<u64>::closed(descriptor.PC(), end_location.PC() - 1);
A64EmitX64::BlockDescriptor block_desc{entrypoint, size, block.Location(), range}; A64EmitX64::BlockDescriptor block_desc{entrypoint, size};
block_descriptors.emplace(descriptor.UniqueHash(), block_desc); block_descriptors.emplace(descriptor.UniqueHash(), block_desc);
block_ranges.add(std::make_pair(range, std::set<IR::LocationDescriptor>{descriptor})); block_ranges.AddRange(range, descriptor);
return block_desc; return block_desc;
} }
void A64EmitX64::ClearCache() {
EmitX64::ClearCache();
block_ranges.ClearCache();
}
void A64EmitX64::InvalidateCacheRanges(const boost::icl::interval_set<u64>& ranges) {
InvalidateBasicBlocks(block_ranges.InvalidateRanges(ranges));
}
void A64EmitX64::EmitA64SetCheckBit(A64EmitContext& ctx, IR::Inst* inst) { void A64EmitX64::EmitA64SetCheckBit(A64EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg8 to_store = ctx.reg_alloc.UseGpr(args[0]).cvt8(); Xbyak::Reg8 to_store = ctx.reg_alloc.UseGpr(args[0]).cvt8();

View file

@ -7,6 +7,7 @@
#pragma once #pragma once
#include "backend_x64/a64_jitstate.h" #include "backend_x64/a64_jitstate.h"
#include "backend_x64/block_range_information.h"
#include "backend_x64/emit_x64.h" #include "backend_x64/emit_x64.h"
#include "dynarmic/A64/config.h" #include "dynarmic/A64/config.h"
#include "frontend/A64/location_descriptor.h" #include "frontend/A64/location_descriptor.h"
@ -25,7 +26,7 @@ struct A64EmitContext final : public EmitContext {
bool FPSCR_DN() const override; bool FPSCR_DN() const override;
}; };
class A64EmitX64 final : public EmitX64<A64JitState> { class A64EmitX64 final : public EmitX64 {
public: public:
A64EmitX64(BlockOfCode* code, A64::UserConfig conf); A64EmitX64(BlockOfCode* code, A64::UserConfig conf);
~A64EmitX64(); ~A64EmitX64();
@ -36,8 +37,13 @@ public:
*/ */
BlockDescriptor Emit(IR::Block& ir); BlockDescriptor Emit(IR::Block& ir);
void ClearCache() override;
void InvalidateCacheRanges(const boost::icl::interval_set<u64>& ranges);
protected: protected:
const A64::UserConfig conf; const A64::UserConfig conf;
BlockRangeInformation<u64> block_ranges;
// Microinstruction emitters // Microinstruction emitters
#define OPCODE(...) #define OPCODE(...)

View file

@ -0,0 +1,47 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#include <unordered_set>
#include <boost/icl/interval_map.hpp>
#include <boost/icl/interval_set.hpp>
#include "backend_x64/block_range_information.h"
#include "common/common_types.h"
namespace Dynarmic {
namespace BackendX64 {
template <typename ProgramCounterType>
void BlockRangeInformation<ProgramCounterType>::AddRange(boost::icl::discrete_interval<ProgramCounterType> range, IR::LocationDescriptor location) {
block_ranges.add(std::make_pair(range, std::set<IR::LocationDescriptor>{location}));
}
template <typename ProgramCounterType>
void BlockRangeInformation<ProgramCounterType>::ClearCache() {
block_ranges.clear();
}
template <typename ProgramCounterType>
std::unordered_set<IR::LocationDescriptor> BlockRangeInformation<ProgramCounterType>::InvalidateRanges(const boost::icl::interval_set<ProgramCounterType>& ranges) {
std::unordered_set<IR::LocationDescriptor> erase_locations;
for (auto invalidate_interval : ranges) {
auto pair = block_ranges.equal_range(invalidate_interval);
for (auto it = pair.first; it != pair.second; ++it) {
for (const auto &descriptor : it->second) {
erase_locations.insert(descriptor);
}
}
}
// TODO: EFFICIENCY: Remove ranges that are to be erased.
return erase_locations;
}
template class BlockRangeInformation<u32>;
template class BlockRangeInformation<u64>;
} // namespace BackendX64
} // namespace Dynarmic

View file

@ -0,0 +1,31 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#pragma once
#include <unordered_set>
#include <boost/icl/interval_map.hpp>
#include <boost/icl/interval_set.hpp>
#include "frontend/ir/location_descriptor.h"
namespace Dynarmic {
namespace BackendX64 {
template <typename ProgramCounterType>
class BlockRangeInformation {
public:
void AddRange(boost::icl::discrete_interval<ProgramCounterType> range, IR::LocationDescriptor location);
void ClearCache();
std::unordered_set<IR::LocationDescriptor> InvalidateRanges(const boost::icl::interval_set<ProgramCounterType>& ranges);
private:
boost::icl::interval_map<ProgramCounterType, std::set<IR::LocationDescriptor>> block_ranges;
};
} // namespace BackendX64
} // namespace Dynarmic

View file

@ -31,40 +31,33 @@ void EmitContext::EraseInstruction(IR::Inst* inst) {
inst->ClearArgs(); inst->ClearArgs();
} }
template <typename JST> EmitX64::EmitX64(BlockOfCode* code)
EmitX64<JST>::EmitX64(BlockOfCode* code)
: code(code) {} : code(code) {}
template <typename JST> EmitX64::~EmitX64() {}
EmitX64<JST>::~EmitX64() {}
template <typename JST> boost::optional<typename EmitX64::BlockDescriptor> EmitX64::GetBasicBlock(IR::LocationDescriptor descriptor) const {
boost::optional<typename EmitX64<JST>::BlockDescriptor> EmitX64<JST>::GetBasicBlock(IR::LocationDescriptor descriptor) const {
auto iter = block_descriptors.find(descriptor); auto iter = block_descriptors.find(descriptor);
if (iter == block_descriptors.end()) if (iter == block_descriptors.end())
return boost::none; return boost::none;
return iter->second; return iter->second;
} }
template <typename JST> void EmitX64::EmitVoid(EmitContext&, IR::Inst*) {
void EmitX64<JST>::EmitVoid(EmitContext&, IR::Inst*) {
} }
template <typename JST> void EmitX64::EmitBreakpoint(EmitContext&, IR::Inst*) {
void EmitX64<JST>::EmitBreakpoint(EmitContext&, IR::Inst*) {
code->int3(); code->int3();
} }
template <typename JST> void EmitX64::EmitIdentity(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitIdentity(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
if (!args[0].IsImmediate()) { if (!args[0].IsImmediate()) {
ctx.reg_alloc.DefineValue(inst, args[0]); ctx.reg_alloc.DefineValue(inst, args[0]);
} }
} }
template <typename JST> void EmitX64::PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, IR::LocationDescriptor target) {
void EmitX64<JST>::PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, IR::LocationDescriptor target) {
using namespace Xbyak::util; using namespace Xbyak::util;
auto iter = block_descriptors.find(target); auto iter = block_descriptors.find(target);
@ -87,8 +80,7 @@ void EmitX64<JST>::PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_r
code->mov(dword[r15 + code->GetJitStateInfo().offsetof_rsb_ptr], index_reg.cvt32()); code->mov(dword[r15 + code->GetJitStateInfo().offsetof_rsb_ptr], index_reg.cvt32());
} }
template <typename JST> void EmitX64::EmitPushRSB(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPushRSB(EmitContext& 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());
u64 unique_hash_of_target = args[0].GetImmediateU64(); u64 unique_hash_of_target = args[0].GetImmediateU64();
@ -100,23 +92,19 @@ void EmitX64<JST>::EmitPushRSB(EmitContext& ctx, IR::Inst* inst) {
PushRSBHelper(loc_desc_reg, index_reg, IR::LocationDescriptor{unique_hash_of_target}); PushRSBHelper(loc_desc_reg, index_reg, IR::LocationDescriptor{unique_hash_of_target});
} }
template <typename JST> void EmitX64::EmitGetCarryFromOp(EmitContext&, IR::Inst*) {
void EmitX64<JST>::EmitGetCarryFromOp(EmitContext&, IR::Inst*) {
ASSERT_MSG(false, "should never happen"); ASSERT_MSG(false, "should never happen");
} }
template <typename JST> void EmitX64::EmitGetOverflowFromOp(EmitContext&, IR::Inst*) {
void EmitX64<JST>::EmitGetOverflowFromOp(EmitContext&, IR::Inst*) {
ASSERT_MSG(false, "should never happen"); ASSERT_MSG(false, "should never happen");
} }
template <typename JST> void EmitX64::EmitGetGEFromOp(EmitContext&, IR::Inst*) {
void EmitX64<JST>::EmitGetGEFromOp(EmitContext&, IR::Inst*) {
ASSERT_MSG(false, "should never happen"); ASSERT_MSG(false, "should never happen");
} }
template <typename JST> void EmitX64::EmitGetNZCVFromOp(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitGetNZCVFromOp(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const int bitsize = [&]{ const int bitsize = [&]{
@ -143,14 +131,12 @@ void EmitX64<JST>::EmitGetNZCVFromOp(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, nzcv); ctx.reg_alloc.DefineValue(inst, nzcv);
} }
template <typename JST> void EmitX64::EmitAddCycles(size_t cycles) {
void EmitX64<JST>::EmitAddCycles(size_t cycles) {
ASSERT(cycles < std::numeric_limits<u32>::max()); ASSERT(cycles < std::numeric_limits<u32>::max());
code->sub(qword[r15 + code->GetJitStateInfo().offsetof_cycles_remaining], static_cast<u32>(cycles)); code->sub(qword[r15 + code->GetJitStateInfo().offsetof_cycles_remaining], static_cast<u32>(cycles));
} }
template <typename JST> Xbyak::Label EmitX64::EmitCond(IR::Cond cond) {
Xbyak::Label EmitX64<JST>::EmitCond(IR::Cond cond) {
Xbyak::Label label; Xbyak::Label label;
const Xbyak::Reg32 cpsr = eax; const Xbyak::Reg32 cpsr = eax;
@ -262,8 +248,7 @@ Xbyak::Label EmitX64<JST>::EmitCond(IR::Cond cond) {
return label; return label;
} }
template <typename JST> void EmitX64::EmitCondPrelude(const IR::Block& block) {
void EmitX64<JST>::EmitCondPrelude(const IR::Block& block) {
if (block.GetCondition() == IR::Cond::AL) { if (block.GetCondition() == IR::Cond::AL) {
ASSERT(!block.HasConditionFailedLocation()); ASSERT(!block.HasConditionFailedLocation());
return; return;
@ -277,8 +262,7 @@ void EmitX64<JST>::EmitCondPrelude(const IR::Block& block) {
code->L(pass); code->L(pass);
} }
template <typename JST> void EmitX64::EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location) {
void EmitX64<JST>::EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location) {
Common::VisitVariant<void>(terminal, [this, &initial_location](auto x) { Common::VisitVariant<void>(terminal, [this, &initial_location](auto x) {
using T = std::decay_t<decltype(x)>; using T = std::decay_t<decltype(x)>;
if constexpr (!std::is_same_v<T, IR::Term::Invalid>) { if constexpr (!std::is_same_v<T, IR::Term::Invalid>) {
@ -289,8 +273,7 @@ void EmitX64<JST>::EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor in
}); });
} }
template <typename JST> void EmitX64::Patch(const IR::LocationDescriptor& desc, CodePtr bb) {
void EmitX64<JST>::Patch(const IR::LocationDescriptor& desc, CodePtr bb) {
const CodePtr save_code_ptr = code->getCurr(); const CodePtr save_code_ptr = code->getCurr();
const PatchInformation& patch_info = patch_information[desc]; const PatchInformation& patch_info = patch_information[desc];
@ -312,39 +295,28 @@ void EmitX64<JST>::Patch(const IR::LocationDescriptor& desc, CodePtr bb) {
code->SetCodePtr(save_code_ptr); code->SetCodePtr(save_code_ptr);
} }
template <typename JST> void EmitX64::Unpatch(const IR::LocationDescriptor& desc) {
void EmitX64<JST>::Unpatch(const IR::LocationDescriptor& desc) {
Patch(desc, nullptr); Patch(desc, nullptr);
} }
template <typename JST> void EmitX64::ClearCache() {
void EmitX64<JST>::ClearCache() {
block_descriptors.clear(); block_descriptors.clear();
patch_information.clear(); patch_information.clear();
} }
template <typename JST> void EmitX64::InvalidateBasicBlocks(const std::unordered_set<IR::LocationDescriptor>& locations) {
void EmitX64<JST>::InvalidateCacheRanges(const boost::icl::interval_set<ProgramCounterType>& ranges) { for (const auto &descriptor : locations) {
// Remove cached block descriptors and patch information overlapping with the given range. auto it = block_descriptors.find(descriptor);
for (auto invalidate_interval : ranges) { if (it == block_descriptors.end()) {
auto pair = block_ranges.equal_range(invalidate_interval); continue;
for (auto it = pair.first; it != pair.second; ++it) {
for (const auto& descriptor : it->second) {
if (patch_information.count(descriptor)) {
Unpatch(descriptor);
}
block_descriptors.erase(descriptor);
}
} }
block_ranges.erase(pair.first, pair.second);
if (patch_information.count(descriptor)) {
Unpatch(descriptor);
}
block_descriptors.erase(it);
} }
} }
} // namespace BackendX64 } // namespace BackendX64
} // namespace Dynarmic } // namespace Dynarmic
#include "backend_x64/a32_jitstate.h"
#include "backend_x64/a64_jitstate.h"
template class Dynarmic::BackendX64::EmitX64<Dynarmic::BackendX64::A32JitState>;
template class Dynarmic::BackendX64::EmitX64<Dynarmic::BackendX64::A64JitState>;

View file

@ -7,10 +7,9 @@
#pragma once #pragma once
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
#include <vector> #include <vector>
#include <boost/icl/interval_map.hpp>
#include <boost/icl/interval_set.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <xbyak_util.h> #include <xbyak_util.h>
@ -44,17 +43,11 @@ struct EmitContext {
IR::Block& block; IR::Block& block;
}; };
template <typename JitStateType>
class EmitX64 { class EmitX64 {
public: public:
using ProgramCounterType = typename JitStateType::ProgramCounterType;
struct BlockDescriptor { struct BlockDescriptor {
CodePtr entrypoint; // Entrypoint of emitted code CodePtr entrypoint; // Entrypoint of emitted code
size_t size; // Length in bytes of emitted code size_t size; // Length in bytes of emitted code
IR::LocationDescriptor start_location;
boost::icl::discrete_interval<ProgramCounterType> range;
}; };
EmitX64(BlockOfCode* code); EmitX64(BlockOfCode* code);
@ -64,9 +57,10 @@ public:
boost::optional<BlockDescriptor> GetBasicBlock(IR::LocationDescriptor descriptor) const; boost::optional<BlockDescriptor> GetBasicBlock(IR::LocationDescriptor descriptor) const;
/// Empties the entire cache. /// Empties the entire cache.
void ClearCache(); virtual void ClearCache();
void InvalidateCacheRanges(const boost::icl::interval_set<ProgramCounterType>& ranges); /// Invalidates a selection of basic blocks.
void InvalidateBasicBlocks(const std::unordered_set<IR::LocationDescriptor>& locations);
protected: protected:
// Microinstruction emitters // Microinstruction emitters
@ -111,7 +105,6 @@ protected:
BlockOfCode* code; BlockOfCode* code;
std::unordered_map<IR::LocationDescriptor, BlockDescriptor> block_descriptors; std::unordered_map<IR::LocationDescriptor, BlockDescriptor> block_descriptors;
std::unordered_map<IR::LocationDescriptor, PatchInformation> patch_information; std::unordered_map<IR::LocationDescriptor, PatchInformation> patch_information;
boost::icl::interval_map<ProgramCounterType, std::set<IR::LocationDescriptor>> block_ranges;
}; };
} // namespace BackendX64 } // namespace BackendX64

View file

@ -17,8 +17,7 @@ namespace BackendX64 {
using namespace Xbyak::util; using namespace Xbyak::util;
template <typename JST> void EmitX64::EmitPack2x32To1x64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPack2x32To1x64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 lo = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 lo = ctx.reg_alloc.UseScratchGpr(args[0]);
Xbyak::Reg64 hi = ctx.reg_alloc.UseScratchGpr(args[1]); Xbyak::Reg64 hi = ctx.reg_alloc.UseScratchGpr(args[1]);
@ -30,14 +29,12 @@ void EmitX64<JST>::EmitPack2x32To1x64(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, lo); ctx.reg_alloc.DefineValue(inst, lo);
} }
template <typename JST> void EmitX64::EmitLeastSignificantWord(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitLeastSignificantWord(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
ctx.reg_alloc.DefineValue(inst, args[0]); ctx.reg_alloc.DefineValue(inst, args[0]);
} }
template <typename JST> void EmitX64::EmitMostSignificantWord(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitMostSignificantWord(EmitContext& ctx, IR::Inst* inst) {
auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -54,20 +51,17 @@ void EmitX64<JST>::EmitMostSignificantWord(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitLeastSignificantHalf(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitLeastSignificantHalf(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
ctx.reg_alloc.DefineValue(inst, args[0]); ctx.reg_alloc.DefineValue(inst, args[0]);
} }
template <typename JST> void EmitX64::EmitLeastSignificantByte(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitLeastSignificantByte(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
ctx.reg_alloc.DefineValue(inst, args[0]); ctx.reg_alloc.DefineValue(inst, args[0]);
} }
template <typename JST> void EmitX64::EmitMostSignificantBit(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitMostSignificantBit(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
// TODO: Flag optimization // TODO: Flag optimization
@ -75,8 +69,7 @@ void EmitX64<JST>::EmitMostSignificantBit(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitIsZero32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitIsZero32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
// TODO: Flag optimization // TODO: Flag optimization
@ -86,8 +79,7 @@ void EmitX64<JST>::EmitIsZero32(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitIsZero64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitIsZero64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
// TODO: Flag optimization // TODO: Flag optimization
@ -97,8 +89,7 @@ void EmitX64<JST>::EmitIsZero64(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitTestBit(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitTestBit(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
ASSERT(args[1].IsImmediate()); ASSERT(args[1].IsImmediate());
@ -108,7 +99,6 @@ void EmitX64<JST>::EmitTestBit(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST>
static void EmitConditionalSelect(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, int bitsize) { static void EmitConditionalSelect(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, int bitsize) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 nzcv = ctx.reg_alloc.ScratchGpr({HostLoc::RAX}).cvt32(); Xbyak::Reg32 nzcv = ctx.reg_alloc.ScratchGpr({HostLoc::RAX}).cvt32();
@ -179,18 +169,15 @@ static void EmitConditionalSelect(BlockOfCode* code, EmitContext& ctx, IR::Inst*
ctx.reg_alloc.DefineValue(inst, else_); ctx.reg_alloc.DefineValue(inst, else_);
} }
template <typename JST> void EmitX64::EmitConditionalSelect32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitConditionalSelect32(EmitContext& ctx, IR::Inst* inst) { EmitConditionalSelect(code, ctx, inst, 32);
EmitConditionalSelect<JST>(code, ctx, inst, 32);
} }
template <typename JST> void EmitX64::EmitConditionalSelect64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitConditionalSelect64(EmitContext& ctx, IR::Inst* inst) { EmitConditionalSelect(code, ctx, inst, 64);
EmitConditionalSelect<JST>(code, ctx, inst, 64);
} }
template <typename JST> void EmitX64::EmitLogicalShiftLeft32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitLogicalShiftLeft32(EmitContext& ctx, IR::Inst* inst) {
auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -290,8 +277,7 @@ void EmitX64<JST>::EmitLogicalShiftLeft32(EmitContext& ctx, IR::Inst* inst) {
} }
} }
template <typename JST> void EmitX64::EmitLogicalShiftLeft64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitLogicalShiftLeft64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& operand_arg = args[0]; auto& operand_arg = args[0];
auto& shift_arg = args[1]; auto& shift_arg = args[1];
@ -324,8 +310,7 @@ void EmitX64<JST>::EmitLogicalShiftLeft64(EmitContext& ctx, IR::Inst* inst) {
} }
} }
template <typename JST> void EmitX64::EmitLogicalShiftRight32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitLogicalShiftRight32(EmitContext& ctx, IR::Inst* inst) {
auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -424,8 +409,7 @@ void EmitX64<JST>::EmitLogicalShiftRight32(EmitContext& ctx, IR::Inst* inst) {
} }
} }
template <typename JST> void EmitX64::EmitLogicalShiftRight64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitLogicalShiftRight64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& operand_arg = args[0]; auto& operand_arg = args[0];
auto& shift_arg = args[1]; auto& shift_arg = args[1];
@ -458,8 +442,7 @@ void EmitX64<JST>::EmitLogicalShiftRight64(EmitContext& ctx, IR::Inst* inst) {
} }
} }
template <typename JST> void EmitX64::EmitArithmeticShiftRight32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitArithmeticShiftRight32(EmitContext& ctx, IR::Inst* inst) {
auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -547,8 +530,7 @@ void EmitX64<JST>::EmitArithmeticShiftRight32(EmitContext& ctx, IR::Inst* inst)
} }
} }
template <typename JST> void EmitX64::EmitArithmeticShiftRight64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitArithmeticShiftRight64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& operand_arg = args[0]; auto& operand_arg = args[0];
auto& shift_arg = args[1]; auto& shift_arg = args[1];
@ -579,8 +561,7 @@ void EmitX64<JST>::EmitArithmeticShiftRight64(EmitContext& ctx, IR::Inst* inst)
} }
} }
template <typename JST> void EmitX64::EmitRotateRight32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitRotateRight32(EmitContext& ctx, IR::Inst* inst) {
auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -659,8 +640,7 @@ void EmitX64<JST>::EmitRotateRight32(EmitContext& ctx, IR::Inst* inst) {
} }
} }
template <typename JST> void EmitX64::EmitRotateRight64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitRotateRight64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& operand_arg = args[0]; auto& operand_arg = args[0];
auto& shift_arg = args[1]; auto& shift_arg = args[1];
@ -683,8 +663,7 @@ void EmitX64<JST>::EmitRotateRight64(EmitContext& ctx, IR::Inst* inst) {
} }
} }
template <typename JST> void EmitX64::EmitRotateRightExtended(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitRotateRightExtended(EmitContext& ctx, IR::Inst* inst) {
auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -788,13 +767,11 @@ static void EmitAdd(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, int bit
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitAdd32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitAdd32(EmitContext& ctx, IR::Inst* inst) {
EmitAdd(code, ctx, inst, 32); EmitAdd(code, ctx, inst, 32);
} }
template <typename JST> void EmitX64::EmitAdd64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitAdd64(EmitContext& ctx, IR::Inst* inst) {
EmitAdd(code, ctx, inst, 64); EmitAdd(code, ctx, inst, 64);
} }
@ -867,18 +844,15 @@ static void EmitSub(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, int bit
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitSub32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitSub32(EmitContext& ctx, IR::Inst* inst) {
EmitSub(code, ctx, inst, 32); EmitSub(code, ctx, inst, 32);
} }
template <typename JST> void EmitX64::EmitSub64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitSub64(EmitContext& ctx, IR::Inst* inst) {
EmitSub(code, ctx, inst, 64); EmitSub(code, ctx, inst, 64);
} }
template <typename JST> void EmitX64::EmitMul32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitMul32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
@ -893,8 +867,7 @@ void EmitX64<JST>::EmitMul32(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitMul64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitMul64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
@ -905,8 +878,7 @@ void EmitX64<JST>::EmitMul64(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitAnd32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitAnd32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
@ -925,8 +897,7 @@ void EmitX64<JST>::EmitAnd32(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitAnd64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitAnd64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
@ -945,8 +916,7 @@ void EmitX64<JST>::EmitAnd64(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitEor32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitEor32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
@ -965,8 +935,7 @@ void EmitX64<JST>::EmitEor32(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitEor64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitEor64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
@ -985,8 +954,7 @@ void EmitX64<JST>::EmitEor64(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitOr32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitOr32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
@ -1005,8 +973,7 @@ void EmitX64<JST>::EmitOr32(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitOr64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitOr64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
@ -1025,8 +992,7 @@ void EmitX64<JST>::EmitOr64(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitNot32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitNot32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 result; Xbyak::Reg32 result;
@ -1040,8 +1006,7 @@ void EmitX64<JST>::EmitNot32(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitNot64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitNot64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result; Xbyak::Reg64 result;
@ -1055,112 +1020,98 @@ void EmitX64<JST>::EmitNot64(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitSignExtendByteToWord(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitSignExtendByteToWord(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
code->movsx(result.cvt32(), result.cvt8()); code->movsx(result.cvt32(), result.cvt8());
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitSignExtendHalfToWord(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitSignExtendHalfToWord(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
code->movsx(result.cvt32(), result.cvt16()); code->movsx(result.cvt32(), result.cvt16());
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitSignExtendByteToLong(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitSignExtendByteToLong(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
code->movsx(result.cvt64(), result.cvt8()); code->movsx(result.cvt64(), result.cvt8());
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitSignExtendHalfToLong(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitSignExtendHalfToLong(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
code->movsx(result.cvt64(), result.cvt16()); code->movsx(result.cvt64(), result.cvt16());
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitSignExtendWordToLong(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitSignExtendWordToLong(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
code->movsxd(result.cvt64(), result.cvt32()); code->movsxd(result.cvt64(), result.cvt32());
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitZeroExtendByteToWord(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitZeroExtendByteToWord(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
code->movzx(result.cvt32(), result.cvt8()); code->movzx(result.cvt32(), result.cvt8());
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitZeroExtendHalfToWord(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitZeroExtendHalfToWord(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
code->movzx(result.cvt32(), result.cvt16()); code->movzx(result.cvt32(), result.cvt16());
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitZeroExtendByteToLong(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitZeroExtendByteToLong(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
code->movzx(result.cvt32(), result.cvt8()); // x64 zeros upper 32 bits on a 32-bit move code->movzx(result.cvt32(), result.cvt8()); // x64 zeros upper 32 bits on a 32-bit move
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitZeroExtendHalfToLong(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitZeroExtendHalfToLong(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
code->movzx(result.cvt32(), result.cvt16()); // x64 zeros upper 32 bits on a 32-bit move code->movzx(result.cvt32(), result.cvt16()); // x64 zeros upper 32 bits on a 32-bit move
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitZeroExtendWordToLong(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitZeroExtendWordToLong(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
code->mov(result.cvt32(), result.cvt32()); // x64 zeros upper 32 bits on a 32-bit move code->mov(result.cvt32(), result.cvt32()); // x64 zeros upper 32 bits on a 32-bit move
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitByteReverseWord(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitByteReverseWord(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
code->bswap(result); code->bswap(result);
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitByteReverseHalf(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitByteReverseHalf(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg16 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt16(); Xbyak::Reg16 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt16();
code->rol(result, 8); code->rol(result, 8);
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitByteReverseDual(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitByteReverseDual(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
code->bswap(result); code->bswap(result);
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitCountLeadingZeros32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitCountLeadingZeros32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
if (code->DoesCpuSupport(Xbyak::util::Cpu::tLZCNT)) { if (code->DoesCpuSupport(Xbyak::util::Cpu::tLZCNT)) {
Xbyak::Reg32 source = ctx.reg_alloc.UseGpr(args[0]).cvt32(); Xbyak::Reg32 source = ctx.reg_alloc.UseGpr(args[0]).cvt32();
@ -1184,8 +1135,7 @@ void EmitX64<JST>::EmitCountLeadingZeros32(EmitContext& ctx, IR::Inst* inst) {
} }
} }
template <typename JST> void EmitX64::EmitCountLeadingZeros64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitCountLeadingZeros64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
if (code->DoesCpuSupport(Xbyak::util::Cpu::tLZCNT)) { if (code->DoesCpuSupport(Xbyak::util::Cpu::tLZCNT)) {
Xbyak::Reg64 source = ctx.reg_alloc.UseGpr(args[0]).cvt64(); Xbyak::Reg64 source = ctx.reg_alloc.UseGpr(args[0]).cvt64();
@ -1211,9 +1161,3 @@ void EmitX64<JST>::EmitCountLeadingZeros64(EmitContext& ctx, IR::Inst* inst) {
} // namespace BackendX64 } // namespace BackendX64
} // namespace Dynarmic } // namespace Dynarmic
#include "backend_x64/a32_jitstate.h"
#include "backend_x64/a64_jitstate.h"
template class Dynarmic::BackendX64::EmitX64<Dynarmic::BackendX64::A32JitState>;
template class Dynarmic::BackendX64::EmitX64<Dynarmic::BackendX64::A64JitState>;

View file

@ -30,7 +30,6 @@ constexpr u64 f64_min_s32 = 0xc1e0000000000000u; // -2147483648 as a double
constexpr u64 f64_max_s32 = 0x41dfffffffc00000u; // 2147483647 as a double constexpr u64 f64_max_s32 = 0x41dfffffffc00000u; // 2147483647 as a double
constexpr u64 f64_min_u32 = 0x0000000000000000u; // 0 as a double constexpr u64 f64_min_u32 = 0x0000000000000000u; // 0 as a double
template <typename JST>
static void DenormalsAreZero32(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Reg32 gpr_scratch) { static void DenormalsAreZero32(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Reg32 gpr_scratch) {
Xbyak::Label end; Xbyak::Label end;
@ -47,7 +46,6 @@ static void DenormalsAreZero32(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::R
code->L(end); code->L(end);
} }
template <typename JST>
static void DenormalsAreZero64(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Reg64 gpr_scratch) { static void DenormalsAreZero64(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Reg64 gpr_scratch) {
Xbyak::Label end; Xbyak::Label end;
@ -66,7 +64,6 @@ static void DenormalsAreZero64(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::R
code->L(end); code->L(end);
} }
template <typename JST>
static void FlushToZero32(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Reg32 gpr_scratch) { static void FlushToZero32(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Reg32 gpr_scratch) {
Xbyak::Label end; Xbyak::Label end;
@ -80,7 +77,6 @@ static void FlushToZero32(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Reg32
code->L(end); code->L(end);
} }
template <typename JST>
static void FlushToZero64(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Reg64 gpr_scratch) { static void FlushToZero64(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Reg64 gpr_scratch) {
Xbyak::Label end; Xbyak::Label end;
@ -123,7 +119,6 @@ static void ZeroIfNaN64(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Xmm xmm_
code->pand(xmm_value, xmm_scratch); code->pand(xmm_value, xmm_scratch);
} }
template <typename JST>
static void FPThreeOp32(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void (Xbyak::CodeGenerator::*fn)(const Xbyak::Xmm&, const Xbyak::Operand&)) { static void FPThreeOp32(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void (Xbyak::CodeGenerator::*fn)(const Xbyak::Xmm&, const Xbyak::Operand&)) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -132,12 +127,12 @@ static void FPThreeOp32(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, voi
Xbyak::Reg32 gpr_scratch = ctx.reg_alloc.ScratchGpr().cvt32(); Xbyak::Reg32 gpr_scratch = ctx.reg_alloc.ScratchGpr().cvt32();
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
DenormalsAreZero32<JST>(code, result, gpr_scratch); DenormalsAreZero32(code, result, gpr_scratch);
DenormalsAreZero32<JST>(code, operand, gpr_scratch); DenormalsAreZero32(code, operand, gpr_scratch);
} }
(code->*fn)(result, operand); (code->*fn)(result, operand);
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
FlushToZero32<JST>(code, result, gpr_scratch); FlushToZero32(code, result, gpr_scratch);
} }
if (ctx.FPSCR_DN()) { if (ctx.FPSCR_DN()) {
DefaultNaN32(code, result); DefaultNaN32(code, result);
@ -146,7 +141,6 @@ static void FPThreeOp32(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, voi
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST>
static void FPThreeOp64(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void (Xbyak::CodeGenerator::*fn)(const Xbyak::Xmm&, const Xbyak::Operand&)) { static void FPThreeOp64(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void (Xbyak::CodeGenerator::*fn)(const Xbyak::Xmm&, const Xbyak::Operand&)) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -155,12 +149,12 @@ static void FPThreeOp64(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, voi
Xbyak::Reg64 gpr_scratch = ctx.reg_alloc.ScratchGpr(); Xbyak::Reg64 gpr_scratch = ctx.reg_alloc.ScratchGpr();
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
DenormalsAreZero64<JST>(code, result, gpr_scratch); DenormalsAreZero64(code, result, gpr_scratch);
DenormalsAreZero64<JST>(code, operand, gpr_scratch); DenormalsAreZero64(code, operand, gpr_scratch);
} }
(code->*fn)(result, operand); (code->*fn)(result, operand);
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
FlushToZero64<JST>(code, result, gpr_scratch); FlushToZero64(code, result, gpr_scratch);
} }
if (ctx.FPSCR_DN()) { if (ctx.FPSCR_DN()) {
DefaultNaN64(code, result); DefaultNaN64(code, result);
@ -169,7 +163,6 @@ static void FPThreeOp64(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, voi
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST>
static void FPTwoOp32(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void (Xbyak::CodeGenerator::*fn)(const Xbyak::Xmm&, const Xbyak::Operand&)) { static void FPTwoOp32(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void (Xbyak::CodeGenerator::*fn)(const Xbyak::Xmm&, const Xbyak::Operand&)) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -177,12 +170,12 @@ static void FPTwoOp32(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void
Xbyak::Reg32 gpr_scratch = ctx.reg_alloc.ScratchGpr().cvt32(); Xbyak::Reg32 gpr_scratch = ctx.reg_alloc.ScratchGpr().cvt32();
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
DenormalsAreZero32<JST>(code, result, gpr_scratch); DenormalsAreZero32(code, result, gpr_scratch);
} }
(code->*fn)(result, result); (code->*fn)(result, result);
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
FlushToZero32<JST>(code, result, gpr_scratch); FlushToZero32(code, result, gpr_scratch);
} }
if (ctx.FPSCR_DN()) { if (ctx.FPSCR_DN()) {
DefaultNaN32(code, result); DefaultNaN32(code, result);
@ -191,7 +184,6 @@ static void FPTwoOp32(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST>
static void FPTwoOp64(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void (Xbyak::CodeGenerator::*fn)(const Xbyak::Xmm&, const Xbyak::Operand&)) { static void FPTwoOp64(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void (Xbyak::CodeGenerator::*fn)(const Xbyak::Xmm&, const Xbyak::Operand&)) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -199,12 +191,12 @@ static void FPTwoOp64(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void
Xbyak::Reg64 gpr_scratch = ctx.reg_alloc.ScratchGpr(); Xbyak::Reg64 gpr_scratch = ctx.reg_alloc.ScratchGpr();
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
DenormalsAreZero64<JST>(code, result, gpr_scratch); DenormalsAreZero64(code, result, gpr_scratch);
} }
(code->*fn)(result, result); (code->*fn)(result, result);
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
FlushToZero64<JST>(code, result, gpr_scratch); FlushToZero64(code, result, gpr_scratch);
} }
if (ctx.FPSCR_DN()) { if (ctx.FPSCR_DN()) {
DefaultNaN64(code, result); DefaultNaN64(code, result);
@ -213,8 +205,7 @@ static void FPTwoOp64(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitFPAbs32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPAbs32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]);
@ -223,8 +214,7 @@ void EmitX64<JST>::EmitFPAbs32(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitFPAbs64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPAbs64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]);
@ -233,8 +223,7 @@ void EmitX64<JST>::EmitFPAbs64(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitFPNeg32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPNeg32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]);
@ -243,8 +232,7 @@ void EmitX64<JST>::EmitFPNeg32(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitFPNeg64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPNeg64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]);
@ -253,57 +241,46 @@ void EmitX64<JST>::EmitFPNeg64(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitFPAdd32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPAdd32(EmitContext& ctx, IR::Inst* inst) { FPThreeOp32(code, ctx, inst, &Xbyak::CodeGenerator::addss);
FPThreeOp32<JST>(code, ctx, inst, &Xbyak::CodeGenerator::addss);
} }
template <typename JST> void EmitX64::EmitFPAdd64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPAdd64(EmitContext& ctx, IR::Inst* inst) { FPThreeOp64(code, ctx, inst, &Xbyak::CodeGenerator::addsd);
FPThreeOp64<JST>(code, ctx, inst, &Xbyak::CodeGenerator::addsd);
} }
template <typename JST> void EmitX64::EmitFPDiv32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPDiv32(EmitContext& ctx, IR::Inst* inst) { FPThreeOp32(code, ctx, inst, &Xbyak::CodeGenerator::divss);
FPThreeOp32<JST>(code, ctx, inst, &Xbyak::CodeGenerator::divss);
} }
template <typename JST> void EmitX64::EmitFPDiv64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPDiv64(EmitContext& ctx, IR::Inst* inst) { FPThreeOp64(code, ctx, inst, &Xbyak::CodeGenerator::divsd);
FPThreeOp64<JST>(code, ctx, inst, &Xbyak::CodeGenerator::divsd);
} }
template <typename JST> void EmitX64::EmitFPMul32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPMul32(EmitContext& ctx, IR::Inst* inst) { FPThreeOp32(code, ctx, inst, &Xbyak::CodeGenerator::mulss);
FPThreeOp32<JST>(code, ctx, inst, &Xbyak::CodeGenerator::mulss);
} }
template <typename JST> void EmitX64::EmitFPMul64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPMul64(EmitContext& ctx, IR::Inst* inst) { FPThreeOp64(code, ctx, inst, &Xbyak::CodeGenerator::mulsd);
FPThreeOp64<JST>(code, ctx, inst, &Xbyak::CodeGenerator::mulsd);
} }
template <typename JST> void EmitX64::EmitFPSqrt32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPSqrt32(EmitContext& ctx, IR::Inst* inst) { FPTwoOp32(code, ctx, inst, &Xbyak::CodeGenerator::sqrtss);
FPTwoOp32<JST>(code, ctx, inst, &Xbyak::CodeGenerator::sqrtss);
} }
template <typename JST> void EmitX64::EmitFPSqrt64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPSqrt64(EmitContext& ctx, IR::Inst* inst) { FPTwoOp64(code, ctx, inst, &Xbyak::CodeGenerator::sqrtsd);
FPTwoOp64<JST>(code, ctx, inst, &Xbyak::CodeGenerator::sqrtsd);
} }
template <typename JST> void EmitX64::EmitFPSub32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPSub32(EmitContext& ctx, IR::Inst* inst) { FPThreeOp32(code, ctx, inst, &Xbyak::CodeGenerator::subss);
FPThreeOp32<JST>(code, ctx, inst, &Xbyak::CodeGenerator::subss);
} }
template <typename JST> void EmitX64::EmitFPSub64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPSub64(EmitContext& ctx, IR::Inst* inst) { FPThreeOp64(code, ctx, inst, &Xbyak::CodeGenerator::subsd);
FPThreeOp64<JST>(code, ctx, inst, &Xbyak::CodeGenerator::subsd);
} }
template <typename JST>
static void SetFpscrNzcvFromFlags(BlockOfCode* code, EmitContext& ctx) { static void SetFpscrNzcvFromFlags(BlockOfCode* code, EmitContext& ctx) {
ctx.reg_alloc.ScratchGpr({HostLoc::RCX}); // shifting requires use of cl ctx.reg_alloc.ScratchGpr({HostLoc::RCX}); // shifting requires use of cl
Xbyak::Reg32 nzcv = ctx.reg_alloc.ScratchGpr().cvt32(); Xbyak::Reg32 nzcv = ctx.reg_alloc.ScratchGpr().cvt32();
@ -316,8 +293,7 @@ static void SetFpscrNzcvFromFlags(BlockOfCode* code, EmitContext& ctx) {
code->mov(dword[r15 + code->GetJitStateInfo().offsetof_FPSCR_nzcv], nzcv); code->mov(dword[r15 + code->GetJitStateInfo().offsetof_FPSCR_nzcv], nzcv);
} }
template <typename JST> void EmitX64::EmitFPCompare32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPCompare32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm reg_a = ctx.reg_alloc.UseXmm(args[0]); Xbyak::Xmm reg_a = ctx.reg_alloc.UseXmm(args[0]);
Xbyak::Xmm reg_b = ctx.reg_alloc.UseXmm(args[1]); Xbyak::Xmm reg_b = ctx.reg_alloc.UseXmm(args[1]);
@ -329,11 +305,10 @@ void EmitX64<JST>::EmitFPCompare32(EmitContext& ctx, IR::Inst* inst) {
code->ucomiss(reg_a, reg_b); code->ucomiss(reg_a, reg_b);
} }
SetFpscrNzcvFromFlags<JST>(code, ctx); SetFpscrNzcvFromFlags(code, ctx);
} }
template <typename JST> void EmitX64::EmitFPCompare64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPCompare64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm reg_a = ctx.reg_alloc.UseXmm(args[0]); Xbyak::Xmm reg_a = ctx.reg_alloc.UseXmm(args[0]);
Xbyak::Xmm reg_b = ctx.reg_alloc.UseXmm(args[1]); Xbyak::Xmm reg_b = ctx.reg_alloc.UseXmm(args[1]);
@ -345,21 +320,20 @@ void EmitX64<JST>::EmitFPCompare64(EmitContext& ctx, IR::Inst* inst) {
code->ucomisd(reg_a, reg_b); code->ucomisd(reg_a, reg_b);
} }
SetFpscrNzcvFromFlags<JST>(code, ctx); SetFpscrNzcvFromFlags(code, ctx);
} }
template <typename JST> void EmitX64::EmitFPSingleToDouble(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPSingleToDouble(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]);
Xbyak::Reg64 gpr_scratch = ctx.reg_alloc.ScratchGpr(); Xbyak::Reg64 gpr_scratch = ctx.reg_alloc.ScratchGpr();
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
DenormalsAreZero32<JST>(code, result, gpr_scratch.cvt32()); DenormalsAreZero32(code, result, gpr_scratch.cvt32());
} }
code->cvtss2sd(result, result); code->cvtss2sd(result, result);
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
FlushToZero64<JST>(code, result, gpr_scratch); FlushToZero64(code, result, gpr_scratch);
} }
if (ctx.FPSCR_DN()) { if (ctx.FPSCR_DN()) {
DefaultNaN64(code, result); DefaultNaN64(code, result);
@ -368,18 +342,17 @@ void EmitX64<JST>::EmitFPSingleToDouble(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitFPDoubleToSingle(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPDoubleToSingle(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]);
Xbyak::Reg64 gpr_scratch = ctx.reg_alloc.ScratchGpr(); Xbyak::Reg64 gpr_scratch = ctx.reg_alloc.ScratchGpr();
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
DenormalsAreZero64<JST>(code, result, gpr_scratch); DenormalsAreZero64(code, result, gpr_scratch);
} }
code->cvtsd2ss(result, result); code->cvtsd2ss(result, result);
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
FlushToZero32<JST>(code, result, gpr_scratch.cvt32()); FlushToZero32(code, result, gpr_scratch.cvt32());
} }
if (ctx.FPSCR_DN()) { if (ctx.FPSCR_DN()) {
DefaultNaN32(code, result); DefaultNaN32(code, result);
@ -388,8 +361,7 @@ void EmitX64<JST>::EmitFPDoubleToSingle(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitFPSingleToS32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPSingleToS32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm from = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm from = ctx.reg_alloc.UseScratchXmm(args[0]);
Xbyak::Reg32 to = ctx.reg_alloc.ScratchGpr().cvt32(); Xbyak::Reg32 to = ctx.reg_alloc.ScratchGpr().cvt32();
@ -400,7 +372,7 @@ void EmitX64<JST>::EmitFPSingleToS32(EmitContext& ctx, IR::Inst* inst) {
// Conversion to double is lossless, and allows for clamping. // Conversion to double is lossless, and allows for clamping.
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
DenormalsAreZero32<JST>(code, from, to); DenormalsAreZero32(code, from, to);
} }
code->cvtss2sd(from, from); code->cvtss2sd(from, from);
// First time is to set flags // First time is to set flags
@ -423,8 +395,7 @@ void EmitX64<JST>::EmitFPSingleToS32(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, to); ctx.reg_alloc.DefineValue(inst, to);
} }
template <typename JST> void EmitX64::EmitFPSingleToU32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPSingleToU32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm from = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm from = ctx.reg_alloc.UseScratchXmm(args[0]);
Xbyak::Reg32 to = ctx.reg_alloc.ScratchGpr().cvt32(); Xbyak::Reg32 to = ctx.reg_alloc.ScratchGpr().cvt32();
@ -440,7 +411,7 @@ void EmitX64<JST>::EmitFPSingleToU32(EmitContext& ctx, IR::Inst* inst) {
if (!ctx.FPSCR_RoundTowardsZero() && !round_towards_zero) { if (!ctx.FPSCR_RoundTowardsZero() && !round_towards_zero) {
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
DenormalsAreZero32<JST>(code, from, to); DenormalsAreZero32(code, from, to);
} }
code->cvtss2sd(from, from); code->cvtss2sd(from, from);
ZeroIfNaN64(code, from, xmm_scratch); ZeroIfNaN64(code, from, xmm_scratch);
@ -460,7 +431,7 @@ void EmitX64<JST>::EmitFPSingleToU32(EmitContext& ctx, IR::Inst* inst) {
Xbyak::Reg32 gpr_mask = ctx.reg_alloc.ScratchGpr().cvt32(); Xbyak::Reg32 gpr_mask = ctx.reg_alloc.ScratchGpr().cvt32();
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
DenormalsAreZero32<JST>(code, from, to); DenormalsAreZero32(code, from, to);
} }
code->cvtss2sd(from, from); code->cvtss2sd(from, from);
ZeroIfNaN64(code, from, xmm_scratch); ZeroIfNaN64(code, from, xmm_scratch);
@ -486,8 +457,7 @@ void EmitX64<JST>::EmitFPSingleToU32(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, to); ctx.reg_alloc.DefineValue(inst, to);
} }
template <typename JST> void EmitX64::EmitFPDoubleToS32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPDoubleToS32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm from = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm from = ctx.reg_alloc.UseScratchXmm(args[0]);
Xbyak::Reg32 to = ctx.reg_alloc.ScratchGpr().cvt32(); Xbyak::Reg32 to = ctx.reg_alloc.ScratchGpr().cvt32();
@ -498,7 +468,7 @@ void EmitX64<JST>::EmitFPDoubleToS32(EmitContext& ctx, IR::Inst* inst) {
// ARM saturates on conversion; this differs from x64 which returns a sentinel value. // ARM saturates on conversion; this differs from x64 which returns a sentinel value.
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
DenormalsAreZero64<JST>(code, from, gpr_scratch.cvt64()); DenormalsAreZero64(code, from, gpr_scratch.cvt64());
} }
// First time is to set flags // First time is to set flags
if (round_towards_zero) { if (round_towards_zero) {
@ -520,8 +490,7 @@ void EmitX64<JST>::EmitFPDoubleToS32(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, to); ctx.reg_alloc.DefineValue(inst, to);
} }
template <typename JST> void EmitX64::EmitFPDoubleToU32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPDoubleToU32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm from = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm from = ctx.reg_alloc.UseScratchXmm(args[0]);
Xbyak::Reg32 to = ctx.reg_alloc.ScratchGpr().cvt32(); Xbyak::Reg32 to = ctx.reg_alloc.ScratchGpr().cvt32();
@ -535,7 +504,7 @@ void EmitX64<JST>::EmitFPDoubleToU32(EmitContext& ctx, IR::Inst* inst) {
if (!ctx.FPSCR_RoundTowardsZero() && !round_towards_zero) { if (!ctx.FPSCR_RoundTowardsZero() && !round_towards_zero) {
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
DenormalsAreZero64<JST>(code, from, gpr_scratch.cvt64()); DenormalsAreZero64(code, from, gpr_scratch.cvt64());
} }
ZeroIfNaN64(code, from, xmm_scratch); ZeroIfNaN64(code, from, xmm_scratch);
// Bring into SSE range // Bring into SSE range
@ -554,7 +523,7 @@ void EmitX64<JST>::EmitFPDoubleToU32(EmitContext& ctx, IR::Inst* inst) {
Xbyak::Reg32 gpr_mask = ctx.reg_alloc.ScratchGpr().cvt32(); Xbyak::Reg32 gpr_mask = ctx.reg_alloc.ScratchGpr().cvt32();
if (ctx.FPSCR_FTZ()) { if (ctx.FPSCR_FTZ()) {
DenormalsAreZero64<JST>(code, from, gpr_scratch.cvt64()); DenormalsAreZero64(code, from, gpr_scratch.cvt64());
} }
ZeroIfNaN64(code, from, xmm_scratch); ZeroIfNaN64(code, from, xmm_scratch);
// Generate masks if out-of-signed-range // Generate masks if out-of-signed-range
@ -579,8 +548,7 @@ void EmitX64<JST>::EmitFPDoubleToU32(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, to); ctx.reg_alloc.DefineValue(inst, to);
} }
template <typename JST> void EmitX64::EmitFPS32ToSingle(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPS32ToSingle(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 from = ctx.reg_alloc.UseGpr(args[0]).cvt32(); Xbyak::Reg32 from = ctx.reg_alloc.UseGpr(args[0]).cvt32();
Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm(); Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm();
@ -592,8 +560,7 @@ void EmitX64<JST>::EmitFPS32ToSingle(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, to); ctx.reg_alloc.DefineValue(inst, to);
} }
template <typename JST> void EmitX64::EmitFPU32ToSingle(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPU32ToSingle(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]); Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]);
Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm(); Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm();
@ -607,8 +574,7 @@ void EmitX64<JST>::EmitFPU32ToSingle(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, to); ctx.reg_alloc.DefineValue(inst, to);
} }
template <typename JST> void EmitX64::EmitFPS32ToDouble(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPS32ToDouble(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 from = ctx.reg_alloc.UseGpr(args[0]).cvt32(); Xbyak::Reg32 from = ctx.reg_alloc.UseGpr(args[0]).cvt32();
Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm(); Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm();
@ -620,8 +586,7 @@ void EmitX64<JST>::EmitFPS32ToDouble(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, to); ctx.reg_alloc.DefineValue(inst, to);
} }
template <typename JST> void EmitX64::EmitFPU32ToDouble(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitFPU32ToDouble(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]); Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]);
Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm(); Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm();
@ -637,9 +602,3 @@ void EmitX64<JST>::EmitFPU32ToDouble(EmitContext& ctx, IR::Inst* inst) {
} // namespace BackendX64 } // namespace BackendX64
} // namespace Dynarmic } // namespace Dynarmic
#include "backend_x64/a32_jitstate.h"
#include "backend_x64/a64_jitstate.h"
template class Dynarmic::BackendX64::EmitX64<Dynarmic::BackendX64::A32JitState>;
template class Dynarmic::BackendX64::EmitX64<Dynarmic::BackendX64::A64JitState>;

View file

@ -17,8 +17,7 @@ namespace BackendX64 {
using namespace Xbyak::util; using namespace Xbyak::util;
template <typename JST> void EmitX64::EmitPackedAddU8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedAddU8(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp); auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
@ -45,8 +44,7 @@ void EmitX64<JST>::EmitPackedAddU8(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
} }
template <typename JST> void EmitX64::EmitPackedAddS8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedAddS8(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp); auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
@ -73,8 +71,7 @@ void EmitX64<JST>::EmitPackedAddS8(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
} }
template <typename JST> void EmitX64::EmitPackedAddU16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedAddU16(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp); auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
@ -116,8 +113,7 @@ void EmitX64<JST>::EmitPackedAddU16(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
} }
template <typename JST> void EmitX64::EmitPackedAddS16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedAddS16(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp); auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
@ -144,8 +140,7 @@ void EmitX64<JST>::EmitPackedAddS16(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
} }
template <typename JST> void EmitX64::EmitPackedSubU8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedSubU8(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp); auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
@ -168,8 +163,7 @@ void EmitX64<JST>::EmitPackedSubU8(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
} }
template <typename JST> void EmitX64::EmitPackedSubS8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedSubS8(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp); auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
@ -196,8 +190,7 @@ void EmitX64<JST>::EmitPackedSubS8(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
} }
template <typename JST> void EmitX64::EmitPackedSubU16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedSubU16(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp); auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
@ -236,8 +229,7 @@ void EmitX64<JST>::EmitPackedSubU16(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
} }
template <typename JST> void EmitX64::EmitPackedSubS16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedSubS16(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp); auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
@ -264,8 +256,7 @@ void EmitX64<JST>::EmitPackedSubS16(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
} }
template <typename JST> void EmitX64::EmitPackedHalvingAddU8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedHalvingAddU8(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
if (args[0].IsInXmm() || args[1].IsInXmm()) { if (args[0].IsInXmm() || args[1].IsInXmm()) {
@ -308,8 +299,7 @@ void EmitX64<JST>::EmitPackedHalvingAddU8(EmitContext& ctx, IR::Inst* inst) {
} }
} }
template <typename JST> void EmitX64::EmitPackedHalvingAddU16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedHalvingAddU16(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
if (args[0].IsInXmm() || args[1].IsInXmm()) { if (args[0].IsInXmm() || args[1].IsInXmm()) {
@ -347,8 +337,7 @@ void EmitX64<JST>::EmitPackedHalvingAddU16(EmitContext& ctx, IR::Inst* inst) {
} }
} }
template <typename JST> void EmitX64::EmitPackedHalvingAddS8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedHalvingAddS8(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 reg_a = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); Xbyak::Reg32 reg_a = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
@ -377,8 +366,7 @@ void EmitX64<JST>::EmitPackedHalvingAddS8(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitPackedHalvingAddS16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedHalvingAddS16(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(args[0]);
@ -399,8 +387,7 @@ void EmitX64<JST>::EmitPackedHalvingAddS16(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
} }
template <typename JST> void EmitX64::EmitPackedHalvingSubU8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedHalvingSubU8(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 minuend = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); Xbyak::Reg32 minuend = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
@ -430,8 +417,7 @@ void EmitX64<JST>::EmitPackedHalvingSubU8(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, minuend); ctx.reg_alloc.DefineValue(inst, minuend);
} }
template <typename JST> void EmitX64::EmitPackedHalvingSubS8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedHalvingSubS8(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 minuend = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); Xbyak::Reg32 minuend = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
@ -467,8 +453,7 @@ void EmitX64<JST>::EmitPackedHalvingSubS8(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, minuend); ctx.reg_alloc.DefineValue(inst, minuend);
} }
template <typename JST> void EmitX64::EmitPackedHalvingSubU16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedHalvingSubU16(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm minuend = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm minuend = ctx.reg_alloc.UseScratchXmm(args[0]);
@ -491,8 +476,7 @@ void EmitX64<JST>::EmitPackedHalvingSubU16(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, minuend); ctx.reg_alloc.DefineValue(inst, minuend);
} }
template <typename JST> void EmitX64::EmitPackedHalvingSubS16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedHalvingSubS16(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm minuend = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm minuend = ctx.reg_alloc.UseScratchXmm(args[0]);
@ -588,43 +572,35 @@ void EmitPackedSubAdd(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, bool
ctx.reg_alloc.DefineValue(inst, reg_a_hi); ctx.reg_alloc.DefineValue(inst, reg_a_hi);
} }
template <typename JST> void EmitX64::EmitPackedAddSubU16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedAddSubU16(EmitContext& ctx, IR::Inst* inst) {
EmitPackedSubAdd(code, ctx, inst, true, false, false); EmitPackedSubAdd(code, ctx, inst, true, false, false);
} }
template <typename JST> void EmitX64::EmitPackedAddSubS16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedAddSubS16(EmitContext& ctx, IR::Inst* inst) {
EmitPackedSubAdd(code, ctx, inst, true, true, false); EmitPackedSubAdd(code, ctx, inst, true, true, false);
} }
template <typename JST> void EmitX64::EmitPackedSubAddU16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedSubAddU16(EmitContext& ctx, IR::Inst* inst) {
EmitPackedSubAdd(code, ctx, inst, false, false, false); EmitPackedSubAdd(code, ctx, inst, false, false, false);
} }
template <typename JST> void EmitX64::EmitPackedSubAddS16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedSubAddS16(EmitContext& ctx, IR::Inst* inst) {
EmitPackedSubAdd(code, ctx, inst, false, true, false); EmitPackedSubAdd(code, ctx, inst, false, true, false);
} }
template <typename JST> void EmitX64::EmitPackedHalvingAddSubU16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedHalvingAddSubU16(EmitContext& ctx, IR::Inst* inst) {
EmitPackedSubAdd(code, ctx, inst, true, false, true); EmitPackedSubAdd(code, ctx, inst, true, false, true);
} }
template <typename JST> void EmitX64::EmitPackedHalvingAddSubS16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedHalvingAddSubS16(EmitContext& ctx, IR::Inst* inst) {
EmitPackedSubAdd(code, ctx, inst, true, true, true); EmitPackedSubAdd(code, ctx, inst, true, true, true);
} }
template <typename JST> void EmitX64::EmitPackedHalvingSubAddU16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedHalvingSubAddU16(EmitContext& ctx, IR::Inst* inst) {
EmitPackedSubAdd(code, ctx, inst, false, false, true); EmitPackedSubAdd(code, ctx, inst, false, false, true);
} }
template <typename JST> void EmitX64::EmitPackedHalvingSubAddS16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedHalvingSubAddS16(EmitContext& ctx, IR::Inst* inst) {
EmitPackedSubAdd(code, ctx, inst, false, true, true); EmitPackedSubAdd(code, ctx, inst, false, true, true);
} }
@ -639,53 +615,43 @@ static void EmitPackedOperation(BlockOfCode* code, EmitContext& ctx, IR::Inst* i
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
} }
template <typename JST> void EmitX64::EmitPackedSaturatedAddU8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedSaturatedAddU8(EmitContext& ctx, IR::Inst* inst) {
EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddusb); EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddusb);
} }
template <typename JST> void EmitX64::EmitPackedSaturatedAddS8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedSaturatedAddS8(EmitContext& ctx, IR::Inst* inst) {
EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddsb); EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddsb);
} }
template <typename JST> void EmitX64::EmitPackedSaturatedSubU8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedSaturatedSubU8(EmitContext& ctx, IR::Inst* inst) {
EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::psubusb); EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::psubusb);
} }
template <typename JST> void EmitX64::EmitPackedSaturatedSubS8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedSaturatedSubS8(EmitContext& ctx, IR::Inst* inst) {
EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::psubsb); EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::psubsb);
} }
template <typename JST> void EmitX64::EmitPackedSaturatedAddU16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedSaturatedAddU16(EmitContext& ctx, IR::Inst* inst) {
EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddusw); EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddusw);
} }
template <typename JST> void EmitX64::EmitPackedSaturatedAddS16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedSaturatedAddS16(EmitContext& ctx, IR::Inst* inst) {
EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddsw); EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddsw);
} }
template <typename JST> void EmitX64::EmitPackedSaturatedSubU16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedSaturatedSubU16(EmitContext& ctx, IR::Inst* inst) {
EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::psubusw); EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::psubusw);
} }
template <typename JST> void EmitX64::EmitPackedSaturatedSubS16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedSaturatedSubS16(EmitContext& ctx, IR::Inst* inst) {
EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::psubsw); EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::psubsw);
} }
template <typename JST> void EmitX64::EmitPackedAbsDiffSumS8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedAbsDiffSumS8(EmitContext& ctx, IR::Inst* inst) {
EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::psadbw); EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::psadbw);
} }
template <typename JST> void EmitX64::EmitPackedSelect(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitPackedSelect(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
size_t num_args_in_xmm = args[0].IsInXmm() + args[1].IsInXmm() + args[2].IsInXmm(); size_t num_args_in_xmm = args[0].IsInXmm() + args[1].IsInXmm() + args[2].IsInXmm();
@ -726,9 +692,3 @@ void EmitX64<JST>::EmitPackedSelect(EmitContext& ctx, IR::Inst* inst) {
} // namespace BackendX64 } // namespace BackendX64
} // namespace Dynarmic } // namespace Dynarmic
#include "backend_x64/a32_jitstate.h"
#include "backend_x64/a64_jitstate.h"
template class Dynarmic::BackendX64::EmitX64<Dynarmic::BackendX64::A32JitState>;
template class Dynarmic::BackendX64::EmitX64<Dynarmic::BackendX64::A64JitState>;

View file

@ -18,8 +18,7 @@ namespace BackendX64 {
using namespace Xbyak::util; using namespace Xbyak::util;
template <typename JST> void EmitX64::EmitSignedSaturatedAdd(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitSignedSaturatedAdd(EmitContext& ctx, IR::Inst* inst) {
auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp); auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -45,8 +44,7 @@ void EmitX64<JST>::EmitSignedSaturatedAdd(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitSignedSaturatedSub(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitSignedSaturatedSub(EmitContext& ctx, IR::Inst* inst) {
auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp); auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -72,8 +70,7 @@ void EmitX64<JST>::EmitSignedSaturatedSub(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitUnsignedSaturation(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitUnsignedSaturation(EmitContext& ctx, IR::Inst* inst) {
auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp); auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -103,8 +100,7 @@ void EmitX64<JST>::EmitUnsignedSaturation(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST> void EmitX64::EmitSignedSaturation(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitSignedSaturation(EmitContext& ctx, IR::Inst* inst) {
auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp); auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -155,9 +151,3 @@ void EmitX64<JST>::EmitSignedSaturation(EmitContext& ctx, IR::Inst* inst) {
} // namespace BackendX64 } // namespace BackendX64
} // namespace Dynarmic } // namespace Dynarmic
#include "backend_x64/a32_jitstate.h"
#include "backend_x64/a64_jitstate.h"
template class Dynarmic::BackendX64::EmitX64<Dynarmic::BackendX64::A32JitState>;
template class Dynarmic::BackendX64::EmitX64<Dynarmic::BackendX64::A64JitState>;

View file

@ -28,33 +28,27 @@ static void EmitVectorOperation(BlockOfCode* code, EmitContext& ctx, IR::Inst* i
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
} }
template <typename JST> void EmitX64::EmitVectorAdd8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitVectorAdd8(EmitContext& ctx, IR::Inst* inst) {
EmitVectorOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddb); EmitVectorOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddb);
} }
template <typename JST> void EmitX64::EmitVectorAdd16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitVectorAdd16(EmitContext& ctx, IR::Inst* inst) {
EmitVectorOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddw); EmitVectorOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddw);
} }
template <typename JST> void EmitX64::EmitVectorAdd32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitVectorAdd32(EmitContext& ctx, IR::Inst* inst) {
EmitVectorOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddd); EmitVectorOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddd);
} }
template <typename JST> void EmitX64::EmitVectorAdd64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitVectorAdd64(EmitContext& ctx, IR::Inst* inst) {
EmitVectorOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddq); EmitVectorOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddq);
} }
template <typename JST> void EmitX64::EmitVectorAnd(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitVectorAnd(EmitContext& ctx, IR::Inst* inst) {
EmitVectorOperation(code, ctx, inst, &Xbyak::CodeGenerator::pand); EmitVectorOperation(code, ctx, inst, &Xbyak::CodeGenerator::pand);
} }
template <typename JST> void EmitX64::EmitVectorLowerPairedAdd8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitVectorLowerPairedAdd8(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(args[0]);
@ -72,8 +66,7 @@ void EmitX64<JST>::EmitVectorLowerPairedAdd8(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
} }
template <typename JST> void EmitX64::EmitVectorLowerPairedAdd16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitVectorLowerPairedAdd16(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(args[0]);
@ -96,8 +89,7 @@ void EmitX64<JST>::EmitVectorLowerPairedAdd16(EmitContext& ctx, IR::Inst* inst)
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
} }
template <typename JST> void EmitX64::EmitVectorLowerPairedAdd32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitVectorLowerPairedAdd32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(args[0]);
@ -119,8 +111,7 @@ void EmitX64<JST>::EmitVectorLowerPairedAdd32(EmitContext& ctx, IR::Inst* inst)
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
} }
template <typename JST> void EmitX64::EmitVectorPairedAdd8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitVectorPairedAdd8(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm a = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm a = ctx.reg_alloc.UseScratchXmm(args[0]);
@ -141,8 +132,7 @@ void EmitX64<JST>::EmitVectorPairedAdd8(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, a); ctx.reg_alloc.DefineValue(inst, a);
} }
template <typename JST> void EmitX64::EmitVectorPairedAdd16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitVectorPairedAdd16(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
if (code->DoesCpuSupport(Xbyak::util::Cpu::tSSSE3)) { if (code->DoesCpuSupport(Xbyak::util::Cpu::tSSSE3)) {
@ -172,8 +162,7 @@ void EmitX64<JST>::EmitVectorPairedAdd16(EmitContext& ctx, IR::Inst* inst) {
} }
} }
template <typename JST> void EmitX64::EmitVectorPairedAdd32(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitVectorPairedAdd32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
if (code->DoesCpuSupport(Xbyak::util::Cpu::tSSSE3)) { if (code->DoesCpuSupport(Xbyak::util::Cpu::tSSSE3)) {
@ -201,8 +190,7 @@ void EmitX64<JST>::EmitVectorPairedAdd32(EmitContext& ctx, IR::Inst* inst) {
} }
} }
template <typename JST> void EmitX64::EmitVectorPairedAdd64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitVectorPairedAdd64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Xmm a = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Xmm a = ctx.reg_alloc.UseScratchXmm(args[0]);
@ -219,9 +207,3 @@ void EmitX64<JST>::EmitVectorPairedAdd64(EmitContext& ctx, IR::Inst* inst) {
} // namespace BackendX64 } // namespace BackendX64
} // namespace Dynarmic } // namespace Dynarmic
#include "backend_x64/a32_jitstate.h"
#include "backend_x64/a64_jitstate.h"
template class Dynarmic::BackendX64::EmitX64<Dynarmic::BackendX64::A32JitState>;
template class Dynarmic::BackendX64::EmitX64<Dynarmic::BackendX64::A64JitState>;