.type OPENSSL_ia32_cpuid,\@function,1
.align 16
OPENSSL_ia32_cpuid:
+.cfi_startproc
mov %rbx,%r8 # save %rbx
+.cfi_register %rbx,%r8
xor %eax,%eax
- mov %eax,8(%rdi) # clear 3rd word
+ mov %eax,8(%rdi) # clear extended feature flags
cpuid
mov %eax,%r11d # max value for standard query level
shr \$14,%r10d
and \$0xfff,%r10d # number of cores -1 per L1D
- cmp \$7,%r11d
- jb .Lnocacheinfo
-
- mov \$7,%eax
- xor %ecx,%ecx
- cpuid
- mov %ebx,8(%rdi)
-
.Lnocacheinfo:
mov \$1,%eax
cpuid
or %ecx,%r9d # merge AMD XOP flag
mov %edx,%r10d # %r9d:%r10d is copy of %ecx:%edx
+
+ cmp \$7,%r11d
+ jb .Lno_extended_info
+ mov \$7,%eax
+ xor %ecx,%ecx
+ cpuid
+ mov %ebx,8(%rdi) # save extended feature flags
+.Lno_extended_info:
+
bt \$27,%r9d # check OSXSAVE bit
jnc .Lclear_avx
xor %ecx,%ecx # XCR0
.byte 0x0f,0x01,0xd0 # xgetbv
+ and \$0xe6,%eax # isolate XMM, YMM and ZMM state support
+ cmp \$0xe6,%eax
+ je .Ldone
+ andl \$0xfffeffff,8(%rdi) # clear AVX512F, ~(1<<16)
+ # note that we don't touch other AVX512
+ # extensions, because they can be used
+ # with YMM (without opmasking though)
and \$6,%eax # isolate XMM and YMM state support
cmp \$6,%eax
je .Ldone
.Lclear_avx:
mov \$0xefffe7ff,%eax # ~(1<<28|1<<12|1<<11)
and %eax,%r9d # clear AVX, FMA and AMD XOP bits
- andl \$0xffffffdf,8(%rdi) # cleax AVX2, ~(1<<5)
+ mov \$0x3fdeffdf,%eax # ~(1<<31|1<<30|1<<21|1<<16|1<<5)
+ and %eax,8(%rdi) # cleax AVX2 and AVX512* bits
.Ldone:
shl \$32,%r9
mov %r10d,%eax
mov %r8,%rbx # restore %rbx
+.cfi_restore %rbx
or %r9,%rax
ret
+.cfi_endproc
.size OPENSSL_ia32_cpuid,.-OPENSSL_ia32_cpuid
.globl OPENSSL_cleanse
___
}
+sub gen_random {
+my $rdop = shift;
print<<___;
-.globl OPENSSL_ia32_rdrand
-.type OPENSSL_ia32_rdrand,\@abi-omnipotent
+.globl OPENSSL_ia32_${rdop}
+.type OPENSSL_ia32_${rdop},\@abi-omnipotent
.align 16
-OPENSSL_ia32_rdrand:
+OPENSSL_ia32_${rdop}:
mov \$8,%ecx
-.Loop_rdrand:
- rdrand %rax
- jc .Lbreak_rdrand
- loop .Loop_rdrand
-.Lbreak_rdrand:
+.Loop_${rdop}:
+ ${rdop} %rax
+ jc .Lbreak_${rdop}
+ loop .Loop_${rdop}
+.Lbreak_${rdop}:
cmp \$0,%rax
cmove %rcx,%rax
ret
-.size OPENSSL_ia32_rdrand,.-OPENSSL_ia32_rdrand
+.size OPENSSL_ia32_${rdop},.-OPENSSL_ia32_${rdop}
-.globl OPENSSL_ia32_rdseed
-.type OPENSSL_ia32_rdseed,\@abi-omnipotent
+.globl OPENSSL_ia32_${rdop}_bytes
+.type OPENSSL_ia32_${rdop}_bytes,\@abi-omnipotent
.align 16
-OPENSSL_ia32_rdseed:
- mov \$8,%ecx
-.Loop_rdseed:
- rdseed %rax
- jc .Lbreak_rdseed
- loop .Loop_rdseed
-.Lbreak_rdseed:
- cmp \$0,%rax
- cmove %rcx,%rax
+OPENSSL_ia32_${rdop}_bytes:
+ xor %rax, %rax # return value
+ cmp \$0,$arg2
+ je .Ldone_${rdop}_bytes
+
+ mov \$8,%r11
+.Loop_${rdop}_bytes:
+ ${rdop} %r10
+ jc .Lbreak_${rdop}_bytes
+ dec %r11
+ jnz .Loop_${rdop}_bytes
+ jmp .Ldone_${rdop}_bytes
+
+.align 16
+.Lbreak_${rdop}_bytes:
+ cmp \$8,$arg2
+ jb .Ltail_${rdop}_bytes
+ mov %r10,($arg1)
+ lea 8($arg1),$arg1
+ add \$8,%rax
+ sub \$8,$arg2
+ jz .Ldone_${rdop}_bytes
+ mov \$8,%r11
+ jmp .Loop_${rdop}_bytes
+
+.align 16
+.Ltail_${rdop}_bytes:
+ mov %r10b,($arg1)
+ lea 1($arg1),$arg1
+ inc %rax
+ shr \$8,%r8
+ dec $arg2
+ jnz .Ltail_${rdop}_bytes
+
+.Ldone_${rdop}_bytes:
ret
-.size OPENSSL_ia32_rdseed,.-OPENSSL_ia32_rdseed
+.size OPENSSL_ia32_${rdop}_bytes,.-OPENSSL_ia32_${rdop}_bytes
___
+}
+gen_random("rdrand");
+gen_random("rdseed");
close STDOUT; # flush