Commit 01adb7ef authored by Albert Astals Cid's avatar Albert Astals Cid

xpdf303: Assembler for some functions

parent 4f87a316
......@@ -45,6 +45,42 @@ static inline int splashFloor(SplashCoord x) {
return FixedPoint::floor(x);
#elif USE_FLOAT
return (int)floorf(x);
#elif __GNUC__ && __i386__
// floor() and (int)() are implemented separately, which results
// in changing the FPCW multiple times - so we optimize it with
// some inline assembly
Gushort oldCW, newCW, t;
int result;
__asm__ volatile("fldl %4\n"
"fnstcw %0\n"
"movw %0, %3\n"
"andw $0xf3ff, %3\n"
"orw $0x0400, %3\n"
"movw %3, %1\n" // round down
"fldcw %1\n"
"fistpl %2\n"
"fldcw %0\n"
: "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
: "m" (x));
return result;
#elif defined(WIN32) && defined(_M_IX86)
// floor() and (int)() are implemented separately, which results
// in changing the FPCW multiple times - so we optimize it with
// some inline assembly
Gushort oldCW, newCW;
int result;
__asm fld QWORD PTR x
__asm fnstcw WORD PTR oldCW
__asm mov ax, WORD PTR oldCW
__asm and ax, 0xf3ff
__asm or ax, 0x0400
__asm mov WORD PTR newCW, ax // round down
__asm fldcw WORD PTR newCW
__asm fistp DWORD PTR result
__asm fldcw WORD PTR oldCW
return result;
#else
if (x > 0) return (int)x;
else return (int)floor(x);
......@@ -56,6 +92,42 @@ static inline int splashCeil(SplashCoord x) {
return FixedPoint::ceil(x);
#elif USE_FLOAT
return (int)ceilf(x);
#elif __GNUC__ && __i386__
// ceil() and (int)() are implemented separately, which results
// in changing the FPCW multiple times - so we optimize it with
// some inline assembly
Gushort oldCW, newCW, t;
int result;
__asm__ volatile("fldl %4\n"
"fnstcw %0\n"
"movw %0, %3\n"
"andw $0xf3ff, %3\n"
"orw $0x0800, %3\n"
"movw %3, %1\n" // round up
"fldcw %1\n"
"fistpl %2\n"
"fldcw %0\n"
: "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
: "m" (x));
return result;
#elif defined(WIN32) && defined(_M_IX86)
// ceil() and (int)() are implemented separately, which results
// in changing the FPCW multiple times - so we optimize it with
// some inline assembly
Gushort oldCW, newCW;
int result;
__asm fld QWORD PTR x
__asm fnstcw WORD PTR oldCW
__asm mov ax, WORD PTR oldCW
__asm and ax, 0xf3ff
__asm or ax, 0x0800
__asm mov WORD PTR newCW, ax // round up
__asm fldcw WORD PTR newCW
__asm fistp DWORD PTR result
__asm fldcw WORD PTR oldCW
return result;
#else
return (int)ceil(x);
#endif
......@@ -64,6 +136,44 @@ static inline int splashCeil(SplashCoord x) {
static inline int splashRound(SplashCoord x) {
#if USE_FIXEDPOINT
return FixedPoint::round(x);
#elif __GNUC__ && __i386__
// this could use round-to-nearest mode and avoid the "+0.5",
// but that produces slightly different results (because i+0.5
// sometimes rounds up and sometimes down using the even rule)
Gushort oldCW, newCW, t;
int result;
x += 0.5;
__asm__ volatile("fldl %4\n"
"fnstcw %0\n"
"movw %0, %3\n"
"andw $0xf3ff, %3\n"
"orw $0x0400, %3\n"
"movw %3, %1\n" // round down
"fldcw %1\n"
"fistpl %2\n"
"fldcw %0\n"
: "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
: "m" (x));
return result;
#elif defined(WIN32) && defined(_M_IX86)
// this could use round-to-nearest mode and avoid the "+0.5",
// but that produces slightly different results (because i+0.5
// sometimes rounds up and sometimes down using the even rule)
Gushort oldCW, newCW;
int result;
x += 0.5;
__asm fld QWORD PTR x
__asm fnstcw WORD PTR oldCW
__asm mov ax, WORD PTR oldCW
__asm and ax, 0xf3ff
__asm or ax, 0x0400
__asm mov WORD PTR newCW, ax // round down
__asm fldcw WORD PTR newCW
__asm fistp DWORD PTR result
__asm fldcw WORD PTR oldCW
return result;
#else
return (int)splashFloor(x + 0.5);
#endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment