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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
|
;
; Microsoft MASM subroutines for setting coprocessor precision
;
.286
.287
_TEXT SEGMENT BYTE PUBLIC 'CODE'
_TEXT ENDS
CONST SEGMENT WORD PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT WORD PUBLIC 'BSS'
_BSS ENDS
_DATA SEGMENT WORD PUBLIC 'DATA'
_DATA ENDS
DGROUP GROUP CONST, _BSS, _DATA
ASSUME CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
EXTRN __fac:QWORD
_BSS SEGMENT
EXTRN __fltused:NEAR
_BSS ENDS
; exception masks (1 = masked)
; 1 invalid operation
; 2 denormalized operand
; 4 zero divide
; 8 overflow
; 10 underflow
; 20 precision
_DATA SEGMENT
; double precision setting
;;ctlwrd dw 01230h ; note this traps on denormal operands!
;;ctld dw 0133fh ; this doesn't trap
ctld dw 01230h
; single precision
ctls dw 01030h
; long double precision
ctlld dw 01320h
_DATA ENDS
ASSUME CS: _TEXT
_TEXT SEGMENT
; Set coprocessor to single precision float
PUBLIC _sprec
_sprec PROC NEAR
fclex
fwait
finit
fwait
fldcw word ptr ctls
fwait
ret
_sprec ENDP
; set coprocessor to long double precision
PUBLIC _ldprec
_ldprec PROC NEAR
fclex
fwait
finit
fwait
fldcw word ptr ctlld
fwait
ret
_ldprec ENDP
; set coprocessor to double precision
PUBLIC _dprec
_dprec PROC NEAR
fclex
fwait
finit
fwait
fldcw word ptr ctld
fwait
ret
_dprec ENDP
; get a double promoted to long double size
; getld( &doub, &ldoub );
PUBLIC _getld
_getld PROC NEAR
push bp
mov bp,sp
push bx
mov bx, word ptr [bp+4]
; fld st(0)
fld qword ptr [bx]
mov bx, word ptr [bp+6]
fstp tbyte ptr [bx]
mov bx, word ptr [bp+4]
fld qword ptr [bx]
mov bx, word ptr [bp+8]
fstp qword ptr [bx]
pop bx
pop bp
ret
_getld ENDP
PUBLIC _getprec
_getprec PROC NEAR
push bp
mov bp,sp
sub sp,4
fstcw [bp-4]
fwait
mov ax,[bp-4]
add sp,4
pop bp
ret
_getprec ENDP
PUBLIC _fpclear
_fpclear PROC NEAR
push bp
mov bp,sp
fnclex
fwait
pop bp
ret
_fpclear ENDP
PUBLIC _noexcept
_noexcept PROC NEAR
push bp
mov bp,sp
push ax
sub sp,4
fnclex
fwait
fstcw [bp-4]
fwait
mov ax,[bp-4]
and ax,0FFC0h
or ax,003fh
mov [bp-4],ax
fldcw [bp-4]
add sp,4
pop ax
pop bp
ret
_noexcept ENDP
;; single precision square root
;; assumes coprocessor precision already set up
;; return value in static __fac
; PUBLIC _sqrtf
;_sqrtf PROC NEAR
; push bp
; mov bp,sp
; fld DWORD PTR [bp+4]
; fsqrt
; fwait
; fstp DWORD PTR __fac
; mov ax,OFFSET __fac
; mov sp,bp
; pop bp
; ret
;_sqrtf ENDP
;
;
;; double precision square root
;; assumes coprocessor precision already set up
;; return value in static __fac
; PUBLIC _sqrt
;_sqrt PROC NEAR
; push bp
; mov bp,sp
; fld QWORD PTR [bp+4]
; fsqrt
; fwait
; fstp QWORD PTR __fac
; mov ax,OFFSET __fac
; mov sp,bp
; pop bp
; ret
;_sqrt ENDP
;
;
;; long double precision square root
;; assumes coprocessor precision already set up
;; return value in fp register
; PUBLIC _sqrtl
;_sqrtl PROC NEAR
; push bp
; mov bp,sp
; fld tbyte ptr [bp+4]
; fsqrt
; fwait
; mov sp,bp
; pop bp
; ret
;_sqrtl ENDP
;
_TEXT ENDS
END
|