sub \$1,%rax()

in src/crypto/fipsmodule/aes/asm/vpaes-x86_64.pl [138:869]


	sub	\$1,%rax	# nr--
	pxor	%xmm3,	%xmm0	# 0 = 2A+3B+C+D

.Lenc_entry:
	# top of round
	movdqa  %xmm9, 	%xmm1	# 1 : i
	movdqa	%xmm11, %xmm5	# 2 : a/k
	pandn	%xmm0, 	%xmm1	# 1 = i<<4
	psrld	\$4,   	%xmm1   # 1 = i
	pand	%xmm9, 	%xmm0   # 0 = k
	pshufb  %xmm0,  %xmm5	# 2 = a/k
	movdqa	%xmm10,	%xmm3  	# 3 : 1/i
	pxor	%xmm1,	%xmm0	# 0 = j
	pshufb  %xmm1, 	%xmm3  	# 3 = 1/i
	movdqa	%xmm10,	%xmm4  	# 4 : 1/j
	pxor	%xmm5, 	%xmm3  	# 3 = iak = 1/i + a/k
	pshufb	%xmm0, 	%xmm4  	# 4 = 1/j
	movdqa	%xmm10,	%xmm2  	# 2 : 1/iak
	pxor	%xmm5, 	%xmm4  	# 4 = jak = 1/j + a/k
	pshufb  %xmm3,	%xmm2  	# 2 = 1/iak
	movdqa	%xmm10, %xmm3   # 3 : 1/jak
	pxor	%xmm0, 	%xmm2  	# 2 = io
	pshufb  %xmm4,  %xmm3   # 3 = 1/jak
	movdqu	(%r9),	%xmm5
	pxor	%xmm1,  %xmm3   # 3 = jo
	jnz	.Lenc_loop

	# middle of last round
	movdqa	-0x60(%r10), %xmm4	# 3 : sbou	.Lk_sbo
	movdqa	-0x50(%r10), %xmm0	# 0 : sbot	.Lk_sbo+16
	pshufb  %xmm2,  %xmm4	# 4 = sbou
	pxor	%xmm5,  %xmm4	# 4 = sb1u + k
	pshufb  %xmm3,	%xmm0	# 0 = sb1t
	movdqa	0x40(%r11,%r10), %xmm1		# .Lk_sr[]
	pxor	%xmm4,	%xmm0	# 0 = A
	pshufb	%xmm1,	%xmm0
	ret
.cfi_endproc
.size	_vpaes_encrypt_core,.-_vpaes_encrypt_core

##
##  _aes_encrypt_core_2x
##
##  AES-encrypt %xmm0 and %xmm6 in parallel.
##
##  Inputs:
##     %xmm0 and %xmm6 = input
##     %xmm9 and %xmm10 as in _vpaes_preheat
##    (%rdx) = scheduled keys
##
##  Output in %xmm0 and %xmm6
##  Clobbers  %xmm1-%xmm5, %xmm7, %xmm8, %xmm11-%xmm13, %r9, %r10, %r11, %rax
##  Preserves %xmm14 and %xmm15
##
##  This function stitches two parallel instances of _vpaes_encrypt_core. x86_64
##  provides 16 XMM registers. _vpaes_encrypt_core computes over six registers
##  (%xmm0-%xmm5) and additionally uses seven registers with preloaded constants
##  from _vpaes_preheat (%xmm9-%xmm15). This does not quite fit two instances,
##  so we spill some of %xmm9 through %xmm15 back to memory. We keep %xmm9 and
##  %xmm10 in registers as these values are used several times in a row. The
##  remainder are read once per round and are spilled to memory. This leaves two
##  registers preserved for the caller.
##
##  Thus, of the two _vpaes_encrypt_core instances, the first uses (%xmm0-%xmm5)
##  as before. The second uses %xmm6-%xmm8,%xmm11-%xmm13. (Add 6 to %xmm2 and
##  below. Add 8 to %xmm3 and up.) Instructions in the second instance are
##  indented by one space.
##
##
.type	_vpaes_encrypt_core_2x,\@abi-omnipotent
.align 16
_vpaes_encrypt_core_2x:
.cfi_startproc
	mov	%rdx,	%r9
	mov	\$16,	%r11
	mov	240(%rdx),%eax
	movdqa	%xmm9,	%xmm1
	 movdqa	%xmm9,	%xmm7
	movdqa	.Lk_ipt(%rip), %xmm2	# iptlo
	 movdqa	%xmm2,	%xmm8
	pandn	%xmm0,	%xmm1
	 pandn	%xmm6,	%xmm7
	movdqu	(%r9),	%xmm5		# round0 key
	 # Also use %xmm5 in the second instance.
	psrld	\$4,	%xmm1
	 psrld	\$4,	%xmm7
	pand	%xmm9,	%xmm0
	 pand	%xmm9,	%xmm6
	pshufb	%xmm0,	%xmm2
	 pshufb	%xmm6,	%xmm8
	movdqa	.Lk_ipt+16(%rip), %xmm0	# ipthi
	 movdqa	%xmm0,	%xmm6
	pshufb	%xmm1,	%xmm0
	 pshufb	%xmm7,	%xmm6
	pxor	%xmm5,	%xmm2
	 pxor	%xmm5,	%xmm8
	add	\$16,	%r9
	pxor	%xmm2,	%xmm0
	 pxor	%xmm8,	%xmm6
	lea	.Lk_mc_backward(%rip),%r10
	jmp	.Lenc2x_entry

