File: dos\fpu387.asm
1 TITLE fpu387.asm (C) 1989, Mark C. Peterson, CompuServe [70441,3353]
2 SUBTTL All rights reserved.
3 ;
4 ; Code may be used in any program provided the author is credited
5 ; either during program execution or in the documentation. Source
6 ; code may be distributed only in combination with public domain or
7 ; shareware source code. Source code may be modified provided the
8 ; copyright notice and this message is left unchanged and all
9 ; modifications are clearly documented.
10 ;
11 ; I would appreciate a copy of any work which incorporates this code,
12 ; however this is optional.
13 ;
14 ; Mark C. Peterson
15 ; 405-C Queen St., Suite #181
16 ; Southington, CT 06489
17 ; (203) 276-9721
18 ;
19 ; Note: Remark statements following floating point commands generally indicate
20 ; the FPU stack contents after the command is completed.
21 ;
22 ; References:
23 ; 80386/80286 Assembly Language Programming
24 ; by William H. Murray, III and Chris H. Pappas
25 ; Published by Osborne McGraw-Hill, 1986
26 ;
27 ;
28 ;
29
30
31
32 IFDEF ??version
33 MASM51
34 QUIRKS
35 ENDIF
36
37 .model medium, c
38
39 .code
40
41 .386
42 .387
43
44 _Loaded387sincos PROC
45 fsincos
46 fwait
47 ret
48 _Loaded387sincos ENDP
49
50
51 FPU387sin PROC x:word, sin:word
52 mov bx, x
53 fld QWORD PTR [bx] ; x
54 fsin ; sin
55 mov bx, sin
56 fstp QWORD PTR [bx] ;
57 ret
58 FPU387sin ENDP
59
60
61 FPU387cos PROC x:word, cos:word
62 mov bx, x
63 fld QWORD PTR [bx] ; x
64 fcos ; cos
65 mov bx, cos
66 fstp QWORD PTR [bx] ;
67 ret
68 FPU387cos ENDP
69
70
71 FPUaptan387 PROC x:word, y:word, z:word
72 mov bx, y
73 fld QWORD PTR [bx] ; y
74 mov bx, x
75 fld QWORD PTR [bx] ; x, y
76 fpatan ; ArtTan
77 mov bx, z
78 fstp QWORD PTR [bx] ;
79 ret
80 FPUaptan387 ENDP
81
82
83 FPUcplxexp387 PROC x:word, z:word
84 mov bx, x
85 fld QWORD PTR [bx+8] ; x.y
86 fsincos ; cos, sin
87 fldln2 ; ln2, cos, sin
88 fdivr QWORD PTR [bx] ; x.x/ln2, cos, sin
89 fld1 ; 1, x.x/ln2, cos, sin
90 fld st(1) ; x.x/ln2, 1, x.x/ln2, cos, sin
91 fprem ; prem, 1, x.x/ln2, cos, sin
92 f2xm1 ; e**prem-1, 1, x.x/ln2, cos, sin
93 fadd ; e**prem, x.x/ln2, cos, sin
94 fscale ; e**x.x, x.x/ln2, cos, sin
95 fstp st(1) ; e**x.x, cos, sin
96 fmul st(2), st ; e**x.x, cos, z.y
97 fmul ; z.x, z.y
98 mov bx, z
99 fstp QWORD PTR [bx] ; z.y
100 fstp QWORD PTR [bx+8] ;
101 ret
102 FPUcplxexp387 ENDP
103
104
105 .data
106
107 extrn overflow:WORD, TrigLimit:DWORD
108
109 PiFg13 dw 6487h
110 InvPiFg17 dw 0a2f9h
111 InvPiFg33 dd 0a2f9836eh
112 InvPiFg65 dq 0a2f9836e4e44152ah
113 InvPiFg16 dw 517ch
114 Ln2Fg16 dw 0b172h
115 Ln2Fg32 dd 0b17217f7h
116 One dd ?
117 ExpSign dd ?
118 Exp dd ?
119 SinNeg dd ?
120 CosNeg dd ?
121
122
123 .code
124
125
126 TaylorTerm MACRO
127 LOCAL Ratio
128 add Factorial, One
129 jnc SHORT Ratio
130
131 rcr Factorial, 1
132 shr Num, 1
133 shr One, 1
134
135 Ratio:
136 mul Num
137 div Factorial
138 ENDM
139
140
141
142 Term equ
143 HiTerm equ
144 Num equ
145 Factorial equ
146 Sin equ
147 Cos equ
148 e equ
149 Inve equ
150 LoPtr equ
151 HiPtr equ 2]>
152
153
154
155 _sincos386 PROC
156 xor Factorial, Factorial
157 mov SinNeg, Factorial
158 mov CosNeg, Factorial
159 mov Exp, Factorial
160 or HiTerm, HiTerm
161 jns AnglePositive
162
163 not Term
164 not HiTerm
165 add Term, 1
166 adc HiTerm, Factorial
167 mov SinNeg, 1
168
169 AnglePositive:
170 mov Sin, Term
171 mov Cos, HiTerm
172 mul DWORD PTR InvPiFg65
173 mov Num, HiTerm
174 mov Term, Cos
175 mul DWORD PTR InvPiFg65
176 add Num, Term
177 adc Factorial, HiTerm
178 mov Term, Sin
179 mul InvPiFg33
180 add Num, Term
181 adc Factorial, HiTerm
182 mov Term, Cos
183 mul InvPiFg33
184 add Term, Factorial
185 adc HiTerm, 0
186
187 and HiTerm, 3
188 mov Exp, HiTerm
189
190 mov Num, Term
191 mov Factorial, InvPiFg33
192 mov One, Factorial
193 mov Cos, Factorial ; Cos = 1
194 mov Sin, Num ; Sin = Num
195
196 LoopIntSinCos:
197 TaylorTerm ; Term = Num * (x/2) * (x/3) * (x/4) * . . .
198 sub Cos, Term ; Cos = 1 - Num*(x/2) + (x**4)/4! - . . .
199 cmp Term, TrigLimit
200 jbe SHORT ExitIntSinCos
201
202 TaylorTerm
203 sub Sin, Term ; Sin = Num - Num*(x/2)*(x/3) + (x**5)/5! - . . .
204 cmp Term, TrigLimit
205 jbe SHORT ExitIntSinCos
206
207 TaylorTerm
208 add Cos, Term
209 cmp Term, TrigLimit
210 jbe SHORT ExitIntSinCos
211
212 TaylorTerm ; Term = Num * (x/2) * (x/3) * . . .
213 add Sin, Term
214 cmp Term, TrigLimit
215 jnbe LoopIntSinCos
216
217 ExitIntSinCos:
218 xor Term, Term
219 mov Factorial, Term
220 cmp Cos, InvPiFg33
221 jb CosDivide ; Cos < 1.0
222
223 inc Factorial ; Cos == 1.0
224 jmp StoreCos
225
226 CosDivide:
227 mov HiTerm, Cos
228 div InvPiFg33
229
230 StoreCos:
231 mov Cos, Term ; Factorial:Cos
232
233 xor Term, Term
234 mov Num, Term
235 cmp Sin, InvPiFg33
236 jb SinDivide ; Sin < 1.0
237
238 inc Num ; Sin == 1.0
239 jmp StoreSin
240
241 SinDivide:
242 mov HiTerm, Sin
243 div InvPiFg33
244
245 StoreSin:
246 mov Sin, Term ; Num:Sin
247
248 test Exp, 1
249 jz ChkNegCos
250
251 xchg Factorial, Num
252 xchg Sin, Cos
253 mov Term, SinNeg
254 xchg Term, CosNeg
255 mov CosNeg, Term
256
257 ChkNegCos:
258 mov Term, Exp
259 shr Term, 1
260 mov Term, 0
261 rcr Term, 1
262 xor Term, Exp
263 jz ChkNegSin
264
265 xor CosNeg, 1
266
267 ChkNegSin:
268 test Exp, 2
269 jz CorrectQuad
270
271 xor SinNeg, 1
272
273 CorrectQuad:
274 ret
275 _sincos386 ENDP
276
277
278 SinCos386 PROC LoNum:DWORD, HiNum:DWORD, SinAddr:DWORD, CosAddr:DWORD
279 mov Term, LoNum
280 mov HiTerm, HiNum
281
282 call _sincos386
283
284 cmp CosNeg, 1
285 jne CosPolarized
286
287 not Cos
288 not Factorial
289 add Cos, 1
290 adc Factorial, 0
291
292 CosPolarized:
293 mov HiTerm, Num
294 mov Num, CosAddr
295 mov LoPtr, Cos
296 mov HiPtr, Factorial
297
298 cmp SinNeg, 1
299 jne SinPolarized
300
301 not Sin
302 not HiTerm
303 add Sin, 1
304 adc HiTerm, 0
305
306 SinPolarized:
307 mov Num, SinAddr
308 mov LoPtr, Sin
309 mov HiPtr, HiTerm
310 ret
311 SinCos386 ENDP
312
313
314
315 _e2y386 PROC ; eTerm =: Num * 2**16, 0 < Num < Ln2
316 mov ExpSign, 0
317 or HiTerm, HiTerm
318 jns CalcExp
319
320 mov ExpSign, 1
321 not Term
322 not HiTerm
323 add Term, 1
324 adc HiTerm, 0
325
326 CalcExp:
327 div Ln2Fg32
328 mov Exp, Term
329 mov Num, HiTerm
330
331 xor Factorial, Factorial
332 stc
333 rcr Factorial, 1
334 mov One, Factorial
335 mov e, Num
336 mov Term, Num
337 shr Num, 1
338
339 Loop_e2y386:
340 TaylorTerm
341 add e, Term ; e = 1 + Num + Num*x/2 + (x**3)/3! + . . .
342 cmp Term, TrigLimit
343 jnbe SHORT Loop_e2y386
344
345 ExitIntSinhCosh:
346 stc
347 rcr e, 1
348 ret ; return e**y * (2**32), 1 < e**y < 2
349 _e2y386 ENDP
350
351
352
353 Exp386 PROC LoNum:DWORD, HiNum:DWORD
354 mov Term, LoNum
355 mov HiTerm, HiNum
356
357 call _e2y386
358
359 cmp Exp, 32
360 jae Overflow
361
362 cmp ExpSign, 0
363 jnz NegNumber
364
365 mov Factorial, Exp
366 shld HiTerm, Term, cl
367 shl Term, cl
368 jmp ExitExp386
369
370 Overflow:
371 xor Term, Term
372 xor HiTerm, HiTerm
373 mov overflow, 1
374 jmp ExitExp386
375
376 NegNumber:
377 cmp e, 80000000h
378 jne DivideE
379
380 mov Term, e
381 dec Exp
382 jmp ShiftE
383
384 DivideE:
385 xor Term, Term
386 mov HiTerm, Term
387 stc
388 rcr HiTerm, 1
389 div e
390
391 ShiftE:
392 xor HiTerm, HiTerm
393 mov Factorial, Exp
394 shr Term, cl
395
396 ExitExp386:
397 ret
398 Exp386 ENDP
399
400
401
402 SinhCosh386 PROC LoNum:DWORD, HiNum:DWORD, SinhAddr:DWORD, CoshAddr:DWORD
403 mov Term, LoNum
404 mov HiTerm, HiNum
405
406 call _e2y386
407
408 cmp e, 80000000h
409 jne InvertE ; e > 1
410
411 mov HiTerm, 1
412 xor Term, Term
413 cmp Exp, 0
414 jne ShiftOne
415
416 mov e, Term
417 mov Factorial, Term
418 jmp ChkSinhSign
419
420 ShiftOne:
421 mov Factorial, Exp
422 shl HiTerm, cl
423 dec Factorial
424 shr e, cl
425 shr HiTerm, 1
426 shr e, 1
427 mov Factorial, HiTerm
428 sub Term, e
429 sbb HiTerm, 0
430 xchg Term, e
431 xchg HiTerm, Factorial
432 jmp ChkSinhSign
433
434 InvertE:
435 xor Term, Term ; calc 1/e
436 mov HiTerm, 80000000h
437 div e
438
439 mov Inve, Term
440
441 ShiftE:
442 mov Factorial, Exp
443 shr Inve, cl
444 inc cl
445 shld HiTerm, e, cl
446 mov Factorial, HiTerm ; Factorial:e == e**Exp
447
448 mov Term, e ; HiTerm:e == e**Exp
449 add Term, Inve
450 adc HiTerm, 0
451 shr HiTerm, 1
452 rcr Term, 1 ; cosh(Num) = (e**Exp + 1/e**Exp) / 2
453
454 sub e, Inve
455 sbb Factorial, 0
456 sar Factorial, 1
457 rcr e, 1
458
459 ChkSinhSign:
460 or HiNum, 0
461 jns StoreHyperbolics
462
463 not e
464 not Factorial
465 add e, 1
466 adc Factorial, 0
467
468 StoreHyperbolics:
469 mov Num, CoshAddr
470 mov LoPtr, Term
471 mov HiPtr, HiTerm
472
473 mov Num, SinhAddr
474 mov LoPtr, e
475 mov HiPtr, Factorial
476
477 ret
478 SinhCosh386 ENDP
479
480
481
482 END
483
484