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
|
! bcc 386 floating point routines (version 2) -- Fmul, Fmuld, Fmulf
! author: Bruce Evans
#include "fplib.h"
#define FRAME_SIZE (3 * GENREG_SIZE + PC_SIZE)
.extern Fpushf
.extern fpoverflow
.extern fpunderflow
.extern normalize2
.globl Fmul
.align ALIGNMENT
Fmul:
push ebp
push edi
push esi
mov eax,FRAME_SIZE+D_LOW[esp]
mov edx,FRAME_SIZE+D_HIGH[esp]
mov ebx,FRAME_SIZE+D_SIZE+D_LOW[esp]
mov ecx,FRAME_SIZE+D_SIZE+D_HIGH[esp]
call multiplication
mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax
mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx
pop esi
pop edi
pop ebp
ret #D_SIZE
.globl Fmuld
.align ALIGNMENT
Fmuld:
push ebp
push edi
push esi
mov eax,FRAME_SIZE+D_LOW[esp]
mov edx,FRAME_SIZE+D_HIGH[esp]
mov ecx,D_HIGH[ebx]
mov ebx,D_LOW[ebx]
call multiplication
mov FRAME_SIZE+D_LOW[esp],eax
mov FRAME_SIZE+D_HIGH[esp],edx
pop esi
pop edi
pop ebp
ret
.globl Fmulf
.align ALIGNMENT
Fmulf:
push ebp
push edi
push esi
call Fpushf
pop ebx ! yl
pop ecx ! xu
mov eax,FRAME_SIZE+D_LOW[esp] ! xl
mov edx,FRAME_SIZE+D_HIGH[esp] ! xu
call multiplication
mov FRAME_SIZE+D_LOW[esp],eax
mov FRAME_SIZE+D_HIGH[esp],edx
pop esi
pop edi
pop ebp
ret
.align ALIGNMENT
exp_x_0:
mov edx,#1 << D_EXP_SHIFT ! change exponent from 0 to 1
jmp x_unpacked ! XXX - check for denormal?
.align ALIGNMENT
exp_y_0:
mov ecx,#1 << D_EXP_SHIFT
jmp y_unpacked
.align ALIGNMENT
multiplication:
mov ebp,edx ! xu
xor ebp,ecx ! xu ^ yu
and ebp,#D_SIGN_MASK ! sign of result is difference of signs
mov esi,edx ! free edx for multiplications
and esi,#D_FRAC_MASK ! discard sign and exponent
and edx,#D_EXP_MASK ! exponent(x)
jz exp_x_0
or esi,#D_NORM_MASK ! normalize
x_unpacked:
mov edi,ecx ! this mainly for consistent naming
and edi,#D_FRAC_MASK
and ecx,#D_EXP_MASK ! exponent(y)
jz exp_y_0
or edi,#D_NORM_MASK
y_unpacked:
add ecx,edx ! add exponents
! exponent is in ecx, sign in ebp, operands in esi:eax and edi:ebx, edx is free
! product to go in esi:eax:ebp:ebx
! terminology: x * y = (xu,xl) * (yu,yl)
! = (xu * yu,0,0) + (0,xu * yl + xl * yu,0) + (0,0,xl * yl)
push ecx
push ebp
mov ecx,eax
mul ebx ! xl * yl
mov ebp,edx ! (xl * yl).u in ebp
xchg ebx,eax ! (xl * yl).l in ebx (final), yl in eax
mul esi ! xu * yl
push eax ! (xu * yl).l on stack
push edx ! (xu * yl).u on stack
mov eax,esi ! xu
mul edi ! xu * yu
mov esi,edx ! (xu * yu).u in esi (final except carries)
xchg ecx,eax ! (xu * yu).l in ecx, xl in eax
mul edi ! xl * yu
add ebp,eax ! (xl * yl).u + (xl * yu).l
pop eax ! (xu * yl).u
adc eax,edx ! (xu * yl).u + (xl * yu).u
adc esi,#0
pop edx ! (xu * yl).l
add ebp,edx ! ((xl * yl).u + (xl * yu).l) + (xu * yl).l
adc eax,ecx ! ((xu * yl).u + (xl * yu).u) + (xu * yu).l
adc esi,#0
pop edx ! sign
pop edi ! exponent
sub edi,#(D_EXP_BIAS+1-(D_EXP_BIT+2)) << D_EXP_SHIFT ! adjust
! cmp edi,#(D_EXP_INFINITE-1+(D_EXP_BIT+2)) << D_EXP_SHIFT
! jae outofbounds ! 0 will be caught as underflow by normalize2
cmp edi,#(2*D_EXP_INFINITE-(D_EXP_BIAS+1)+(D_EXP_BIT+2)) << D_EXP_SHIFT
ja underflow
br normalize2
.align ALIGNMENT
overflow:
mov edx,ebp ! put sign in usual reg
call fpoverflow
mov eax,ecx ! XXX - wrong reg
ret
.align ALIGNMENT
underflow:
mov edx,ebp ! put sign in usual reg
neg edi
shr edi,#D_EXP_SHIFT
inc edi
br fpunderflow
|