.align 16
.Lenc2x_loop:
	# middle of middle round
	movdqa  .Lk_sb1(%rip),	%xmm4		# 4 : sb1u
	movdqa  .Lk_sb1+16(%rip),%xmm0		# 0 : sb1t
	 movdqa	%xmm4,	%xmm12
	 movdqa	%xmm0,	%xmm6
	pshufb  %xmm2,	%xmm4			# 4 = sb1u
	 pshufb	%xmm8,	%xmm12
	pshufb  %xmm3,	%xmm0			# 0 = sb1t
	 pshufb	%xmm11,	%xmm6
	pxor	%xmm5,	%xmm4			# 4 = sb1u + k
	 pxor	%xmm5,	%xmm12
	movdqa  .Lk_sb2(%rip),	%xmm5		# 4 : sb2u
	 movdqa	%xmm5,	%xmm13
	pxor	%xmm4,	%xmm0			# 0 = A
	 pxor	%xmm12,	%xmm6
	movdqa	-0x40(%r11,%r10), %xmm1		# .Lk_mc_forward[]
	 # Also use %xmm1 in the second instance.
	pshufb	%xmm2,	%xmm5			# 4 = sb2u
	 pshufb	%xmm8,	%xmm13
	movdqa	(%r11,%r10), %xmm4		# .Lk_mc_backward[]
	 # Also use %xmm4 in the second instance.
	movdqa	.Lk_sb2+16(%rip), %xmm2		# 2 : sb2t
	 movdqa	%xmm2,	%xmm8
	pshufb	%xmm3,  %xmm2			# 2 = sb2t
	 pshufb	%xmm11,	%xmm8
	movdqa	%xmm0,  %xmm3			# 3 = A
	 movdqa	%xmm6,	%xmm11
	pxor	%xmm5,	%xmm2			# 2 = 2A
	 pxor	%xmm13,	%xmm8
	pshufb  %xmm1,  %xmm0			# 0 = B
	 pshufb	%xmm1,	%xmm6
	add	\$16,	%r9			# next key
	pxor	%xmm2,  %xmm0			# 0 = 2A+B
	 pxor	%xmm8,	%xmm6
	pshufb	%xmm4,	%xmm3			# 3 = D
	 pshufb	%xmm4,	%xmm11
	add	\$16,	%r11			# next mc
	pxor	%xmm0,	%xmm3			# 3 = 2A+B+D
	 pxor	%xmm6,	%xmm11
	pshufb  %xmm1,	%xmm0			# 0 = 2B+C
	 pshufb	%xmm1,	%xmm6
	and	\$0x30,	%r11			# ... mod 4
	sub	\$1,%rax			# nr--
	pxor	%xmm3,	%xmm0			# 0 = 2A+3B+C+D
	 pxor	%xmm11,	%xmm6

