diff --git a/Core/MIPS/IR/IRCompVFPU.cpp b/Core/MIPS/IR/IRCompVFPU.cpp index 4c9138fef2..734c81b721 100644 --- a/Core/MIPS/IR/IRCompVFPU.cpp +++ b/Core/MIPS/IR/IRCompVFPU.cpp @@ -425,11 +425,11 @@ namespace MIPSComp { void IRFrontend::Comp_VMatrixInit(MIPSOpcode op) { CONDITIONAL_DISABLE(VFPU_XFER); MatrixSize sz = GetMtxSize(op); - if (sz != M_4x4) { + if (sz != M_4x4 || !js.HasNoPrefix()) { DISABLE; } - // Matrix init (no prefixes) + // Matrix init (weird prefixes) // d[N,M] = CONST[N,M] // Not really about trying here, it will work if enabled. diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index c7e7ca2946..e1cb4c59eb 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -288,24 +288,20 @@ namespace MIPSInt PC += 4; } - void Int_VMatrixInit(MIPSOpcode op) - { - static const float idt[16] = - { + void Int_VMatrixInit(MIPSOpcode op) { + static const float idt[16] = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, }; - static const float zero[16] = - { + static const float zero[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }; - static const float one[16] = - { + static const float one[16] = { 1,1,1,1, 1,1,1,1, 1,1,1,1, @@ -315,8 +311,7 @@ namespace MIPSInt MatrixSize sz = GetMtxSize(op); const float *m; - switch ((op >> 16) & 0xF) - { + switch ((op >> 16) & 0xF) { case 3: m=idt; break; //identity // vmidt case 6: m=zero; break; // vmzero case 7: m=one; break; // vmone @@ -327,7 +322,25 @@ namespace MIPSInt return; } - WriteMatrix(m, sz, vd); + // The S prefix generates constants, but only for the final (possibly transposed) row. + if (currentMIPS->vfpuCtrl[VFPU_CTRL_SPREFIX] & 0xF0F00) { + float prefixed[16]; + memcpy(prefixed, m, sizeof(prefixed)); + + int off = GetMatrixSide(sz) - 1; + u32 sprefixRemove = VFPU_ANY_SWIZZLE(); + u32 sprefixAdd = VFPU_CONST(1, 1, 1, 1); + switch ((op >> 16) & 0xF) { + case 3: sprefixAdd |= VFPU_SWIZZLE(off == 0, off == 1, off == 2, off == 3); break; + case 6: sprefixAdd |= VFPU_SWIZZLE(0, 0, 0, 0); break; + case 7: sprefixAdd |= VFPU_SWIZZLE(1, 1, 1, 1); break; + } + ApplyPrefixST(&prefixed[off * 4], VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), V_Quad); + WriteMatrix(prefixed, sz, vd); + } else { + // Write mask applies to the final (maybe transposed) row. Sat causes hang. + WriteMatrix(m, sz, vd); + } PC += 4; EatPrefixes(); }