mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-16 05:21:22 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f1fdb389a4 | |||
| 21bb1b8210 |
@@ -348,7 +348,11 @@ void A32EmitX64::EmitA32SetRegister(A32EmitContext& ctx, IR::Inst* inst) {
|
|||||||
code.mov(MJitStateReg(reg), args[1].GetImmediateU32());
|
code.mov(MJitStateReg(reg), args[1].GetImmediateU32());
|
||||||
} else if (args[1].IsInXmm(ctx.reg_alloc)) {
|
} else if (args[1].IsInXmm(ctx.reg_alloc)) {
|
||||||
const Xbyak::Xmm to_store = ctx.reg_alloc.UseXmm(code, args[1]);
|
const Xbyak::Xmm to_store = ctx.reg_alloc.UseXmm(code, args[1]);
|
||||||
|
if (code.HasHostFeature(HostFeature::AVX)) {
|
||||||
|
code.vmovd(MJitStateReg(reg), to_store);
|
||||||
|
} else {
|
||||||
code.movd(MJitStateReg(reg), to_store);
|
code.movd(MJitStateReg(reg), to_store);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const Xbyak::Reg32 to_store = ctx.reg_alloc.UseGpr(code, args[1]).cvt32();
|
const Xbyak::Reg32 to_store = ctx.reg_alloc.UseGpr(code, args[1]).cvt32();
|
||||||
code.mov(MJitStateReg(reg), to_store);
|
code.mov(MJitStateReg(reg), to_store);
|
||||||
@@ -641,7 +645,11 @@ void A32EmitX64::EmitA32OrQFlag(A32EmitContext& ctx, IR::Inst* inst) {
|
|||||||
|
|
||||||
void A32EmitX64::EmitA32GetGEFlags(A32EmitContext& ctx, IR::Inst* inst) {
|
void A32EmitX64::EmitA32GetGEFlags(A32EmitContext& ctx, IR::Inst* inst) {
|
||||||
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(code);
|
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(code);
|
||||||
|
if (code.HasHostFeature(HostFeature::AVX)) {
|
||||||
|
code.vmovd(result, dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_ge)]);
|
||||||
|
} else {
|
||||||
code.movd(result, dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_ge)]);
|
code.movd(result, dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_ge)]);
|
||||||
|
}
|
||||||
ctx.reg_alloc.DefineValue(code, inst, result);
|
ctx.reg_alloc.DefineValue(code, inst, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,7 +659,11 @@ void A32EmitX64::EmitA32SetGEFlags(A32EmitContext& ctx, IR::Inst* inst) {
|
|||||||
|
|
||||||
if (args[0].IsInXmm(ctx.reg_alloc)) {
|
if (args[0].IsInXmm(ctx.reg_alloc)) {
|
||||||
const Xbyak::Xmm to_store = ctx.reg_alloc.UseXmm(code, args[0]);
|
const Xbyak::Xmm to_store = ctx.reg_alloc.UseXmm(code, args[0]);
|
||||||
|
if (code.HasHostFeature(HostFeature::AVX)) {
|
||||||
|
code.vmovd(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_ge)], to_store);
|
||||||
|
} else {
|
||||||
code.movd(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_ge)], to_store);
|
code.movd(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_ge)], to_store);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const Xbyak::Reg32 to_store = ctx.reg_alloc.UseGpr(code, args[0]).cvt32();
|
const Xbyak::Reg32 to_store = ctx.reg_alloc.UseGpr(code, args[0]).cvt32();
|
||||||
code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_ge)], to_store);
|
code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, cpsr_ge)], to_store);
|
||||||
|
|||||||
@@ -339,7 +339,11 @@ void A64EmitX64::EmitA64GetS(A64EmitContext& ctx, IR::Inst* inst) {
|
|||||||
const auto addr = qword[code.ABI_JIT_PTR + offsetof(A64JitState, vec) + sizeof(u64) * 2 * static_cast<size_t>(vec)];
|
const auto addr = qword[code.ABI_JIT_PTR + offsetof(A64JitState, vec) + sizeof(u64) * 2 * static_cast<size_t>(vec)];
|
||||||
|
|
||||||
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(code);
|
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(code);
|
||||||
|
if (code.HasHostFeature(HostFeature::AVX)) {
|
||||||
|
code.vmovd(result, addr);
|
||||||
|
} else {
|
||||||
code.movd(result, addr);
|
code.movd(result, addr);
|
||||||
|
}
|
||||||
ctx.reg_alloc.DefineValue(code, inst, result);
|
ctx.reg_alloc.DefineValue(code, inst, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,7 +352,11 @@ void A64EmitX64::EmitA64GetD(A64EmitContext& ctx, IR::Inst* inst) {
|
|||||||
const auto addr = qword[code.ABI_JIT_PTR + offsetof(A64JitState, vec) + sizeof(u64) * 2 * static_cast<size_t>(vec)];
|
const auto addr = qword[code.ABI_JIT_PTR + offsetof(A64JitState, vec) + sizeof(u64) * 2 * static_cast<size_t>(vec)];
|
||||||
|
|
||||||
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(code);
|
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(code);
|
||||||
|
if (code.HasHostFeature(HostFeature::AVX)) {
|
||||||
|
code.vmovq(result, addr);
|
||||||
|
} else {
|
||||||
code.movq(result, addr);
|
code.movq(result, addr);
|
||||||
|
}
|
||||||
ctx.reg_alloc.DefineValue(code, inst, result);
|
ctx.reg_alloc.DefineValue(code, inst, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ void EmitPostProcessNaNs(BlockOfCode& code, Xbyak::Xmm result, Xbyak::Xmm op1, X
|
|||||||
// op1 == Inf && op2 == QNaN
|
// op1 == Inf && op2 == QNaN
|
||||||
// op1 == QNaN && op2 == SNaN <<< The problematic case
|
// op1 == QNaN && op2 == SNaN <<< The problematic case
|
||||||
// op1 == QNaN && op2 == Inf
|
// op1 == QNaN && op2 == Inf
|
||||||
|
if (code.HasHostFeature(HostFeature::AVX)) {
|
||||||
if constexpr (fsize == 32) {
|
if constexpr (fsize == 32) {
|
||||||
code.movd(tmp.cvt32(), op2);
|
code.movd(tmp.cvt32(), op2);
|
||||||
code.shl(tmp.cvt32(), 32 - mantissa_msb_bit);
|
code.shl(tmp.cvt32(), 32 - mantissa_msb_bit);
|
||||||
@@ -234,6 +234,15 @@ void EmitPostProcessNaNs(BlockOfCode& code, Xbyak::Xmm result, Xbyak::Xmm op1, X
|
|||||||
code.movq(tmp, op2);
|
code.movq(tmp, op2);
|
||||||
code.shl(tmp, 64 - mantissa_msb_bit);
|
code.shl(tmp, 64 - mantissa_msb_bit);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if constexpr (fsize == 32) {
|
||||||
|
code.vmovd(tmp.cvt32(), op2);
|
||||||
|
code.shl(tmp.cvt32(), 32 - mantissa_msb_bit);
|
||||||
|
} else {
|
||||||
|
code.vmovq(tmp, op2);
|
||||||
|
code.shl(tmp, 64 - mantissa_msb_bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
// If op2 is a SNaN, CF = 0 and ZF = 0.
|
// If op2 is a SNaN, CF = 0 and ZF = 0.
|
||||||
code.jna(end, code.T_NEAR);
|
code.jna(end, code.T_NEAR);
|
||||||
|
|
||||||
@@ -477,11 +486,19 @@ static inline void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::
|
|||||||
tmp.setBit(fsize);
|
tmp.setBit(fsize);
|
||||||
|
|
||||||
const auto move_to_tmp = [=, &code](const Xbyak::Xmm& xmm) {
|
const auto move_to_tmp = [=, &code](const Xbyak::Xmm& xmm) {
|
||||||
|
if (code.HasHostFeature(HostFeature::AVX)) {
|
||||||
|
if constexpr (fsize == 32) {
|
||||||
|
code.vmovd(tmp.cvt32(), xmm);
|
||||||
|
} else {
|
||||||
|
code.vmovq(tmp.cvt64(), xmm);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if constexpr (fsize == 32) {
|
if constexpr (fsize == 32) {
|
||||||
code.movd(tmp.cvt32(), xmm);
|
code.movd(tmp.cvt32(), xmm);
|
||||||
} else {
|
} else {
|
||||||
code.movq(tmp.cvt64(), xmm);
|
code.movq(tmp.cvt64(), xmm);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
SharedLabel end = ctx.GenSharedLabel(), z = ctx.GenSharedLabel();
|
SharedLabel end = ctx.GenSharedLabel(), z = ctx.GenSharedLabel();
|
||||||
@@ -1156,7 +1173,11 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
|
|||||||
|
|
||||||
code.L(*bad_values);
|
code.L(*bad_values);
|
||||||
if constexpr (fsize == 32) {
|
if constexpr (fsize == 32) {
|
||||||
|
if (code.HasHostFeature(HostFeature::AVX)) {
|
||||||
|
code.vmovd(tmp, operand);
|
||||||
|
} else {
|
||||||
code.movd(tmp, operand);
|
code.movd(tmp, operand);
|
||||||
|
}
|
||||||
|
|
||||||
if (!ctx.FPCR().FZ()) {
|
if (!ctx.FPCR().FZ()) {
|
||||||
if (ctx.FPCR().DN()) {
|
if (ctx.FPCR().DN()) {
|
||||||
@@ -1186,7 +1207,12 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
|
|||||||
}
|
}
|
||||||
|
|
||||||
code.L(default_nan);
|
code.L(default_nan);
|
||||||
|
|
||||||
|
if (code.HasHostFeature(HostFeature::AVX)) {
|
||||||
|
code.vmovd(result, code.Const(xword, 0x7FC00000));
|
||||||
|
} else {
|
||||||
code.movd(result, code.Const(xword, 0x7FC00000));
|
code.movd(result, code.Const(xword, 0x7FC00000));
|
||||||
|
}
|
||||||
code.jmp(*end, code.T_NEAR);
|
code.jmp(*end, code.T_NEAR);
|
||||||
} else {
|
} else {
|
||||||
Xbyak::Label nan, zero;
|
Xbyak::Label nan, zero;
|
||||||
|
|||||||
@@ -227,8 +227,12 @@ void EmitX64::EmitVectorGetElement32(EmitContext& ctx, IR::Inst* inst) {
|
|||||||
} else {
|
} else {
|
||||||
auto const source = ctx.reg_alloc.UseScratchXmm(code, args[0]);
|
auto const source = ctx.reg_alloc.UseScratchXmm(code, args[0]);
|
||||||
code.pshufd(source, source, index);
|
code.pshufd(source, source, index);
|
||||||
|
if (code.HasHostFeature(HostFeature::AVX)) {
|
||||||
|
code.vmovd(dest, source);
|
||||||
|
} else {
|
||||||
code.movd(dest, source);
|
code.movd(dest, source);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(code, inst, dest);
|
ctx.reg_alloc.DefineValue(code, inst, dest);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <smmintrin.h>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "dynarmic/mcl/function_info.hpp"
|
#include "dynarmic/mcl/function_info.hpp"
|
||||||
@@ -1652,25 +1653,23 @@ static void EmitFPVectorRoundIntThunk(VectorArray<FPT>& output, const VectorArra
|
|||||||
|
|
||||||
template<size_t fsize>
|
template<size_t fsize>
|
||||||
void EmitFPVectorRoundInt(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
void EmitFPVectorRoundInt(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
//auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
const auto rounding = FP::RoundingMode(inst->GetArg(1).GetU8());
|
const auto rounding = FP::RoundingMode(inst->GetArg(1).GetU8());
|
||||||
const bool exact = inst->GetArg(2).GetU1();
|
const bool exact = inst->GetArg(2).GetU1();
|
||||||
|
|
||||||
if constexpr (fsize != 16) {
|
if constexpr (fsize != 16) {
|
||||||
if (code.HasHostFeature(HostFeature::SSE41) && rounding != FP::RoundingMode::ToNearest_TieAwayFromZero && !exact) {
|
if (code.HasHostFeature(HostFeature::SSE41) && rounding != FP::RoundingMode::ToNearest_TieAwayFromZero && !exact) {
|
||||||
const u8 round_imm = [&]() -> u8 {
|
const u8 round_imm = [rounding]() -> u8 {
|
||||||
switch (rounding) {
|
switch (rounding) {
|
||||||
case FP::RoundingMode::ToNearest_TieEven: return 0b00;
|
case FP::RoundingMode::ToNearest_TieEven: return _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC;
|
||||||
case FP::RoundingMode::TowardsPlusInfinity: return 0b10;
|
case FP::RoundingMode::TowardsPlusInfinity: return _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC;
|
||||||
case FP::RoundingMode::TowardsMinusInfinity: return 0b01;
|
case FP::RoundingMode::TowardsMinusInfinity: return _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC;
|
||||||
case FP::RoundingMode::TowardsZero: return 0b11;
|
case FP::RoundingMode::TowardsZero: return _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC;
|
||||||
default: UNREACHABLE();
|
default: UNREACHABLE();
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
EmitTwoOpVectorOperation<fsize, DefaultIndexer, 3>(code, ctx, inst, [&code, round_imm](const Xbyak::Xmm result, const Xbyak::Xmm xmm_a) {
|
||||||
EmitTwoOpVectorOperation<fsize, DefaultIndexer, 3>(code, ctx, inst, [&](const Xbyak::Xmm& result, const Xbyak::Xmm& xmm_a) {
|
|
||||||
FCODE(roundp)(result, xmm_a, round_imm);
|
FCODE(roundp)(result, xmm_a, round_imm);
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1678,33 +1677,21 @@ void EmitFPVectorRoundInt(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||||||
// Do not make a LUT out of this, let the compiler do it's thing
|
// Do not make a LUT out of this, let the compiler do it's thing
|
||||||
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
using FPT = mcl::unsigned_integer_of_size<fsize>;
|
||||||
switch (rounding) {
|
switch (rounding) {
|
||||||
case FP::RoundingMode::ToNearest_TieEven:
|
#define ROUND_LIST \
|
||||||
exact
|
ROUND_ELEM(ToNearest_TieEven) \
|
||||||
? EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::ToNearest_TieEven, true>)
|
ROUND_ELEM(TowardsPlusInfinity) \
|
||||||
: EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::ToNearest_TieEven, false>);
|
ROUND_ELEM(TowardsMinusInfinity) \
|
||||||
break;
|
ROUND_ELEM(TowardsZero) \
|
||||||
case FP::RoundingMode::TowardsPlusInfinity:
|
ROUND_ELEM(ToNearest_TieAwayFromZero)
|
||||||
exact
|
#define ROUND_ELEM(name) \
|
||||||
? EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::TowardsPlusInfinity, true>)
|
case FP::RoundingMode::name: \
|
||||||
: EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::TowardsPlusInfinity, false>);
|
return exact \
|
||||||
break;
|
? EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::name, true>) \
|
||||||
case FP::RoundingMode::TowardsMinusInfinity:
|
: EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::name, false>);
|
||||||
exact
|
ROUND_LIST
|
||||||
? EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::TowardsMinusInfinity, true>)
|
#undef ROUND_ELEM
|
||||||
: EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::TowardsMinusInfinity, false>);
|
#undef ROUND_LIST
|
||||||
break;
|
default: UNREACHABLE();
|
||||||
case FP::RoundingMode::TowardsZero:
|
|
||||||
exact
|
|
||||||
? EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::TowardsZero, true>)
|
|
||||||
: EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::TowardsZero, false>);
|
|
||||||
break;
|
|
||||||
case FP::RoundingMode::ToNearest_TieAwayFromZero:
|
|
||||||
exact
|
|
||||||
? EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::ToNearest_TieAwayFromZero, true>)
|
|
||||||
: EmitTwoOpFallback<3>(code, ctx, inst, EmitFPVectorRoundIntThunk<FPT, FP::RoundingMode::ToNearest_TieAwayFromZero, false>);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user