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
|
;
; Borland assembler header
;
; Microsoft MASM subroutines for setting coprocessor precision
;
.286
.287
PREC_TEXT SEGMENT BYTE PUBLIC 'CODE'
PREC_TEXT ENDS
DGROUP group _DATA,_BSS
assume cs:PREC_TEXT,ds:DGROUP
_DATA segment word public 'DATA'
d@ label byte
d@w label word
_DATA ends
_BSS segment word public 'BSS'
b@ label byte
b@w label word
_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
PREC_TEXT segment byte public 'CODE'
assume cs:PREC_TEXT,ds:DGROUP
; Set coprocessor to single precision float
PUBLIC _sprec
_sprec PROC FAR
fclex
fwait
finit
fwait
fldcw word ptr ctls
fwait
ret
_sprec ENDP
; set coprocessor to long double precision
PUBLIC _ldprec
_ldprec PROC far
fclex
fwait
finit
fwait
fldcw word ptr ctlld
fwait
ret
_ldprec ENDP
; set coprocessor to double precision
PUBLIC _dprec
_dprec PROC far
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 far
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 far
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 far
push bp
mov bp,sp
fnclex
fwait
pop bp
ret
_fpclear ENDP
PUBLIC _noexcept
_noexcept PROC far
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 FAR
push bp
mov bp,sp
fld DWORD PTR [bp+6]
fsqrt
fwait
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 FAR
push bp
mov bp,sp
fld QWORD PTR [bp+6]
fsqrt
fwait
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 FAR
push bp
mov bp,sp
fld tbyte ptr [bp+6]
fsqrt
fwait
mov sp,bp
pop bp
ret
_sqrtl ENDP
PREC_TEXT ends
_DATA segment word public 'DATA'
s@ label byte
_DATA ends
PREC_TEXT segment byte public 'CODE'
PREC_TEXT ends
_s@ equ s@
public _sprec
public _dprec
public _ldprec
end
|