SPARCv9 assembler pack: refine CPU detection on Linux, fix for "unaligned
[openssl.git] / crypto / sparccpuid.S
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*.
25 OPENSSL_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         ld      [%o0],%f0
38         ld      [%o0],%f1
39
40         subcc   %g0,1,%o0
41         ! Following is V9 "rd %ccr,%o0" instruction. However! V8
42         ! specification says that it ("rd %asr2,%o0" in V8 terms) does
43         ! not cause illegal_instruction trap. It therefore can be used
44         ! to determine if the CPU the code is executing on is V8- or
45         ! V9-compliant, as V9 returns a distinct value of 0x99,
46         ! "negative" and "borrow" bits set in both %icc and %xcc.
47         .word   0x91408000      !rd     %ccr,%o0
48         cmp     %o0,0x99
49         bne     .v8
50         nop
51                         ! Even though we do not use %fp register bank,
52                         ! we wipe it as memcpy might have used it...
53                         .word   0xbfa00040      !fmovd  %f0,%f62
54                         .word   0xbba00040      !...
55                         .word   0xb7a00040
56                         .word   0xb3a00040
57                         .word   0xafa00040
58                         .word   0xaba00040
59                         .word   0xa7a00040
60                         .word   0xa3a00040
61                         .word   0x9fa00040
62                         .word   0x9ba00040
63                         .word   0x97a00040
64                         .word   0x93a00040
65                         .word   0x8fa00040
66                         .word   0x8ba00040
67                         .word   0x87a00040
68                         .word   0x83a00040      !fmovd  %f0,%f32
69 .v8:                    fmovs   %f1,%f31
70         clr     %o0
71                         fmovs   %f0,%f30
72         clr     %o1
73                         fmovs   %f1,%f29
74         clr     %o2
75                         fmovs   %f0,%f28
76         clr     %o3
77                         fmovs   %f1,%f27
78         clr     %o4
79                         fmovs   %f0,%f26
80         clr     %o5
81                         fmovs   %f1,%f25
82         clr     %o7
83                         fmovs   %f0,%f24
84         clr     %l0
85                         fmovs   %f1,%f23
86         clr     %l1
87                         fmovs   %f0,%f22
88         clr     %l2
89                         fmovs   %f1,%f21
90         clr     %l3
91                         fmovs   %f0,%f20
92         clr     %l4
93                         fmovs   %f1,%f19
94         clr     %l5
95                         fmovs   %f0,%f18
96         clr     %l6
97                         fmovs   %f1,%f17
98         clr     %l7
99                         fmovs   %f0,%f16
100         clr     %i0
101                         fmovs   %f1,%f15
102         clr     %i1
103                         fmovs   %f0,%f14
104         clr     %i2
105                         fmovs   %f1,%f13
106         clr     %i3
107                         fmovs   %f0,%f12
108         clr     %i4
109                         fmovs   %f1,%f11
110         clr     %i5
111                         fmovs   %f0,%f10
112         clr     %g1
113                         fmovs   %f1,%f9
114         clr     %g2
115                         fmovs   %f0,%f8
116         clr     %g3
117                         fmovs   %f1,%f7
118         clr     %g4
119                         fmovs   %f0,%f6
120         clr     %g5
121                         fmovs   %f1,%f5
122                         fmovs   %f0,%f4
123                         fmovs   %f1,%f3
124                         fmovs   %f0,%f2
125
126         add     %fp,BIAS,%i0    ! return pointer to callerĀ“s top of stack
127
128         ret
129         restore
130
131 .zero:  .long   0x0,0x0
132 .PIC.zero.up:
133         retl
134         add     %o0,%o7,%o0
135 #ifdef DEBUG
136 .global walk_reg_wins
137 .type   walk_reg_wins,#function
138 walk_reg_wins:
139 #endif
140 .walk.reg.wins:
141         save    %sp,FRAME,%sp
142         cmp     %i7,%o7
143         be      2f
144         clr     %o0
145         cmp     %o7,0   ! compiler never cleans %o7...
146         be      1f      ! could have been a leaf function...
147         clr     %o1
148         call    .walk.reg.wins
149         nop
150 1:      clr     %o2
151         clr     %o3
152         clr     %o4
153         clr     %o5
154         clr     %o7
155         clr     %l0
156         clr     %l1
157         clr     %l2
158         clr     %l3
159         clr     %l4
160         clr     %l5
161         clr     %l6
162         clr     %l7
163         add     %o0,1,%i0       ! used for debugging
164 2:      ret
165         restore
166 .size   OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu
167
168 .global OPENSSL_atomic_add
169 .type   OPENSSL_atomic_add,#function
170 .align  32
171 OPENSSL_atomic_add:
172 #ifndef ABI64
173         subcc   %g0,1,%o2
174         .word   0x95408000      !rd     %ccr,%o2, see comment above
175         cmp     %o2,0x99
176         be      .v9
177         nop
178         save    %sp,FRAME,%sp
179         ba      .enter
180         nop
181 #ifdef __sun
182 ! Note that you do not have to link with libthread to call thr_yield,
183 ! as libc provides a stub, which is overloaded the moment you link
184 ! with *either* libpthread or libthread...
185 #define YIELD_CPU       thr_yield
186 #else
187 ! applies at least to Linux and FreeBSD... Feedback expected...
188 #define YIELD_CPU       sched_yield
189 #endif
190 .spin:  call    YIELD_CPU
191         nop
192 .enter: ld      [%i0],%i2
193         cmp     %i2,-4096
194         be      .spin
195         mov     -1,%i2
196         swap    [%i0],%i2
197         cmp     %i2,-1
198         be      .spin
199         add     %i2,%i1,%i2
200         stbar
201         st      %i2,[%i0]
202         sra     %i2,%g0,%i0
203         ret
204         restore
205 .v9:
206 #endif
207         ld      [%o0],%o2
208 1:      add     %o1,%o2,%o3
209         .word   0xd7e2100a      !cas [%o0],%o2,%o3, compare [%o0] with %o2 and swap %o3
210         cmp     %o2,%o3
211         bne     1b
212         mov     %o3,%o2         ! cas is always fetching to dest. register
213         add     %o1,%o2,%o0     ! OpenSSL expects the new value
214         retl
215         sra     %o0,%g0,%o0     ! we return signed int, remember?
216 .size   OPENSSL_atomic_add,.-OPENSSL_atomic_add
217
218 .global _sparcv9_rdtick
219 .align  32
220 _sparcv9_rdtick:
221         subcc   %g0,1,%o0
222         .word   0x91408000      !rd     %ccr,%o0
223         cmp     %o0,0x99
224         bne     .notick
225         xor     %o0,%o0,%o0
226         .word   0x91410000      !rd     %tick,%o0
227         retl
228         .word   0x93323020      !srlx   %o0,32,%o1
229 .notick:
230         retl
231         xor     %o1,%o1,%o1
232 .type   _sparcv9_rdtick,#function
233 .size   _sparcv9_rdtick,.-_sparcv9_rdtick
234
235 .global _sparcv9_rdwrasi
236 .align  8
237 _sparcv9_rdwrasi:
238         .word   0x9340c000      !rd     %asi,%o1
239         .word   0x87820000      !wr     %o0,%g0,%asi
240         retl
241         mov     %o1,%o0
242 .type   _sparcv9_rdwrasi,#function
243 .size   _sparcv9_rdwrasi,.-_sparcv9_rdwrasi
244
245 .global _sparcv9_vis1_probe
246 .align  8
247 _sparcv9_vis1_probe:
248         .word   0x81b00c20      !fzeros %f0
249         .word   0xc19ba002+BIAS !ldda   [%sp+BIAS+2]%asi,%f0
250         retl
251         nop
252 .type   _sparcv9_vis1_probe,#function
253 .size   _sparcv9_vis1_probe,.-_sparcv9_vis1_probe
254
255 .global OPENSSL_cleanse
256 .align  32
257 OPENSSL_cleanse:
258         cmp     %o1,14
259         nop
260 #ifdef ABI64
261         bgu     %xcc,.Lot
262 #else
263         bgu     .Lot
264 #endif
265         cmp     %o1,0
266         bne     .Little
267         nop
268         retl
269         nop
270
271 .Little:
272         stb     %g0,[%o0]
273         subcc   %o1,1,%o1
274         bnz     .Little
275         add     %o0,1,%o0
276         retl
277         nop
278 .align  32
279 .Lot:
280 #ifndef ABI64
281         subcc   %g0,1,%g1
282         ! see above for explanation
283         .word   0x83408000      !rd     %ccr,%g1
284         cmp     %g1,0x99
285         bne     .v8lot
286         nop
287 #endif
288
289 .v9lot: andcc   %o0,7,%g0
290         bz      .v9aligned
291         nop
292         stb     %g0,[%o0]
293         sub     %o1,1,%o1
294         ba      .v9lot
295         add     %o0,1,%o0
296 .align  16,0x01000000
297 .v9aligned:
298         .word   0xc0720000      !stx    %g0,[%o0]
299         sub     %o1,8,%o1
300         andcc   %o1,-8,%g0
301 #ifdef ABI64
302         .word   0x126ffffd      !bnz    %xcc,.v9aligned
303 #else
304         .word   0x124ffffd      !bnz    %icc,.v9aligned
305 #endif
306         add     %o0,8,%o0
307
308         cmp     %o1,0
309         bne     .Little
310         nop
311         retl
312         nop
313 #ifndef ABI64
314 .v8lot: andcc   %o0,3,%g0
315         bz      .v8aligned
316         nop
317         stb     %g0,[%o0]
318         sub     %o1,1,%o1
319         ba      .v8lot
320         add     %o0,1,%o0
321         nop
322 .v8aligned:
323         st      %g0,[%o0]
324         sub     %o1,4,%o1
325         andcc   %o1,-4,%g0
326         bnz     .v8aligned
327         add     %o0,4,%o0
328
329         cmp     %o1,0
330         bne     .Little
331         nop
332         retl
333         nop
334 #endif
335 .type   OPENSSL_cleanse,#function
336 .size   OPENSSL_cleanse,.-OPENSSL_cleanse
337
338 .section        ".init",#alloc,#execinstr
339         call    OPENSSL_cpuid_setup
340         nop