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