SPARCv9 assembly pack: fine-tune run-time switch.
[openssl.git] / crypto / sparccpuid.S
1 #ifdef OPENSSL_FIPSCANISTER
2 #include <openssl/fipssyms.h>
3 #endif
4
5 #if defined(__SUNPRO_C) && defined(__sparcv9)
6 # define ABI64  /* They've said -xarch=v9 at command line */
7 #elif defined(__GNUC__) && defined(__arch64__)
8 # define ABI64  /* They've said -m64 at command line */
9 #endif
10
11 #ifdef ABI64
12   .register     %g2,#scratch
13   .register     %g3,#scratch
14 # define        FRAME   -192
15 # define        BIAS    2047
16 #else
17 # define        FRAME   -96
18 # define        BIAS    0
19 #endif
20
21 .text
22 .align  32
23 .global OPENSSL_wipe_cpu
24 .type   OPENSSL_wipe_cpu,#function
25 ! Keep in mind that this does not excuse us from wiping the stack!
26 ! This routine wipes registers, but not the backing store [which
27 ! resides on the stack, toward lower addresses]. To facilitate for
28 ! stack wiping I return pointer to the top of stack of the *caller*.
29 OPENSSL_wipe_cpu:
30         save    %sp,FRAME,%sp
31         nop
32 #ifdef __sun
33 #include <sys/trap.h>
34         ta      ST_CLEAN_WINDOWS
35 #else
36         call    .walk.reg.wins
37 #endif
38         nop
39         call    .PIC.zero.up
40         mov     .zero-(.-4),%o0
41         ld      [%o0],%f0
42         ld      [%o0],%f1
43
44         subcc   %g0,1,%o0
45         ! Following is V9 "rd %ccr,%o0" instruction. However! V8
46         ! specification says that it ("rd %asr2,%o0" in V8 terms) does
47         ! not cause illegal_instruction trap. It therefore can be used
48         ! to determine if the CPU the code is executing on is V8- or
49         ! V9-compliant, as V9 returns a distinct value of 0x99,
50         ! "negative" and "borrow" bits set in both %icc and %xcc.
51         .word   0x91408000      !rd     %ccr,%o0
52         cmp     %o0,0x99
53         bne     .v8
54         nop
55                         ! Even though we do not use %fp register bank,
56                         ! we wipe it as memcpy might have used it...
57                         .word   0xbfa00040      !fmovd  %f0,%f62
58                         .word   0xbba00040      !...
59                         .word   0xb7a00040
60                         .word   0xb3a00040
61                         .word   0xafa00040
62                         .word   0xaba00040
63                         .word   0xa7a00040
64                         .word   0xa3a00040
65                         .word   0x9fa00040
66                         .word   0x9ba00040
67                         .word   0x97a00040
68                         .word   0x93a00040
69                         .word   0x8fa00040
70                         .word   0x8ba00040
71                         .word   0x87a00040
72                         .word   0x83a00040      !fmovd  %f0,%f32
73 .v8:                    fmovs   %f1,%f31
74         clr     %o0
75                         fmovs   %f0,%f30
76         clr     %o1
77                         fmovs   %f1,%f29
78         clr     %o2
79                         fmovs   %f0,%f28
80         clr     %o3
81                         fmovs   %f1,%f27
82         clr     %o4
83                         fmovs   %f0,%f26
84         clr     %o5
85                         fmovs   %f1,%f25
86         clr     %o7
87                         fmovs   %f0,%f24
88         clr     %l0
89                         fmovs   %f1,%f23
90         clr     %l1
91                         fmovs   %f0,%f22
92         clr     %l2
93                         fmovs   %f1,%f21
94         clr     %l3
95                         fmovs   %f0,%f20
96         clr     %l4
97                         fmovs   %f1,%f19
98         clr     %l5
99                         fmovs   %f0,%f18
100         clr     %l6
101                         fmovs   %f1,%f17
102         clr     %l7
103                         fmovs   %f0,%f16
104         clr     %i0
105                         fmovs   %f1,%f15
106         clr     %i1
107                         fmovs   %f0,%f14
108         clr     %i2
109                         fmovs   %f1,%f13
110         clr     %i3
111                         fmovs   %f0,%f12
112         clr     %i4
113                         fmovs   %f1,%f11
114         clr     %i5
115                         fmovs   %f0,%f10
116         clr     %g1
117                         fmovs   %f1,%f9
118         clr     %g2
119                         fmovs   %f0,%f8
120         clr     %g3
121                         fmovs   %f1,%f7
122         clr     %g4
123                         fmovs   %f0,%f6
124         clr     %g5
125                         fmovs   %f1,%f5
126                         fmovs   %f0,%f4
127                         fmovs   %f1,%f3
128                         fmovs   %f0,%f2
129
130         add     %fp,BIAS,%i0    ! return pointer to callerĀ“s top of stack
131
132         ret
133         restore
134
135 .zero:  .long   0x0,0x0
136 .PIC.zero.up:
137         retl
138         add     %o0,%o7,%o0
139 #ifdef DEBUG
140 .global walk_reg_wins
141 .type   walk_reg_wins,#function
142 walk_reg_wins:
143 #endif
144 .walk.reg.wins:
145         save    %sp,FRAME,%sp
146         cmp     %i7,%o7
147         be      2f
148         clr     %o0
149         cmp     %o7,0   ! compiler never cleans %o7...
150         be      1f      ! could have been a leaf function...
151         clr     %o1
152         call    .walk.reg.wins
153         nop
154 1:      clr     %o2
155         clr     %o3
156         clr     %o4
157         clr     %o5
158         clr     %o7
159         clr     %l0
160         clr     %l1
161         clr     %l2
162         clr     %l3
163         clr     %l4
164         clr     %l5
165         clr     %l6
166         clr     %l7
167         add     %o0,1,%i0       ! used for debugging
168 2:      ret
169         restore
170 .size   OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu
171
172 .global OPENSSL_atomic_add
173 .type   OPENSSL_atomic_add,#function
174 .align  32
175 OPENSSL_atomic_add:
176 #ifndef ABI64
177         subcc   %g0,1,%o2
178         .word   0x95408000      !rd     %ccr,%o2, see comment above
179         cmp     %o2,0x99
180         be      .v9
181         nop
182         save    %sp,FRAME,%sp
183         ba      .enter
184         nop
185 #ifdef __sun
186 ! Note that you do not have to link with libthread to call thr_yield,
187 ! as libc provides a stub, which is overloaded the moment you link
188 ! with *either* libpthread or libthread...
189 #define YIELD_CPU       thr_yield
190 #else
191 ! applies at least to Linux and FreeBSD... Feedback expected...
192 #define YIELD_CPU       sched_yield
193 #endif
194 .spin:  call    YIELD_CPU
195         nop
196 .enter: ld      [%i0],%i2
197         cmp     %i2,-4096
198         be      .spin
199         mov     -1,%i2
200         swap    [%i0],%i2
201         cmp     %i2,-1
202         be      .spin
203         add     %i2,%i1,%i2
204         stbar
205         st      %i2,[%i0]
206         sra     %i2,%g0,%i0
207         ret
208         restore
209 .v9:
210 #endif
211         ld      [%o0],%o2
212 1:      add     %o1,%o2,%o3
213         .word   0xd7e2100a      !cas [%o0],%o2,%o3, compare [%o0] with %o2 and swap %o3
214         cmp     %o2,%o3
215         bne     1b
216         mov     %o3,%o2         ! cas is always fetching to dest. register
217         add     %o1,%o2,%o0     ! OpenSSL expects the new value
218         retl
219         sra     %o0,%g0,%o0     ! we return signed int, remember?
220 .size   OPENSSL_atomic_add,.-OPENSSL_atomic_add
221
222 .global _sparcv9_rdtick
223 .align  32
224 _sparcv9_rdtick:
225         subcc   %g0,1,%o0
226         .word   0x91408000      !rd     %ccr,%o0
227         cmp     %o0,0x99
228         bne     .notick
229         xor     %o0,%o0,%o0
230         .word   0x91410000      !rd     %tick,%o0
231         retl
232         .word   0x93323020      !srlx   %o0,32,%o1
233 .notick:
234         retl
235         xor     %o1,%o1,%o1
236 .type   _sparcv9_rdtick,#function
237 .size   _sparcv9_rdtick,.-_sparcv9_rdtick
238
239 .global _sparcv9_vis1_probe
240 .align  8
241 _sparcv9_vis1_probe:
242         add     %sp,BIAS+2,%o1
243         .word   0xc19a5a40      !ldda   [%o1]ASI_FP16_P,%f0
244         retl
245         .word   0x81b00d80      !fxor   %f0,%f0,%f0
246 .type   _sparcv9_vis1_probe,#function
247 .size   _sparcv9_vis1_probe,.-_sparcv9_vis1_probe
248
249 ! Probe and instrument VIS1 instruction. Output is number of cycles it
250 ! takes to execute rdtick and pair of VIS1 instructions. US-Tx VIS unit
251 ! is slow (documented to be 6 cycles on T2) and the core is in-order
252 ! single-issue, it should be possible to distinguish Tx reliably...
253 ! Observed return values are:
254 !
255 !       UltraSPARC IIe          7
256 !       UltraSPARC III          7
257 !       UltraSPARC T1           24
258 !       SPARC T4                65(*)
259 !
260 ! (*)   result has lesser to do with VIS instruction latencies, rdtick
261 !       appears that slow, but it does the trick in sense that FP and
262 !       VIS code paths are still slower than integer-only ones.
263 !
264 ! Numbers for T2 and SPARC64 V-VII are more than welcomed.
265 !
266 ! It would be possible to detect specifically US-T1 by instrumenting
267 ! fmul8ulx16, which is emulated on T1 and as such accounts for quite
268 ! a lot of %tick-s, couple of thousand on Linux...
269 .global _sparcv9_vis1_instrument
270 .align  8
271 _sparcv9_vis1_instrument:
272         .word   0x81b00d80      !fxor   %f0,%f0,%f0
273         .word   0x85b08d82      !fxor   %f2,%f2,%f2
274         .word   0x91410000      !rd     %tick,%o0
275         .word   0x81b00d80      !fxor   %f0,%f0,%f0
276         .word   0x85b08d82      !fxor   %f2,%f2,%f2
277         .word   0x93410000      !rd     %tick,%o1
278         .word   0x81b00d80      !fxor   %f0,%f0,%f0
279         .word   0x85b08d82      !fxor   %f2,%f2,%f2
280         .word   0x95410000      !rd     %tick,%o2
281         .word   0x81b00d80      !fxor   %f0,%f0,%f0
282         .word   0x85b08d82      !fxor   %f2,%f2,%f2
283         .word   0x97410000      !rd     %tick,%o3
284         .word   0x81b00d80      !fxor   %f0,%f0,%f0
285         .word   0x85b08d82      !fxor   %f2,%f2,%f2
286         .word   0x99410000      !rd     %tick,%o4
287
288         ! calculate intervals
289         sub     %o1,%o0,%o0
290         sub     %o2,%o1,%o1
291         sub     %o3,%o2,%o2
292         sub     %o4,%o3,%o3
293
294         ! find minumum value
295         cmp     %o0,%o1
296         .word   0x38680002      !bgu,a  %xcc,.+8
297         mov     %o1,%o0
298         cmp     %o0,%o2
299         .word   0x38680002      !bgu,a  %xcc,.+8
300         mov     %o2,%o0
301         cmp     %o0,%o3
302         .word   0x38680002      !bgu,a  %xcc,.+8
303         mov     %o3,%o0
304
305         retl
306         nop
307 .type   _sparcv9_vis1_instrument,#function
308 .size   _sparcv9_vis1_instrument,.-_sparcv9_vis1_instrument
309
310 .global _sparcv9_vis2_probe
311 .align  8
312 _sparcv9_vis2_probe:
313         retl
314         .word   0x81b00980      !bshuffle       %f0,%f0,%f0
315 .type   _sparcv9_vis2_probe,#function
316 .size   _sparcv9_vis2_probe,.-_sparcv9_vis2_probe
317
318 .global _sparcv9_fmadd_probe
319 .align  8
320 _sparcv9_fmadd_probe:
321         .word   0x81b00d80      !fxor   %f0,%f0,%f0
322         .word   0x85b08d82      !fxor   %f2,%f2,%f2
323         retl
324         .word   0x81b80440      !fmaddd %f0,%f0,%f2,%f0
325 .type   _sparcv9_fmadd_probe,#function
326 .size   _sparcv9_fmadd_probe,.-_sparcv9_fmadd_probe
327
328 .global _sparcv9_rdcfr
329 .align  8
330 _sparcv9_rdcfr:
331         retl
332         .word   0x91468000      !rd     %asr26,%o0
333 .type   _sparcv9_rdcfr,#function
334 .size   _sparcv9_rdcfr,.-_sparcv9_rdcfr
335
336 .global _sparcv9_vis3_probe
337 .align  8
338 _sparcv9_vis3_probe:
339         retl
340         .word   0x81b022a0      !xmulx  %g0,%g0,%g0
341 .type   _sparcv9_vis3_probe,#function
342 .size   _sparcv9_vis3_probe,.-_sparcv9_vis3_probe
343
344 .global _sparcv9_random
345 .align  8
346 _sparcv9_random:
347         retl
348         .word   0x91b002a0      !random %o0
349 .type   _sparcv9_random,#function
350 .size   _sparcv9_random,.-_sparcv9_vis3_probe
351
352 .global _sparcv9_fjaesx_probe
353 .align  8
354 _sparcv9_fjaesx_probe:
355         .word   0x81b09206      !faesencx %f2,%f6,%f0
356         retl
357         nop
358 .size   _sparcv9_fjaesx_probe,.-_sparcv9_fjaesx_probe
359
360 .global OPENSSL_cleanse
361 .align  32
362 OPENSSL_cleanse:
363         cmp     %o1,14
364         nop
365 #ifdef ABI64
366         bgu     %xcc,.Lot
367 #else
368         bgu     .Lot
369 #endif
370         cmp     %o1,0
371         bne     .Little
372         nop
373         retl
374         nop
375
376 .Little:
377         stb     %g0,[%o0]
378         subcc   %o1,1,%o1
379         bnz     .Little
380         add     %o0,1,%o0
381         retl
382         nop
383 .align  32
384 .Lot:
385 #ifndef ABI64
386         subcc   %g0,1,%g1
387         ! see above for explanation
388         .word   0x83408000      !rd     %ccr,%g1
389         cmp     %g1,0x99
390         bne     .v8lot
391         nop
392 #endif
393
394 .v9lot: andcc   %o0,7,%g0
395         bz      .v9aligned
396         nop
397         stb     %g0,[%o0]
398         sub     %o1,1,%o1
399         ba      .v9lot
400         add     %o0,1,%o0
401 .align  16,0x01000000
402 .v9aligned:
403         .word   0xc0720000      !stx    %g0,[%o0]
404         sub     %o1,8,%o1
405         andcc   %o1,-8,%g0
406 #ifdef ABI64
407         .word   0x126ffffd      !bnz    %xcc,.v9aligned
408 #else
409         .word   0x124ffffd      !bnz    %icc,.v9aligned
410 #endif
411         add     %o0,8,%o0
412
413         cmp     %o1,0
414         bne     .Little
415         nop
416         retl
417         nop
418 #ifndef ABI64
419 .v8lot: andcc   %o0,3,%g0
420         bz      .v8aligned
421         nop
422         stb     %g0,[%o0]
423         sub     %o1,1,%o1
424         ba      .v8lot
425         add     %o0,1,%o0
426         nop
427 .v8aligned:
428         st      %g0,[%o0]
429         sub     %o1,4,%o1
430         andcc   %o1,-4,%g0
431         bnz     .v8aligned
432         add     %o0,4,%o0
433
434         cmp     %o1,0
435         bne     .Little
436         nop
437         retl
438         nop
439 #endif
440 .type   OPENSSL_cleanse,#function
441 .size   OPENSSL_cleanse,.-OPENSSL_cleanse
442
443 .global _sparcv9_vis1_instrument_bus
444 .align  8
445 _sparcv9_vis1_instrument_bus:
446         mov     %o1,%o3                                 ! save cnt
447         .word   0x99410000      !rd     %tick,%o4       ! tick
448         mov     %o4,%o5                                 ! lasttick = tick
449         set     0,%g4                                   ! diff
450
451         andn    %o0,63,%g1
452         .word   0xc1985e00      !ldda   [%g1]0xf0,%f0   ! block load
453         .word   0x8143e040      !membar #Sync
454         .word   0xc1b85c00      !stda   %f0,[%g1]0xe0   ! block store and commit
455         .word   0x8143e040      !membar #Sync
456         ld      [%o0],%o4
457         add     %o4,%g4,%g4
458         .word   0xc9e2100c      !cas    [%o0],%o4,%g4
459
460 .Loop:  .word   0x99410000      !rd     %tick,%o4
461         sub     %o4,%o5,%g4                             ! diff=tick-lasttick
462         mov     %o4,%o5                                 ! lasttick=tick
463
464         andn    %o0,63,%g1
465         .word   0xc1985e00      !ldda   [%g1]0xf0,%f0   ! block load
466         .word   0x8143e040      !membar #Sync
467         .word   0xc1b85c00      !stda   %f0,[%g1]0xe0   ! block store and commit
468         .word   0x8143e040      !membar #Sync
469         ld      [%o0],%o4
470         add     %o4,%g4,%g4
471         .word   0xc9e2100c      !cas    [%o0],%o4,%g4
472         subcc   %o1,1,%o1                               ! --$cnt
473         bnz     .Loop
474         add     %o0,4,%o0                               ! ++$out
475
476         retl
477         mov     %o3,%o0
478 .type   _sparcv9_vis1_instrument_bus,#function
479 .size   _sparcv9_vis1_instrument_bus,.-_sparcv9_vis1_instrument_bus
480
481 .global _sparcv9_vis1_instrument_bus2
482 .align  8
483 _sparcv9_vis1_instrument_bus2:
484         mov     %o1,%o3                                 ! save cnt
485         sll     %o1,2,%o1                               ! cnt*=4
486
487         .word   0x99410000      !rd     %tick,%o4       ! tick
488         mov     %o4,%o5                                 ! lasttick = tick
489         set     0,%g4                                   ! diff
490
491         andn    %o0,63,%g1
492         .word   0xc1985e00      !ldda   [%g1]0xf0,%f0   ! block load
493         .word   0x8143e040      !membar #Sync
494         .word   0xc1b85c00      !stda   %f0,[%g1]0xe0   ! block store and commit
495         .word   0x8143e040      !membar #Sync
496         ld      [%o0],%o4
497         add     %o4,%g4,%g4
498         .word   0xc9e2100c      !cas    [%o0],%o4,%g4
499
500         .word   0x99410000      !rd     %tick,%o4       ! tick
501         sub     %o4,%o5,%g4                             ! diff=tick-lasttick
502         mov     %o4,%o5                                 ! lasttick=tick
503         mov     %g4,%g5                                 ! lastdiff=diff
504 .Loop2:
505         andn    %o0,63,%g1
506         .word   0xc1985e00      !ldda   [%g1]0xf0,%f0   ! block load
507         .word   0x8143e040      !membar #Sync
508         .word   0xc1b85c00      !stda   %f0,[%g1]0xe0   ! block store and commit
509         .word   0x8143e040      !membar #Sync
510         ld      [%o0],%o4
511         add     %o4,%g4,%g4
512         .word   0xc9e2100c      !cas    [%o0],%o4,%g4
513
514         subcc   %o2,1,%o2                               ! --max
515         bz      .Ldone2
516         nop
517
518         .word   0x99410000      !rd     %tick,%o4       ! tick
519         sub     %o4,%o5,%g4                             ! diff=tick-lasttick
520         mov     %o4,%o5                                 ! lasttick=tick
521         cmp     %g4,%g5
522         mov     %g4,%g5                                 ! lastdiff=diff
523
524         .word   0x83408000      !rd     %ccr,%g1
525         and     %g1,4,%g1                               ! isolate zero flag
526         xor     %g1,4,%g1                               ! flip zero flag
527
528         subcc   %o1,%g1,%o1                             ! conditional --$cnt
529         bnz     .Loop2
530         add     %o0,%g1,%o0                             ! conditional ++$out
531
532 .Ldone2:
533         srl     %o1,2,%o1
534         retl
535         sub     %o3,%o1,%o0
536 .type   _sparcv9_vis1_instrument_bus2,#function
537 .size   _sparcv9_vis1_instrument_bus2,.-_sparcv9_vis1_instrument_bus2
538
539 .section        ".init",#alloc,#execinstr
540         call    OPENSSL_cpuid_setup
541         nop