1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */ 2da957e11SThomas Gleixner .file "reg_u_mul.S" 3da957e11SThomas Gleixner/*---------------------------------------------------------------------------+ 4da957e11SThomas Gleixner | reg_u_mul.S | 5da957e11SThomas Gleixner | | 6da957e11SThomas Gleixner | Core multiplication routine | 7da957e11SThomas Gleixner | | 8da957e11SThomas Gleixner | Copyright (C) 1992,1993,1995,1997 | 9da957e11SThomas Gleixner | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia | 10da957e11SThomas Gleixner | E-mail billm@suburbia.net | 11da957e11SThomas Gleixner | | 12da957e11SThomas Gleixner | | 13da957e11SThomas Gleixner +---------------------------------------------------------------------------*/ 14da957e11SThomas Gleixner 15da957e11SThomas Gleixner/*---------------------------------------------------------------------------+ 16da957e11SThomas Gleixner | Basic multiplication routine. | 17da957e11SThomas Gleixner | Does not check the resulting exponent for overflow/underflow | 18da957e11SThomas Gleixner | | 19da957e11SThomas Gleixner | FPU_u_mul(FPU_REG *a, FPU_REG *b, FPU_REG *c, unsigned int cw); | 20da957e11SThomas Gleixner | | 21da957e11SThomas Gleixner | Internal working is at approx 128 bits. | 22da957e11SThomas Gleixner | Result is rounded to nearest 53 or 64 bits, using "nearest or even". | 23da957e11SThomas Gleixner +---------------------------------------------------------------------------*/ 24da957e11SThomas Gleixner 25da957e11SThomas Gleixner#include "exception.h" 26da957e11SThomas Gleixner#include "fpu_emu.h" 27da957e11SThomas Gleixner#include "control_w.h" 28da957e11SThomas Gleixner 29da957e11SThomas Gleixner 30da957e11SThomas Gleixner 31da957e11SThomas Gleixner#ifndef NON_REENTRANT_FPU 32da957e11SThomas Gleixner/* Local storage on the stack: */ 33da957e11SThomas Gleixner#define FPU_accum_0 -4(%ebp) /* ms word */ 34da957e11SThomas Gleixner#define FPU_accum_1 -8(%ebp) 35da957e11SThomas Gleixner 36da957e11SThomas Gleixner#else 37da957e11SThomas Gleixner/* Local storage in a static area: */ 38da957e11SThomas Gleixner.data 39da957e11SThomas Gleixner .align 4,0 40da957e11SThomas GleixnerFPU_accum_0: 41da957e11SThomas Gleixner .long 0 42da957e11SThomas GleixnerFPU_accum_1: 43da957e11SThomas Gleixner .long 0 44da957e11SThomas Gleixner#endif /* NON_REENTRANT_FPU */ 45da957e11SThomas Gleixner 46da957e11SThomas Gleixner 47da957e11SThomas Gleixner.text 486d685e53SJiri SlabySYM_FUNC_START(FPU_u_mul) 49da957e11SThomas Gleixner pushl %ebp 50da957e11SThomas Gleixner movl %esp,%ebp 51da957e11SThomas Gleixner#ifndef NON_REENTRANT_FPU 52da957e11SThomas Gleixner subl $8,%esp 53da957e11SThomas Gleixner#endif /* NON_REENTRANT_FPU */ 54da957e11SThomas Gleixner 55da957e11SThomas Gleixner pushl %esi 56da957e11SThomas Gleixner pushl %edi 57da957e11SThomas Gleixner pushl %ebx 58da957e11SThomas Gleixner 59da957e11SThomas Gleixner movl PARAM1,%esi 60da957e11SThomas Gleixner movl PARAM2,%edi 61da957e11SThomas Gleixner 62da957e11SThomas Gleixner#ifdef PARANOID 63da957e11SThomas Gleixner testl $0x80000000,SIGH(%esi) 64da957e11SThomas Gleixner jz L_bugged 65da957e11SThomas Gleixner testl $0x80000000,SIGH(%edi) 66da957e11SThomas Gleixner jz L_bugged 67da957e11SThomas Gleixner#endif /* PARANOID */ 68da957e11SThomas Gleixner 69da957e11SThomas Gleixner xorl %ecx,%ecx 70da957e11SThomas Gleixner xorl %ebx,%ebx 71da957e11SThomas Gleixner 72da957e11SThomas Gleixner movl SIGL(%esi),%eax 73da957e11SThomas Gleixner mull SIGL(%edi) 74da957e11SThomas Gleixner movl %eax,FPU_accum_0 75da957e11SThomas Gleixner movl %edx,FPU_accum_1 76da957e11SThomas Gleixner 77da957e11SThomas Gleixner movl SIGL(%esi),%eax 78da957e11SThomas Gleixner mull SIGH(%edi) 79da957e11SThomas Gleixner addl %eax,FPU_accum_1 80da957e11SThomas Gleixner adcl %edx,%ebx 81da957e11SThomas Gleixner/* adcl $0,%ecx // overflow here is not possible */ 82da957e11SThomas Gleixner 83da957e11SThomas Gleixner movl SIGH(%esi),%eax 84da957e11SThomas Gleixner mull SIGL(%edi) 85da957e11SThomas Gleixner addl %eax,FPU_accum_1 86da957e11SThomas Gleixner adcl %edx,%ebx 87da957e11SThomas Gleixner adcl $0,%ecx 88da957e11SThomas Gleixner 89da957e11SThomas Gleixner movl SIGH(%esi),%eax 90da957e11SThomas Gleixner mull SIGH(%edi) 91da957e11SThomas Gleixner addl %eax,%ebx 92da957e11SThomas Gleixner adcl %edx,%ecx 93da957e11SThomas Gleixner 94da957e11SThomas Gleixner /* Get the sum of the exponents. */ 95da957e11SThomas Gleixner movl PARAM6,%eax 96da957e11SThomas Gleixner subl EXP_BIAS-1,%eax 97da957e11SThomas Gleixner 98da957e11SThomas Gleixner /* Two denormals can cause an exponent underflow */ 99da957e11SThomas Gleixner cmpl EXP_WAY_UNDER,%eax 100da957e11SThomas Gleixner jg Exp_not_underflow 101da957e11SThomas Gleixner 102da957e11SThomas Gleixner /* Set to a really low value allow correct handling */ 103da957e11SThomas Gleixner movl EXP_WAY_UNDER,%eax 104da957e11SThomas Gleixner 105da957e11SThomas GleixnerExp_not_underflow: 106da957e11SThomas Gleixner 107da957e11SThomas Gleixner/* Have now finished with the sources */ 108da957e11SThomas Gleixner movl PARAM3,%edi /* Point to the destination */ 109da957e11SThomas Gleixner movw %ax,EXP(%edi) 110da957e11SThomas Gleixner 111da957e11SThomas Gleixner/* Now make sure that the result is normalized */ 112da957e11SThomas Gleixner testl $0x80000000,%ecx 113da957e11SThomas Gleixner jnz LResult_Normalised 114da957e11SThomas Gleixner 115da957e11SThomas Gleixner /* Normalize by shifting left one bit */ 116da957e11SThomas Gleixner shll $1,FPU_accum_0 117da957e11SThomas Gleixner rcll $1,FPU_accum_1 118da957e11SThomas Gleixner rcll $1,%ebx 119da957e11SThomas Gleixner rcll $1,%ecx 120da957e11SThomas Gleixner decw EXP(%edi) 121da957e11SThomas Gleixner 122da957e11SThomas GleixnerLResult_Normalised: 123da957e11SThomas Gleixner movl FPU_accum_0,%eax 124da957e11SThomas Gleixner movl FPU_accum_1,%edx 125da957e11SThomas Gleixner orl %eax,%eax 126da957e11SThomas Gleixner jz L_extent_zero 127da957e11SThomas Gleixner 128da957e11SThomas Gleixner orl $1,%edx 129da957e11SThomas Gleixner 130da957e11SThomas GleixnerL_extent_zero: 131da957e11SThomas Gleixner movl %ecx,%eax 132da957e11SThomas Gleixner jmp fpu_reg_round 133da957e11SThomas Gleixner 134da957e11SThomas Gleixner 135da957e11SThomas Gleixner#ifdef PARANOID 136da957e11SThomas GleixnerL_bugged: 137da957e11SThomas Gleixner pushl EX_INTERNAL|0x205 138da957e11SThomas Gleixner call EXCEPTION 139da957e11SThomas Gleixner pop %ebx 140da957e11SThomas Gleixner jmp L_exit 141da957e11SThomas Gleixner 142da957e11SThomas GleixnerL_exit: 143da957e11SThomas Gleixner popl %ebx 144da957e11SThomas Gleixner popl %edi 145da957e11SThomas Gleixner popl %esi 146da957e11SThomas Gleixner leave 147da957e11SThomas Gleixner ret 148da957e11SThomas Gleixner#endif /* PARANOID */ 149da957e11SThomas Gleixner 1506d685e53SJiri SlabySYM_FUNC_END(FPU_u_mul) 151