FCOM/FUCOM now use inline assembler on x86 targets. Unreal now works.
This commit is contained in:
parent
630592125c
commit
19c318675a
2 changed files with 77 additions and 16 deletions
|
|
@ -164,6 +164,74 @@ static inline void x87_stmmx(MMX_REG r)
|
||||||
writememw(easeg, eaaddr + 8, 0xffff);
|
writememw(easeg, eaaddr + 8, 0xffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint16_t x87_compare(double a, double b)
|
||||||
|
{
|
||||||
|
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
uint32_t out;
|
||||||
|
|
||||||
|
/* Memory barrier, to force GCC to write to the input parameters
|
||||||
|
* before the compare rather than after */
|
||||||
|
asm volatile ("" : : : "memory");
|
||||||
|
|
||||||
|
asm(
|
||||||
|
"fldl %2\n"
|
||||||
|
"fldl %1\n"
|
||||||
|
"fclex\n"
|
||||||
|
"fcompp\n"
|
||||||
|
"fnstsw %0\n"
|
||||||
|
: "=m" (out)
|
||||||
|
: "m" (a), "m" (b)
|
||||||
|
);
|
||||||
|
|
||||||
|
return out & (C0|C2|C3);
|
||||||
|
#else
|
||||||
|
/* Generic C version is known to give incorrect results in some
|
||||||
|
* situations, eg comparison of infinity (Unreal) */
|
||||||
|
uint32_t out = 0;
|
||||||
|
|
||||||
|
if (a == b)
|
||||||
|
out |= C3;
|
||||||
|
else if (a < b)
|
||||||
|
out |= C0;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t x87_ucompare(double a, double b)
|
||||||
|
{
|
||||||
|
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
|
||||||
|
uint32_t out;
|
||||||
|
|
||||||
|
/* Memory barrier, to force GCC to write to the input parameters
|
||||||
|
* before the compare rather than after */
|
||||||
|
asm volatile ("" : : : "memory");
|
||||||
|
|
||||||
|
asm(
|
||||||
|
"fldl %2\n"
|
||||||
|
"fldl %1\n"
|
||||||
|
"fclex\n"
|
||||||
|
"fucompp\n"
|
||||||
|
"fnstsw %0\n"
|
||||||
|
: "=m" (out)
|
||||||
|
: "m" (a), "m" (b)
|
||||||
|
);
|
||||||
|
|
||||||
|
return out & (C0|C2|C3);
|
||||||
|
#else
|
||||||
|
/* Generic C version is known to give incorrect results in some
|
||||||
|
* situations, eg comparison of infinity (Unreal) */
|
||||||
|
uint32_t out = 0;
|
||||||
|
|
||||||
|
if (a == b)
|
||||||
|
out |= C3;
|
||||||
|
else if (a < b)
|
||||||
|
out |= C0;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
typedef union
|
typedef union
|
||||||
{
|
{
|
||||||
float s;
|
float s;
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,7 @@ static int opFCOM ## name ## _a ## a_size(uint32_t fetchdat) \
|
||||||
fetch_ea_ ## a_size(fetchdat); \
|
fetch_ea_ ## a_size(fetchdat); \
|
||||||
load_var = get(); if (abrt) return 1; \
|
load_var = get(); if (abrt) return 1; \
|
||||||
npxs &= ~(C0|C2|C3); \
|
npxs &= ~(C0|C2|C3); \
|
||||||
if (ST(0) == use_var) npxs |= C3; \
|
npxs |= x87_compare(ST(0), (double)use_var); \
|
||||||
else if (ST(0) < use_var) npxs |= C0; \
|
|
||||||
CLOCK_CYCLES(4); \
|
CLOCK_CYCLES(4); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
|
|
@ -28,8 +27,7 @@ static int opFCOMP ## name ## _a ## a_size(uint32_t fetchdat) \
|
||||||
fetch_ea_ ## a_size(fetchdat); \
|
fetch_ea_ ## a_size(fetchdat); \
|
||||||
load_var = get(); if (abrt) return 1; \
|
load_var = get(); if (abrt) return 1; \
|
||||||
npxs &= ~(C0|C2|C3); \
|
npxs &= ~(C0|C2|C3); \
|
||||||
if (ST(0) == use_var) npxs |= C3; \
|
npxs |= x87_compare(ST(0), (double)use_var); \
|
||||||
else if (ST(0) < use_var) npxs |= C0; \
|
|
||||||
x87_pop(); \
|
x87_pop(); \
|
||||||
CLOCK_CYCLES(4); \
|
CLOCK_CYCLES(4); \
|
||||||
return 0; \
|
return 0; \
|
||||||
|
|
@ -146,8 +144,7 @@ static int opFCOMP(uint32_t fetchdat)
|
||||||
pc++;
|
pc++;
|
||||||
if (fplog) pclog("FCOMP\n");
|
if (fplog) pclog("FCOMP\n");
|
||||||
npxs &= ~(C0|C2|C3);
|
npxs &= ~(C0|C2|C3);
|
||||||
if (ST(0) == ST(fetchdat & 7)) npxs |= C3;
|
npxs |= x87_compare(ST(0), ST(fetchdat & 7));
|
||||||
else if (ST(0) < ST(fetchdat & 7)) npxs |= C0;
|
|
||||||
x87_pop();
|
x87_pop();
|
||||||
CLOCK_CYCLES(4);
|
CLOCK_CYCLES(4);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -161,10 +158,9 @@ static int opFCOMPP(uint32_t fetchdat)
|
||||||
npxs &= ~(C0|C2|C3);
|
npxs &= ~(C0|C2|C3);
|
||||||
if (*(uint64_t *)&ST(0) == ((uint64_t)1 << 63) && *(uint64_t *)&ST(1) == 0)
|
if (*(uint64_t *)&ST(0) == ((uint64_t)1 << 63) && *(uint64_t *)&ST(1) == 0)
|
||||||
npxs |= C0; /*Nasty hack to fix 80387 detection*/
|
npxs |= C0; /*Nasty hack to fix 80387 detection*/
|
||||||
else if (ST(0) == ST(1))
|
else
|
||||||
npxs |= C3;
|
npxs |= x87_compare(ST(0), ST(1));
|
||||||
else if (ST(0) < ST(1))
|
|
||||||
npxs |= C0;
|
|
||||||
x87_pop();
|
x87_pop();
|
||||||
x87_pop();
|
x87_pop();
|
||||||
CLOCK_CYCLES(4);
|
CLOCK_CYCLES(4);
|
||||||
|
|
@ -176,8 +172,7 @@ static int opFUCOMPP(uint32_t fetchdat)
|
||||||
pc++;
|
pc++;
|
||||||
if (fplog) pclog("FUCOMPP\n", easeg, eaaddr);
|
if (fplog) pclog("FUCOMPP\n", easeg, eaaddr);
|
||||||
npxs &= ~(C0|C2|C3);
|
npxs &= ~(C0|C2|C3);
|
||||||
if (ST(0) == ST(1)) npxs |= C3;
|
npxs |= x87_ucompare(ST(0), ST(1));
|
||||||
else if (ST(0) < ST(1)) npxs |= C0;
|
|
||||||
x87_pop();
|
x87_pop();
|
||||||
x87_pop();
|
x87_pop();
|
||||||
CLOCK_CYCLES(5);
|
CLOCK_CYCLES(5);
|
||||||
|
|
@ -335,8 +330,7 @@ static int opFUCOM(uint32_t fetchdat)
|
||||||
pc++;
|
pc++;
|
||||||
if (fplog) pclog("FUCOM\n");
|
if (fplog) pclog("FUCOM\n");
|
||||||
npxs &= ~(C0|C2|C3);
|
npxs &= ~(C0|C2|C3);
|
||||||
if (ST(0) == ST(fetchdat&7)) npxs |= C3;
|
npxs |= x87_ucompare(ST(0), ST(fetchdat & 7));
|
||||||
else if (ST(0) < ST(fetchdat&7)) npxs |= C0;
|
|
||||||
CLOCK_CYCLES(4);
|
CLOCK_CYCLES(4);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -347,8 +341,7 @@ static int opFUCOMP(uint32_t fetchdat)
|
||||||
pc++;
|
pc++;
|
||||||
if (fplog) pclog("FUCOMP\n");
|
if (fplog) pclog("FUCOMP\n");
|
||||||
npxs &= ~(C0|C2|C3);
|
npxs &= ~(C0|C2|C3);
|
||||||
if (ST(0) == ST(fetchdat&7)) npxs |= C3;
|
npxs |= x87_ucompare(ST(0), ST(fetchdat & 7));
|
||||||
else if (ST(0) < ST(fetchdat&7)) npxs |= C0;
|
|
||||||
x87_pop();
|
x87_pop();
|
||||||
CLOCK_CYCLES(4);
|
CLOCK_CYCLES(4);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue