Subversion Repositories Kolibri OS

Rev

Rev 554 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
554 serge 1
;*****************************************************************************
2
;*
3
;*                            Open Watcom Project
4
;*
5
;*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
6
;*
7
;*  ========================================================================
8
;*
9
;*    This file contains Original Code and/or Modifications of Original
10
;*    Code as defined in and that are subject to the Sybase Open Watcom
11
;*    Public License version 1.0 (the 'License'). You may not use this file
12
;*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
13
;*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
14
;*    provided with the Original Code and Modifications, and is also
15
;*    available at www.sybase.com/developer/opensource.
16
;*
17
;*    The Original Code and all software distributed under the License are
18
;*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
19
;*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
20
;*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
21
;*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
22
;*    NON-INFRINGEMENT. Please see the License for the specific language
23
;*    governing rights and limitations under the License.
24
;*
25
;*  ========================================================================
26
;*
27
;* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
28
;*               DESCRIBE IT HERE!
29
;*
30
;*****************************************************************************
31
 
32
 
33
; static char sccs_id[] = "@(#)patch32.asm      1.12  12/21/94  14:53:51";
34
;
35
; This code is being published by Intel to users of the Pentium(tm)
36
; processor.  Recipients are authorized to copy, modify, compile, use and
37
; distribute the code.
38
;
39
; Intel makes no warranty of any kind with regard to this code, including
40
; but not limited to, implied warranties or merchantability and fitness for
41
; a particular purpose. Intel assumes no responsibility for any errors that
42
; may appear in this code.
43
;
44
; No patent licenses are granted, express or implied.
45
;
46
;
47
include mdef.inc
48
 
49
.386
50
.387
51
 
52
DENOM           EQU     0
53
NUMER           EQU     12
54
PREV_CW         EQU     28      ; 24 + 4 (return size)
55
PATCH_CW        EQU     32      ; 28 + 4 (return size)
56
 
57
DENOM_SAVE      EQU     32
58
 
59
MAIN_DENOM      EQU     4
60
MAIN_NUMER      EQU     16
61
 
62
SPILL_SIZE      EQU     12
63
MEM_OPERAND     EQU     8
64
STACK_SIZE      EQU     44
65
SPILL_MEM_OPERAND       EQU     20
66
 
67
ONESMASK        EQU     0e000000h
68
 
69
SINGLE_NAN      EQU     07f800000h
70
DOUBLE_NAN      EQU     07ff00000h
71
 
72
ILLEGAL_OPC     EQU     6
73
 
74
f_stsw  macro   where
75
        fstsw   where
76
endm
77
 
78
fdivr_st        MACRO   reg_index, reg_index_minus1
79
        fstp    tbyte ptr [esp+DENOM]
80
IF      reg_index_minus1 GE 1
81
        fxch    st(reg_index_minus1)
82
ENDIF
83
        fstp    tbyte ptr [esp+NUMER]
84
        call    fdiv_main_routine
85
IF      reg_index_minus1 GE 1
86
        fxch    st(reg_index_minus1)
87
ENDIF
88
        fld     tbyte ptr [esp+NUMER]
89
        fxch    st(reg_index)
90
        add     esp, STACK_SIZE
91
ENDM
92
 
93
fdivr_sti       MACRO   reg_index, reg_index_minus1
94
        fstp    tbyte ptr [esp+NUMER]
95
IF      reg_index_minus1 GE 1
96
        fxch    st(reg_index_minus1)
97
ENDIF
98
        fstp    tbyte ptr [esp+DENOM]
99
        call    fdiv_main_routine
100
IF      reg_index_minus1 GE 1
101
        fxch    st(reg_index_minus1)
102
ENDIF
103
        fld     tbyte ptr [esp+NUMER]
104
        add     esp, STACK_SIZE
105
ENDM
106
 
107
fdivrp_sti      MACRO   reg_index, reg_index_minus1
108
        fstp    tbyte ptr [esp+NUMER]
109
IF      reg_index_minus1 GE 1
110
        fxch    st(reg_index_minus1)
111
ENDIF
112
        fstp    tbyte ptr [esp+DENOM]
113
        call    fdiv_main_routine
114
IF      reg_index_minus1 GE 1
115
        fxch    st(reg_index_minus1)
116
ENDIF
117
        add     esp, STACK_SIZE
118
ENDM
119
 
120
fdiv_st         MACRO   reg_index, reg_index_minus1
121
        fstp    tbyte ptr [esp+NUMER]
122
IF      reg_index_minus1 GE 1
123
        fxch    st(reg_index_minus1)
124
ENDIF
125
        fld     st
126
        fstp    tbyte ptr [esp+DENOM]
127
        fstp    tbyte ptr [esp+DENOM_SAVE]      ; save original denom,
