123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- .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 */
|