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 billm@suburbia.net | 10 | | 11 | | 12 +---------------------------------------------------------------------------*/ 13 14/*---------------------------------------------------------------------------+ 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 +---------------------------------------------------------------------------*/ 23 24#include "exception.h" 25#include "fpu_emu.h" 26#include "control_w.h" 27 28 29 30#ifndef NON_REENTRANT_FPU 31/* Local storage on the stack: */ 32#define FPU_accum_0 -4(%ebp) /* ms word */ 33#define FPU_accum_1 -8(%ebp) 34 35#else 36/* Local storage in a static area: */ 37.data 38 .align 4,0 39FPU_accum_0: 40 .long 0 41FPU_accum_1: 42 .long 0 43#endif /* NON_REENTRANT_FPU */ 44 45 46.text 47ENTRY(FPU_u_mul) 48 pushl %ebp 49 movl %esp,%ebp 50#ifndef NON_REENTRANT_FPU 51 subl $8,%esp 52#endif /* NON_REENTRANT_FPU */ 53 54 pushl %esi 55 pushl %edi 56 pushl %ebx 57 58 movl PARAM1,%esi 59 movl PARAM2,%edi 60 61#ifdef PARANOID 62 testl $0x80000000,SIGH(%esi) 63 jz L_bugged 64 testl $0x80000000,SIGH(%edi) 65 jz L_bugged 66#endif /* PARANOID */ 67 68 xorl %ecx,%ecx 69 xorl %ebx,%ebx 70 71 movl SIGL(%esi),%eax 72 mull SIGL(%edi) 73 movl %eax,FPU_accum_0 74 movl %edx,FPU_accum_1 75 76 movl SIGL(%esi),%eax 77 mull SIGH(%edi) 78 addl %eax,FPU_accum_1 79 adcl %edx,%ebx 80/* adcl $0,%ecx // overflow here is not possible */ 81 82 movl SIGH(%esi),%eax 83 mull SIGL(%edi) 84 addl %eax,FPU_accum_1 85 adcl %edx,%ebx 86 adcl $0,%ecx 87 88 movl SIGH(%esi),%eax 89 mull SIGH(%edi) 90 addl %eax,%ebx 91 adcl %edx,%ecx 92 93 /* Get the sum of the exponents. */ 94 movl PARAM6,%eax 95 subl EXP_BIAS-1,%eax 96 97 /* Two denormals can cause an exponent underflow */ 98 cmpl EXP_WAY_UNDER,%eax 99 jg Exp_not_underflow 100 101 /* Set to a really low value allow correct handling */ 102 movl EXP_WAY_UNDER,%eax 103 104Exp_not_underflow: 105 106/* Have now finished with the sources */ 107 movl PARAM3,%edi /* Point to the destination */ 108 movw %ax,EXP(%edi) 109 110/* Now make sure that the result is normalized */ 111 testl $0x80000000,%ecx 112 jnz LResult_Normalised 113 114 /* Normalize by shifting left one bit */ 115 shll $1,FPU_accum_0 116 rcll $1,FPU_accum_1 117 rcll $1,%ebx 118 rcll $1,%ecx 119 decw EXP(%edi) 120 121LResult_Normalised: 122 movl FPU_accum_0,%eax 123 movl FPU_accum_1,%edx 124 orl %eax,%eax 125 jz L_extent_zero 126 127 orl $1,%edx 128 129L_extent_zero: 130 movl %ecx,%eax 131 jmp fpu_reg_round 132 133 134#ifdef PARANOID 135L_bugged: 136 pushl EX_INTERNAL|0x205 137 call EXCEPTION 138 pop %ebx 139 jmp L_exit 140 141L_exit: 142 popl %ebx 143 popl %edi 144 popl %esi 145 leave 146 ret 147#endif /* PARANOID */ 148 149