}
};
+my $rdseed = sub {
+ if (shift =~ /%[er](\w+)/) {
+ my @opcode=();
+ my $dst=$1;
+ if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; }
+ rex(\@opcode,0,$1,8);
+ push @opcode,0x0f,0xc7,0xf8|($dst&7);
+ @opcode;
+ } else {
+ ();
+ }
+};
+
sub rxb {
local *opcode=shift;
my ($dst,$src1,$src2,$rxb)=@_;
{ &::generic("rdrand",@_); }
}
+sub ::rdseed
+{ my ($dst)=@_;
+ if ($dst =~ /(e[a-dsd][ixp])/)
+ { &::data_byte(0x0f,0xc7,0xf8|$regrm{$dst}); }
+ else
+ { &::generic("rdrand",@_); }
+}
+
sub rxb {
local *opcode=shift;
my ($dst,$src1,$src2,$rxb)=@_;
cmove %rcx,%rax
ret
.size OPENSSL_ia32_rdrand,.-OPENSSL_ia32_rdrand
+
+.globl OPENSSL_ia32_rdseed
+.type OPENSSL_ia32_rdseed,\@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
+ ret
+.size OPENSSL_ia32_rdseed,.-OPENSSL_ia32_rdseed
___
close STDOUT; # flush
&ret ();
&function_end_B("OPENSSL_ia32_rdrand");
+&function_begin_B("OPENSSL_ia32_rdseed");
+ &mov ("ecx",8);
+&set_label("loop");
+ &rdseed ("eax");
+ &jc (&label("break"));
+ &loop (&label("loop"));
+&set_label("break");
+ &cmp ("eax",0);
+ &cmove ("eax","ecx");
+ &ret ();
+&function_end_B("OPENSSL_ia32_rdseed");
+
&initseg("OPENSSL_cpuid_setup");
&hidden("OPENSSL_cpuid_setup");