[SVE256] Handle 256-bit AES operations

Currently we split these into two 128-bit operations since VIXL doesn't
have support for the unified SVE operations yet.

Now we fully support VAES on SVE256.
This commit is contained in:
LC committed 2026-07-03 21:52:59 -04:00
1 parent f8967aa207
commit 7fd9b897c2
3 files changed
+132 -36

No files matched your search

@@ -208,14 +208,25 @@ void OpDispatchBuilder::AESEncOp(OpcodeArgs) {
void OpDispatchBuilder::VAESEncOp(OpcodeArgs) {
const auto DstSize = OpSizeFromDst(Op);
const auto Is128Bit = DstSize == OpSize::i128Bit;
// TODO: Handle 256-bit VAESENC.
LOGMAN_THROW_A_FMT(Is128Bit, "256-bit VAESENC unimplemented");
const auto Is256Bit = DstSize == OpSize::i256Bit;
Ref State = LoadSourceFPR(Op, Op->Src[0], Op->Flags);
Ref Key = LoadSourceFPR(Op, Op->Src[1], Op->Flags);
Ref Result = _VAESEnc(DstSize, State, Key, LoadZeroVector(DstSize));
Ref ZeroVec = LoadZeroVector(DstSize);
Ref Result {};
if (Is256Bit) {
// TODO: Handle as one operation once vixl supports it.
auto UpperState = _VDupElement(DstSize, OpSize::i128Bit, State, 1);
auto UpperKey = _VDupElement(DstSize, OpSize::i128Bit, Key, 1);
auto Lower = _VAESEnc(OpSize::i128Bit, State, Key, ZeroVec);
auto Upper = _VAESEnc(OpSize::i128Bit, UpperState, UpperKey, ZeroVec);
Result = _VInsElement(DstSize, OpSize::i128Bit, 1, 0, Lower, Upper);
} else {
Result = _VAESEnc(DstSize, State, Key, ZeroVec);
}
StoreResultFPR(Op, Result);
}
@@ -233,14 +244,25 @@ void OpDispatchBuilder::AESEncLastOp(OpcodeArgs) {
void OpDispatchBuilder::VAESEncLastOp(OpcodeArgs) {
const auto DstSize = OpSizeFromDst(Op);
const auto Is128Bit = DstSize == OpSize::i128Bit;
// TODO: Handle 256-bit VAESENCLAST.
LOGMAN_THROW_A_FMT(Is128Bit, "256-bit VAESENCLAST unimplemented");
const auto Is256Bit = DstSize == OpSize::i256Bit;
Ref State = LoadSourceFPR(Op, Op->Src[0], Op->Flags);
Ref Key = LoadSourceFPR(Op, Op->Src[1], Op->Flags);
Ref Result = _VAESEncLast(DstSize, State, Key, LoadZeroVector(DstSize));
Ref ZeroVec = LoadZeroVector(DstSize);
Ref Result {};
if (Is256Bit) {
// TODO: Handle as one operation once vixl supports it.
auto UpperState = _VDupElement(DstSize, OpSize::i128Bit, State, 1);
auto UpperKey = _VDupElement(DstSize, OpSize::i128Bit, Key, 1);
auto Lower = _VAESEncLast(OpSize::i128Bit, State, Key, ZeroVec);
auto Upper = _VAESEncLast(OpSize::i128Bit, UpperState, UpperKey, ZeroVec);
Result = _VInsElement(DstSize, OpSize::i128Bit, 1, 0, Lower, Upper);
} else {
Result = _VAESEncLast(DstSize, State, Key, ZeroVec);
}
StoreResultFPR(Op, Result);
}
@@ -258,14 +280,25 @@ void OpDispatchBuilder::AESDecOp(OpcodeArgs) {
void OpDispatchBuilder::VAESDecOp(OpcodeArgs) {
const auto DstSize = OpSizeFromDst(Op);
const auto Is128Bit = DstSize == OpSize::i128Bit;
// TODO: Handle 256-bit VAESDEC.
LOGMAN_THROW_A_FMT(Is128Bit, "256-bit VAESDEC unimplemented");
const auto Is256Bit = DstSize == OpSize::i256Bit;
Ref State = LoadSourceFPR(Op, Op->Src[0], Op->Flags);
Ref Key = LoadSourceFPR(Op, Op->Src[1], Op->Flags);
Ref Result = _VAESDec(DstSize, State, Key, LoadZeroVector(DstSize));
Ref ZeroVec = LoadZeroVector(DstSize);
Ref Result {};
if (Is256Bit) {
// TODO: Handle as one operation once vixl supports it.
auto UpperState = _VDupElement(DstSize, OpSize::i128Bit, State, 1);
auto UpperKey = _VDupElement(DstSize, OpSize::i128Bit, Key, 1);
auto Lower = _VAESDec(OpSize::i128Bit, State, Key, ZeroVec);
auto Upper = _VAESDec(OpSize::i128Bit, UpperState, UpperKey, ZeroVec);
Result = _VInsElement(DstSize, OpSize::i128Bit, 1, 0, Lower, Upper);
} else {
Result = _VAESDec(DstSize, State, Key, ZeroVec);
}
StoreResultFPR(Op, Result);
}
@@ -283,14 +316,25 @@ void OpDispatchBuilder::AESDecLastOp(OpcodeArgs) {
void OpDispatchBuilder::VAESDecLastOp(OpcodeArgs) {
const auto DstSize = OpSizeFromDst(Op);
const auto Is128Bit = DstSize == OpSize::i128Bit;
// TODO: Handle 256-bit VAESDECLAST.
LOGMAN_THROW_A_FMT(Is128Bit, "256-bit VAESDECLAST unimplemented");
const auto Is256Bit = DstSize == OpSize::i256Bit;
Ref State = LoadSourceFPR(Op, Op->Src[0], Op->Flags);
Ref Key = LoadSourceFPR(Op, Op->Src[1], Op->Flags);
Ref Result = _VAESDecLast(DstSize, State, Key, LoadZeroVector(DstSize));
Ref ZeroVec = LoadZeroVector(DstSize);
Ref Result {};
if (Is256Bit) {
// TODO: Handle as one operation once vixl supports it.
auto UpperState = _VDupElement(DstSize, OpSize::i128Bit, State, 1);
auto UpperKey = _VDupElement(DstSize, OpSize::i128Bit, Key, 1);
auto Lower = _VAESDecLast(OpSize::i128Bit, State, Key, ZeroVec);
auto Upper = _VAESDecLast(OpSize::i128Bit, UpperState, UpperKey, ZeroVec);
Result = _VInsElement(DstSize, OpSize::i128Bit, 1, 0, Lower, Upper);
} else {
Result = _VAESDecLast(DstSize, State, Key, ZeroVec);
}
StoreResultFPR(Op, Result);
}
-8
View File
@@ -1,11 +1,3 @@
# AES unsupported in 256-bit SVE currently
Test_VEX/vaesdec.asm
Test_VEX/vaesdeclast.asm
Test_VEX/vaesdec256.asm
Test_VEX/vaesdeclast256.asm
Test_VEX/vaesenc256.asm
Test_VEX/vaesenclast256.asm
# Simulator can't handle self-modifying code
Test_SelfModifyingCode/Delinking.asm
Test_SelfModifyingCode/DifferentBlock.asm
+68 -8
View File
@@ -4751,10 +4751,26 @@
]
},
"vaesenc ymm0, ymm1, ymm2": {
"ExpectedInstructionCount": -1,
"Skip": "Yes",
"ExpectedInstructionCount": 15,
"Comment": [
"Map 2 0b01 0xdc 256-bit"
],
"ExpectedArm64ASM": [
"movi v2.2d, #0x0",
"mov z3.q, z17.q[1]",
"mov z4.q, z18.q[1]",
"mov v0.16b, v17.16b",
"aese v0.16b, v2.16b",
"aesmc v0.16b, v0.16b",
"eor v5.16b, v0.16b, v18.16b",
"mov v0.16b, v3.16b",
"aese v0.16b, v2.16b",
"aesmc v0.16b, v0.16b",
"eor v2.16b, v0.16b, v4.16b",
"mov z1.q, q2",
"mov z16.d, z5.d",
"not p0.b, p7/z, p6.b",
"mov z16.b, p0/m, z1.b"
]
},
"vaesenclast xmm0, xmm1, xmm2": {
@@ -4770,10 +4786,24 @@
]
},
"vaesenclast ymm0, ymm1, ymm2": {
"ExpectedInstructionCount": -1,
"Skip": "Yes",
"ExpectedInstructionCount": 13,
"Comment": [
"Map 2 0b01 0xdd 256-bit"
],
"ExpectedArm64ASM": [
"movi v2.2d, #0x0",
"mov z3.q, z17.q[1]",
"mov z4.q, z18.q[1]",
"mov v0.16b, v17.16b",
"aese v0.16b, v2.16b",
"eor v5.16b, v0.16b, v18.16b",
"mov v0.16b, v3.16b",
"aese v0.16b, v2.16b",
"eor v2.16b, v0.16b, v4.16b",
"mov z1.q, q2",
"mov z16.d, z5.d",
"not p0.b, p7/z, p6.b",
"mov z16.b, p0/m, z1.b"
]
},
"vaesdec xmm0, xmm1, xmm2": {
@@ -4790,10 +4820,26 @@
]
},
"vaesdec ymm0, ymm1, ymm2": {
"ExpectedInstructionCount": -1,
"Skip": "Yes",
"ExpectedInstructionCount": 15,
"Comment": [
"Map 2 0b01 0xde 256-bit"
],
"ExpectedArm64ASM": [
"movi v2.2d, #0x0",
"mov z3.q, z17.q[1]",
"mov z4.q, z18.q[1]",
"mov v0.16b, v17.16b",
"aesd v0.16b, v2.16b",
"aesimc v0.16b, v0.16b",
"eor v5.16b, v0.16b, v18.16b",
"mov v0.16b, v3.16b",
"aesd v0.16b, v2.16b",
"aesimc v0.16b, v0.16b",
"eor v2.16b, v0.16b, v4.16b",
"mov z1.q, q2",
"mov z16.d, z5.d",
"not p0.b, p7/z, p6.b",
"mov z16.b, p0/m, z1.b"
]
},
"vaesdeclast xmm0, xmm1, xmm2": {
@@ -4809,10 +4855,24 @@
]
},
"vaesdeclast ymm0, ymm1, ymm2": {
"ExpectedInstructionCount": -1,
"Skip": "Yes",
"ExpectedInstructionCount": 13,
"Comment": [
"Map 2 0b01 0xdf 256-bit"
],
"ExpectedArm64ASM": [
"movi v2.2d, #0x0",
"mov z3.q, z17.q[1]",
"mov z4.q, z18.q[1]",
"mov v0.16b, v17.16b",
"aesd v0.16b, v2.16b",
"eor v5.16b, v0.16b, v18.16b",
"mov v0.16b, v3.16b",
"aesd v0.16b, v2.16b",
"eor v2.16b, v0.16b, v4.16b",
"mov z1.q, q2",
"mov z16.d, z5.d",
"not p0.b, p7/z, p6.b",
"mov z16.b, p0/m, z1.b"
]
},
"andn eax, ebx, ecx": {