diff options
Diffstat (limited to 'openssl/crypto/sparccpuid.S')
-rw-r--r-- | openssl/crypto/sparccpuid.S | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/openssl/crypto/sparccpuid.S b/openssl/crypto/sparccpuid.S new file mode 100644 index 000000000..c17350fc8 --- /dev/null +++ b/openssl/crypto/sparccpuid.S @@ -0,0 +1,239 @@ +#if defined(__SUNPRO_C) && defined(__sparcv9) +# define ABI64 /* They've said -xarch=v9 at command line */ +#elif defined(__GNUC__) && defined(__arch64__) +# define ABI64 /* They've said -m64 at command line */ +#endif + +#ifdef ABI64 + .register %g2,#scratch + .register %g3,#scratch +# define FRAME -192 +# define BIAS 2047 +#else +# define FRAME -96 +# define BIAS 0 +#endif + +.text +.align 32 +.global OPENSSL_wipe_cpu +.type OPENSSL_wipe_cpu,#function +! Keep in mind that this does not excuse us from wiping the stack! +! This routine wipes registers, but not the backing store [which +! resides on the stack, toward lower addresses]. To facilitate for +! stack wiping I return pointer to the top of stack of the *caller*. +OPENSSL_wipe_cpu: + save %sp,FRAME,%sp + nop +#ifdef __sun +#include <sys/trap.h> + ta ST_CLEAN_WINDOWS +#else + call .walk.reg.wins +#endif + nop + call .PIC.zero.up + mov .zero-(.-4),%o0 + ldd [%o0],%f0 + + subcc %g0,1,%o0 + ! Following is V9 "rd %ccr,%o0" instruction. However! V8 + ! specification says that it ("rd %asr2,%o0" in V8 terms) does + ! not cause illegal_instruction trap. It therefore can be used + ! to determine if the CPU the code is executing on is V8- or + ! V9-compliant, as V9 returns a distinct value of 0x99, + ! "negative" and "borrow" bits set in both %icc and %xcc. + .word 0x91408000 !rd %ccr,%o0 + cmp %o0,0x99 + bne .v8 + nop + ! Even though we do not use %fp register bank, + ! we wipe it as memcpy might have used it... + .word 0xbfa00040 !fmovd %f0,%f62 + .word 0xbba00040 !... + .word 0xb7a00040 + .word 0xb3a00040 + .word 0xafa00040 + .word 0xaba00040 + .word 0xa7a00040 + .word 0xa3a00040 + .word 0x9fa00040 + .word 0x9ba00040 + .word 0x97a00040 + .word 0x93a00040 + .word 0x8fa00040 + .word 0x8ba00040 + .word 0x87a00040 + .word 0x83a00040 !fmovd %f0,%f32 +.v8: fmovs %f1,%f31 + clr %o0 + fmovs %f0,%f30 + clr %o1 + fmovs %f1,%f29 + clr %o2 + fmovs %f0,%f28 + clr %o3 + fmovs %f1,%f27 + clr %o4 + fmovs %f0,%f26 + clr %o5 + fmovs %f1,%f25 + clr %o7 + fmovs %f0,%f24 + clr %l0 + fmovs %f1,%f23 + clr %l1 + fmovs %f0,%f22 + clr %l2 + fmovs %f1,%f21 + clr %l3 + fmovs %f0,%f20 + clr %l4 + fmovs %f1,%f19 + clr %l5 + fmovs %f0,%f18 + clr %l6 + fmovs %f1,%f17 + clr %l7 + fmovs %f0,%f16 + clr %i0 + fmovs %f1,%f15 + clr %i1 + fmovs %f0,%f14 + clr %i2 + fmovs %f1,%f13 + clr %i3 + fmovs %f0,%f12 + clr %i4 + fmovs %f1,%f11 + clr %i5 + fmovs %f0,%f10 + clr %g1 + fmovs %f1,%f9 + clr %g2 + fmovs %f0,%f8 + clr %g3 + fmovs %f1,%f7 + clr %g4 + fmovs %f0,%f6 + clr %g5 + fmovs %f1,%f5 + fmovs %f0,%f4 + fmovs %f1,%f3 + fmovs %f0,%f2 + + add %fp,BIAS,%i0 ! return pointer to callerīs top of stack + + ret + restore + +.zero: .long 0x0,0x0 +.PIC.zero.up: + retl + add %o0,%o7,%o0 +#ifdef DEBUG +.global walk_reg_wins +.type walk_reg_wins,#function +walk_reg_wins: +#endif +.walk.reg.wins: + save %sp,FRAME,%sp + cmp %i7,%o7 + be 2f + clr %o0 + cmp %o7,0 ! compiler never cleans %o7... + be 1f ! could have been a leaf function... + clr %o1 + call .walk.reg.wins + nop +1: clr %o2 + clr %o3 + clr %o4 + clr %o5 + clr %o7 + clr %l0 + clr %l1 + clr %l2 + clr %l3 + clr %l4 + clr %l5 + clr %l6 + clr %l7 + add %o0,1,%i0 ! used for debugging +2: ret + restore +.size OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu + +.global OPENSSL_atomic_add +.type OPENSSL_atomic_add,#function +OPENSSL_atomic_add: +#ifndef ABI64 + subcc %g0,1,%o2 + .word 0x95408000 !rd %ccr,%o2, see comment above + cmp %o2,0x99 + be .v9 + nop + save %sp,FRAME,%sp + ba .enter + nop +#ifdef __sun +! Note that you don't have to link with libthread to call thr_yield, +! as libc provides a stub, which is overloaded the moment you link +! with *either* libpthread or libthread... +#define YIELD_CPU thr_yield +#else +! applies at least to Linux and FreeBSD... Feedback expected... +#define YIELD_CPU sched_yield +#endif +.spin: call YIELD_CPU + nop +.enter: ld [%i0],%i2 + cmp %i2,-4096 + be .spin + mov -1,%i2 + swap [%i0],%i2 + cmp %i2,-1 + be .spin + add %i2,%i1,%i2 + stbar + st %i2,[%i0] + sra %i2,%g0,%i0 + ret + restore +.v9: +#endif + ld [%o0],%o2 +1: add %o1,%o2,%o3 + .word 0xd7e2100a !cas [%o0],%o2,%o3, compare [%o0] with %o2 and swap %o3 + cmp %o2,%o3 + bne 1b + mov %o3,%o2 ! cas is always fetching to dest. register + add %o1,%o2,%o0 ! OpenSSL expects the new value + retl + sra %o0,%g0,%o0 ! we return signed int, remember? +.size OPENSSL_atomic_add,.-OPENSSL_atomic_add + +.global OPENSSL_rdtsc + subcc %g0,1,%o0 + .word 0x91408000 !rd %ccr,%o0 + cmp %o0,0x99 + bne .notsc + xor %o0,%o0,%o0 + save %sp,FRAME-16,%sp + mov 513,%o0 !SI_PLATFORM + add %sp,BIAS+16,%o1 + call sysinfo + mov 256,%o2 + + add %sp,BIAS-16,%o1 + ld [%o1],%l0 + ld [%o1+4],%l1 + ld [%o1+8],%l2 + mov %lo('SUNW'),%l3 + ret + restore +.notsc: + retl + nop +.type OPENSSL_rdtsc,#function +.size OPENSSL_rdtsc,.-OPENSSL_atomic_add |