1#if defined(__SUNPRO_C) && defined(__sparcv9)
2# define ABI64  /* They've said -xarch=v9 at command line */
3#elif defined(__GNUC__) && defined(__arch64__)
4# define ABI64  /* They've said -m64 at command line */
5#endif
6
7#ifdef ABI64
8  .register	%g2,#scratch
9  .register	%g3,#scratch
10# define	FRAME	-192
11# define	BIAS	2047
12#else
13# define	FRAME	-96
14# define	BIAS	0
15#endif
16
17.text
18.align	32
19.global	OPENSSL_wipe_cpu
20.type	OPENSSL_wipe_cpu,#function
21! Keep in mind that this does not excuse us from wiping the stack!
22! This routine wipes registers, but not the backing store [which
23! resides on the stack, toward lower addresses]. To facilitate for
24! stack wiping I return pointer to the top of stack of the *caller*.
25OPENSSL_wipe_cpu:
26	save	%sp,FRAME,%sp
27	nop
28#ifdef __sun
29#include <sys/trap.h>
30	ta	ST_CLEAN_WINDOWS
31#else
32	call	.walk.reg.wins
33#endif
34	nop
35	call	.PIC.zero.up
36	mov	.zero-(.-4),%o0
37	ldd	[%o0],%f0
38
39	subcc	%g0,1,%o0
40	! Following is V9 "rd %ccr,%o0" instruction. However! V8
41	! specification says that it ("rd %asr2,%o0" in V8 terms) does
42	! not cause illegal_instruction trap. It therefore can be used
43	! to determine if the CPU the code is executing on is V8- or
44	! V9-compliant, as V9 returns a distinct value of 0x99,
45	! "negative" and "borrow" bits set in both %icc and %xcc.
46	.word	0x91408000	!rd	%ccr,%o0
47	cmp	%o0,0x99
48	bne	.v8
49	nop
50			! Even though we do not use %fp register bank,
51			! we wipe it as memcpy might have used it...
52			.word	0xbfa00040	!fmovd	%f0,%f62
53			.word	0xbba00040	!...
54			.word	0xb7a00040
55			.word	0xb3a00040
56			.word	0xafa00040
57			.word	0xaba00040
58			.word	0xa7a00040
59			.word	0xa3a00040
60			.word	0x9fa00040
61			.word	0x9ba00040
62			.word	0x97a00040
63			.word	0x93a00040
64			.word	0x8fa00040
65			.word	0x8ba00040
66			.word	0x87a00040
67			.word	0x83a00040	!fmovd	%f0,%f32
68.v8:			fmovs	%f1,%f31
69	clr	%o0
70			fmovs	%f0,%f30
71	clr	%o1
72			fmovs	%f1,%f29
73	clr	%o2
74			fmovs	%f0,%f28
75	clr	%o3
76			fmovs	%f1,%f27
77	clr	%o4
78			fmovs	%f0,%f26
79	clr	%o5
80			fmovs	%f1,%f25
81	clr	%o7
82			fmovs	%f0,%f24
83	clr	%l0
84			fmovs	%f1,%f23
85	clr	%l1
86			fmovs	%f0,%f22
87	clr	%l2
88			fmovs	%f1,%f21
89	clr	%l3
90			fmovs	%f0,%f20
91	clr	%l4
92			fmovs	%f1,%f19
93	clr	%l5
94			fmovs	%f0,%f18
95	clr	%l6
96			fmovs	%f1,%f17
97	clr	%l7
98			fmovs	%f0,%f16
99	clr	%i0
100			fmovs	%f1,%f15
101	clr	%i1
102			fmovs	%f0,%f14
103	clr	%i2
104			fmovs	%f1,%f13
105	clr	%i3
106			fmovs	%f0,%f12
107	clr	%i4
108			fmovs	%f1,%f11
109	clr	%i5
110			fmovs	%f0,%f10
111	clr	%g1
112			fmovs	%f1,%f9
113	clr	%g2
114			fmovs	%f0,%f8
115	clr	%g3
116			fmovs	%f1,%f7
117	clr	%g4
118			fmovs	%f0,%f6
119	clr	%g5
120			fmovs	%f1,%f5
121			fmovs	%f0,%f4
122			fmovs	%f1,%f3
123			fmovs	%f0,%f2
124
125	add	%fp,BIAS,%i0	! return pointer to caller�s top of stack
126
127	ret
128	restore
129
130.zero:	.long	0x0,0x0
131.PIC.zero.up:
132	retl
133	add	%o0,%o7,%o0
134#ifdef DEBUG
135.global	walk_reg_wins
136.type	walk_reg_wins,#function
137walk_reg_wins:
138#endif
139.walk.reg.wins:
140	save	%sp,FRAME,%sp
141	cmp	%i7,%o7
142	be	2f
143	clr	%o0
144	cmp	%o7,0	! compiler never cleans %o7...
145	be	1f	! could have been a leaf function...
146	clr	%o1
147	call	.walk.reg.wins
148	nop
1491:	clr	%o2
150	clr	%o3
151	clr	%o4
152	clr	%o5
153	clr	%o7
154	clr	%l0
155	clr	%l1
156	clr	%l2
157	clr	%l3
158	clr	%l4
159	clr	%l5
160	clr	%l6
161	clr	%l7
162	add	%o0,1,%i0	! used for debugging
1632:	ret
164	restore
165.size	OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu
166
167.global	OPENSSL_atomic_add
168.type	OPENSSL_atomic_add,#function
169OPENSSL_atomic_add:
170#ifndef ABI64
171	subcc	%g0,1,%o2
172	.word	0x95408000	!rd	%ccr,%o2, see comment above
173	cmp	%o2,0x99
174	be	.v9
175	nop
176	save	%sp,FRAME,%sp
177	ba	.enter
178	nop
179#ifdef __sun
180! Note that you don't have to link with libthread to call thr_yield,
181! as libc provides a stub, which is overloaded the moment you link
182! with *either* libpthread or libthread...
183#define	YIELD_CPU	thr_yield
184#else
185! applies at least to Linux and FreeBSD... Feedback expected...
186#define	YIELD_CPU	sched_yield
187#endif
188.spin:	call	YIELD_CPU
189	nop
190.enter:	ld	[%i0],%i2
191	cmp	%i2,-4096
192	be	.spin
193	mov	-1,%i2
194	swap	[%i0],%i2
195	cmp	%i2,-1
196	be	.spin
197	add	%i2,%i1,%i2
198	stbar
199	st	%i2,[%i0]
200	sra	%i2,%g0,%i0
201	ret
202	restore
203.v9:
204#endif
205	ld	[%o0],%o2
2061:	add	%o1,%o2,%o3
207	.word	0xd7e2100a	!cas [%o0],%o2,%o3, compare [%o0] with %o2 and swap %o3
208	cmp	%o2,%o3
209	bne	1b
210	mov	%o3,%o2		! cas is always fetching to dest. register
211	add	%o1,%o2,%o0	! OpenSSL expects the new value
212	retl
213	sra	%o0,%g0,%o0	! we return signed int, remember?
214.size	OPENSSL_atomic_add,.-OPENSSL_atomic_add
215
216.global	OPENSSL_rdtsc
217	subcc	%g0,1,%o0
218	.word	0x91408000	!rd	%ccr,%o0
219	cmp	%o0,0x99
220	bne	.notsc
221	xor	%o0,%o0,%o0
222	save	%sp,FRAME-16,%sp
223	mov	513,%o0		!SI_PLATFORM
224	add	%sp,BIAS+16,%o1
225	call	sysinfo
226	mov	256,%o2
227
228	add	%sp,BIAS-16,%o1
229	ld	[%o1],%l0
230	ld	[%o1+4],%l1
231	ld	[%o1+8],%l2
232	mov	%lo('SUNW'),%l3
233	ret
234	restore
235.notsc:
236	retl
237	nop
238.type	OPENSSL_rdtsc,#function
239.size	OPENSSL_rdtsc,.-OPENSSL_atomic_add
240