diff options
author | Andy Polyakov <appro@openssl.org> | 2004-07-26 20:18:55 +0000 |
---|---|---|
committer | Andy Polyakov <appro@openssl.org> | 2004-07-26 20:18:55 +0000 |
commit | 14e21f863a3e3278bb8660ea9844e92e52e1f2f7 (patch) | |
tree | 5bcc6cfa9002eb94d2788bc3fa8c72eb5b9f188e /crypto | |
parent | f10725a6e19f0d72df5789e38601918539e64082 (diff) |
Add framework for yet another assembler module dubbed "cpuid." Idea
is to have a placeholder to small routines, which can be written only
in assembler. In IA-32 case this includes processor capability
identification and access to Time-Stamp Counter. As discussed earlier
OPENSSL_ia32cap is introduced to control recently added SSE2 code
pathes (see docs/crypto/OPENSSL_ia32cap.pod). For the moment the
code is operational on ELF platforms only. I haven't checked it yet,
but I have all reasons to believe that Windows build should fail to
link too. I'll be looking into it shortly...
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/Makefile.ssl | 12 | ||||
-rw-r--r-- | crypto/amd64cpuid.pl | 30 | ||||
-rw-r--r-- | crypto/cryptlib.c | 33 | ||||
-rw-r--r-- | crypto/evp/c_all.c | 7 | ||||
-rw-r--r-- | crypto/ia64cpuid.S | 9 | ||||
-rw-r--r-- | crypto/perlasm/x86ms.pl | 4 | ||||
-rw-r--r-- | crypto/perlasm/x86nasm.pl | 4 | ||||
-rw-r--r-- | crypto/perlasm/x86unix.pl | 26 | ||||
-rw-r--r-- | crypto/x86cpuid.pl | 43 |
9 files changed, 163 insertions, 5 deletions
diff --git a/crypto/Makefile.ssl b/crypto/Makefile.ssl index 40b3b7c113..8d5939528e 100644 --- a/crypto/Makefile.ssl +++ b/crypto/Makefile.ssl @@ -22,6 +22,7 @@ PEX_LIBS= EX_LIBS= CFLAGS= $(INCLUDE) $(CFLAG) +ASFLAGS= $(INCLUDE) $(ASFLAG) LIBS= @@ -39,7 +40,7 @@ GENERAL=Makefile README crypto-lib.com install.com LIB= $(TOP)/libcrypto.a SHARED_LIB= libcrypto$(SHLIB_EXT) LIBSRC= cryptlib.c mem.c mem_clr.c mem_dbg.c cversion.c ex_data.c tmdiff.c cpt_err.c ebcdic.c uid.c o_time.c o_str.c o_dir.c -LIBOBJ= cryptlib.o mem.o mem_clr.o mem_dbg.o cversion.o ex_data.o tmdiff.o cpt_err.o ebcdic.o uid.o o_time.o o_str.o o_dir.o +LIBOBJ= cryptlib.o mem.o mem_clr.o mem_dbg.o cversion.o ex_data.o tmdiff.o cpt_err.o ebcdic.o uid.o o_time.o o_str.o o_dir.o $(CPUID_OBJ) SRC= $(LIBSRC) @@ -62,6 +63,13 @@ buildinf.h: ../Makefile.ssl echo " #define DATE \"`LC_ALL=C LC_TIME=C date`\""; \ echo '#endif' ) >buildinf.h +x86cpuid-elf.s: x86cpuid.pl perlasm/x86asm.pl + $(PERL) x86cpuid.pl elf $(CFLAGS) $(PROCESSOR) > $@ +amd64cpuid.s: amd64cpuid.pl + $(PERL) amd64cpuid.pl $@ +ia64cpuid.s: ia64cpuid.S + $(CC) $(CFLAGS) -E ia64cpuid.S > $@ + testapps: if echo ${SDIRS} | fgrep ' des '; \ then cd des && $(MAKE) CC='$(CC)' INCLUDES='${INCLUDES}' CFLAG='${CFLAG}' INSTALLTOP='${INSTALLTOP}' PEX_LIBS='${PEX_LIBS}' EX_LIBS='${EX_LIBS}' BN_ASM='${BN_ASM}' DES_ENC='${DES_ENC}' SHA1_ASM_OBJ='${SHA1_ASM_OBJ}' MD5_ASM_OBJ='${MD5_ASM_OBJ}' RMD160_ASM_OBJ='${RMD160_ASM_OBJ}' BF_ENC='${BF_ENC}' CAST_ENC='${CAST_ENC}' RC4_ENC='${RC4_ENC}' RC5_ENC='${RC5_ENC}' AR='${AR}' PROCESSOR='${PROCESSOR}' PERL='${PERL}' RANLIB='${RANLIB}' des; fi @@ -148,7 +156,7 @@ depend: done; clean: - rm -f buildinf.h *.o */*.o *.obj lib tags core .pure .nfs* *.old *.bak fluff + rm -f buildinf.h *.s *.o */*.o *.obj lib tags core .pure .nfs* *.old *.bak fluff @for i in $(SDIRS) ;\ do \ (cd $$i && echo "making clean in crypto/$$i..." && \ diff --git a/crypto/amd64cpuid.pl b/crypto/amd64cpuid.pl new file mode 100644 index 0000000000..baf801d062 --- /dev/null +++ b/crypto/amd64cpuid.pl @@ -0,0 +1,30 @@ +#!/usr/bin/env perl + +$output=shift; +$win64a=1 if ($output =~ /win64a\.[s|asm]/); +open STDOUT,">$output" || die "can't open $output: $!"; + +print<<___ if(defined($win64a)); +TEXT SEGMENT +PUBLIC OPENSSL_rdtsc +ALIGN 16 +OPENSSL_rdtsc PROC NEAR + rdtsc + shl rdx,32 + or rax,rdx + ret +OPENSSL_rdtsc ENDP +TEXT ENDS +END +___ +print<<___ if(!defined($win64a)); +.text +.globl OPENSSL_rdtsc +.align 16 +OPENSSL_rdtsc: + rdtsc + shl \$32,%rdx + or %rdx,%rax + ret +.size OPENSSL_rdtsc,.-OPENSSL_rdtsc +___ diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c index b180aebce9..79c54b920e 100644 --- a/crypto/cryptlib.c +++ b/crypto/cryptlib.c @@ -539,6 +539,38 @@ const char *CRYPTO_get_lock_name(int type) return(sk_value(app_locks,type-CRYPTO_NUM_LOCKS)); } +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__) + +unsigned long OPENSSL_ia32cap=0; +unsigned long *OPENSSL_ia32cap_loc() { return &OPENSSL_ia32cap; } + +#if !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY) +#define OPENSSL_CPUID_SETUP +void OPENSSL_cpuid_setup() +{ static int trigger=0; + unsigned long OPENSSL_ia32_cpuid(); + char *env; + + if (trigger) return; + + trigger=1; + if ((env=getenv("OPENSSL_ia32cap"))) + OPENSSL_ia32cap = strtoul(env,NULL,0)|(1<<10); + else + OPENSSL_ia32cap = OPENSSL_ia32_cpuid()|(1<<10); + /* + * |(1<<10) sets a reserved bit to signal that variable + * was initialized already... This is to avoid interference + * with cpuid snippets in ELF .init segment. + */ +} +#endif + +#endif +#if !defined(OPENSSL_CPUID_SETUP) +void OPENSSL_cpuid_setup() {} +#endif + #ifdef _DLL #ifdef OPENSSL_SYS_WIN32 @@ -551,6 +583,7 @@ BOOL WINAPI DLLEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, switch(fdwReason) { case DLL_PROCESS_ATTACH: + OPENSSL_cpuid_setup(); break; case DLL_THREAD_ATTACH: break; diff --git a/crypto/evp/c_all.c b/crypto/evp/c_all.c index fa60a73ead..c6a3315e64 100644 --- a/crypto/evp/c_all.c +++ b/crypto/evp/c_all.c @@ -74,6 +74,13 @@ void OpenSSL_add_all_algorithms(void) void OPENSSL_add_all_algorithms_noconf(void) { + /* + * For the moment OPENSSL_cpuid_setup does something + * only on IA-32, but we reserve the option for all + * platforms... + */ + void OPENSSL_cpuid_setup(); + OPENSSL_cpuid_setup(); OpenSSL_add_all_ciphers(); OpenSSL_add_all_digests(); #ifndef OPENSSL_NO_ENGINE diff --git a/crypto/ia64cpuid.S b/crypto/ia64cpuid.S new file mode 100644 index 0000000000..a800527a58 --- /dev/null +++ b/crypto/ia64cpuid.S @@ -0,0 +1,9 @@ +// Works on all IA-64 platforms: Linux, HP-UX, Win64i... +// On Win64i compile with ias.exe. +.text +.global OPENSSL_rdtsc# +.proc OPENSSL_rdtsc# +OPENSSL_rdtsc: + mov r8=ar.itc + br.ret b0 +.endp OPENSSL_rdtsc# diff --git a/crypto/perlasm/x86ms.pl b/crypto/perlasm/x86ms.pl index dd62348b6a..f6e225c644 100644 --- a/crypto/perlasm/x86ms.pl +++ b/crypto/perlasm/x86ms.pl @@ -160,6 +160,8 @@ sub main'jne { &out1("jne",@_); } sub main'jno { &out1("jno",@_); } sub main'push { &out1("push",@_); $stack+=4; } sub main'pop { &out1("pop",@_); $stack-=4; } +sub main'pushf { &out0("pushf"); $stack+=4; } +sub main'popf { &out0("popf"); $stack-=4; } sub main'bswap { &out1("bswap",@_); &using486(); } sub main'not { &out1("not",@_); } sub main'call { &out1("call",($_[0]=~/^\$L/?'':'_').$_[0]); } @@ -168,6 +170,8 @@ sub main'nop { &out0("nop"); } sub main'test { &out2("test",@_); } sub main'bt { &out2("bt",@_); } sub main'leave { &out0("leave"); } +sub main'cpuid { &out0("cpuid"); } +sub main'rdtsc { &out0("rdtsc"); } # SSE2 sub main'emms { &out0("emms"); } diff --git a/crypto/perlasm/x86nasm.pl b/crypto/perlasm/x86nasm.pl index da2a1d471b..4cb09ddea6 100644 --- a/crypto/perlasm/x86nasm.pl +++ b/crypto/perlasm/x86nasm.pl @@ -169,6 +169,8 @@ sub main'jno { &out1("jno NEAR",@_); } sub main'push { &out1("push",@_); $stack+=4; } sub main'pop { &out1("pop",@_); $stack-=4; } +sub main'pushf { &out0("pushf"); $stack+=4; } +sub main'popf { &out0("popf"); $stack-=4; } sub main'bswap { &out1("bswap",@_); &using486(); } sub main'not { &out1("not",@_); } sub main'call { &out1("call",($_[0]=~/^\$L/?'':'_').$_[0]); } @@ -177,6 +179,8 @@ sub main'nop { &out0("nop"); } sub main'test { &out2("test",@_); } sub main'bt { &out2("bt",@_); } sub main'leave { &out0("leave"); } +sub main'cpuid { &out0("cpuid"); } +sub main'rdtsc { &out0("rdtsc"); } # SSE2 sub main'emms { &out0("emms"); } diff --git a/crypto/perlasm/x86unix.pl b/crypto/perlasm/x86unix.pl index 99e2865aa0..12ff816ebf 100644 --- a/crypto/perlasm/x86unix.pl +++ b/crypto/perlasm/x86unix.pl @@ -199,6 +199,8 @@ sub main'nop { &out0("nop"); } sub main'test { &out2("testl",@_); } sub main'bt { &out2("btl",@_); } sub main'leave { &out0("leave"); } +sub main'cpuid { &out0(".word\t0xa20f"); } +sub main'rdtsc { &out0(".word\t0x310f"); } # SSE2 sub main'emms { &out0("emms"); } @@ -519,11 +521,14 @@ sub main'file_end # SSE/MMX module with this snippet... Well, it's 72 # bytes long and for the moment we have two modules. # Let's argue when we have 7 modules or so... + # + # $1<<10 sets a reserved bit to signal that variable + # was initialized already... &main'picmeup("edx","OPENSSL_ia32cap"); $tmp=<<___; cmpl \$0,(%edx) jne 1f - movl \$1,(%edx) + movl \$1<<10,(%edx) pushf popl %eax movl %eax,%ecx @@ -539,12 +544,13 @@ sub main'file_end pushl %ebx movl %edx,%edi movl \$1,%eax - cpuid - orl \$1,%edx + .word 0xa20f + orl \$1<<10,%edx movl %edx,0(%edi) movl %ecx,4(%edi) popl %ebx popl %edi + .align 4 1: ___ push (@out,$tmp); @@ -675,3 +681,17 @@ ___ } sub main'blindpop { &out1("popl",@_); } + +sub main'initseg + { + local($f)=@_; + if ($main'elf) + { + local($tmp)=<<___; +.pushsection .init + call $under$f +.popsection +___ + push(@out,$tmp); + } + } diff --git a/crypto/x86cpuid.pl b/crypto/x86cpuid.pl new file mode 100644 index 0000000000..85fbef7417 --- /dev/null +++ b/crypto/x86cpuid.pl @@ -0,0 +1,43 @@ +#!/usr/bin/env perl + +push(@INC,"perlasm"); +require "x86asm.pl"; + +&asm_init($ARGV[0],"x86cpuid"); + +&function_begin("OPENSSL_ia32_cpuid"); + &xor ("edx","edx"); + &pushf (); + &pop ("eax"); + &mov ("ecx","eax"); + &xor ("eax",1<<21); + &push ("eax"); + &popf (); + &pushf (); + &pop ("eax"); + &xor ("ecx","eax"); + &bt ("ecx",21); + &jnc (&label("nocpuid")); + &mov ("eax",1); + &cpuid (); +&set_label("nocpuid"); + &mov ("eax","edx"); + &mov ("edx","ecx"); +&function_end("OPENSSL_ia32_cpuid"); + +&external_label("OPENSSL_ia32cap"); + +&function_begin_B("OPENSSL_rdtsc"); + &xor ("eax","eax"); + &xor ("edx","edx"); + &picmeup("ecx","OPENSSL_ia32cap"); + &bt (&DWP(0,"ecx"),4); + &jnc (&label("notsc")); + &rdtsc (); +&set_label("notsc"); + &ret (); +&function_end_B("OPENSSL_rdtsc"); + +&initseg("OPENSSL_cpuid_setup") if ($main'elf); + +&asm_finish(); |