Remove FixedMul and FixedDiv2 asm implementations

Actually works this time
This commit is contained in:
tertu marybig 2021-09-28 08:31:14 -05:00
parent 923e6f31aa
commit 4424f6ba9a
2 changed files with 22 additions and 158 deletions

View file

@ -21,50 +21,6 @@
#include "doomdef.h" #include "doomdef.h"
#include "m_fixed.h" #include "m_fixed.h"
#ifdef __USE_C_FIXEDMUL__
/** \brief The FixedMul function
\param a fixed_t number
\param b fixed_t number
\return a*b>>FRACBITS
*/
fixed_t FixedMul(fixed_t a, fixed_t b)
{
// Need to cast to unsigned before shifting to avoid undefined behaviour
// for negative integers
return (fixed_t)(((UINT64)((INT64)a * b)) >> FRACBITS);
}
#endif //__USE_C_FIXEDMUL__
#ifdef __USE_C_FIXEDDIV__
/** \brief The FixedDiv2 function
\param a fixed_t number
\param b fixed_t number
\return a/b * FRACUNIT
*/
fixed_t FixedDiv2(fixed_t a, fixed_t b)
{
INT64 ret;
if (b == 0)
I_Error("FixedDiv: divide by zero");
ret = (((INT64)a * FRACUNIT)) / b;
if ((ret > INT32_MAX) || (ret < INT32_MIN))
I_Error("FixedDiv: divide by zero");
return (fixed_t)ret;
}
#endif // __USE_C_FIXEDDIV__
fixed_t FixedSqrt(fixed_t x) fixed_t FixedSqrt(fixed_t x)
{ {
#ifdef HAVE_SQRT #ifdef HAVE_SQRT

View file

@ -53,127 +53,35 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FloatToFixed(float f)
#define FIXED_TO_FLOAT(x) FixedToFloat(x) // (((float)(x)) / ((float)FRACUNIT)) #define FIXED_TO_FLOAT(x) FixedToFloat(x) // (((float)(x)) / ((float)FRACUNIT))
#define FLOAT_TO_FIXED(f) FloatToFixed(f) // (fixed_t)((f) * ((float)FRACUNIT)) #define FLOAT_TO_FIXED(f) FloatToFixed(f) // (fixed_t)((f) * ((float)FRACUNIT))
/** \brief The FixedMul function
#if defined (__WATCOMC__) && FRACBITS == 16 \param a fixed_t number
#pragma aux FixedMul = \ \param b fixed_t number
"imul ebx", \
"shrd eax,edx,16" \
parm [eax] [ebx] \
value [eax] \
modify exact [eax edx]
#pragma aux FixedDiv2 = \ \return a*b>>FRACBITS
"cdq", \
"shld edx,eax,16", \
"sal eax,16", \
"idiv ebx" \
parm [eax] [ebx] \
value [eax] \
modify exact [eax edx]
#elif defined (__GNUC__) && defined (__i386__) && !defined (NOASM)
// i386 linux, cygwin or mingw
FUNCMATH FUNCINLINE static inline fixed_t FixedMul(fixed_t a, fixed_t b) // asm
{
fixed_t ret;
asm
(
"imull %2;" // a*b
"shrdl %3,%%edx,%0;" // shift logical right FRACBITS bits
:"=a" (ret) // eax is always the result and the first operand (%0,%1)
:"0" (a), "r" (b) // and %2 is what we use imull on with what in %1
, "I" (FRACBITS) // %3 holds FRACBITS (normally 16)
:"cc", "%edx" // edx and condition codes clobbered
);
return ret;
}
FUNCMATH FUNCINLINE static inline fixed_t FixedDiv2(fixed_t a, fixed_t b) */
{ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedMul(fixed_t a, fixed_t b)
fixed_t ret; {
asm // Need to cast to unsigned before shifting to avoid undefined behaviour
( // for negative integers
"movl %1,%%edx;" // these two instructions allow the next two to pair, on the Pentium processor. return (fixed_t)(((UINT64)((INT64)a * b)) >> FRACBITS);
"sarl $31,%%edx;" // shift arithmetic right 31 on EDX }
"shldl %3,%1,%%edx;" // DP shift logical left FRACBITS on EDX
"sall %3,%0;" // shift arithmetic left FRACBITS on EAX
"idivl %2;" // EDX/b = EAX
: "=a" (ret)
: "0" (a), "r" (b)
, "I" (FRACBITS)
: "%edx"
);
return ret;
}
#elif defined (__GNUC__) && defined (__arm__) && !defined(__thumb__) && !defined(NOASM) //ARMv4 ASM
FUNCMATH FUNCINLINE static inline fixed_t FixedMul(fixed_t a, fixed_t b) // let abuse smull
{
fixed_t ret;
asm
(
"smull %[lo], r1, %[a], %[b];"
"mov %[lo], %[lo], lsr %3;"
"orr %[lo], %[lo], r1, lsl %3;"
: [lo] "=&r" (ret) // rhi, rlo and rm must be distinct registers
: [a] "r" (a), [b] "r" (b)
, "i" (FRACBITS)
: "r1"
);
return ret;
}
#define __USE_C_FIXEDDIV__ // no double or asm div in ARM land /** \brief The FixedDiv2 function
#elif defined (__GNUC__) && defined (__ppc__) && !defined(NOASM) && 0 // WII: PPC CPU
FUNCMATH FUNCINLINE static inline fixed_t FixedMul(fixed_t a, fixed_t b) // asm
{
fixed_t ret, hi, lo;
asm
(
"mullw %0, %2, %3;"
"mulhw %1, %2, %3"
: "=r" (hi), "=r" (lo)
: "r" (a), "r" (b)
, "I" (FRACBITS)
);
ret = (INT64)((hi>>FRACBITS)+lo)<<FRACBITS;
return ret;
}
#define __USE_C_FIXEDDIV__// Alam: I am lazy \param a fixed_t number
#elif defined (__GNUC__) && defined (__mips__) && !defined(NOASM) && 0 // PSP: MIPS CPU \param b fixed_t number
FUNCMATH FUNCINLINE static inline fixed_t FixedMul(fixed_t a, fixed_t b) // asm
{
fixed_t ret;
asm
(
"mult %3, %4;" // a*b=h<32+l
: "=r" (ret), "=l" (a), "=h" (b) //todo: abuse shr opcode
: "0" (a), "r" (b)
, "I" (FRACBITS)
//: "+l", "+h"
);
ret = (INT64)((a>>FRACBITS)+b)<<FRACBITS;
return ret;
}
#define __USE_C_FIXEDDIV__ // no 64b asm div in MIPS land \return a/b * FRACUNIT
#elif defined (__GNUC__) && defined (__sh__) && 0 // DC: SH4 CPU
#elif defined (__GNUC__) && defined (__m68k__) && 0 // DEAD: Motorola 6800 CPU
#elif defined (_MSC_VER) && defined(USEASM) && FRACBITS == 16
// Microsoft Visual C++ (no asm inline)
fixed_t __cdecl FixedMul(fixed_t a, fixed_t b);
fixed_t __cdecl FixedDiv2(fixed_t a, fixed_t b);
#else
#define __USE_C_FIXEDMUL__
#define __USE_C_FIXEDDIV__
#endif
#ifdef __USE_C_FIXEDMUL__ */
FUNCMATH fixed_t FixedMul(fixed_t a, fixed_t b); FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedDiv2(fixed_t a, fixed_t b)
#endif {
// This does not check for division overflow or division by 0!
#ifdef __USE_C_FIXEDDIV__ // That is the caller's responsibility.
FUNCMATH fixed_t FixedDiv2(fixed_t a, fixed_t b); return (fixed_t)(((INT64)a * FRACUNIT) / b);
#endif }
/** \brief The FixedInt function /** \brief The FixedInt function