128
        call    fdiv_main_routine
129
IF      reg_index_minus1 GE 1
130
        fxch    st(reg_index_minus1)
131
ENDIF
132
        fld     tbyte ptr [esp+DENOM_SAVE]
133
        fxch    st(reg_index)
134
        add     esp, STACK_SIZE
135
ENDM
136
 
137
fdiv_sti        MACRO   reg_index, reg_index_minus1
138
        fxch    st(reg_index)
139
        fstp    tbyte ptr [esp+NUMER]
140
IF      reg_index_minus1 GE 1
141
        fxch    st(reg_index_minus1)
142
ENDIF
143
        fld     st
144
        fstp    tbyte ptr [esp+DENOM]
145
        fstp    tbyte ptr [esp+DENOM_SAVE]      ; save original denom,
146
        call    fdiv_main_routine
147
IF      reg_index_minus1 GE 1
148
        fxch    st(reg_index_minus1)
149
ENDIF
150
        fld     tbyte ptr [esp+DENOM_SAVE]
151
        add     esp, STACK_SIZE
152
ENDM
153
 
154
fdivp_sti       MACRO   reg_index, reg_index_minus1
155
        fstp    tbyte ptr [esp+DENOM]
156
IF      reg_index_minus1 GE 1
157
        fxch    st(reg_index_minus1)
158
ENDIF
159
        fstp    tbyte ptr [esp+NUMER]
160
        call    fdiv_main_routine
161
IF      reg_index_minus1 GE 1
162
        fxch    st(reg_index_minus1)
163
ENDIF
164
        add     esp, STACK_SIZE
165
ENDM
166
 
167
_TEXT  SEGMENT DWORD USE32 PUBLIC 'CODE'
168
_TEXT  ENDS
169
 
704 serge 170
_DATA  SEGMENT DWORD USE32 PUBLIC 'DATA'
171
_DATA  ENDS
554 serge 172
 
704 serge 173
CONST SEGMENT DWORD USE32 PUBLIC 'DATA'
174
CONST ENDS
554 serge 175
 
704 serge 176
_BSS   SEGMENT DWORD USE32 PUBLIC 'BSS'
177
_BSS   ENDS
554 serge 178
 
704 serge 179
DGROUP  GROUP CONST,_DATA,_BSS
554 serge 180
 
181
 
704 serge 182
_DATA  SEGMENT DWORD USE32 PUBLIC 'DATA'
554 serge 183
 
184
fdiv_risc_table DB      0, 1, 0, 0, 4, 0, 0, 7, 0, 0, 10, 0, 0, 13, 0, 0
185
fdiv_scale_1    DD      03f700000h              ;0.9375
186
fdiv_scale_2    DD      03f880000h              ;1.0625
187
one_shl_63      DD      05f000000h
188
 
189
 
190
dispatch_table DD       offset label0
191
        DD      offset label1
192
        DD      offset label2
193
        DD      offset label3
194
        DD      offset label4
195
        DD      offset label5
196
        DD      offset label6
197
        DD      offset label7
198
        DD      offset label8
199
        DD      offset label9
200
        DD      offset label10
201
        DD      offset label11
202
        DD      offset label12
203
        DD      offset label13
204
        DD      offset label14
205
        DD      offset label15
206
        DD      offset label16
207
        DD      offset label17
208
        DD      offset label18
209
        DD      offset label19
210
        DD      offset label20
211
        DD      offset label21
212
        DD      offset label22
213
        DD      offset label23
214
        DD      offset label24
215
        DD      offset label25
216
        DD      offset label26
217
        DD      offset label27
218
        DD      offset label28
219
        DD      offset label29
220
        DD      offset label30
221
        DD      offset label31
222
        DD      offset label32
223
        DD      offset label33
224
        DD      offset label34
225
        DD      offset label35
226
        DD      offset label36
227
        DD      offset label37
228
        DD      offset label38
229
        DD      offset label39
230
        DD      offset label40
231
        DD      offset label41
232
        DD      offset label42
233
        DD      offset label43
234
        DD      offset label44
235
        DD      offset label45
236
        DD      offset label46
237
        DD      offset label47
238
        DD      offset label48
239
        DD      offset label49
240
        DD      offset label50
241
        DD      offset label51
242
        DD      offset label52
243
        DD      offset label53
244
        DD      offset label54
245
        DD      offset label55
246
        DD      offset label56
247
        DD      offset label57
248
        DD      offset label58
249
        DD      offset label59
250
        DD      offset label60
251
        DD      offset label61
252
        DD      offset label62
253
        DD      offset label63
254
 
704 serge 255
_DATA   ENDS
554 serge 256
 
257
 
258
_TEXT  SEGMENT   DWORD USE32 PUBLIC 'CODE'
259
 