.Lenc2x_entry:
	# top of round
	movdqa  %xmm9, 	%xmm1	# 1 : i
	 movdqa	%xmm9,	%xmm7
	movdqa	.Lk_inv+16(%rip), %xmm5	# 2 : a/k
	 movdqa	%xmm5,	%xmm13
	pandn	%xmm0, 	%xmm1	# 1 = i<<4
	 pandn	%xmm6,	%xmm7
	psrld	\$4,   	%xmm1   # 1 = i
	 psrld	\$4,	%xmm7
	pand	%xmm9, 	%xmm0   # 0 = k
	 pand	%xmm9,	%xmm6
	pshufb  %xmm0,  %xmm5	# 2 = a/k
	 pshufb	%xmm6,	%xmm13
	movdqa	%xmm10,	%xmm3  	# 3 : 1/i
	 movdqa	%xmm10,	%xmm11
	pxor	%xmm1,	%xmm0	# 0 = j
	 pxor	%xmm7,	%xmm6
	pshufb  %xmm1, 	%xmm3  	# 3 = 1/i
	 pshufb	%xmm7,	%xmm11
	movdqa	%xmm10,	%xmm4  	# 4 : 1/j
	 movdqa	%xmm10,	%xmm12
	pxor	%xmm5, 	%xmm3  	# 3 = iak = 1/i + a/k
	 pxor	%xmm13,	%xmm11
	pshufb	%xmm0, 	%xmm4  	# 4 = 1/j
	 pshufb	%xmm6,	%xmm12
	movdqa	%xmm10,	%xmm2  	# 2 : 1/iak
	 movdqa	%xmm10,	%xmm8
	pxor	%xmm5, 	%xmm4  	# 4 = jak = 1/j + a/k
	 pxor	%xmm13,	%xmm12
	pshufb  %xmm3,	%xmm2  	# 2 = 1/iak
	 pshufb	%xmm11,	%xmm8
	movdqa	%xmm10, %xmm3   # 3 : 1/jak
	 movdqa	%xmm10,	%xmm11
	pxor	%xmm0, 	%xmm2  	# 2 = io
	 pxor	%xmm6,	%xmm8
	pshufb  %xmm4,  %xmm3   # 3 = 1/jak
	 pshufb	%xmm12,	%xmm11
	movdqu	(%r9),	%xmm5
	 # Also use %xmm5 in the second instance.
	pxor	%xmm1,  %xmm3   # 3 = jo
	 pxor	%xmm7,	%xmm11
	jnz	.Lenc2x_loop

	# middle of last round
	movdqa	-0x60(%r10), %xmm4	# 3 : sbou	.Lk_sbo
	movdqa	-0x50(%r10), %xmm0	# 0 : sbot	.Lk_sbo+16
	 movdqa	%xmm4,	%xmm12
	 movdqa	%xmm0,	%xmm6
	pshufb  %xmm2,  %xmm4	# 4 = sbou
	 pshufb	%xmm8,	%xmm12
	pxor	%xmm5,  %xmm4	# 4 = sb1u + k
	 pxor	%xmm5,	%xmm12
	pshufb  %xmm3,	%xmm0	# 0 = sb1t
	 pshufb	%xmm11,	%xmm6
	movdqa	0x40(%r11,%r10), %xmm1		# .Lk_sr[]
	 # Also use %xmm1 in the second instance.
	pxor	%xmm4,	%xmm0	# 0 = A
	 pxor	%xmm12,	%xmm6
	pshufb	%xmm1,	%xmm0
	 pshufb	%xmm1,	%xmm6
	ret
.cfi_endproc
.size	_vpaes_encrypt_core_2x,.-_vpaes_encrypt_core_2x

