From 622f2f7f66aacbf7c3b2cd59b670876e94c73555 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 5 Jul 2018 15:30:08 +0300 Subject: [PATCH] SPU LLVM: constant computation fixes Fixed instructions: Gather Bits: GB, GBH, GBB Form Select Mask: FSM, FSMH, FSMB --- rpcs3/Emu/Cell/SPURecompiler.cpp | 83 ++++++++++++++++++++++++++------ 1 file changed, 69 insertions(+), 14 deletions(-) diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index 2a4e932217..e8a84758f4 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -3208,45 +3208,100 @@ public: void GB(spu_opcode_t op) { - // TODO - value_t m; - m.value = eval((get_vr(op.ra) << 31) < 0).value; - m.value = m_ir->CreateBitCast(m.value, m_ir->getIntNTy(4)); - m.value = m_ir->CreateZExt(m.value, get_type()); + const auto a = get_vr(op.ra); + + if (auto cv = llvm::dyn_cast(a.value)) + { + v128 data = get_const_vector(cv, m_pos, 680); + u32 res = 0; + for (u32 i = 0; i < 4; i++) + res |= (data._u32[i] & 1) << i; + set_vr(op.rt, build(0, 0, 0, res)); + return; + } + + const auto m = zext(bitcast(trunc(a))); set_vr(op.rt, insert(splat(0), 3, m)); } void GBH(spu_opcode_t op) { - const auto m = zext(bitcast((get_vr(op.ra) << 15) < 0)); + const auto a = get_vr(op.ra); + + if (auto cv = llvm::dyn_cast(a.value)) + { + v128 data = get_const_vector(cv, m_pos, 684); + u32 res = 0; + for (u32 i = 0; i < 8; i++) + res |= (data._u16[i] & 1) << i; + set_vr(op.rt, build(0, 0, 0, res)); + return; + } + + const auto m = zext(bitcast(trunc(a))); set_vr(op.rt, insert(splat(0), 3, m)); } void GBB(spu_opcode_t op) { - const auto m = zext(bitcast((get_vr(op.ra) << 7) < 0)); + const auto a = get_vr(op.ra); + + if (auto cv = llvm::dyn_cast(a.value)) + { + v128 data = get_const_vector(cv, m_pos, 688); + u32 res = 0; + for (u32 i = 0; i < 16; i++) + res |= (data._u8[i] & 1) << i; + set_vr(op.rt, build(0, 0, 0, res)); + return; + } + + const auto m = zext(bitcast(trunc(a))); set_vr(op.rt, insert(splat(0), 3, m)); } void FSM(spu_opcode_t op) { - // TODO - value_t m; - m.value = extract(get_vr(op.ra), 3).value; - m.value = m_ir->CreateTrunc(m.value, m_ir->getIntNTy(4)); - m.value = m_ir->CreateBitCast(m.value, get_type()); + const auto v = extract(get_vr(op.ra), 3); + + if (auto cv = llvm::dyn_cast(v.value)) + { + const u64 v = cv->getZExtValue() & 0xf; + set_vr(op.rt, -(build(v >> 0, v >> 1, v >> 2, v >> 3) & 1)); + return; + } + + const auto m = bitcast(trunc(v)); set_vr(op.rt, sext(m)); } void FSMH(spu_opcode_t op) { - const auto m = bitcast(trunc(extract(get_vr(op.ra), 3))); + const auto v = extract(get_vr(op.ra), 3); + + if (auto cv = llvm::dyn_cast(v.value)) + { + const u64 v = cv->getZExtValue() & 0xff; + set_vr(op.rt, -(build(v >> 0, v >> 1, v >> 2, v >> 3, v >> 4, v >> 5, v >> 6, v >> 7) & 1)); + return; + } + + const auto m = bitcast(trunc(v)); set_vr(op.rt, sext(m)); } void FSMB(spu_opcode_t op) { - const auto m = bitcast(trunc(extract(get_vr(op.ra), 3))); + const auto v = extract(get_vr(op.ra), 3); + + if (auto cv = llvm::dyn_cast(v.value)) + { + const u64 v = cv->getZExtValue() & 0xffff; + op.i16 = static_cast(v); + return FSMBI(op); + } + + const auto m = bitcast(trunc(v)); set_vr(op.rt, sext(m)); }