Skip to content

Commit

Permalink
VFPU: Ensure that sin(4*x) returns 0.0 (and cos 1) for all x. Fixes #…
Browse files Browse the repository at this point in the history
  • Loading branch information
hrydgard committed Jun 15, 2014
1 parent 9503603 commit 0879d76
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 29 deletions.
12 changes: 3 additions & 9 deletions Core/MIPS/ARM/ArmCompVFPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1832,24 +1832,18 @@ namespace MIPSComp
fpr.ReleaseSpillLocksAndDiscardTemps();
}

#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif
// sincosf is unavailable in the Android NDK:
// https://code.google.com/p/android/issues/detail?id=38423
double SinCos(float angle) {
union { struct { float sin; float cos; }; double out; } sincos;
angle *= (float)M_PI_2;
sincos.sin = sinf(angle);
sincos.cos = cosf(angle);
vfpu_sincos(angle, sincos.sin, sincos.cos);
return sincos.out;
}

double SinCosNegSin(float angle) {
union { struct { float sin; float cos; }; double out; } sincos;
angle *= (float)M_PI_2;
sincos.sin = -sinf(angle);
sincos.cos = cosf(angle);
vfpu_sincos(angle, sincos.sin, sincos.cos);
sincos.sin = -sincos.sin;
return sincos.out;
}

Expand Down
3 changes: 3 additions & 0 deletions Core/MIPS/MIPS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ u8 fromvoffset[128];
#define M_LN10 2.30258509299404568402f
#undef M_PI
#define M_PI 3.14159265358979323846f

#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923f
#endif
#define M_PI_4 0.785398163397448309616f
#define M_1_PI 0.318309886183790671538f
#define M_2_PI 0.636619772367581343076f
Expand Down
22 changes: 11 additions & 11 deletions Core/MIPS/MIPSIntVFPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@
#define M_LN10 2.30258509299404568402f
#undef M_PI
#define M_PI 3.14159265358979323846f
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923f
#endif
#define M_PI_4 0.785398163397448309616f
#define M_1_PI 0.318309886183790671538f
#define M_2_PI 0.636619772367581343076f
Expand Down Expand Up @@ -517,14 +519,15 @@ namespace MIPSInt
case 5: if (s[i] < -1.0f) d[i] = -1.0f; else {if(s[i] > 1.0f) d[i] = 1.0f; else d[i] = s[i];} break; // vsat1
case 16: d[i] = 1.0f / s[i]; break; //vrcp
case 17: d[i] = 1.0f / sqrtf(s[i]); break; //vrsq
case 18: d[i] = sinf((float)M_PI_2 * s[i]); break; //vsin
case 19: d[i] = cosf((float)M_PI_2 * s[i]); break; //vcos

case 18: { d[i] = vfpu_sin(s[i]); } break; //vsin
case 19: { d[i] = vfpu_cos(s[i]); } break; //vcos
case 20: d[i] = powf(2.0f, s[i]); break; //vexp2
case 21: d[i] = logf(s[i])/log(2.0f); break; //vlog2
case 22: d[i] = fabsf(sqrtf(s[i])); break; //vsqrt
case 23: d[i] = asinf(s[i]) / M_PI_2; break; //vasin
case 24: d[i] = -1.0f / s[i]; break; // vnrcp
case 26: d[i] = -sinf((float)M_PI_2 * s[i]); break; // vnsin
case 26: { d[i] = -vfpu_sin(s[i]); } break; // vnsin
case 28: d[i] = 1.0f / powf(2.0, s[i]); break; // vrexp2
default:
_dbg_assert_msg_(CPU,0,"Trying to interpret VV2Op instruction that can't be interpreted");
Expand Down Expand Up @@ -1285,21 +1288,18 @@ namespace MIPSInt
}

// Generates one line of a rotation matrix around one of the three axes
void Int_Vrot(MIPSOpcode op)
{
void Int_Vrot(MIPSOpcode op) {
int vd = _VD;
int vs = _VS;
int imm = (op >> 16) & 0x1f;
VectorSize sz = GetVecSize(op);
float angle = V(vs) * M_PI_2;
bool negSin = (imm & 0x10) ? true : false;
float sine = sinf(angle);
float cosine = cosf(angle);
float sine, cosine;
vfpu_sincos(V(vs), sine, cosine);
if (negSin)
sine = -sine;
float d[4] = {0};
if (((imm >> 2) & 3) == (imm & 3))
{
if (((imm >> 2) & 3) == (imm & 3)) {
for (int i = 0; i < 4; i++)
d[i] = sine;
}
Expand Down Expand Up @@ -1845,7 +1845,7 @@ namespace MIPSInt
ERROR_LOG_REPORT(CPU, "vsbn not implemented for size %d", GetNumVectorElements(sz));
}
for (int i = 0; i < GetNumVectorElements(sz); ++i) {
// Simply replace the expontent bits.
// Simply replace the exponent bits.
u32 prev = s.u[i] & 0x7F800000;
if (prev != 0 && prev != 0x7F800000) {
d.u[i] = (s.u[i] & ~0x7F800000) | (exp << 23);
Expand Down
28 changes: 25 additions & 3 deletions Core/MIPS/MIPSVFPUUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,39 @@

#pragma once


#include <cmath>

#define _VD (op & 0x7F)
#define _VS ((op>>8) & 0x7F)
#define _VT ((op>>16) & 0x7F)

inline int Xpose(int v)
{
inline int Xpose(int v) {
return v^0x20;
}

#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif

inline float vfpu_sin(float angle) {
angle -= floorf(angle * 4.0f) * 0.25f;
angle *= (float)M_PI_2;
return sinf(angle);
}

inline float vfpu_cos(float angle) {
angle -= floorf(angle * 4.0f) * 0.25f;
angle *= (float)M_PI_2;
return cosf(angle);
}

inline void vfpu_sincos(float angle, float &sine, float &cosine) {
angle -= floorf(angle * 4.0f) * 0.25f;
angle *= (float)M_PI_2;
sine = sinf(angle);
cosine = cosf(angle);
}

#define VFPU_FLOAT16_EXP_MAX 0x1f
#define VFPU_SH_FLOAT16_SIGN 15
#define VFPU_MASK_FLOAT16_SIGN 0x1
Expand Down
9 changes: 3 additions & 6 deletions Core/MIPS/x86/CompVFPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2125,15 +2125,12 @@ typedef u32float SinCosArg;
#endif

void SinCos(SinCosArg angle) {
angle *= (float)1.57079632679489661923; // pi / 2
sincostemp[0] = sinf(angle);
sincostemp[1] = cosf(angle);
vfpu_sincos(angle, sincostemp[0], sincostemp[1]);
}

void SinCosNegSin(SinCosArg angle) {
angle *= (float)1.57079632679489661923; // pi / 2
sincostemp[0] = -sinf(angle);
sincostemp[1] = cosf(angle);
vfpu_sincos(angle, sincostemp[0], sincostemp[1]);
sincostemp[0] = -sincostemp[0];
}

// Very heavily used by FF:CC
Expand Down

0 comments on commit 0879d76

Please sign in to comment.