* added compilers lcc and bcc (linux86)
[mascara-docs.git] / compilers / linux86-0.16.17 / libc / i386fp / fmul.x
blobaa62b5c70b0b32db62da7e81a31fd14b4370b087
1 ! bcc 386 floating point routines (version 2) -- Fmul, Fmuld, Fmulf
2 ! author: Bruce Evans
4 #include "fplib.h"
6 #define FRAME_SIZE      (3 * GENREG_SIZE + PC_SIZE)
8         .extern Fpushf
9         .extern fpoverflow
10         .extern fpunderflow
11         .extern normalize2
13         .globl  Fmul
14         .align  ALIGNMENT
15 Fmul:
16         push    ebp
17         push    edi
18         push    esi
19         mov     eax,FRAME_SIZE+D_LOW[esp]
20         mov     edx,FRAME_SIZE+D_HIGH[esp]
21         mov     ebx,FRAME_SIZE+D_SIZE+D_LOW[esp]
22         mov     ecx,FRAME_SIZE+D_SIZE+D_HIGH[esp]
23         call    multiplication
24         mov     FRAME_SIZE+D_SIZE+D_LOW[esp],eax
25         mov     FRAME_SIZE+D_SIZE+D_HIGH[esp],edx
26         pop     esi
27         pop     edi
28         pop     ebp
29         ret     #D_SIZE
31         .globl  Fmuld
32         .align  ALIGNMENT
33 Fmuld:
34         push    ebp
35         push    edi
36         push    esi
37         mov     eax,FRAME_SIZE+D_LOW[esp]
38         mov     edx,FRAME_SIZE+D_HIGH[esp]
39         mov     ecx,D_HIGH[ebx]
40         mov     ebx,D_LOW[ebx]
41         call    multiplication
42         mov     FRAME_SIZE+D_LOW[esp],eax
43         mov     FRAME_SIZE+D_HIGH[esp],edx
44         pop     esi
45         pop     edi
46         pop     ebp
47         ret
49         .globl  Fmulf
50         .align  ALIGNMENT
51 Fmulf:
52         push    ebp
53         push    edi
54         push    esi
55         call    Fpushf
56         pop     ebx     ! yl
57         pop     ecx     ! xu
58         mov     eax,FRAME_SIZE+D_LOW[esp]       ! xl
59         mov     edx,FRAME_SIZE+D_HIGH[esp]      ! xu
60         call    multiplication
61         mov     FRAME_SIZE+D_LOW[esp],eax
62         mov     FRAME_SIZE+D_HIGH[esp],edx
63         pop     esi
64         pop     edi
65         pop     ebp
66         ret
68         .align  ALIGNMENT
69 exp_x_0:
70         mov     edx,#1 << D_EXP_SHIFT   ! change exponent from 0 to 1
71         jmp     x_unpacked              ! XXX - check for denormal?
73         .align  ALIGNMENT
74 exp_y_0:
75         mov     ecx,#1 << D_EXP_SHIFT
76         jmp     y_unpacked
78         .align  ALIGNMENT
79 multiplication:
80         mov     ebp,edx         ! xu
81         xor     ebp,ecx         ! xu ^ yu
82         and     ebp,#D_SIGN_MASK        ! sign of result is difference of signs
84         mov     esi,edx         ! free edx for multiplications
85         and     esi,#D_FRAC_MASK        ! discard sign and exponent
86         and     edx,#D_EXP_MASK ! exponent(x)
87         jz      exp_x_0
88         or      esi,#D_NORM_MASK        ! normalize
89 x_unpacked:
91         mov     edi,ecx         ! this mainly for consistent naming
92         and     edi,#D_FRAC_MASK
93         and     ecx,#D_EXP_MASK ! exponent(y)
94         jz      exp_y_0
95         or      edi,#D_NORM_MASK
96 y_unpacked:
98         add     ecx,edx         ! add exponents
100 ! exponent is in ecx, sign in ebp, operands in esi:eax and edi:ebx, edx is free
101 ! product to go in esi:eax:ebp:ebx
102 ! terminology: x * y = (xu,xl) * (yu,yl)
103 ! = (xu * yu,0,0) + (0,xu * yl + xl * yu,0) + (0,0,xl * yl)
105         push    ecx
106         push    ebp
107         mov     ecx,eax
108         mul     ebx             ! xl * yl
109         mov     ebp,edx         ! (xl * yl).u in ebp
110         xchg    ebx,eax         ! (xl * yl).l in ebx (final), yl in eax
111         mul     esi             ! xu * yl
112         push    eax             ! (xu * yl).l on stack
113         push    edx             ! (xu * yl).u on stack
114         mov     eax,esi         ! xu
115         mul     edi             ! xu * yu
116         mov     esi,edx         ! (xu * yu).u in esi (final except carries)
117         xchg    ecx,eax         ! (xu * yu).l in ecx, xl in eax
118         mul     edi             ! xl * yu
120         add     ebp,eax         ! (xl * yl).u + (xl * yu).l
121         pop     eax             ! (xu * yl).u
122         adc     eax,edx         ! (xu * yl).u + (xl * yu).u
123         adc     esi,#0
124         pop     edx             ! (xu * yl).l
125         add     ebp,edx         ! ((xl * yl).u + (xl * yu).l) + (xu * yl).l
126         adc     eax,ecx         ! ((xu * yl).u + (xl * yu).u) + (xu * yu).l
127         adc     esi,#0
128         pop     edx             ! sign
129         pop     edi             ! exponent
130         sub     edi,#(D_EXP_BIAS+1-(D_EXP_BIT+2)) << D_EXP_SHIFT        ! adjust
131 !       cmp     edi,#(D_EXP_INFINITE-1+(D_EXP_BIT+2)) << D_EXP_SHIFT
132 !       jae     outofbounds     ! 0 will be caught as underflow by normalize2
133 cmp edi,#(2*D_EXP_INFINITE-(D_EXP_BIAS+1)+(D_EXP_BIT+2)) << D_EXP_SHIFT
134 ja underflow
135         br      normalize2
137         .align  ALIGNMENT
138 overflow:
139         mov     edx,ebp         ! put sign in usual reg
140         call    fpoverflow
141         mov     eax,ecx         ! XXX - wrong reg
142         ret
144         .align  ALIGNMENT
145 underflow:
146         mov     edx,ebp         ! put sign in usual reg
147         neg     edi
148         shr     edi,#D_EXP_SHIFT
149         inc     edi
150         br      fpunderflow