##
##  Decryption core
##
##  Same API as encryption core.
##
.type	_vpaes_decrypt_core,\@abi-omnipotent
.align	16
_vpaes_decrypt_core:
.cfi_startproc
	mov	%rdx,	%r9		# load key
	mov	240(%rdx),%eax
	movdqa	%xmm9,	%xmm1
	movdqa	.Lk_dipt(%rip), %xmm2	# iptlo
	pandn	%xmm0,	%xmm1
	mov	%rax,	%r11
	psrld	\$4,	%xmm1
	movdqu	(%r9),	%xmm5		# round0 key
	shl	\$4,	%r11
	pand	%xmm9,	%xmm0
	pshufb	%xmm0,	%xmm2
	movdqa	.Lk_dipt+16(%rip), %xmm0 # ipthi
	xor	\$0x30,	%r11
	lea	.Lk_dsbd(%rip),%r10
	pshufb	%xmm1,	%xmm0
	and	\$0x30,	%r11
	pxor	%xmm5,	%xmm2
	movdqa	.Lk_mc_forward+48(%rip), %xmm5
	pxor	%xmm2,	%xmm0
	add	\$16,	%r9
	add	%r10,	%r11
	jmp	.Ldec_entry

.align 16
.Ldec_loop:
##
##  Inverse mix columns
##
	movdqa  -0x20(%r10),%xmm4	# 4 : sb9u
	movdqa  -0x10(%r10),%xmm1	# 0 : sb9t
	pshufb	%xmm2,	%xmm4		# 4 = sb9u
	pshufb	%xmm3,	%xmm1		# 0 = sb9t
	pxor	%xmm4,	%xmm0
	movdqa  0x00(%r10),%xmm4	# 4 : sbdu
	pxor	%xmm1,	%xmm0		# 0 = ch
	movdqa  0x10(%r10),%xmm1	# 0 : sbdt

	pshufb	%xmm2,	%xmm4		# 4 = sbdu
	pshufb	%xmm5,	%xmm0		# MC ch
	pshufb	%xmm3,	%xmm1		# 0 = sbdt
	pxor	%xmm4,	%xmm0		# 4 = ch
	movdqa  0x20(%r10),%xmm4	# 4 : sbbu
	pxor	%xmm1,	%xmm0		# 0 = ch
	movdqa  0x30(%r10),%xmm1	# 0 : sbbt

	pshufb	%xmm2,	%xmm4		# 4 = sbbu
	pshufb	%xmm5,	%xmm0		# MC ch
	pshufb	%xmm3,	%xmm1		# 0 = sbbt
	pxor	%xmm4,	%xmm0		# 4 = ch
	movdqa  0x40(%r10),%xmm4	# 4 : sbeu
	pxor	%xmm1,	%xmm0		# 0 = ch
	movdqa  0x50(%r10),%xmm1	# 0 : sbet

	pshufb	%xmm2,	%xmm4		# 4 = sbeu
	pshufb	%xmm5,	%xmm0		# MC ch
	pshufb	%xmm3,	%xmm1		# 0 = sbet
	pxor	%xmm4,	%xmm0		# 4 = ch
	add	\$16, %r9		# next round key
	palignr	\$12,	%xmm5,	%xmm5
	pxor	%xmm1,	%xmm0		# 0 = ch
	sub	\$1,%rax		# nr--