260
 
261
        assume cs:_TEXT, ds:DGROUP, es:DGROUP, ss:nothing
262
 
263
;
264
;  PRELIMINARY VERSION for register-register divides.
265
;
266
 
267
 
268
                                        ; In this implementation the
269
                                        ; fdiv_main_routine is called,
270
                                        ; therefore all the stack frame
271
                                        ; locations are adjusted for the
272
                                        ; return pointer.
273
 
274
fdiv_main_routine PROC  NEAR
275
 
276
        fld     tbyte ptr [esp+MAIN_NUMER]      ; load the numerator
277
        fld     tbyte ptr [esp+MAIN_DENOM]      ; load the denominator
278
retry:
279
 
280
;  The following three lines test for denormals and zeros.
281
;  A denormal or zero has a 0 in the explicit digit to the left of the
282
;  binary point.  Since that bit is the high bit of the word, adding
283
;  it to itself will produce a carry if and only if the number is not
284
;  denormal or zero.
285
;
286
        mov     eax, [esp+MAIN_DENOM+4] ; get mantissa bits 32-64
287
        add     eax,eax                 ; shift the one's bit onto carry
288
        jnc     denormal                ; if no carry, we're denormal
289
 
290
;  The following three lines test the three bits after the four bit
291
;  pattern (1,4,7,a,d).  If these three bits are not all one, then
292
;  the denominator cannot expose the flaw.  This condition is tested by
293
;  inverting the bits and testing that all are equal to zero afterward.
294
 
295
        xor     eax, ONESMASK           ; invert the bits that must be ones
296
        test    eax, ONESMASK           ; and make sure they are all ones
297
        jz      scale_if_needed         ; if all are one scale numbers
298
        fdivp   st(1), st               ; use of hardware is OK.
299
        ret
300
 
301
;
302
;  Now we test the four bits for one of the five patterns.
303
;
304
scale_if_needed:
305
        shr     eax, 28                 ; keep first 4 bits after point
306
        cmp     byte ptr fdiv_risc_table[eax], 0        ; check for (1,4,7,a,d)
307
        jnz     divide_scaled           ; are in potential problem area
308
        fdivp   st(1), st               ; use of hardware is OK.
309
        ret
310
 
311
divide_scaled:
312
        mov     eax, [esp + MAIN_DENOM+8]       ; test denominator exponent
313
        and     eax, 07fffh             ; if pseudodenormal ensure that only
314
        jz      invalid_denom           ; invalid exception flag is set
315
        cmp     eax, 07fffh             ; if NaN or infinity  ensure that only
316
        je      invalid_denom           ; invalid exception flag is set
317
;
318
;  The following six lines turn off exceptions and set the
319
;  precision control to 80 bits.  The former is necessary to
320
;  force any traps to be taken at the divide instead of the scaling
321
;  code.  The latter is necessary in order to get full precision for
322
;  codes with incoming 32 and 64 bit precision settings.  If
323
;  it can be guaranteed that before reaching this point, the underflow
324
;  exception is masked and the precision control is at 80 bits, these
325
;  six lines can be omitted.
326
;
327
        fnstcw  [esp+PREV_CW]           ; save caller's control word
328
        mov     eax, [esp+PREV_CW]
329
        or      eax, 033fh              ; mask exceptions, pc=80
330
        and     eax, 0f3ffh             ; set rounding mode to nearest
331
        mov     [esp+PATCH_CW], eax
332
        fldcw   [esp+PATCH_CW]          ; mask exceptions & pc=80
333
 
334
;  The following lines check the numerator exponent before scaling.
335
;  This in order to prevent undeflow when scaling the numerator,
336
;  which will cause a denormal exception flag to be set when the
337
;  actual divide is preformed. This flag would not have been set
338
;  normally. If there is a risk of underflow, the scale factor is
339
;  17/16 instead of 15/16.
340
;
341
        mov     eax, [esp+MAIN_NUMER+8] ; test numerator exponent
342
        and     eax, 07fffh
343
        cmp     eax, 00001h
344
        je      small_numer
345
 
346
        fmul    fdiv_scale_1            ; scale denominator by 15/16
347
        fxch
348
        fmul    fdiv_scale_1            ; scale numerator by 15/16
349
        fxch
350
 
351
;
352
;  The next line restores the users control word.  If the incoming
353
;  control word had the underflow exception masked and precision
354
;  control set to 80 bits, this line can be omitted.
355
;
356
 
357
        fldcw   [esp+PREV_CW]           ; restore caller's control word
358
        fdivp   st(1), st               ; use of hardware is OK.
359
        ret
360
 
361
small_numer:
362
        fmul    fdiv_scale_2            ; scale denominator by 17/16
