Blame view

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