diff --git a/rpcs3/Emu/CPU/CPUTranslator.h b/rpcs3/Emu/CPU/CPUTranslator.h index 0ae5179916..97020f039a 100644 --- a/rpcs3/Emu/CPU/CPUTranslator.h +++ b/rpcs3/Emu/CPU/CPUTranslator.h @@ -3670,6 +3670,23 @@ public: #endif } + template + value_t vperm2d128From512(T1 a, T2 b, T3 c) + { + value_t result; + value_t perm512; + + const auto data0 = a.eval(m_ir); + const auto index128 = b.eval(m_ir); + const auto data1 = c.eval(m_ir); + + const auto index512 = m_ir->CreateInsertVector(get_type(), llvm::UndefValue::get(get_type()), index128, m_ir->getInt64(0)); + perm512.value = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::x86_avx512_vpermi2var_d_512), {data0, index512, data1}); + + result.value = m_ir->CreateExtractVector(get_type(), perm512.value, m_ir->getInt64(0)); + return result; + } + template value_t gf2p8affineqb(T1 a, T2 b, u8 c) { diff --git a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp index 5f5c90f6f4..392f2f339b 100644 --- a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp @@ -7498,13 +7498,23 @@ public: const auto a_sign = (a & splat(0x80000000)); value_t final_result = eval(splat(0)); - for (u32 i = 0; i < 4; i++) + if (m_use_avx512) { - const auto eval_fraction = eval(extract(a_fraction, i)); + value_t lo_lut; + value_t hi_lut; + lo_lut.value = llvm::ConstantDataVector::get(m_context, llvm::ArrayRef(spu_frest_fraction_lut, 16)); + hi_lut.value = llvm::ConstantDataVector::get(m_context, llvm::ArrayRef(spu_frest_fraction_lut + 16, 16)); - value_t r_fraction = load_const(m_spu_frest_fraction_lut, eval_fraction); - - final_result = eval(insert(final_result, i, r_fraction)); + final_result = vperm2d128From512(lo_lut, a_fraction, hi_lut); + } + else + { + for (u32 i = 0; i < 4; i++) + { + const auto eval_fraction = eval(extract(a_fraction, i)); + value_t r_fraction = load_const(m_spu_frest_fraction_lut, eval_fraction); + final_result = eval(insert(final_result, i, r_fraction)); + } } //final_result = eval(select(final_result != (0), final_result, bitcast(pshufb(splat(0), bitcast(final_result))))); @@ -8551,13 +8561,23 @@ public: const auto a_sign = (a & splat(0x80000000)); value_t b = eval(splat(0)); - for (u32 i = 0; i < 4; i++) + if (m_use_avx512) { - const auto eval_fraction = eval(extract(a_fraction, i)); + value_t lo_lut; + value_t hi_lut; + lo_lut.value = llvm::ConstantDataVector::get(m_context, llvm::ArrayRef(spu_frest_fraction_lut, 16)); + hi_lut.value = llvm::ConstantDataVector::get(m_context, llvm::ArrayRef(spu_frest_fraction_lut + 16, 16)); - value_t r_fraction = load_const(m_spu_frest_fraction_lut, eval_fraction); - - b = eval(insert(b, i, r_fraction)); + b = vperm2d128From512(lo_lut, a_fraction, hi_lut); + } + else + { + for (u32 i = 0; i < 4; i++) + { + const auto eval_fraction = eval(extract(a_fraction, i)); + value_t r_fraction = load_const(m_spu_frest_fraction_lut, eval_fraction); + b = eval(insert(b, i, r_fraction)); + } } b = eval(b | fix_exponent | a_sign);