363
        fxch
364
        fmul    fdiv_scale_2            ; scale numerator by 17/16
365
        fxch
366
 
367
;
368
;  The next line restores the users control word.  If the incoming
369
;  control word had the underflow exception masked and precision
370
;  control set to 80 bits, this line can be omitted.
371
;
372
 
373
        fldcw   [esp+PREV_CW]           ; restore caller's control word
374
        fdivp   st(1), st               ; use of hardware is OK.
375
        ret
376
 
377
denormal:
378
        mov     eax, [esp+MAIN_DENOM]   ; test for whole mantissa == 0
379
        or      eax, [esp+MAIN_DENOM+4] ; test for whole mantissa == 0
380
        jnz     denormal_divide_scaled  ; denominator is not zero
381
invalid_denom:                          ; zero or invalid denominator
382
        fdivp   st(1), st               ; use of hardware is OK.
383
        ret
384
 
385
denormal_divide_scaled:
386
        mov     eax, [esp + MAIN_DENOM + 8]     ; get exponent
387
        and     eax, 07fffh             ; check for zero exponent
388
        jnz     invalid_denom           ;
389
;
390
;  The following six lines turn off exceptions and set the
391
;  precision control to 80 bits.  The former is necessary to
392
;  force any traps to be taken at the divide instead of the scaling
393
;  code.  The latter is necessary in order to get full precision for
394
;  codes with incoming 32 and 64 bit precision settings.  If
395
;  it can be guaranteed that before reaching this point, the underflow
396
;  exception is masked and the precision control is at 80 bits, these
397
;  five lines can be omitted.
398
;
399
 
400
        fnstcw  [esp+PREV_CW]           ; save caller's control word
401
        mov     eax, [esp+PREV_CW]
402
        or      eax, 033fh              ; mask exceptions, pc=80
403
        and     eax, 0f3ffh             ; set rounding mode to nearest
404
        mov     [esp+PATCH_CW], eax
405
        fldcw   [esp+PATCH_CW]          ; mask exceptions & pc=80
406
 
407
        mov     eax, [esp + MAIN_NUMER +8]      ; test numerator exponent
408
        and     eax, 07fffh             ; check for denormal numerator
409
        je      denormal_numer
410
        cmp     eax, 07fffh             ; NaN or infinity
411
        je      invalid_numer
412
        mov     eax, [esp + MAIN_NUMER + 4]     ; get bits 32..63 of mantissa
413
        add     eax, eax                ; shift the first bit into carry
414
        jnc     invalid_numer           ; if there is no carry, we have an
415
                                        ; invalid numer
416
        jmp     numer_ok
417
 
418
denormal_numer:
419
        mov     eax, [esp + MAIN_NUMER + 4]     ; get bits 32..63 of mantissa
420
        add     eax, eax                ; shift the first bit into carry
421
        jc      invalid_numer           ; if there is a carry, we have an
422
                                        ; invalid numer
423
 
424
numer_ok:
425
        fxch
426
        fstp    st                      ; pop numerator
427
        fld     st                      ; make copy of denominator
428
        fmul    dword ptr[one_shl_63]   ; make denominator not denormal
429
        fstp    tbyte ptr [esp+MAIN_DENOM]      ; save modified denominator
430
        fld     tbyte ptr [esp+MAIN_NUMER]      ; load numerator
431
        fxch                            ; restore proper order
432
        fwait
433
 
434
;  The next line restores the users control word.  If the incoming
435
;  control word had the underflow exception masked and precision
436
;  control set to 80 bits, this line can be omitted.
437
;
438
 
439
        fldcw   [esp+PREV_CW]           ; restore caller's control word
440
        jmp     retry                   ; start the whole thing over
441
 
442
invalid_numer:
443
;
444
;  The next line restores the users control word.  If the incoming
445
;  control word had the underflow exception masked and precision
446
;  control set to 80 bits, this line can be omitted.
447
;
448
        fldcw   [esp + PREV_CW]
449
        fdivp   st(1), st               ; use of hardware is OK.
450
        ret
451
 
452
fdiv_main_routine       ENDP
453
 
454
        public  __fdiv_fpr
455
        defpe   __fdiv_fpr
456
 
457
        sub     esp, STACK_SIZE
458
        jmp     dword ptr dispatch_table[eax*4]
459
 
460
 
461
label0:
462
        fdiv    st,st(0)                ; D8 F0         FDIV    ST,ST(0)
463
        add     esp, STACK_SIZE
464
        ret
465
label1:
466
        add     esp, STACK_SIZE
467
        int     ILLEGAL_OPC
468
label2:
469
        fdivr   st,st(0)                ; D8 F8         FDIVR   ST,ST(0)
470
        add     esp, STACK_SIZE
471
        ret