.Ldec_entry:
	# top of round
	movdqa  %xmm9, 	%xmm1	# 1 : i
	pandn	%xmm0, 	%xmm1	# 1 = i<<4
	movdqa	%xmm11, %xmm2	# 2 : a/k
	psrld	\$4,    %xmm1	# 1 = i
	pand	%xmm9, 	%xmm0	# 0 = k
	pshufb  %xmm0,  %xmm2	# 2 = a/k
	movdqa	%xmm10,	%xmm3	# 3 : 1/i
	pxor	%xmm1,	%xmm0	# 0 = j
	pshufb  %xmm1, 	%xmm3	# 3 = 1/i
	movdqa	%xmm10,	%xmm4	# 4 : 1/j
	pxor	%xmm2, 	%xmm3	# 3 = iak = 1/i + a/k
	pshufb	%xmm0, 	%xmm4	# 4 = 1/j
	pxor	%xmm2, 	%xmm4	# 4 = jak = 1/j + a/k
	movdqa	%xmm10,	%xmm2	# 2 : 1/iak
	pshufb  %xmm3,	%xmm2	# 2 = 1/iak
	movdqa	%xmm10, %xmm3	# 3 : 1/jak
	pxor	%xmm0, 	%xmm2	# 2 = io
	pshufb  %xmm4,  %xmm3	# 3 = 1/jak
	movdqu	(%r9),	%xmm0
	pxor	%xmm1,  %xmm3	# 3 = jo
	jnz	.Ldec_loop

	# middle of last round
	movdqa	0x60(%r10), %xmm4	# 3 : sbou
	pshufb  %xmm2,  %xmm4	# 4 = sbou
	pxor	%xmm0,  %xmm4	# 4 = sb1u + k
	movdqa	0x70(%r10), %xmm0	# 0 : sbot
	movdqa	-0x160(%r11), %xmm2	# .Lk_sr-.Lk_dsbd=-0x160
	pshufb  %xmm3,	%xmm0	# 0 = sb1t
	pxor	%xmm4,	%xmm0	# 0 = A
	pshufb	%xmm2,	%xmm0
	ret
.cfi_endproc
.size	_vpaes_decrypt_core,.-_vpaes_decrypt_core

########################################################
##                                                    ##
##                  AES key schedule                  ##
##                                                    ##
########################################################
.type	_vpaes_schedule_core,\@abi-omnipotent
.align	16
_vpaes_schedule_core:
.cfi_startproc
	# rdi = key
	# rsi = size in bits
	# rdx = buffer
	# rcx = direction.  0=encrypt, 1=decrypt

	call	_vpaes_preheat		# load the tables
	movdqa	.Lk_rcon(%rip), %xmm8	# load rcon
	movdqu	(%rdi),	%xmm0		# load key (unaligned)

	# input transform
	movdqa	%xmm0,	%xmm3
	lea	.Lk_ipt(%rip), %r11
	call	_vpaes_schedule_transform
	movdqa	%xmm0,	%xmm7

	lea	.Lk_sr(%rip),%r10
	test	%rcx,	%rcx
	jnz	.Lschedule_am_decrypting

	# encrypting, output zeroth round key after transform
	movdqu	%xmm0,	(%rdx)
	jmp	.Lschedule_go

.Lschedule_am_decrypting:
	# decrypting, output zeroth round key after shiftrows
	movdqa	(%r8,%r10),%xmm1
	pshufb  %xmm1,	%xmm3
	movdqu	%xmm3,	(%rdx)
	xor	\$0x30, %r8

.Lschedule_go:
	cmp	\$192,	%esi
	ja	.Lschedule_256
	je	.Lschedule_192
	# 128: fall though

##
##  .schedule_128
##
##  128-bit specific part of key schedule.
##
##  This schedule is really simple, because all its parts
##  are accomplished by the subroutines.
##
.Lschedule_128:
	mov	\$10, %esi

.Loop_schedule_128:
	call 	_vpaes_schedule_round
	dec	%rsi
	jz 	.Lschedule_mangle_last
	call	_vpaes_schedule_mangle	# write output
	jmp 	.Loop_schedule_128

##
##  .aes_schedule_192
##
##  192-bit specific part of key schedule.
##
##  The main body of this schedule is the same as the 128-bit
##  schedule, but with more smearing.  The long, high side is
##  stored in %xmm7 as before, and the short, low side is in
##  the high bits of %xmm6.
##
##  This schedule is somewhat nastier, however, because each
##  round produces 192 bits of key material, or 1.5 round keys.
##  Therefore, on each cycle we do 2 rounds and produce 3 round
##  keys.
##
.align	16
.Lschedule_192:
	movdqu	8(%rdi),%xmm0		# load key part 2 (very unaligned)
	call	_vpaes_schedule_transform	# input transform
	movdqa	%xmm0,	%xmm6		# save short part
	pxor	%xmm4,	%xmm4		# clear 4
	movhlps	%xmm4,	%xmm6		# clobber low side with zeros
	mov	\$4,	%esi

