summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorAndy Polyakov <appro@openssl.org>2004-07-26 20:18:55 +0000
committerAndy Polyakov <appro@openssl.org>2004-07-26 20:18:55 +0000
commit14e21f863a3e3278bb8660ea9844e92e52e1f2f7 (patch)
tree5bcc6cfa9002eb94d2788bc3fa8c72eb5b9f188e /crypto
parentf10725a6e19f0d72df5789e38601918539e64082 (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.ssl12
-rw-r--r--crypto/amd64cpuid.pl30
-rw-r--r--crypto/cryptlib.c33
-rw-r--r--crypto/evp/c_all.c7
-rw-r--r--crypto/ia64cpuid.S9
-rw-r--r--crypto/perlasm/x86ms.pl4
-rw-r--r--crypto/perlasm/x86nasm.pl4
-rw-r--r--crypto/perlasm/x86unix.pl26
-rw-r--r--crypto/x86cpuid.pl43
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();