i386: move math-emu
[safe/jmp/linux-2.6] / arch / x86 / math-emu / reg_u_mul.S
diff --git a/arch/x86/math-emu/reg_u_mul.S b/arch/x86/math-emu/reg_u_mul.S
new file mode 100644 (file)
index 0000000..973f12a
--- /dev/null
@@ -0,0 +1,148 @@
+       .file   "reg_u_mul.S"
+/*---------------------------------------------------------------------------+
+ |  reg_u_mul.S                                                              |
+ |                                                                           |
+ | Core multiplication routine                                               |
+ |                                                                           |
+ | Copyright (C) 1992,1993,1995,1997                                         |
+ |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
+ |                  E-mail   billm@suburbia.net                              |
+ |                                                                           |
+ |                                                                           |
+ +---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------+
+ |   Basic multiplication routine.                                           |
+ |   Does not check the resulting exponent for overflow/underflow            |
+ |                                                                           |
+ |   FPU_u_mul(FPU_REG *a, FPU_REG *b, FPU_REG *c, unsigned int cw);         |
+ |                                                                           |
+ |   Internal working is at approx 128 bits.                                 |
+ |   Result is rounded to nearest 53 or 64 bits, using "nearest or even".    |
+ +---------------------------------------------------------------------------*/
+
+#include "exception.h"
+#include "fpu_emu.h"
+#include "control_w.h"
+
+
+
+#ifndef NON_REENTRANT_FPU
+/*  Local storage on the stack: */
+#define FPU_accum_0    -4(%ebp)        /* ms word */
+#define FPU_accum_1    -8(%ebp)
+
+#else
+/*  Local storage in a static area: */
+.data
+       .align 4,0
+FPU_accum_0:
+       .long   0
+FPU_accum_1:
+       .long   0
+#endif /* NON_REENTRANT_FPU */
+
+
+.text
+ENTRY(FPU_u_mul)
+       pushl   %ebp
+       movl    %esp,%ebp
+#ifndef NON_REENTRANT_FPU
+       subl    $8,%esp
+#endif /* NON_REENTRANT_FPU */ 
+
+       pushl   %esi
+       pushl   %edi
+       pushl   %ebx
+
+       movl    PARAM1,%esi
+       movl    PARAM2,%edi
+
+#ifdef PARANOID
+       testl   $0x80000000,SIGH(%esi)
+       jz      L_bugged
+       testl   $0x80000000,SIGH(%edi)
+       jz      L_bugged
+#endif /* PARANOID */
+
+       xorl    %ecx,%ecx
+       xorl    %ebx,%ebx
+
+       movl    SIGL(%esi),%eax
+       mull    SIGL(%edi)
+       movl    %eax,FPU_accum_0
+       movl    %edx,FPU_accum_1
+
+       movl    SIGL(%esi),%eax
+       mull    SIGH(%edi)
+       addl    %eax,FPU_accum_1
+       adcl    %edx,%ebx
+/*     adcl    $0,%ecx         // overflow here is not possible */
+
+       movl    SIGH(%esi),%eax
+       mull    SIGL(%edi)
+       addl    %eax,FPU_accum_1
+       adcl    %edx,%ebx
+       adcl    $0,%ecx
+
+       movl    SIGH(%esi),%eax
+       mull    SIGH(%edi)
+       addl    %eax,%ebx
+       adcl    %edx,%ecx
+
+       /* Get the sum of the exponents. */
+       movl    PARAM6,%eax
+       subl    EXP_BIAS-1,%eax
+
+       /* Two denormals can cause an exponent underflow */
+       cmpl    EXP_WAY_UNDER,%eax
+       jg      Exp_not_underflow
+
+       /* Set to a really low value allow correct handling */
+       movl    EXP_WAY_UNDER,%eax
+
+Exp_not_underflow:
+
+/*  Have now finished with the sources */
+       movl    PARAM3,%edi     /* Point to the destination */
+       movw    %ax,EXP(%edi)
+
+/*  Now make sure that the result is normalized */
+       testl   $0x80000000,%ecx
+       jnz     LResult_Normalised
+
+       /* Normalize by shifting left one bit */
+       shll    $1,FPU_accum_0
+       rcll    $1,FPU_accum_1
+       rcll    $1,%ebx
+       rcll    $1,%ecx
+       decw    EXP(%edi)
+
+LResult_Normalised:
+       movl    FPU_accum_0,%eax
+       movl    FPU_accum_1,%edx
+       orl     %eax,%eax
+       jz      L_extent_zero
+
+       orl     $1,%edx
+
+L_extent_zero:
+       movl    %ecx,%eax
+       jmp     fpu_reg_round
+
+
+#ifdef PARANOID
+L_bugged:
+       pushl   EX_INTERNAL|0x205
+       call    EXCEPTION
+       pop     %ebx
+       jmp     L_exit
+
+L_exit:
+       popl    %ebx
+       popl    %edi
+       popl    %esi
+       leave
+       ret
+#endif /* PARANOID */ 
+