.Loop_schedule_192:
	call	_vpaes_schedule_round
	palignr	\$8,%xmm6,%xmm0
	call	_vpaes_schedule_mangle	# save key n
	call	_vpaes_schedule_192_smear
	call	_vpaes_schedule_mangle	# save key n+1
	call	_vpaes_schedule_round
	dec	%rsi
	jz 	.Lschedule_mangle_last
	call	_vpaes_schedule_mangle	# save key n+2
	call	_vpaes_schedule_192_smear
	jmp	.Loop_schedule_192

##
##  .aes_schedule_256
##
##  256-bit specific part of key schedule.
##
##  The structure here is very similar to the 128-bit
##  schedule, but with an additional "low side" in
##  %xmm6.  The low side's rounds are the same as the
##  high side's, except no rcon and no rotation.
##
.align	16
.Lschedule_256:
	movdqu	16(%rdi),%xmm0		# load key part 2 (unaligned)
	call	_vpaes_schedule_transform	# input transform
	mov	\$7, %esi

.Loop_schedule_256:
	call	_vpaes_schedule_mangle	# output low result
	movdqa	%xmm0,	%xmm6		# save cur_lo in xmm6

	# high round
	call	_vpaes_schedule_round
	dec	%rsi
	jz 	.Lschedule_mangle_last
	call	_vpaes_schedule_mangle

	# low round. swap xmm7 and xmm6
	pshufd	\$0xFF,	%xmm0,	%xmm0
	movdqa	%xmm7,	%xmm5
	movdqa	%xmm6,	%xmm7
	call	_vpaes_schedule_low_round
	movdqa	%xmm5,	%xmm7

	jmp	.Loop_schedule_256


##
##  .aes_schedule_mangle_last
##
##  Mangler for last round of key schedule
##  Mangles %xmm0
##    when encrypting, outputs out(%xmm0) ^ 63
##    when decrypting, outputs unskew(%xmm0)
##
##  Always called right before return... jumps to cleanup and exits
##
.align	16
.Lschedule_mangle_last:
	# schedule last round key from xmm0
	lea	.Lk_deskew(%rip),%r11	# prepare to deskew
	test	%rcx, 	%rcx
	jnz	.Lschedule_mangle_last_dec

	# encrypting
	movdqa	(%r8,%r10),%xmm1
	pshufb	%xmm1,	%xmm0		# output permute
	lea	.Lk_opt(%rip),	%r11	# prepare to output transform
	add	\$32,	%rdx

.Lschedule_mangle_last_dec:
	add	\$-16,	%rdx
	pxor	.Lk_s63(%rip),	%xmm0
	call	_vpaes_schedule_transform # output transform
	movdqu	%xmm0,	(%rdx)		# save last key

	# cleanup
	pxor	%xmm0,  %xmm0
	pxor	%xmm1,  %xmm1
	pxor	%xmm2,  %xmm2
	pxor	%xmm3,  %xmm3
	pxor	%xmm4,  %xmm4
	pxor	%xmm5,  %xmm5
	pxor	%xmm6,  %xmm6
	pxor	%xmm7,  %xmm7
	ret
.cfi_endproc
.size	_vpaes_schedule_core,.-_vpaes_schedule_core

##
##  .aes_schedule_192_smear
##
##  Smear the short, low side in the 192-bit key schedule.
##
##  Inputs:
##    %xmm7: high side, b  a  x  y
##    %xmm6:  low side, d  c  0  0
##    %xmm13: 0
##
##  Outputs:
##    %xmm6: b+c+d  b+c  0  0
##    %xmm0: b+c+d  b+c  b  a
##
.type	_vpaes_schedule_192_smear,\@abi-omnipotent
.align	16
_vpaes_schedule_192_smear:
.cfi_startproc
	pshufd	\$0x80,	%xmm6,	%xmm1	# d c 0 0 -> c 0 0 0
	pshufd	\$0xFE,	%xmm7,	%xmm0	# b a _ _ -> b b b a
	pxor	%xmm1,	%xmm6		# -> c+d c 0 0
	pxor	%xmm1,	%xmm1
	pxor	%xmm0,	%xmm6		# -> b+c+d b+c b a
	movdqa	%xmm6,	%xmm0
	movhlps	%xmm1,	%xmm6		# clobber low side with zeros
	ret
