Commit | Line | Data |
---|---|---|
1da177e4 LT |
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 | |
39 | FPU_accum_0: | |
40 | .long 0 | |
41 | FPU_accum_1: | |
42 | .long 0 | |
43 | #endif /* NON_REENTRANT_FPU */ | |
44 | ||
45 | ||
46 | .text | |
47 | ENTRY(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 | ||
104 | Exp_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 | ||
121 | LResult_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 | ||
129 | L_extent_zero: | |
130 | movl %ecx,%eax | |
131 | jmp fpu_reg_round | |
132 | ||
133 | ||
134 | #ifdef PARANOID | |
135 | L_bugged: | |
136 | pushl EX_INTERNAL|0x205 | |
137 | call EXCEPTION | |
138 | pop %ebx | |
139 | jmp L_exit | |
140 | ||
141 | L_exit: | |
142 | popl %ebx | |
143 | popl %edi | |
144 | popl %esi | |
145 | leave | |
146 | ret | |
147 | #endif /* PARANOID */ | |
148 |