Commit | Line | Data |
---|---|---|
1da177e4 LT |
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 |