diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9679b0e5..19d53cc6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -167,6 +167,7 @@ if (ARCHITECTURE_x86_64) backend_x64/emit_x64_packed.cpp backend_x64/emit_x64_saturation.cpp backend_x64/emit_x64_vector.cpp + backend_x64/emit_x64_vector_floating_point.cpp backend_x64/hostloc.cpp backend_x64/hostloc.h backend_x64/jitstate_info.h diff --git a/src/backend_x64/emit_x64_vector_floating_point.cpp b/src/backend_x64/emit_x64_vector_floating_point.cpp new file mode 100644 index 00000000..53003f1f --- /dev/null +++ b/src/backend_x64/emit_x64_vector_floating_point.cpp @@ -0,0 +1,36 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 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 "backend_x64/block_of_code.h" +#include "backend_x64/emit_x64.h" +#include "frontend/ir/basic_block.h" +#include "frontend/ir/microinstruction.h" + +namespace Dynarmic::BackendX64 { + +using namespace Xbyak::util; + +template +static void EmitVectorOperation(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + + Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(args[0]); + Xbyak::Xmm xmm_b = ctx.reg_alloc.UseXmm(args[1]); + + (code.*fn)(xmm_a, xmm_b); + + ctx.reg_alloc.DefineValue(inst, xmm_a); +} + +void EmitX64::EmitFPVectorSub32(EmitContext& ctx, IR::Inst* inst) { + EmitVectorOperation(code, ctx, inst, &Xbyak::CodeGenerator::subps); +} + +void EmitX64::EmitFPVectorSub64(EmitContext& ctx, IR::Inst* inst) { + EmitVectorOperation(code, ctx, inst, &Xbyak::CodeGenerator::subpd); +} + +} // namespace Dynarmic::BackendX64 diff --git a/src/frontend/ir/ir_emitter.cpp b/src/frontend/ir/ir_emitter.cpp index 402319e3..1c79797c 100644 --- a/src/frontend/ir/ir_emitter.cpp +++ b/src/frontend/ir/ir_emitter.cpp @@ -1139,6 +1139,17 @@ U64 IREmitter::FPU32ToDouble(const U32& a, bool round_to_nearest, bool fpscr_con return Inst(Opcode::FPU32ToDouble, a, Imm1(round_to_nearest)); } +U128 IREmitter::FPVectorSub(size_t esize, const U128& a, const U128& b) { + switch (esize) { + case 32: + return Inst(Opcode::FPVectorSub32, a, b); + case 64: + return Inst(Opcode::FPVectorSub64, a, b); + } + UNREACHABLE(); + return {}; +} + void IREmitter::Breakpoint() { Inst(Opcode::Breakpoint); } diff --git a/src/frontend/ir/ir_emitter.h b/src/frontend/ir/ir_emitter.h index 436f8d11..c25d891f 100644 --- a/src/frontend/ir/ir_emitter.h +++ b/src/frontend/ir/ir_emitter.h @@ -247,6 +247,8 @@ public: U64 FPS32ToDouble(const U32& a, bool round_to_nearest, bool fpscr_controlled); U64 FPU32ToDouble(const U32& a, bool round_to_nearest, bool fpscr_controlled); + U128 FPVectorSub(size_t esize, const U128& a, const U128& b); + void Breakpoint(); void SetTerm(const Terminal& terminal); diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index 54690b71..85bd88b7 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -289,6 +289,10 @@ OPCODE(FPS32ToSingle, T::U32, T::U32, T::U1 OPCODE(FPU32ToDouble, T::U64, T::U32, T::U1 ) OPCODE(FPS32ToDouble, T::U64, T::U32, T::U1 ) +// Floating-point vector instructions +OPCODE(FPVectorSub32, T::U128, T::U128, T::U128 ) +OPCODE(FPVectorSub64, T::U128, T::U128, T::U128 ) + // A32 Memory access A32OPC(ClearExclusive, T::Void, ) A32OPC(SetExclusive, T::Void, T::U32, T::U8 )