.cfi_endproc
.size	_vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear

##
##  .aes_schedule_round
##
##  Runs one main round of the key schedule on %xmm0, %xmm7
##
##  Specifically, runs subbytes on the high dword of %xmm0
##  then rotates it by one byte and xors into the low dword of
##  %xmm7.
##
##  Adds rcon from low byte of %xmm8, then rotates %xmm8 for
##  next rcon.
##
##  Smears the dwords of %xmm7 by xoring the low into the
##  second low, result into third, result into highest.
##
##  Returns results in %xmm7 = %xmm0.
##  Clobbers %xmm1-%xmm4, %r11.
##
.type	_vpaes_schedule_round,\@abi-omnipotent
.align	16
_vpaes_schedule_round:
.cfi_startproc
	# extract rcon from xmm8
	pxor	%xmm1,	%xmm1
	palignr	\$15,	%xmm8,	%xmm1
	palignr	\$15,	%xmm8,	%xmm8
	pxor	%xmm1,	%xmm7

	# rotate
	pshufd	\$0xFF,	%xmm0,	%xmm0
	palignr	\$1,	%xmm0,	%xmm0

	# fall through...

	# low round: same as high round, but no rotation and no rcon.
_vpaes_schedule_low_round:
	# smear xmm7
	movdqa	%xmm7,	%xmm1
	pslldq	\$4,	%xmm7
	pxor	%xmm1,	%xmm7
	movdqa	%xmm7,	%xmm1
	pslldq	\$8,	%xmm7
	pxor	%xmm1,	%xmm7
	pxor	.Lk_s63(%rip), %xmm7

	# subbytes
	movdqa  %xmm9, 	%xmm1
	pandn	%xmm0, 	%xmm1
	psrld	\$4,    %xmm1		# 1 = i
	pand	%xmm9, 	%xmm0		# 0 = k
	movdqa	%xmm11, %xmm2		# 2 : a/k
	pshufb  %xmm0,  %xmm2		# 2 = a/k
	pxor	%xmm1,	%xmm0		# 0 = j
	movdqa	%xmm10,	%xmm3		# 3 : 1/i
	pshufb  %xmm1, 	%xmm3		# 3 = 1/i
	pxor	%xmm2, 	%xmm3		# 3 = iak = 1/i + a/k
	movdqa	%xmm10,	%xmm4		# 4 : 1/j
	pshufb	%xmm0, 	%xmm4		# 4 = 1/j
	pxor	%xmm2, 	%xmm4		# 4 = jak = 1/j + a/k
	movdqa	%xmm10,	%xmm2		# 2 : 1/iak
	pshufb  %xmm3,	%xmm2		# 2 = 1/iak
	pxor	%xmm0, 	%xmm2		# 2 = io
	movdqa	%xmm10, %xmm3		# 3 : 1/jak
	pshufb  %xmm4,  %xmm3		# 3 = 1/jak
	pxor	%xmm1,  %xmm3		# 3 = jo
	movdqa	%xmm13, %xmm4		# 4 : sbou
	pshufb  %xmm2,  %xmm4		# 4 = sbou
	movdqa	%xmm12, %xmm0		# 0 : sbot
	pshufb  %xmm3,	%xmm0		# 0 = sb1t
	pxor	%xmm4, 	%xmm0		# 0 = sbox output

	# add in smeared stuff
	pxor	%xmm7,	%xmm0
	movdqa	%xmm0,	%xmm7
	ret
.cfi_endproc
.size	_vpaes_schedule_round,.-_vpaes_schedule_round

