diff --git a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp index 10be1f28f2..b7093a01bf 100644 --- a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp @@ -5657,22 +5657,44 @@ public: } const auto v = extract(get_vr(op.ra), 3); +#ifdef ARCH_ARM64 +// Workaround for bad codegen via LLVM +// More idiomatic version that compiles to 2 neon instructions +// Remove me when addressed by upstream llvm: https://github.com/llvm/llvm-project/issues/200325 - Whatcookie + const auto masks = build(1, 2, 4, 8); + const auto bits = vsplat(zext(trunc(v))); + set_vr(op.rt, sext((bits & masks) == masks)); +#else const auto m = bitcast(trunc(v)); set_vr(op.rt, sext(m)); +#endif } void FSMH(spu_opcode_t op) { const auto v = extract(get_vr(op.ra), 3); +#ifdef ARCH_ARM64 + const auto masks = build(1, 2, 4, 8, 16, 32, 64, 128); + const auto bits = vsplat(zext(trunc(v))); + set_vr(op.rt, sext((bits & masks) == masks)); +#else const auto m = bitcast(trunc(v)); set_vr(op.rt, sext(m)); +#endif } void FSMB(spu_opcode_t op) { const auto v = extract(get_vr(op.ra), 3); +#ifdef ARCH_ARM64 + const auto masks = build(1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128); + const auto bytes = bitcast(vsplat(trunc(v))); + const auto bits = zshuffle(bytes, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1); + set_vr(op.rt, sext((bits & masks) == masks)); +#else const auto m = bitcast(trunc(v)); set_vr(op.rt, sext(m)); +#endif } template @@ -6333,8 +6355,15 @@ public: void FSMBI(spu_opcode_t op) { +#ifdef ARCH_ARM64 + const auto masks = build(1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128); + const auto bytes = bitcast(vsplat(get_imm(op.i16))); + const auto bits = zshuffle(bytes, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1); + set_vr(op.rt, sext((bits & masks) == masks)); +#else const auto m = bitcast(get_imm(op.i16)); set_vr(op.rt, sext(m)); +#endif } void IL(spu_opcode_t op)