spu: Check exponent bits in FMA ops (#2683)

This commit is contained in:
kd-11 2017-04-13 23:02:51 +03:00 committed by GitHub
parent a5fd7abcf7
commit 65bdcaed29
2 changed files with 91 additions and 14 deletions

View file

@ -1297,17 +1297,50 @@ void spu_interpreter::MPYA(SPUThread& spu, spu_opcode_t op)
void spu_interpreter_fast::FNMS(SPUThread& spu, spu_opcode_t op)
{
spu.gpr[op.rt4].vf = _mm_sub_ps(spu.gpr[op.rc].vf, _mm_mul_ps(spu.gpr[op.ra].vf, spu.gpr[op.rb].vf));
const u32 test_bits = 0x7f800000;
auto mask = _mm_set1_ps((f32&)test_bits);
auto test_a = _mm_and_ps(spu.gpr[op.ra].vf, mask);
auto mask_a = _mm_cmpneq_ps(test_a, mask);
auto test_b = _mm_and_ps(spu.gpr[op.rb].vf, mask);
auto mask_b = _mm_cmpneq_ps(test_b, mask);
auto a = _mm_and_ps(spu.gpr[op.ra].vf, mask_a);
auto b = _mm_and_ps(spu.gpr[op.rb].vf, mask_b);
spu.gpr[op.rt4].vf = _mm_sub_ps(spu.gpr[op.rc].vf, _mm_mul_ps(a, b));
}
void spu_interpreter_fast::FMA(SPUThread& spu, spu_opcode_t op)
{
spu.gpr[op.rt4].vf = _mm_add_ps(_mm_mul_ps(spu.gpr[op.ra].vf, spu.gpr[op.rb].vf), spu.gpr[op.rc].vf);
const u32 test_bits = 0x7f800000;
auto mask = _mm_set1_ps((f32&)test_bits);
auto test_a = _mm_and_ps(spu.gpr[op.ra].vf, mask);
auto mask_a = _mm_cmpneq_ps(test_a, mask);
auto test_b = _mm_and_ps(spu.gpr[op.rb].vf, mask);
auto mask_b = _mm_cmpneq_ps(test_b, mask);
auto a = _mm_and_ps(spu.gpr[op.ra].vf, mask_a);
auto b = _mm_and_ps(spu.gpr[op.rb].vf, mask_b);
spu.gpr[op.rt4].vf = _mm_add_ps(_mm_mul_ps(a, b), spu.gpr[op.rc].vf);
}
void spu_interpreter_fast::FMS(SPUThread& spu, spu_opcode_t op)
{
spu.gpr[op.rt4].vf = _mm_sub_ps(_mm_mul_ps(spu.gpr[op.ra].vf, spu.gpr[op.rb].vf), spu.gpr[op.rc].vf);
const u32 test_bits = 0x7f800000;
auto mask = _mm_set1_ps((f32&)test_bits);
auto test_a = _mm_and_ps(spu.gpr[op.ra].vf, mask);
auto mask_a = _mm_cmpneq_ps(test_a, mask);
auto test_b = _mm_and_ps(spu.gpr[op.rb].vf, mask);
auto mask_b = _mm_cmpneq_ps(test_b, mask);
auto a = _mm_and_ps(spu.gpr[op.ra].vf, mask_a);
auto b = _mm_and_ps(spu.gpr[op.rb].vf, mask_b);
spu.gpr[op.rt4].vf = _mm_sub_ps(_mm_mul_ps(a, b), spu.gpr[op.rc].vf);
}
static void SetHostRoundingMode(u32 rn)