472
label3:
473
        add     esp, STACK_SIZE
474
        int     ILLEGAL_OPC
475
label4:
476
        fdiv    st(0),st                ; DC F8/D8 F0   FDIV    ST(0),ST
477
        add     esp, STACK_SIZE
478
        ret
479
label5:
480
        fdivp   st(0),st                ; DE F8         FDIVP   ST(0),ST
481
        add     esp, STACK_SIZE
482
        ret
483
label6:
484
        fdivr   st(0),st                ; DC F0/DE F0   FDIVR   ST(0),ST
485
        add     esp, STACK_SIZE
486
        ret
487
label7:
488
        fdivrp  st(0),st                ; DE F0         FDIVRP  ST(0),ST
489
        add     esp, STACK_SIZE
490
        ret
491
label8:
492
        fdiv_st 1, 0
493
        ret
494
label9:
495
        add     esp, STACK_SIZE
496
        int     ILLEGAL_OPC
497
label10:
498
        fdivr_st 1, 0
499
        ret
500
label11:
501
        add     esp, STACK_SIZE
502
        int     ILLEGAL_OPC
503
label12:
504
        fdiv_sti 1, 0
505
        ret
506
label13:
507
        fdivp_sti 1, 0
508
        ret
509
label14:
510
        fdivr_sti 1, 0
511
        ret
512
label15:
513
        fdivrp_sti 1, 0
514
        ret
515
label16:
516
        fdiv_st 2, 1
517
        ret
518
label17:
519
        add     esp, STACK_SIZE
520
        int     ILLEGAL_OPC
521
label18:
522
        fdivr_st 2, 1
523
        ret
524
label19:
525
        add     esp, STACK_SIZE
526
        int     ILLEGAL_OPC
527
label20:
528
        fdiv_sti 2, 1
529
        ret
530
label21:
531
        fdivp_sti 2, 1
532
        ret
533
label22:
534
        fdivr_sti 2, 1
535
        ret
536
label23:
537
        fdivrp_sti 2, 1
538
        ret
539
label24:
540
        fdiv_st 3, 2
541
        ret
542
label25:
543
        add     esp, STACK_SIZE
544
        int     ILLEGAL_OPC
545
label26:
546
        fdivr_st 3, 2
547
        ret
548
label27:
549
        add     esp, STACK_SIZE
550
        int     ILLEGAL_OPC
551
label28:
552
        fdiv_sti 3, 2
553
        ret
554
label29:
555
        fdivp_sti 3, 2
556
        ret
557
label30:
558
        fdivr_sti 3, 2
559
        ret
560
label31:
561
        fdivrp_sti 3, 2
562
        ret
563
label32:
564
        fdiv_st 4, 3
565
        ret
566
label33:
567
        add     esp, STACK_SIZE
568
        int     ILLEGAL_OPC
569
label34:
570
        fdivr_st 4, 3
571
        ret
572
label35:
573
        add     esp, STACK_SIZE
574
        int     ILLEGAL_OPC
575
label36:
576
        fdiv_sti 4, 3
577
        ret
578
label37:
579
        fdivp_sti 4, 3
580
        ret
581
label38:
582
        fdivr_sti 4, 3
583
        ret
584
label39:
585
        fdivrp_sti 4, 3
586
        ret
587
label40:
588
        fdiv_st 5, 4
589
        ret
590
label41:
591
        add     esp, STACK_SIZE
592
        int     ILLEGAL_OPC
593
label42:
594
        fdivr_st 5, 4
595
        ret
596
label43:
597
        add     esp, STACK_SIZE
598
        int     ILLEGAL_OPC
599
label44:
600
        fdiv_sti 5, 4
601
        ret
602
label45:
603
        fdivp_sti 5, 4
604
        ret
605
label46:
606
        fdivr_sti 5, 4
607
        ret
608
label47:
609
        fdivrp_sti 5, 4
610
        ret
611
label48:
612
        fdiv_st 6, 5
613
        ret
614
label49:
615
        add     esp, STACK_SIZE
616
        int     ILLEGAL_OPC
617
label50:
618
        fdivr_st 6, 5
619
        ret
620
label51:
621
        add     esp, STACK_SIZE
622
        int     ILLEGAL_OPC
623
label52:
624
        fdiv_sti 6, 5
625
        ret
626
label53:
627
        fdivp_sti 6, 5
628
        ret
629
label54:
630
        fdivr_sti 6, 5
631
        ret
632
label55:
633
        fdivrp_sti 6, 5
634
        ret
635
label56:
636
        fdiv_st 7, 6
637
        ret
638
label57:
639
        add     esp, STACK_SIZE
640
        int     ILLEGAL_OPC
641
label58:
642
        fdivr_st 7, 6
643
        ret
