.file "reg_u_mul.S"1/*---------------------------------------------------------------------------+2| reg_u_mul.S |3| |4| Core multiplication routine |5| |6| Copyright (C) 1992,1993,1995,1997 |7| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |8| E-mail [email protected] |9| |10| |11+---------------------------------------------------------------------------*/1213/*---------------------------------------------------------------------------+14| Basic multiplication routine. |15| Does not check the resulting exponent for overflow/underflow |16| |17| FPU_u_mul(FPU_REG *a, FPU_REG *b, FPU_REG *c, unsigned int cw); |18| |19| Internal working is at approx 128 bits. |20| Result is rounded to nearest 53 or 64 bits, using "nearest or even". |21+---------------------------------------------------------------------------*/2223#include "exception.h"24#include "fpu_emu.h"25#include "control_w.h"26272829#ifndef NON_REENTRANT_FPU30/* Local storage on the stack: */31#define FPU_accum_0 -4(%ebp) /* ms word */32#define FPU_accum_1 -8(%ebp)3334#else35/* Local storage in a static area: */36.data37.align 4,038FPU_accum_0:39.long 040FPU_accum_1:41.long 042#endif /* NON_REENTRANT_FPU */434445.text46ENTRY(FPU_u_mul)47pushl %ebp48movl %esp,%ebp49#ifndef NON_REENTRANT_FPU50subl $8,%esp51#endif /* NON_REENTRANT_FPU */5253pushl %esi54pushl %edi55pushl %ebx5657movl PARAM1,%esi58movl PARAM2,%edi5960#ifdef PARANOID61testl $0x80000000,SIGH(%esi)62jz L_bugged63testl $0x80000000,SIGH(%edi)64jz L_bugged65#endif /* PARANOID */6667xorl %ecx,%ecx68xorl %ebx,%ebx6970movl SIGL(%esi),%eax71mull SIGL(%edi)72movl %eax,FPU_accum_073movl %edx,FPU_accum_17475movl SIGL(%esi),%eax76mull SIGH(%edi)77addl %eax,FPU_accum_178adcl %edx,%ebx79/* adcl $0,%ecx // overflow here is not possible */8081movl SIGH(%esi),%eax82mull SIGL(%edi)83addl %eax,FPU_accum_184adcl %edx,%ebx85adcl $0,%ecx8687movl SIGH(%esi),%eax88mull SIGH(%edi)89addl %eax,%ebx90adcl %edx,%ecx9192/* Get the sum of the exponents. */93movl PARAM6,%eax94subl EXP_BIAS-1,%eax9596/* Two denormals can cause an exponent underflow */97cmpl EXP_WAY_UNDER,%eax98jg Exp_not_underflow99100/* Set to a really low value allow correct handling */101movl EXP_WAY_UNDER,%eax102103Exp_not_underflow:104105/* Have now finished with the sources */106movl PARAM3,%edi /* Point to the destination */107movw %ax,EXP(%edi)108109/* Now make sure that the result is normalized */110testl $0x80000000,%ecx111jnz LResult_Normalised112113/* Normalize by shifting left one bit */114shll $1,FPU_accum_0115rcll $1,FPU_accum_1116rcll $1,%ebx117rcll $1,%ecx118decw EXP(%edi)119120LResult_Normalised:121movl FPU_accum_0,%eax122movl FPU_accum_1,%edx123orl %eax,%eax124jz L_extent_zero125126orl $1,%edx127128L_extent_zero:129movl %ecx,%eax130jmp fpu_reg_round131132133#ifdef PARANOID134L_bugged:135pushl EX_INTERNAL|0x205136call EXCEPTION137pop %ebx138jmp L_exit139140L_exit:141popl %ebx142popl %edi143popl %esi144leave145ret146#endif /* PARANOID */147148149150