/* SPDX-License-Identifier: GPL-2.0 */1.file "reg_u_mul.S"2/*---------------------------------------------------------------------------+3| reg_u_mul.S |4| |5| Core multiplication routine |6| |7| Copyright (C) 1992,1993,1995,1997 |8| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |9| E-mail [email protected] |10| |11| |12+---------------------------------------------------------------------------*/1314/*---------------------------------------------------------------------------+15| Basic multiplication routine. |16| Does not check the resulting exponent for overflow/underflow |17| |18| FPU_u_mul(FPU_REG *a, FPU_REG *b, FPU_REG *c, unsigned int cw); |19| |20| Internal working is at approx 128 bits. |21| Result is rounded to nearest 53 or 64 bits, using "nearest or even". |22+---------------------------------------------------------------------------*/2324#include "exception.h"25#include "fpu_emu.h"26#include "control_w.h"27282930#ifndef NON_REENTRANT_FPU31/* Local storage on the stack: */32#define FPU_accum_0 -4(%ebp) /* ms word */33#define FPU_accum_1 -8(%ebp)3435#else36/* Local storage in a static area: */37.data38.align 4,039FPU_accum_0:40.long 041FPU_accum_1:42.long 043#endif /* NON_REENTRANT_FPU */444546.text47SYM_FUNC_START(FPU_u_mul)48pushl %ebp49movl %esp,%ebp50#ifndef NON_REENTRANT_FPU51subl $8,%esp52#endif /* NON_REENTRANT_FPU */5354pushl %esi55pushl %edi56pushl %ebx5758movl PARAM1,%esi59movl PARAM2,%edi6061#ifdef PARANOID62testl $0x80000000,SIGH(%esi)63jz L_bugged64testl $0x80000000,SIGH(%edi)65jz L_bugged66#endif /* PARANOID */6768xorl %ecx,%ecx69xorl %ebx,%ebx7071movl SIGL(%esi),%eax72mull SIGL(%edi)73movl %eax,FPU_accum_074movl %edx,FPU_accum_17576movl SIGL(%esi),%eax77mull SIGH(%edi)78addl %eax,FPU_accum_179adcl %edx,%ebx80/* adcl $0,%ecx // overflow here is not possible */8182movl SIGH(%esi),%eax83mull SIGL(%edi)84addl %eax,FPU_accum_185adcl %edx,%ebx86adcl $0,%ecx8788movl SIGH(%esi),%eax89mull SIGH(%edi)90addl %eax,%ebx91adcl %edx,%ecx9293/* Get the sum of the exponents. */94movl PARAM6,%eax95subl EXP_BIAS-1,%eax9697/* Two denormals can cause an exponent underflow */98cmpl EXP_WAY_UNDER,%eax99jg Exp_not_underflow100101/* Set to a really low value allow correct handling */102movl EXP_WAY_UNDER,%eax103104Exp_not_underflow:105106/* Have now finished with the sources */107movl PARAM3,%edi /* Point to the destination */108movw %ax,EXP(%edi)109110/* Now make sure that the result is normalized */111testl $0x80000000,%ecx112jnz LResult_Normalised113114/* Normalize by shifting left one bit */115shll $1,FPU_accum_0116rcll $1,FPU_accum_1117rcll $1,%ebx118rcll $1,%ecx119decw EXP(%edi)120121LResult_Normalised:122movl FPU_accum_0,%eax123movl FPU_accum_1,%edx124orl %eax,%eax125jz L_extent_zero126127orl $1,%edx128129L_extent_zero:130movl %ecx,%eax131jmp fpu_reg_round132133134#ifdef PARANOID135L_bugged:136pushl EX_INTERNAL|0x205137call EXCEPTION138pop %ebx139jmp L_exit140141L_exit:142popl %ebx143popl %edi144popl %esi145leave146RET147#endif /* PARANOID */148149SYM_FUNC_END(FPU_u_mul)150151152