644
label59:
645
        add     esp, STACK_SIZE
646
        int     ILLEGAL_OPC
647
label60:
648
        fdiv_sti 7, 6
649
        ret
650
label61:
651
        fdivp_sti 7, 6
652
        ret
653
label62:
654
        fdivr_sti 7, 6
655
        ret
656
label63:
657
        fdivrp_sti 7, 6
658
        ret
659
__fdiv_fpr      ENDP
660
 
661
 
662
__fdivp_sti_st    PROC    NEAR
663
                                ; for calling from mem routines
664
        sub     esp, STACK_SIZE
665
        fdivp_sti 1, 0
666
        ret
667
__fdivp_sti_st    ENDP
668
 
669
__fdivrp_sti_st   PROC    NEAR
670
                                ; for calling from mem routines
671
        sub     esp, STACK_SIZE
672
        fdivrp_sti 1, 0
673
        ret
674
__fdivrp_sti_st   ENDP
675
 
676
        public  __fdiv_chk
677
        defpe __fdiv_chk
678
                                ; for calling from mem routines
679
        sub     esp, STACK_SIZE
680
        fdivrp_sti 1, 0
681
        ret
682
__fdiv_chk   ENDP
683
 
684
;
685
;  PRELIMINARY VERSIONS of the routines for register-memory
686
;  divide instructions
687
;
688
 
689
;;; FDIV_M32 - FDIV m32real FIX
690
;;
691
;;      Input : Value of the m32real in the top of STACK
692
;;
693
;;      Output: Result of FDIV in ST
694
 
695
        PUBLIC  __fdiv_m32
696
        defpe   __fdiv_m32
697
 
698
        push    eax                             ; save eax
699
        mov     eax, [esp + MEM_OPERAND]        ; check for
700
        and     eax, SINGLE_NAN                 ; NaN
701
        cmp     eax, SINGLE_NAN                 ;
702
        je      memory_divide_m32               ;
703
 
704
        f_stsw  ax                              ; get status word
705
        and     eax, 3800h                      ; get top of stack
706
        je      spill_fpstack                   ; is FP stack full?
707
        fld     dword ptr[esp + MEM_OPERAND]    ; load m32real in ST
708
        call    __fdivp_sti_st                    ; do actual divide
709
        pop     eax
710
        ret     4
711
spill_fpstack:
712
        fxch
713
        sub     esp, SPILL_SIZE                 ; make temp space
714
        fstp    tbyte ptr[esp ]                 ; save user's ST(1)
715
        fld     dword ptr[esp + SPILL_MEM_OPERAND] ; load m32 real
716
        call    __fdivp_sti_st                    ; do actual divide
717
        fld     tbyte ptr[esp]                  ; restore user's ST(1)
718
                                                ;esp is adjusted by fdivrp fn
719
        fxch
720
        add     esp, SPILL_SIZE
721
        pop     eax
722
        ret     4
723
memory_divide_m32:
724
        fdiv    dword ptr[esp + MEM_OPERAND]    ; do actual divide
725
        pop     eax
726
        ret     4
727
 
728
__fdiv_m32        ENDP
729
 
730
 
731
;;; FDIV_M64 - FDIV m64real FIX
732
;;
733
;;      Input : Value of the m64real in the top of STACK
734
;;
735
;;      Output: Result of FDIV in ST
736
 
737
        PUBLIC  __fdiv_m64
738
        defpe   __fdiv_m64
739
 
740
        push    eax                             ; save eax
741
        mov     eax, [esp + MEM_OPERAND + 4]    ; check for
742
        and     eax, DOUBLE_NAN                 ; NaN
743
        cmp     eax, DOUBLE_NAN                 ;
744
        je      memory_divide_m64               ;
745
 
746
        f_stsw  ax                              ; get status word
747
        and     eax, 3800h                      ; get top of stack
748
        je      spill_fpstack_m64               ; is FP stack full?
749
        fld     qword ptr[esp + MEM_OPERAND]    ; load m64real in ST
750
        call    __fdivp_sti_st                    ; do actual divide
751
        pop     eax
752
        ret     8
753
spill_fpstack_m64:
754
        fxch
755
        sub     esp, SPILL_SIZE                 ; make temp space
756
        fstp    tbyte ptr[esp]                  ; save user's ST(1)
757
        fld     qword ptr[esp + SPILL_MEM_OPERAND] ; load m64real
758
        call    __fdivp_sti_st                    ; do actual divide
759
        fld     tbyte ptr[esp]                  ; restore user's ST(1)
760
                                                ;esp is adjusted by fdivrp fn
761
        fxch
762
        add     esp, SPILL_SIZE
763
        pop     eax
764
        ret     8
765
 
