SPU LLVM: emulate PSHUFB

For targets without SSSE3 support
This commit is contained in:
Nekotekina 2018-05-28 22:28:39 +03:00
parent 759370ea1b
commit 37577714fa
3 changed files with 45 additions and 1 deletions

View File

@ -500,6 +500,25 @@ jit_compiler::~jit_compiler()
{
}
bool jit_compiler::has_ssse3() const
{
if (m_cpu == "generic" ||
m_cpu == "k8" ||
m_cpu == "opteron" ||
m_cpu == "athlon64" ||
m_cpu == "athlon-fx" ||
m_cpu == "k8-sse3" ||
m_cpu == "opteron-sse3" ||
m_cpu == "athlon64-sse3" ||
m_cpu == "amdfam10" ||
m_cpu == "barcelona")
{
return false;
}
return true;
}
void jit_compiler::add(std::unique_ptr<llvm::Module> module, const std::string& path)
{
ObjectCache cache{path};

View File

@ -111,6 +111,9 @@ public:
return *m_engine;
}
// Test SSSE3 feature
bool has_ssse3() const;
// Add module (path to obj cache dir)
void add(std::unique_ptr<llvm::Module> module, const std::string& path);

View File

@ -1089,7 +1089,29 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
value_t<u8[16]> pshufb(T1 a, T2 b)
{
value_t<u8[16]> result;
result.value = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::x86_ssse3_pshuf_b_128), {a.eval(m_ir), b.eval(m_ir)});
if (m_spurt->m_jit.has_ssse3())
{
result.value = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::x86_ssse3_pshuf_b_128), {a.eval(m_ir), b.eval(m_ir)});
}
else
{
const auto data0 = a.eval(m_ir);
const auto index = b.eval(m_ir);
const auto mask = m_ir->CreateAnd(index, 0xf);
const auto zero = llvm::ConstantInt::get(get_type<u8[16]>(), 0u);
result.value = zero;
for (u32 i = 0; i < 16; i++)
{
const auto x = m_ir->CreateExtractElement(data0, m_ir->CreateExtractElement(mask, i));
result.value = m_ir->CreateInsertElement(result.value, x, i);
}
result.value = m_ir->CreateSelect(m_ir->CreateICmpSLT(index, zero), zero, result.value);
}
return result;
}