x86_64cpuid.pl 8.8 KB
Newer Older
R
Rich Salz 已提交
1 2 3 4 5 6 7 8
#! /usr/bin/env perl
# Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License").  You may not use
# this file except in compliance with the License.  You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html

9

10 11 12
$flavour = shift;
$output  = shift;
if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
13

14
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
15

16
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
17 18 19 20
( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
( $xlate="${dir}perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";

21
open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
22
*STDOUT=*OUT;
23

24 25 26
($arg1,$arg2,$arg3,$arg4)=$win64?("%rcx","%rdx","%r8", "%r9") :	# Win64 order
				 ("%rdi","%rsi","%rdx","%rcx");	# Unix order

27 28
print<<___;
.extern		OPENSSL_cpuid_setup
29
.hidden		OPENSSL_cpuid_setup
30 31
.section	.init
	call	OPENSSL_cpuid_setup
A
Andy Polyakov 已提交
32

33
.hidden	OPENSSL_ia32cap_P
34
.comm	OPENSSL_ia32cap_P,16,4
35

36
.text
37 38

.globl	OPENSSL_atomic_add
39
.type	OPENSSL_atomic_add,\@abi-omnipotent
40 41
.align	16
OPENSSL_atomic_add:
42 43 44 45
	movl	($arg1),%eax
.Lspin:	leaq	($arg2,%rax),%r8
	.byte	0xf0		# lock
	cmpxchgl	%r8d,($arg1)
46
	jne	.Lspin
47
	movl	%r8d,%eax
48
	.byte	0x48,0x98	# cltq/cdqe
49 50 51
	ret
.size	OPENSSL_atomic_add,.-OPENSSL_atomic_add

A
Andy Polyakov 已提交
52 53 54 55 56 57 58 59 60 61
.globl	OPENSSL_rdtsc
.type	OPENSSL_rdtsc,\@abi-omnipotent
.align	16
OPENSSL_rdtsc:
	rdtsc
	shl	\$32,%rdx
	or	%rdx,%rax
	ret
.size	OPENSSL_rdtsc,.-OPENSSL_rdtsc

62
.globl	OPENSSL_ia32_cpuid
63
.type	OPENSSL_ia32_cpuid,\@function,1
64 65
.align	16
OPENSSL_ia32_cpuid:
66
	mov	%rbx,%r8		# save %rbx
67 68

	xor	%eax,%eax
69
	mov	%eax,8(%rdi)		# clear 3rd word
70
	cpuid
71 72
	mov	%eax,%r11d		# max value for standard query level

73 74 75 76 77 78 79 80 81
	xor	%eax,%eax
	cmp	\$0x756e6547,%ebx	# "Genu"
	setne	%al
	mov	%eax,%r9d
	cmp	\$0x49656e69,%edx	# "ineI"
	setne	%al
	or	%eax,%r9d
	cmp	\$0x6c65746e,%ecx	# "ntel"
	setne	%al
82 83 84 85 86 87 88 89 90 91 92 93 94 95
	or	%eax,%r9d		# 0 indicates Intel CPU
	jz	.Lintel

	cmp	\$0x68747541,%ebx	# "Auth"
	setne	%al
	mov	%eax,%r10d
	cmp	\$0x69746E65,%edx	# "enti"
	setne	%al
	or	%eax,%r10d
	cmp	\$0x444D4163,%ecx	# "cAMD"
	setne	%al
	or	%eax,%r10d		# 0 indicates AMD CPU
	jnz	.Lintel

96
	# AMD specific
97 98
	mov	\$0x80000000,%eax
	cpuid
99 100 101 102 103 104 105 106 107
	cmp	\$0x80000001,%eax
	jb	.Lintel
	mov	%eax,%r10d
	mov	\$0x80000001,%eax
	cpuid
	or	%ecx,%r9d
	and	\$0x00000801,%r9d	# isolate AMD XOP bit, 1<<11

	cmp	\$0x80000008,%r10d
108 109 110 111 112 113
	jb	.Lintel

	mov	\$0x80000008,%eax
	cpuid
	movzb	%cl,%r10		# number of cores - 1
	inc	%r10			# number of cores
114

115 116 117
	mov	\$1,%eax
	cpuid
	bt	\$28,%edx		# test hyper-threading bit
118
	jnc	.Lgeneric
119 120
	shr	\$16,%ebx		# number of logical processors
	cmp	%r10b,%bl
121
	ja	.Lgeneric
122
	and	\$0xefffffff,%edx	# ~(1<<28)
123
	jmp	.Lgeneric
124

125
.Lintel:
126 127 128 129 130 131 132 133 134 135 136
	cmp	\$4,%r11d
	mov	\$-1,%r10d
	jb	.Lnocacheinfo

	mov	\$4,%eax
	mov	\$0,%ecx		# query L1D
	cpuid
	mov	%eax,%r10d
	shr	\$14,%r10d
	and	\$0xfff,%r10d		# number of cores -1 per L1D

137 138 139 140 141 142 143 144
	cmp	\$7,%r11d
	jb	.Lnocacheinfo

	mov	\$7,%eax
	xor	%ecx,%ecx
	cpuid
	mov	%ebx,8(%rdi)

145
.Lnocacheinfo:
A
Andy Polyakov 已提交
146
	mov	\$1,%eax
147
	cpuid
148
	and	\$0xbfefffff,%edx	# force reserved bits to 0
A
Andy Polyakov 已提交
149
	cmp	\$0,%r9d
150
	jne	.Lnotintel
151
	or	\$0x40000000,%edx	# set reserved bit#30 on Intel CPUs
152 153
	and	\$15,%ah
	cmp	\$15,%ah		# examine Family ID
154 155
	jne	.Lnotintel
	or	\$0x00100000,%edx	# set reserved bit#20 to engage RC4_CHAR
156
.Lnotintel:
A
Andy Polyakov 已提交
157
	bt	\$28,%edx		# test hyper-threading bit
158
	jnc	.Lgeneric
159 160
	and	\$0xefffffff,%edx	# ~(1<<28)
	cmp	\$0,%r10d
161
	je	.Lgeneric
162 163

	or	\$0x10000000,%edx	# 1<<28
164
	shr	\$16,%ebx
165
	cmp	\$1,%bl			# see if cache is shared
166
	ja	.Lgeneric
A
Andy Polyakov 已提交
167
	and	\$0xefffffff,%edx	# ~(1<<28)
168 169 170
.Lgeneric:
	and	\$0x00000800,%r9d	# isolate AMD XOP flag
	and	\$0xfffff7ff,%ecx
171
	or	%ecx,%r9d		# merge AMD XOP flag
172

173 174
	mov	%edx,%r10d		# %r9d:%r10d is copy of %ecx:%edx
	bt	\$27,%r9d		# check OSXSAVE bit
175 176 177 178 179 180 181 182
	jnc	.Lclear_avx
	xor	%ecx,%ecx		# XCR0
	.byte	0x0f,0x01,0xd0		# xgetbv
	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)
183
	and	%eax,%r9d		# clear AVX, FMA and AMD XOP bits
184
	andl	\$0xffffffdf,8(%rdi)	# cleax AVX2, ~(1<<5)
185
.Ldone:
186 187
	shl	\$32,%r9
	mov	%r10d,%eax
188
	mov	%r8,%rbx		# restore %rbx
189
	or	%r9,%rax
190 191
	ret
.size	OPENSSL_ia32_cpuid,.-OPENSSL_ia32_cpuid
192 193

.globl  OPENSSL_cleanse
194
.type   OPENSSL_cleanse,\@abi-omnipotent
195 196 197
.align  16
OPENSSL_cleanse:
	xor	%rax,%rax
198
	cmp	\$15,$arg2
199
	jae	.Lot
200 201
	cmp	\$0,$arg2
	je	.Lret
202
.Little:
203 204 205
	mov	%al,($arg1)
	sub	\$1,$arg2
	lea	1($arg1),$arg1
206
	jnz	.Little
207 208
.Lret:
	ret
209 210
.align	16
.Lot:
211
	test	\$7,$arg1
212
	jz	.Laligned
213 214 215
	mov	%al,($arg1)
	lea	-1($arg2),$arg2
	lea	1($arg1),$arg1
216 217
	jmp	.Lot
.Laligned:
218 219 220 221
	mov	%rax,($arg1)
	lea	-8($arg2),$arg2
	test	\$-8,$arg2
	lea	8($arg1),$arg1
222
	jnz	.Laligned
223
	cmp	\$0,$arg2
224 225 226
	jne	.Little
	ret
.size	OPENSSL_cleanse,.-OPENSSL_cleanse
A
Andy Polyakov 已提交
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248

.globl  CRYPTO_memcmp
.type   CRYPTO_memcmp,\@abi-omnipotent
.align  16
CRYPTO_memcmp:
	xor	%rax,%rax
	xor	%r10,%r10
	cmp	\$0,$arg3
	je	.Lno_data
.Loop_cmp:
	mov	($arg1),%r10b
	lea	1($arg1),$arg1
	xor	($arg2),%r10b
	lea	1($arg2),$arg2
	or	%r10b,%al
	dec	$arg3
	jnz	.Loop_cmp
	neg	%rax
	shr	\$63,%rax
.Lno_data:
	ret
.size	CRYPTO_memcmp,.-CRYPTO_memcmp
249
___
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304

print<<___ if (!$win64);
.globl	OPENSSL_wipe_cpu
.type	OPENSSL_wipe_cpu,\@abi-omnipotent
.align	16
OPENSSL_wipe_cpu:
	pxor	%xmm0,%xmm0
	pxor	%xmm1,%xmm1
	pxor	%xmm2,%xmm2
	pxor	%xmm3,%xmm3
	pxor	%xmm4,%xmm4
	pxor	%xmm5,%xmm5
	pxor	%xmm6,%xmm6
	pxor	%xmm7,%xmm7
	pxor	%xmm8,%xmm8
	pxor	%xmm9,%xmm9
	pxor	%xmm10,%xmm10
	pxor	%xmm11,%xmm11
	pxor	%xmm12,%xmm12
	pxor	%xmm13,%xmm13
	pxor	%xmm14,%xmm14
	pxor	%xmm15,%xmm15
	xorq	%rcx,%rcx
	xorq	%rdx,%rdx
	xorq	%rsi,%rsi
	xorq	%rdi,%rdi
	xorq	%r8,%r8
	xorq	%r9,%r9
	xorq	%r10,%r10
	xorq	%r11,%r11
	leaq	8(%rsp),%rax
	ret
.size	OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu
___
print<<___ if ($win64);
.globl	OPENSSL_wipe_cpu
.type	OPENSSL_wipe_cpu,\@abi-omnipotent
.align	16
OPENSSL_wipe_cpu:
	pxor	%xmm0,%xmm0
	pxor	%xmm1,%xmm1
	pxor	%xmm2,%xmm2
	pxor	%xmm3,%xmm3
	pxor	%xmm4,%xmm4
	pxor	%xmm5,%xmm5
	xorq	%rcx,%rcx
	xorq	%rdx,%rdx
	xorq	%r8,%r8
	xorq	%r9,%r9
	xorq	%r10,%r10
	xorq	%r11,%r11
	leaq	8(%rsp),%rax
	ret
.size	OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu
___
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
{
my $out="%r10";
my $cnt="%rcx";
my $max="%r11";
my $lasttick="%r8d";
my $lastdiff="%r9d";
my $redzone=win64?8:-8;

print<<___;
.globl	OPENSSL_instrument_bus
.type	OPENSSL_instrument_bus,\@abi-omnipotent
.align	16
OPENSSL_instrument_bus:
	mov	$arg1,$out	# tribute to Win64
	mov	$arg2,$cnt
	mov	$arg2,$max

	rdtsc			# collect 1st tick
	mov	%eax,$lasttick	# lasttick = tick
	mov	\$0,$lastdiff	# lastdiff = 0
	clflush	($out)
326
	.byte	0xf0		# lock
327 328 329 330 331 332 333 334 335
	add	$lastdiff,($out)
	jmp	.Loop
.align	16
.Loop:	rdtsc
	mov	%eax,%edx
	sub	$lasttick,%eax
	mov	%edx,$lasttick
	mov	%eax,$lastdiff
	clflush	($out)
336
	.byte	0xf0		# lock
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
	add	%eax,($out)
	lea	4($out),$out
	sub	\$1,$cnt
	jnz	.Loop

	mov	$max,%rax
	ret
.size	OPENSSL_instrument_bus,.-OPENSSL_instrument_bus

.globl	OPENSSL_instrument_bus2
.type	OPENSSL_instrument_bus2,\@abi-omnipotent
.align	16
OPENSSL_instrument_bus2:
	mov	$arg1,$out	# tribute to Win64
	mov	$arg2,$cnt
	mov	$arg3,$max
	mov	$cnt,$redzone(%rsp)

	rdtsc			# collect 1st tick
	mov	%eax,$lasttick	# lasttick = tick
	mov	\$0,$lastdiff	# lastdiff = 0

	clflush	($out)
360
	.byte	0xf0		# lock
361 362 363 364 365 366 367 368 369
	add	$lastdiff,($out)

	rdtsc			# collect 1st diff
	mov	%eax,%edx
	sub	$lasttick,%eax	# diff
	mov	%edx,$lasttick	# lasttick = tick
	mov	%eax,$lastdiff	# lastdiff = diff
.Loop2:
	clflush	($out)
370
	.byte	0xf0		# lock
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
	add	%eax,($out)	# accumulate diff

	sub	\$1,$max
	jz	.Ldone2

	rdtsc
	mov	%eax,%edx
	sub	$lasttick,%eax	# diff
	mov	%edx,$lasttick	# lasttick = tick
	cmp	$lastdiff,%eax
	mov	%eax,$lastdiff	# lastdiff = diff
	mov	\$0,%edx
	setne	%dl
	sub	%rdx,$cnt	# conditional --$cnt
	lea	($out,%rdx,4),$out	# conditional ++$out
	jnz	.Loop2

.Ldone2:
	mov	$redzone(%rsp),%rax
	sub	$cnt,%rax
	ret
.size	OPENSSL_instrument_bus2,.-OPENSSL_instrument_bus2
___
}
395

396 397
sub gen_random {
my $rdop = shift;
398
print<<___;
399 400
.globl	OPENSSL_ia32_${rdop}
.type	OPENSSL_ia32_${rdop},\@abi-omnipotent
401
.align	16
402
OPENSSL_ia32_${rdop}:
403
	mov	\$8,%ecx
404 405 406 407 408
.Loop_${rdop}:
	${rdop}	%rax
	jc	.Lbreak_${rdop}
	loop	.Loop_${rdop}
.Lbreak_${rdop}:
409 410 411
	cmp	\$0,%rax
	cmove	%rcx,%rax
	ret
412
.size	OPENSSL_ia32_${rdop},.-OPENSSL_ia32_${rdop}
413

414 415
.globl	OPENSSL_ia32_${rdop}_bytes
.type	OPENSSL_ia32_${rdop}_bytes,\@abi-omnipotent
416
.align	16
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
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:
452
	ret
453
.size	OPENSSL_ia32_${rdop}_bytes,.-OPENSSL_ia32_${rdop}_bytes
454
___
455 456 457
}
gen_random("rdrand");
gen_random("rdseed");
458

A
Andy Polyakov 已提交
459
close STDOUT;	# flush