766
memory_divide_m64:
767
        fdiv    qword ptr[esp + MEM_OPERAND]    ; do actual divide
768
        pop     eax
769
        ret     8
770
 
771
__fdiv_m64        ENDP
772
 
773
 
774
 
775
;;; FDIVR_M32 - FDIVR m32real FIX
776
;;
777
;;      Input : Value of the m32real in the top of STACK
778
;;
779
;;      Output: Result of FDIVR in ST
780
 
781
        PUBLIC  __fdiv_m32r
782
        defpe   __fdiv_m32r
783
        push    eax                             ; save eax
784
        mov     eax, [esp + MEM_OPERAND]        ; check for
785
        and     eax, SINGLE_NAN                 ; NaN
786
        cmp     eax, SINGLE_NAN                 ;
787
        je      memory_divide_m32r              ;
788
 
789
        f_stsw  ax                              ; get status word
790
        and     eax, 3800h                      ; get top of stack
791
        je      spill_fpstack_m32r              ; is FP stack full?
792
        fld     dword ptr[esp + MEM_OPERAND]    ; load m32real in ST
793
        call    __fdivrp_sti_st                   ; do actual divide
794
        pop     eax
795
        ret     4
796
spill_fpstack_m32r:
797
        fxch
798
        sub     esp, SPILL_SIZE                 ; make temp space
799
        fstp    tbyte ptr[esp ]                 ; save user's ST(1)
800
        fld     dword ptr[esp + SPILL_MEM_OPERAND] ; load m32 real
801
        call    __fdivrp_sti_st                   ; do actual divide
802
        fld     tbyte ptr[esp]                  ; restore user's ST(1)
803
                                                ;esp is adjusted by fdivp fn
804
        fxch
805
        add     esp, SPILL_SIZE
806
        pop     eax
807
        ret     4
808
memory_divide_m32r:
809
        fdivr   dword ptr[esp + MEM_OPERAND]    ; do actual divide
810
        pop     eax
811
        ret     4
812
 
813
__fdiv_m32r     ENDP
814
 
815
 
816
;;; FDIVR_M64 - FDIVR m64real FIX
817
;;
818
;;      Input : Value of the m64real in the top of STACK
819
;;
820
;;      Output: Result of FDIVR in ST
821
 
822
        PUBLIC  __fdiv_m64r
823
        defpe   __fdiv_m64r
824
        push    eax                             ; save eax
825
        mov     eax, [esp + MEM_OPERAND + 4]    ; check for
826
        and     eax, DOUBLE_NAN                 ; NaN
827
        cmp     eax, DOUBLE_NAN                 ;
828
        je      memory_divide_m64r              ;
829
 
830
        f_stsw  ax                              ; get status word
831
        and     eax, 3800h                      ; get top of stack
832
        je      spill_fpstack_m64r              ; is FP stack full?
833
        fld     qword ptr[esp + MEM_OPERAND]    ; load m64real in ST
834
        call    __fdivrp_sti_st                   ; do actual divide
835
        pop     eax
836
        ret     8
837
spill_fpstack_m64r:
838
        fxch
839
        sub     esp, SPILL_SIZE                 ; make temp space
840
        fstp    tbyte ptr[esp ]                 ; save user's ST(1)
841
        fld     qword ptr[esp + SPILL_MEM_OPERAND] ; load m64real
842
        call    __fdivrp_sti_st                   ; do actual divide
843
        fld     tbyte ptr[esp]                  ; restore user's ST(1)
844
                                                ;esp is adjusted by fdivp fn
845
        fxch
846
        add     esp, SPILL_SIZE
847
        pop     eax
848
        ret     8
849
memory_divide_m64r:
850
        fdivr   qword ptr[esp + MEM_OPERAND]    ; do actual divide
851
        pop     eax
852
        ret     8
853
 
854
 
855
__fdiv_m64r       ENDP
856
 
857
comment ~******************************************************************
858
;;; FDIV_M16I - FDIV m16int FIX
859
;;
860
;;      Input : Value of the m16int in the top of STACK
861
;;
862
;;      Output: Result of FDIV in ST
863
 
864
        PUBLIC  FDIV_M16I
865
FDIV_M16I       PROC    NEAR
866
        push    eax                             ; save eax
867
        f_stsw  ax                              ; get status word
868
        and     eax, 3800h                      ; get top of stack
869
        je      spill_fpstack_m16i              ; is FP stack full?
870
        fild    word ptr[esp + MEM_OPERAND]     ; load m16int in ST
871
        call    __fdivp_sti_st                    ; do actual divide
872
        pop     eax
873
        ret
874
spill_fpstack_m16i:
875
        fxch
876
        sub     esp, SPILL_SIZE                 ; make temp space
877
        fstp    tbyte ptr[esp ]                 ; save user's ST(1)