##
##  .aes_schedule_transform
##
##  Linear-transform %xmm0 according to tables at (%r11)
##
##  Requires that %xmm9 = 0x0F0F... as in preheat
##  Output in %xmm0
##  Clobbers %xmm1, %xmm2
##
.type	_vpaes_schedule_transform,\@abi-omnipotent
.align	16
_vpaes_schedule_transform:
.cfi_startproc
	movdqa	%xmm9,	%xmm1
	pandn	%xmm0,	%xmm1
	psrld	\$4,	%xmm1
	pand	%xmm9,	%xmm0
	movdqa	(%r11), %xmm2 	# lo
	pshufb	%xmm0,	%xmm2
	movdqa	16(%r11), %xmm0 # hi
	pshufb	%xmm1,	%xmm0
	pxor	%xmm2,	%xmm0
	ret
.cfi_endproc
.size	_vpaes_schedule_transform,.-_vpaes_schedule_transform

##
##  .aes_schedule_mangle
##
##  Mangle xmm0 from (basis-transformed) standard version
##  to our version.
##
##  On encrypt,
##    xor with 0x63
##    multiply by circulant 0,1,1,1
##    apply shiftrows transform
##
##  On decrypt,
##    xor with 0x63
##    multiply by "inverse mixcolumns" circulant E,B,D,9
##    deskew
##    apply shiftrows transform
##
##
##  Writes out to (%rdx), and increments or decrements it
##  Keeps track of round number mod 4 in %r8
##  Preserves xmm0
##  Clobbers xmm1-xmm5
##
.type	_vpaes_schedule_mangle,\@abi-omnipotent
.align	16
_vpaes_schedule_mangle:
.cfi_startproc
	movdqa	%xmm0,	%xmm4	# save xmm0 for later
	movdqa	.Lk_mc_forward(%rip),%xmm5
	test	%rcx, 	%rcx
	jnz	.Lschedule_mangle_dec

	# encrypting
	add	\$16,	%rdx
	pxor	.Lk_s63(%rip),%xmm4
	pshufb	%xmm5,	%xmm4
	movdqa	%xmm4,	%xmm3
	pshufb	%xmm5,	%xmm4
	pxor	%xmm4,	%xmm3
	pshufb	%xmm5,	%xmm4
	pxor	%xmm4,	%xmm3

	jmp	.Lschedule_mangle_both
.align	16
.Lschedule_mangle_dec:
	# inverse mix columns
	lea	.Lk_dksd(%rip),%r11
	movdqa	%xmm9,	%xmm1
	pandn	%xmm4,	%xmm1
	psrld	\$4,	%xmm1	# 1 = hi
	pand	%xmm9,	%xmm4	# 4 = lo

	movdqa	0x00(%r11), %xmm2
	pshufb	%xmm4,	%xmm2
	movdqa	0x10(%r11), %xmm3
	pshufb	%xmm1,	%xmm3
	pxor	%xmm2,	%xmm3
	pshufb	%xmm5,	%xmm3

	movdqa	0x20(%r11), %xmm2
	pshufb	%xmm4,	%xmm2
	pxor	%xmm3,	%xmm2
	movdqa	0x30(%r11), %xmm3
	pshufb	%xmm1,	%xmm3
	pxor	%xmm2,	%xmm3
	pshufb	%xmm5,	%xmm3

	movdqa	0x40(%r11), %xmm2
	pshufb	%xmm4,	%xmm2
	pxor	%xmm3,	%xmm2
	movdqa	0x50(%r11), %xmm3
	pshufb	%xmm1,	%xmm3
	pxor	%xmm2,	%xmm3
	pshufb	%xmm5,	%xmm3

	movdqa	0x60(%r11), %xmm2
	pshufb	%xmm4,	%xmm2
	pxor	%xmm3,	%xmm2
	movdqa	0x70(%r11), %xmm3
	pshufb	%xmm1,	%xmm3
	pxor	%xmm2,	%xmm3

	add	\$-16,	%rdx

.Lschedule_mangle_both:
	movdqa	(%r8,%r10),%xmm1
	pshufb	%xmm1,%xmm3
	add	\$-16,	%r8
	and	\$0x30,	%r8
	movdqu	%xmm3,	(%rdx)
	ret
.cfi_endproc
.size	_vpaes_schedule_mangle,.-_vpaes_schedule_mangle

#
# Interface to OpenSSL
#
.globl	${PREFIX}_set_encrypt_key