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