878
        fild    word ptr[esp + SPILL_MEM_OPERAND] ; load m16int
879
        call    __fdivp_sti_st                    ; do actual divide
880
        fld     tbyte ptr[esp]                  ; restore user's ST(1)
881
                                                ;esp is adjusted by fdivrp fn
882
        fxch
883
        add     esp, SPILL_SIZE
884
        pop     eax
885
        ret
886
 
887
FDIV_M16I       ENDP
888
 
889
;;; FDIV_M32I - FDIV m16int FIX
890
;;
891
;;      Input : Value of the m16int in the top of STACK
892
;;
893
;;      Output: Result of FDIV in ST
894
 
895
        PUBLIC  FDIV_M32I
896
FDIV_M32I       PROC    NEAR
897
        push    eax                             ; save eax
898
        f_stsw  ax                              ; get status word
899
        and     eax, 3800h                      ; get top of stack
900
        je      spill_fpstack_m32i              ; is FP stack full?
901
        fild    dword ptr[esp + MEM_OPERAND]    ; load m32int in ST
902
        call    __fdivp_sti_st                    ; do actual divide
903
        pop     eax
904
        ret
905
spill_fpstack_m32i:
906
        fxch
907
        sub     esp, SPILL_SIZE                 ; make temp space
908
        fstp    tbyte ptr[esp ]                 ; save user's ST(1)
909
        fild    dword ptr[esp + SPILL_MEM_OPERAND] ; load m32int
910
        call    __fdivp_sti_st                    ; do actual divide
911
        fld     tbyte ptr[esp]                  ; restore user's ST(1)
912
                                                ;esp is adjusted by fdivrp fn
913
        fxch
914
        add     esp, SPILL_SIZE
915
        pop     eax
916
        ret
917
 
918
 
919
FDIV_M32I       ENDP
920
 
921
 
922
;;; FDIVR_M16I - FDIVR m16int FIX
923
;;
924
;;      Input : Value of the m16int in the top of STACK
925
;;
926
;;      Output: Result of FDIVR in ST
927
 
928
        PUBLIC  FDIVR_M16I
929
FDIVR_M16I      PROC    NEAR
930
        push    eax                             ; save eax
931
        f_stsw  ax                              ; get status word
932
        and     eax, 3800h                      ; get top of stack
933
        je      spill_fpstack_m16ir             ; is FP stack full?
934
        fild    word ptr[esp + MEM_OPERAND]     ; load m16int in ST
935
        call    __fdivrp_sti_st                   ; do actual divide
936
        pop     eax
937
        ret
938
spill_fpstack_m16ir:
939
        fxch
940
        sub     esp, SPILL_SIZE                 ; make temp space
941
        fstp    tbyte ptr[esp ]                 ; save user's ST(1)
942
        fild    word ptr[esp + SPILL_MEM_OPERAND] ; load m16int
943
        call    __fdivrp_sti_st                   ; do actual divide
944
        fld     tbyte ptr[esp]                  ; restore user's ST(1)
945
                                                ;esp is adjusted by fdivp fn
946
        fxch
947
        add     esp, SPILL_SIZE
948
        pop     eax
949
        ret
950
 
951
 
952
FDIVR_M16I      ENDP
953
 
954
 
955
;;; FDIVR_M32I - FDIVR m32int FIX
956
;;
957
;;      Input : Value of the m32int in the top of STACK
958
;;
959
;;      Output: Result of FDIVR in ST
960
 
961
        PUBLIC  FDIVR_M32I
962
FDIVR_M32I      PROC    NEAR
963
        push    eax                             ; save eax
964
        f_stsw  ax                              ; get status word
965
        and     eax, 3800h                      ; get top of stack
966
        je      spill_fpstack_m32ir             ; is FP stack full?
967
        fild    dword ptr[esp + MEM_OPERAND]    ; load m32int in ST
968
        call    __fdivrp_sti_st                   ; do actual divide
969
        pop     eax
970
        ret
971
spill_fpstack_m32ir:
972
        fxch
973
        sub     esp, SPILL_SIZE                 ; make temp space
974
        fstp    tbyte ptr[esp ]                 ; save user's ST(1)
975
        fild    dword ptr[esp + SPILL_MEM_OPERAND] ; load m32int
976
        call    __fdivrp_sti_st                   ; do actual divide
977
        fld     tbyte ptr[esp]                  ; restore user's ST(1)
978
                                                ;esp is adjusted by fdivp fn
979
        fxch
980
        add     esp, SPILL_SIZE
981
        pop     eax
982
        ret
983
 
984
FDIVR_M32I      ENDP
985
**********************************************************************~
986
 
987
 
988
 
989
_TEXT  ENDS
990
 
991
        end