Merge branches 'x86/apic', 'x86/asm', 'x86/cleanups', 'x86/debug', 'x86/kconfig'...
[linux-2.6] / arch / x86 / math-emu / wm_shrx.S
1         .file   "wm_shrx.S"
2 /*---------------------------------------------------------------------------+
3  |  wm_shrx.S                                                                |
4  |                                                                           |
5  | 64 bit right shift functions                                              |
6  |                                                                           |
7  | Copyright (C) 1992,1995                                                   |
8  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
9  |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
10  |                                                                           |
11  | Call from C as:                                                           |
12  |   unsigned FPU_shrx(void *arg1, unsigned arg2)                            |
13  | and                                                                       |
14  |   unsigned FPU_shrxs(void *arg1, unsigned arg2)                           |
15  |                                                                           |
16  +---------------------------------------------------------------------------*/
17
18 #include "fpu_emu.h"
19
20 .text
21 /*---------------------------------------------------------------------------+
22  |   unsigned FPU_shrx(void *arg1, unsigned arg2)                            |
23  |                                                                           |
24  |   Extended shift right function.                                          |
25  |   Fastest for small shifts.                                               |
26  |   Shifts the 64 bit quantity pointed to by the first arg (arg1)           |
27  |   right by the number of bits specified by the second arg (arg2).         |
28  |   Forms a 96 bit quantity from the 64 bit arg and eax:                    |
29  |                [  64 bit arg ][ eax ]                                     |
30  |            shift right  --------->                                        |
31  |   The eax register is initialized to 0 before the shifting.               |
32  |   Results returned in the 64 bit arg and eax.                             |
33  +---------------------------------------------------------------------------*/
34
35 ENTRY(FPU_shrx)
36         push    %ebp
37         movl    %esp,%ebp
38         pushl   %esi
39         movl    PARAM2,%ecx
40         movl    PARAM1,%esi
41         cmpl    $32,%ecx        /* shrd only works for 0..31 bits */
42         jnc     L_more_than_31
43
44 /* less than 32 bits */
45         pushl   %ebx
46         movl    (%esi),%ebx     /* lsl */
47         movl    4(%esi),%edx    /* msl */
48         xorl    %eax,%eax       /* extension */
49         shrd    %cl,%ebx,%eax
50         shrd    %cl,%edx,%ebx
51         shr     %cl,%edx
52         movl    %ebx,(%esi)
53         movl    %edx,4(%esi)
54         popl    %ebx
55         popl    %esi
56         leave
57         ret
58
59 L_more_than_31:
60         cmpl    $64,%ecx
61         jnc     L_more_than_63
62
63         subb    $32,%cl
64         movl    (%esi),%eax     /* lsl */
65         movl    4(%esi),%edx    /* msl */
66         shrd    %cl,%edx,%eax
67         shr     %cl,%edx
68         movl    %edx,(%esi)
69         movl    $0,4(%esi)
70         popl    %esi
71         leave
72         ret
73
74 L_more_than_63:
75         cmpl    $96,%ecx
76         jnc     L_more_than_95
77
78         subb    $64,%cl
79         movl    4(%esi),%eax    /* msl */
80         shr     %cl,%eax
81         xorl    %edx,%edx
82         movl    %edx,(%esi)
83         movl    %edx,4(%esi)
84         popl    %esi
85         leave
86         ret
87
88 L_more_than_95:
89         xorl    %eax,%eax
90         movl    %eax,(%esi)
91         movl    %eax,4(%esi)
92         popl    %esi
93         leave
94         ret
95
96
97 /*---------------------------------------------------------------------------+
98  |   unsigned FPU_shrxs(void *arg1, unsigned arg2)                           |
99  |                                                                           |
100  |   Extended shift right function (optimized for small floating point       |
101  |   integers).                                                              |
102  |   Shifts the 64 bit quantity pointed to by the first arg (arg1)           |
103  |   right by the number of bits specified by the second arg (arg2).         |
104  |   Forms a 96 bit quantity from the 64 bit arg and eax:                    |
105  |                [  64 bit arg ][ eax ]                                     |
106  |            shift right  --------->                                        |
107  |   The eax register is initialized to 0 before the shifting.               |
108  |   The lower 8 bits of eax are lost and replaced by a flag which is        |
109  |   set (to 0x01) if any bit, apart from the first one, is set in the       |
110  |   part which has been shifted out of the arg.                             |
111  |   Results returned in the 64 bit arg and eax.                             |
112  +---------------------------------------------------------------------------*/
113 ENTRY(FPU_shrxs)
114         push    %ebp
115         movl    %esp,%ebp
116         pushl   %esi
117         pushl   %ebx
118         movl    PARAM2,%ecx
119         movl    PARAM1,%esi
120         cmpl    $64,%ecx        /* shrd only works for 0..31 bits */
121         jnc     Ls_more_than_63
122
123         cmpl    $32,%ecx        /* shrd only works for 0..31 bits */
124         jc      Ls_less_than_32
125
126 /* We got here without jumps by assuming that the most common requirement
127    is for small integers */
128 /* Shift by [32..63] bits */
129         subb    $32,%cl
130         movl    (%esi),%eax     /* lsl */
131         movl    4(%esi),%edx    /* msl */
132         xorl    %ebx,%ebx
133         shrd    %cl,%eax,%ebx
134         shrd    %cl,%edx,%eax
135         shr     %cl,%edx
136         orl     %ebx,%ebx               /* test these 32 bits */
137         setne   %bl
138         test    $0x7fffffff,%eax        /* and 31 bits here */
139         setne   %bh
140         orw     %bx,%bx                 /* Any of the 63 bit set ? */
141         setne   %al
142         movl    %edx,(%esi)
143         movl    $0,4(%esi)
144         popl    %ebx
145         popl    %esi
146         leave
147         ret
148
149 /* Shift by [0..31] bits */
150 Ls_less_than_32:
151         movl    (%esi),%ebx     /* lsl */
152         movl    4(%esi),%edx    /* msl */
153         xorl    %eax,%eax       /* extension */
154         shrd    %cl,%ebx,%eax
155         shrd    %cl,%edx,%ebx
156         shr     %cl,%edx
157         test    $0x7fffffff,%eax        /* only need to look at eax here */
158         setne   %al
159         movl    %ebx,(%esi)
160         movl    %edx,4(%esi)
161         popl    %ebx
162         popl    %esi
163         leave
164         ret
165
166 /* Shift by [64..95] bits */
167 Ls_more_than_63:
168         cmpl    $96,%ecx
169         jnc     Ls_more_than_95
170
171         subb    $64,%cl
172         movl    (%esi),%ebx     /* lsl */
173         movl    4(%esi),%eax    /* msl */
174         xorl    %edx,%edx       /* extension */
175         shrd    %cl,%ebx,%edx
176         shrd    %cl,%eax,%ebx
177         shr     %cl,%eax
178         orl     %ebx,%edx
179         setne   %bl
180         test    $0x7fffffff,%eax        /* only need to look at eax here */
181         setne   %bh
182         orw     %bx,%bx
183         setne   %al
184         xorl    %edx,%edx
185         movl    %edx,(%esi)     /* set to zero */
186         movl    %edx,4(%esi)    /* set to zero */
187         popl    %ebx
188         popl    %esi
189         leave
190         ret
191
192 Ls_more_than_95:
193 /* Shift by [96..inf) bits */
194         xorl    %eax,%eax
195         movl    (%esi),%ebx
196         orl     4(%esi),%ebx
197         setne   %al
198         xorl    %ebx,%ebx
199         movl    %ebx,(%esi)
200         movl    %ebx,4(%esi)
201         popl    %ebx
202         popl    %esi
203         leave
204         ret