Fixed some borderline cases with CMPSS opcode ([DYNAREC] too)

This commit is contained in:
ptitSeb 2021-11-07 09:15:05 +01:00
parent f6415a746c
commit 679dbafc9e
7 changed files with 252 additions and 129 deletions

View File

@ -295,21 +295,17 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
u8 = F8;
if((u8&7)==6){
VCMP_F64(d0, v0);
} else {
VCMP_F64(v0, d0);
}
VCMP_F64(v0, d0);
VMRS_APSR();
MOVW(x2, 0);
switch(u8&7) {
case 0: MVN_COND_REG_LSL_IMM5(cEQ, x2, x2, 0); MOVW_COND(cVS, x2, 0); break; // Equal
case 1: MVN_COND_REG_LSL_IMM5(cMI, x2, x2, 0); MOVW_COND(cVS, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM5(cLE, x2, x2, 0); MOVW_COND(cVS, x2, 0); break; // Less or equal
case 0: MVN_COND_REG_LSL_IMM5(cEQ, x2, x2, 0); break; // Equal
case 1: MVN_COND_REG_LSL_IMM5(cCC, x2, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM5(cLS, x2, x2, 0); break; // Less or equal
case 3: MVN_COND_REG_LSL_IMM5(cVS, x2, x2, 0); break; // NaN
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal (or unordered on ARM, not on X86...)
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal or unordered
case 5: MVN_COND_REG_LSL_IMM5(cCS, x2, x2, 0); break; // Greater or equal or unordered
case 6: MVN_COND_REG_LSL_IMM5(cLT, x2, x2, 0); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
case 6: MVN_COND_REG_LSL_IMM5(cHI, x2, x2, 0); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
case 7: MVN_COND_REG_LSL_IMM5(cVC, x2, x2, 0); break; // not NaN
}
VMOVtoV_D(v0, x2, x2);

View File

@ -598,21 +598,17 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
s0 = d0*2;
u8 = F8;
if((u8&7)==6){
VCMP_F32(s1, s0);
} else {
VCMP_F32(s0, s1);
}
VCMP_F32(s0, s1);
VMRS_APSR();
MOVW(x2, 0);
switch(u8&7) {
case 0: MVN_COND_REG_LSL_IMM5(cEQ, x2, x2, 0); MOVW_COND(cVS, x2, 0); break; // Equal
case 1: MVN_COND_REG_LSL_IMM5(cMI, x2, x2, 0); MOVW_COND(cVS, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM5(cLE, x2, x2, 0); MOVW_COND(cVS, x2, 0); break; // Less or equal
case 0: MVN_COND_REG_LSL_IMM5(cEQ, x2, x2, 0); break; // Equal
case 1: MVN_COND_REG_LSL_IMM5(cCC, x2, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM5(cLS, x2, x2, 0); break; // Less or equal
case 3: MVN_COND_REG_LSL_IMM5(cVS, x2, x2, 0); break; // NaN
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal (or unordered on ARM, not on X86...)
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal or unordered
case 5: MVN_COND_REG_LSL_IMM5(cCS, x2, x2, 0); break; // Greater or equal or unordered
case 6: MVN_COND_REG_LSL_IMM5(cLT, x2, x2, 0); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
case 6: MVN_COND_REG_LSL_IMM5(cHI, x2, x2, 0); break; // Greater or unordered
case 7: MVN_COND_REG_LSL_IMM5(cVC, x2, x2, 0); break; // not NaN
}
VMOVtoDx_32(v0, 0, x2);

View File

@ -218,8 +218,8 @@
tmp8s = 0;
switch(tmp8u&7) {
case 0: tmp8s=(GX.d[0] == EX->d[0]); break;
case 1: tmp8s=isless(GX.d[0], EX->d[0]); break;
case 2: tmp8s=islessequal(GX.d[0], EX->d[0]); break;
case 1: tmp8s=isless(GX.d[0], EX->d[0]) && !(isnan(GX.d[0]) || isnan(EX->d[0])); break;
case 2: tmp8s=islessequal(GX.d[0], EX->d[0]) && !(isnan(GX.d[0]) || isnan(EX->d[0])); break;
case 3: tmp8s=isnan(GX.d[0]) || isnan(EX->d[0]); break;
case 4: tmp8s=(GX.d[0] != EX->d[0]); break;
case 5: tmp8s=isnan(GX.d[0]) || isnan(EX->d[0]) || isgreaterequal(GX.d[0], EX->d[0]); break;

View File

@ -207,8 +207,8 @@
tmp8s = 0;
switch(tmp8u&7) {
case 0: tmp8s=(GX.f[0] == EX->f[0]); break;
case 1: tmp8s=isless(GX.f[0], EX->f[0]); break;
case 2: tmp8s=islessequal(GX.f[0], EX->f[0]); break;
case 1: tmp8s=isless(GX.f[0], EX->f[0]) && !(isnan(GX.f[0]) || isnan(EX->f[0])); break;
case 2: tmp8s=islessequal(GX.f[0], EX->f[0]) && !(isnan(GX.f[0]) || isnan(EX->f[0])); break;
case 3: tmp8s=isnan(GX.f[0]) || isnan(EX->f[0]); break;
case 4: tmp8s=(GX.f[0] != EX->f[0]); break;
case 5: tmp8s=isnan(GX.f[0]) || isnan(EX->f[0]) || isgreaterequal(GX.f[0], EX->f[0]); break;

View File

@ -7,7 +7,10 @@ ucomiss -inf, 1.000000 => 0x202
ucomiss 1.000000, nan => 0x247
ucomiss nan, 1.000000 => 0x247
ucomiss 1.000000, 1.000000 => 0x242
ucomiss 1.000000, 1.000000 => 0x242
ucomiss inf, inf => 0x242
ucomiss -inf, inf => 0x202
ucomiss inf, -inf => 0x203
ucomiss nan, nan => 0x247
minss 1, 2 => 1
minss 2, 1 => 1
@ -31,9 +34,121 @@ maxss inf, 2 => inf
maxss 2, inf => inf
maxss nan, 2 => 2
maxss 2, nan => nan
maxss nan, -3.40282e+38 => -3.40282e+38
maxss -3.40282e+38, nan => nan
maxss -inf, -3.40282e+38 => -3.40282e+38
maxss -3.40282e+38, -inf => -3.40282e+38
maxss inf, -3.40282e+38 => inf
maxss -3.40282e+38, inf => inf
maxss nan, 3.40282e+38 => 3.40282e+38
maxss 3.40282e+38, nan => nan
maxss -inf, 3.40282e+38 => 3.40282e+38
maxss 3.40282e+38, -inf => 3.40282e+38
maxss inf, 3.40282e+38 => inf
maxss 3.40282e+38, inf => inf
cmpss 0 1.000000, 2.000000 => 0x0
cmpss 0 2.000000, 1.000000 => 0x0
cmpss 0 1.000000, inf => 0x0
cmpss 0 inf, 1.000000 => 0x0
cmpss 0 1.000000, -inf => 0x0
cmpss 0 -inf, 1.000000 => 0x0
cmpss 0 1.000000, nan => 0x0
cmpss 0 nan, 1.000000 => 0x0
cmpss 0 1.000000, 1.000000 => 0xffffffff
cmpss 0 1.000000, 1.000000 => 0xffffffff
cmpss 0 inf, inf => 0xffffffff
cmpss 0 -inf, inf => 0x0
cmpss 0 inf, -inf => 0x0
cmpss 0 nan, nan => 0x0
cmpss 1 1.000000, 2.000000 => 0xffffffff
cmpss 1 2.000000, 1.000000 => 0x0
cmpss 1 1.000000, inf => 0xffffffff
cmpss 1 inf, 1.000000 => 0x0
cmpss 1 1.000000, -inf => 0x0
cmpss 1 -inf, 1.000000 => 0xffffffff
cmpss 1 1.000000, nan => 0x0
cmpss 1 nan, 1.000000 => 0x0
cmpss 1 1.000000, 1.000000 => 0x0
cmpss 1 1.000000, 1.000000 => 0x0
cmpss 1 inf, inf => 0x0
cmpss 1 -inf, inf => 0xffffffff
cmpss 1 inf, -inf => 0x0
cmpss 1 nan, nan => 0x0
cmpss 2 1.000000, 2.000000 => 0xffffffff
cmpss 2 2.000000, 1.000000 => 0x0
cmpss 2 1.000000, inf => 0xffffffff
cmpss 2 inf, 1.000000 => 0x0
cmpss 2 1.000000, -inf => 0x0
cmpss 2 -inf, 1.000000 => 0xffffffff
cmpss 2 1.000000, nan => 0x0
cmpss 2 nan, 1.000000 => 0x0
cmpss 2 1.000000, 1.000000 => 0xffffffff
cmpss 2 1.000000, 1.000000 => 0xffffffff
cmpss 2 inf, inf => 0xffffffff
cmpss 2 -inf, inf => 0xffffffff
cmpss 2 inf, -inf => 0x0
cmpss 2 nan, nan => 0x0
cmpss 3 1.000000, 2.000000 => 0x0
cmpss 3 2.000000, 1.000000 => 0x0
cmpss 3 1.000000, inf => 0x0
cmpss 3 inf, 1.000000 => 0x0
cmpss 3 1.000000, -inf => 0x0
cmpss 3 -inf, 1.000000 => 0x0
cmpss 3 1.000000, nan => 0xffffffff
cmpss 3 nan, 1.000000 => 0xffffffff
cmpss 3 1.000000, 1.000000 => 0x0
cmpss 3 1.000000, 1.000000 => 0x0
cmpss 3 inf, inf => 0x0
cmpss 3 -inf, inf => 0x0
cmpss 3 inf, -inf => 0x0
cmpss 3 nan, nan => 0xffffffff
cmpss 4 1.000000, 2.000000 => 0xffffffff
cmpss 4 2.000000, 1.000000 => 0xffffffff
cmpss 4 1.000000, inf => 0xffffffff
cmpss 4 inf, 1.000000 => 0xffffffff
cmpss 4 1.000000, -inf => 0xffffffff
cmpss 4 -inf, 1.000000 => 0xffffffff
cmpss 4 1.000000, nan => 0xffffffff
cmpss 4 nan, 1.000000 => 0xffffffff
cmpss 4 1.000000, 1.000000 => 0x0
cmpss 4 1.000000, 1.000000 => 0x0
cmpss 4 inf, inf => 0x0
cmpss 4 -inf, inf => 0xffffffff
cmpss 4 inf, -inf => 0xffffffff
cmpss 4 nan, nan => 0xffffffff
cmpss 5 1.000000, 2.000000 => 0x0
cmpss 5 2.000000, 1.000000 => 0xffffffff
cmpss 5 1.000000, inf => 0x0
cmpss 5 inf, 1.000000 => 0xffffffff
cmpss 5 1.000000, -inf => 0xffffffff
cmpss 5 -inf, 1.000000 => 0x0
cmpss 5 1.000000, nan => 0xffffffff
cmpss 5 nan, 1.000000 => 0xffffffff
cmpss 5 1.000000, 1.000000 => 0xffffffff
cmpss 5 1.000000, 1.000000 => 0xffffffff
cmpss 5 inf, inf => 0xffffffff
cmpss 5 -inf, inf => 0x0
cmpss 5 inf, -inf => 0xffffffff
cmpss 5 nan, nan => 0xffffffff
cmpss 6 1.000000, 2.000000 => 0x0
cmpss 6 2.000000, 1.000000 => 0xffffffff
cmpss 6 1.000000, inf => 0x0
cmpss 6 inf, 1.000000 => 0xffffffff
cmpss 6 1.000000, -inf => 0xffffffff
cmpss 6 -inf, 1.000000 => 0x0
cmpss 6 1.000000, nan => 0xffffffff
cmpss 6 nan, 1.000000 => 0xffffffff
cmpss 6 1.000000, 1.000000 => 0x0
cmpss 6 1.000000, 1.000000 => 0x0
cmpss 6 inf, inf => 0x0
cmpss 6 -inf, inf => 0x0
cmpss 6 inf, -inf => 0xffffffff
cmpss 6 nan, nan => 0xffffffff
cmpss 7 1.000000, 2.000000 => 0xffffffff
cmpss 7 2.000000, 1.000000 => 0xffffffff
cmpss 7 1.000000, inf => 0xffffffff
cmpss 7 inf, 1.000000 => 0xffffffff
cmpss 7 1.000000, -inf => 0xffffffff
cmpss 7 -inf, 1.000000 => 0xffffffff
cmpss 7 1.000000, nan => 0x0
cmpss 7 nan, 1.000000 => 0x0
cmpss 7 1.000000, 1.000000 => 0xffffffff
cmpss 7 1.000000, 1.000000 => 0xffffffff
cmpss 7 inf, inf => 0xffffffff
cmpss 7 -inf, inf => 0xffffffff
cmpss 7 inf, -inf => 0xffffffff
cmpss 7 nan, nan => 0x0

Binary file not shown.

View File

@ -34,6 +34,16 @@ uint64_t _maxss_(float a, float b)
:"=a" (ret)::"xmm0","xmm1","cc");
return ret;
}
#define CMPSS(A) \
uint64_t _cmpss_##A(float a, float b) \
{ \
uint64_t ret; \
asm volatile ( \
"cmpss $" #A ", %%xmm1, %%xmm0\n" \
"movd %%xmm0, %%eax" \
:"=a" (ret)::"xmm0","xmm1","cc"); \
return ret; \
}
#else
uint64_t _ucomiss_(float a, float b)
{
@ -69,7 +79,27 @@ uint64_t _maxss_(float a, float b)
:"=a" (ret):"m"(a), "m"(b):"xmm0", "xmm1", "cc");
return ret;
}
#define CMPSS(A) \
uint64_t _cmpss_##A(float a, float b) \
{ \
uint32_t ret; \
asm volatile ( \
"movss %1, %%xmm0\n" \
"movss %2, %%xmm1\n" \
"cmpss $" #A ", %%xmm1, %%xmm0\n" \
"movd %%xmm0, %%eax" \
:"=a" (ret):"m"(a), "m"(b):"xmm0", "xmm1", "cc"); \
return ret; \
}
#endif
CMPSS(0)
CMPSS(1)
CMPSS(2)
CMPSS(3)
CMPSS(4)
CMPSS(5)
CMPSS(6)
CMPSS(7)
int main(int argc, const char** argv)
{
@ -78,107 +108,93 @@ int main(int argc, const char** argv)
uint32_t maxf = 0x7f7fffff;
uint32_t minf = 0xff7fffff;
uint32_t r;
a = 1.0f; b = 2.0f;
flags = _ucomiss_(a, b);
printf("ucomiss %f, %f => 0x%lx\n", a, b, flags);
flags = _ucomiss_(b, a);
printf("ucomiss %f, %f => 0x%lx\n", b, a, flags);
b = INFINITY;
flags = _ucomiss_(a, b);
printf("ucomiss %f, %f => 0x%lx\n", a, b, flags);
flags = _ucomiss_(b, a);
printf("ucomiss %f, %f => 0x%lx\n", b, a, flags);
b = -INFINITY;
flags = _ucomiss_(a, b);
printf("ucomiss %f, %f => 0x%lx\n", a, b, flags);
flags = _ucomiss_(b, a);
printf("ucomiss %f, %f => 0x%lx\n", b, a, flags);
b = NAN;
flags = _ucomiss_(a, b);
printf("ucomiss %f, %f => 0x%lx\n", a, b, flags);
flags = _ucomiss_(b, a);
printf("ucomiss %f, %f => 0x%lx\n", b, a, flags);
b = a;
flags = _ucomiss_(a, b);
printf("ucomiss %f, %f => 0x%lx\n", a, b, flags);
a = b = INFINITY;
flags = _ucomiss_(a, b);
printf("ucomiss %f, %f => 0x%lx\n", a, b, flags);
a = b = NAN;
flags = _ucomiss_(a, b);
printf("ucomiss %f, %f => 0x%lx\n", a, b, flags);
a = 1.0f; b = 2.0f;
r = _minss_(a, b);
printf("minss %g, %g => %g\n", a, b, *(float*)&r);
r = _minss_(b, a);
printf("minss %g, %g => %g\n", b, a, *(float*)&r);
a = -INFINITY;
r = _minss_(a, b);
printf("minss %g, %g => %g\n", a, b, *(float*)&r);
r = _minss_(b, a);
printf("minss %g, %g => %g\n", b, a, *(float*)&r);
a = +INFINITY;
r = _minss_(a, b);
printf("minss %g, %g => %g\n", a, b, *(float*)&r);
r = _minss_(b, a);
printf("minss %g, %g => %g\n", b, a, *(float*)&r);
a = NAN;
r = _minss_(a, b);
printf("minss %g, %g => %g\n", a, b, *(float*)&r);
r = _minss_(b, a);
printf("minss %g, %g => %g\n", b, a, *(float*)&r);
b = *(float*)&maxf;
r = _minss_(a, b);
printf("minss %g, %g => %g\n", a, b, *(float*)&r);
r = _minss_(b, a);
printf("minss %g, %g => %g\n", b, a, *(float*)&r);
a = -INFINITY;
r = _minss_(a, b);
printf("minss %g, %g => %g\n", a, b, *(float*)&r);
r = _minss_(b, a);
printf("minss %g, %g => %g\n", b, a, *(float*)&r);
a = +INFINITY;
r = _minss_(a, b);
printf("minss %g, %g => %g\n", a, b, *(float*)&r);
r = _minss_(b, a);
printf("minss %g, %g => %g\n", b, a, *(float*)&r);
#define GO1(A, N) \
a = 1.0f; b = 2.0f; \
flags = A(a, b); \
printf(N " %f, %f => 0x%lx\n", a, b, flags); \
flags = A(b, a); \
printf(N " %f, %f => 0x%lx\n", b, a, flags); \
b = INFINITY; \
flags = A(a, b); \
printf(N " %f, %f => 0x%lx\n", a, b, flags); \
flags = A(b, a); \
printf(N " %f, %f => 0x%lx\n", b, a, flags); \
b = -INFINITY; \
flags = A(a, b); \
printf(N " %f, %f => 0x%lx\n", a, b, flags); \
flags = A(b, a); \
printf(N " %f, %f => 0x%lx\n", b, a, flags); \
b = NAN; \
flags = A(a, b); \
printf(N " %f, %f => 0x%lx\n", a, b, flags); \
flags = A(b, a); \
printf(N " %f, %f => 0x%lx\n", b, a, flags); \
b = a; \
flags = A(a, b); \
printf(N " %f, %f => 0x%lx\n", a, b, flags); \
flags = A(b, a); \
printf(N " %f, %f => 0x%lx\n", b, a, flags); \
a = b = INFINITY; \
flags = A(a, b); \
printf(N " %f, %f => 0x%lx\n", a, b, flags); \
a = -INFINITY; \
flags = A(a, b); \
printf(N " %f, %f => 0x%lx\n", a, b, flags); \
flags = A(b, a); \
printf(N " %f, %f => 0x%lx\n", b, a, flags); \
a = b = NAN; \
flags = A(a, b); \
printf(N " %f, %f => 0x%lx\n", a, b, flags);
a = 1.0f; b = 2.0f;
r = _maxss_(a, b);
printf("maxss %g, %g => %g\n", a, b, *(float*)&r);
r = _maxss_(b, a);
printf("maxss %g, %g => %g\n", b, a, *(float*)&r);
a = -INFINITY;
r = _maxss_(a, b);
printf("maxss %g, %g => %g\n", a, b, *(float*)&r);
r = _maxss_(b, a);
printf("maxss %g, %g => %g\n", b, a, *(float*)&r);
a = +INFINITY;
r = _maxss_(a, b);
printf("maxss %g, %g => %g\n", a, b, *(float*)&r);
r = _maxss_(b, a);
printf("maxss %g, %g => %g\n", b, a, *(float*)&r);
a = NAN;
r = _maxss_(a, b);
printf("maxss %g, %g => %g\n", a, b, *(float*)&r);
r = _maxss_(b, a);
printf("maxss %g, %g => %g\n", b, a, *(float*)&r);
b = *(float*)&minf;
r = _maxss_(a, b);
printf("maxss %g, %g => %g\n", a, b, *(float*)&r);
r = _maxss_(b, a);
printf("maxss %g, %g => %g\n", b, a, *(float*)&r);
a = -INFINITY;
r = _maxss_(a, b);
printf("maxss %g, %g => %g\n", a, b, *(float*)&r);
r = _maxss_(b, a);
printf("maxss %g, %g => %g\n", b, a, *(float*)&r);
a = +INFINITY;
r = _maxss_(a, b);
printf("maxss %g, %g => %g\n", a, b, *(float*)&r);
r = _maxss_(b, a);
printf("maxss %g, %g => %g\n", b, a, *(float*)&r);
#define GO2(A, N) \
a = 1.0f; b = 2.0f; \
r = A(a, b); \
printf(N " %g, %g => %g\n", a, b, *(float*)&r); \
r = A(b, a); \
printf(N " %g, %g => %g\n", b, a, *(float*)&r); \
a = -INFINITY; \
r = A(a, b); \
printf(N " %g, %g => %g\n", a, b, *(float*)&r); \
r = A(b, a); \
printf(N " %g, %g => %g\n", b, a, *(float*)&r); \
a = +INFINITY; \
r = A(a, b); \
printf(N " %g, %g => %g\n", a, b, *(float*)&r); \
r = A(b, a); \
printf(N " %g, %g => %g\n", b, a, *(float*)&r); \
a = NAN; \
r = A(a, b); \
printf(N " %g, %g => %g\n", a, b, *(float*)&r); \
r = A(b, a); \
printf(N " %g, %g => %g\n", b, a, *(float*)&r); \
b = *(float*)&maxf; \
r = A(a, b); \
printf(N " %g, %g => %g\n", a, b, *(float*)&r); \
r = A(b, a); \
printf(N " %g, %g => %g\n", b, a, *(float*)&r); \
a = -INFINITY; \
r = A(a, b); \
printf(N " %g, %g => %g\n", a, b, *(float*)&r); \
r = A(b, a); \
printf(N " %g, %g => %g\n", b, a, *(float*)&r); \
a = +INFINITY; \
r = A(a, b); \
printf(N " %g, %g => %g\n", a, b, *(float*)&r); \
r = A(b, a); \
printf(N " %g, %g => %g\n", b, a, *(float*)&r);
GO1(_ucomiss_, "ucomiss")
GO2(_minss_, "minss")
GO2(_maxss_, "maxss")
GO1(_cmpss_0, "cmpss 0")
GO1(_cmpss_1, "cmpss 1")
GO1(_cmpss_2, "cmpss 2")
GO1(_cmpss_3, "cmpss 3")
GO1(_cmpss_4, "cmpss 4")
GO1(_cmpss_5, "cmpss 5")
GO1(_cmpss_6, "cmpss 6")
GO1(_cmpss_7, "cmpss 7")
return 0;
}