Instruction
XCRYPTCBC
Encrypts or decrypts rCX blocks from [rSI] to [rDI] with AES in CBC mode; rAX, rBX and rDX point to IV, key and control word; VIA PadLock.
A VIA extension: Intel and AMD processors do not have these instructions.
- Extensions
- Forms
- 1 (1 Legacy)
- Data
- Intel XED v2026.08.23
Forms
| Instruction | Encoding | Requires |
|---|---|---|
REP XCRYPTCBC
REP_XCRYPTCBC | F3 0F A7 D0 | VIA_PADLOCK_AES + VIA_PADLOCK_AES_EN |
Operation
What the forms do, in pseudocode that our tests run against results recorded on real processors. How to read.
via = cpuid_leaf(0xC0000001, 0)[3]
if via >> 6 & 3 != 3:
fault(UD) # CPUID: no ACE, or it is off
if not cr4 >> 9 & 1:
fault(UD) # no SSE
c = low(rdx, ASIZE) # the control word, 16 bytes
k = low(rbx, ASIZE) # the key, or the round keys
if not key_loaded: # RFLAGS bit 30 clear: the engine
if (c | k) & 15: # loads both, 16-byte aligned,
fault(GP, 0) # and keeps them for the next
ace_load(c, k)
key_loaded = 1
cw = ace_cw
n = aCX # blocks of 16 bytes
s = aSI
d = aDI
v = low(rax, ASIZE) # the IV
dec = cw >> 9 & 1 # CW[9]: decryption
mac = cw >> 4 & 1 # CW[4]: every block to [rDI]
if ace_defined():
if v & 15: # the IV: 16-byte aligned
fault(GP, 0)
if (s | d) & 15 and not cw >> 5 & 1:
fault(GP, 0) # CW[5]: data at any alignment
iv = load(v, 128)
o = d
for i in range(n):
x = load(s + 16 * i, 128)
o = d if mac else d + 16 * i
if dec:
y = ace_decrypt(x) ^ iv
iv = x # the next block's chaining
else: # value: the ciphertext
y = ace_encrypt(x ^ iv)
iv = y
store(o, 128, y)
if dec and n:
store(v, 128, iv) # the last ciphertext block,
elif n and ASIZE == 64: # in memory or by its address
rax = o
elif n:
eax = o
aSI = s + 16 * n
aDI = d if mac else d + 16 * n
aCX = 0
else: # what VIA leaves undefined
for i in range(n):
store(d + 16 * i, 128, UNDEFINED)
store(v, 128, UNDEFINED)
aSI = aDI = aCX = UNDEFINED
rax = UNDEFINED
# so that the next REP XCRYPTCBC goes on with the chain. With CW[4]
# the result is a CBC-MAC at [rDI], encrypting or notRun on AMD Zen 5 (EPYC 9645): 1 case. It ran where CPUID reported no PadLock ACE, and raised an exception.
Operands
| Operand | Kind | Action |
|---|---|---|
REP XCRYPTCBC | ||
m8 at ES:[rDI] | implicit | write |
rCX | implicit | read, write |
rDX | implicit | read |
rBX | implicit | read |
rAX | implicit | read |
rDI | implicit | read, write |
m8 at [rSI] | implicit | conditional read |
rSI | implicit | read, conditional write |
Flags
None: XED records no flag that the forms test or change.
Attributes
What else XED records about the forms. How to read.
- All forms
- repeated: count in rCX
CPUID and processors
Each form belongs to an XED ISA set. A form can be used when the processor reports every CPUID bit of one of its ISA set's alternatives.
| ISA set | CPUID | Processors |
|---|---|---|
VIA_PADLOCK_AES | VIA_PADLOCK_AES + VIA_PADLOCK_AES_EN | None in XED’s model. |
More VIA PadLock instructions
Sources
- Intel XED v2026.08.23 (commit
0bcb6237345c): forms, encodings, operands, flags, exception classes, attributes, ISA sets, CPUID bits and chip model. - Linux 7.3: drivers/crypto/padlock-aes.c and padlock-sha.c (VIA PadLock AES and SHA)
- Linux 7.3: drivers/char/hw_random/via-rng.c (VIA PadLock random number generator)
The tables are derived from Intel XED, Copyright Intel Corporation, licensed under the Apache License 2.0; x86-64.net converted and reformatted them. The text is our own.