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