@ -197,6 +197,67 @@ FT_BEGIN_HEADER
#endif /* FT_SIZEOF_LONG == 8 */
#if !defined(FT_CONFIG_OPTION_NO_ASSEMBLER)
/* provide assembler fragments for performance-critical
* functions. these must be defined static __inline__
* with GCC
*/
#if defined(__GNUC__)
# if defined(__arm__) && !defined(__thumb__)
# define FT_MULFIX_ASSEMBLER FT_MulFix_arm
static __inline__ FT_Int32
FT_MulFix_arm( FT_Int32 a, FT_Int32 b )
{
register FT_Int32 t, t2;
asm __volatile__ (
"smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */
"mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */
"add %0, %0, #0x8000\n\t" /* %0 += 0x8000 */
"adds %1, %1, %0\n\t" /* %1 += %0 */
"adc %2, %2, #0\n\t" /* %2 += carry */
"mov %0, %1, lsr #16\n\t" /* %0 = %1 >> 16 */
"orr %0, %2, lsl #16\n\t" /* %0 |= %2 << 16 */
: "=r"(a), "=&r"(t2), "=&r"(t)
: "r"(a), "r"(b)
);
return a;
}
# endif /* __arm__ */
# if defined(i386)
# define FT_MULFIX_ASSEMBLER FT_MulFix_i386
static __inline__ FT_Int32
FT_MulFix_i386( FT_Int32 a, FT_Int32 b )
{
register FT_Int32 result;
__asm__ __volatile__ (
"imul %%edx\n"
"movl %%edx, %%ecx\n"
"sarl $31, %%ecx\n"
"addl $0x8000, %%ecx\n"
"addl %%ecx, %%eax\n"
"adcl $0, %%edx\n"
"shrl $16, %%eax\n"
"shll $16, %%edx\n"
"addl %%edx, %%eax\n"
: "=a"(result), "+d"(b)
: "a"(a)
: "%ecx"
);
return result;
}
# endif /* i386 */
#endif /* __GNUC__ */
#endif /* !NO_ASSEMBLER */
#ifdef FT_CONFIG_OPTION_INLINE_MULFIX
# ifdef FT_MULFIX_ASSEMBLER
# define FT_MULFIX_INLINED FT_MULFIX_ASSEMBLER
# endif
#endif
#define FT_BEGIN_STMNT do {
#define FT_END_STMNT } while ( 0 )