Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/x86/math-emu/reg_u_mul.S
10817 views
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 [email protected] |
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
149
150