diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Crypto.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Crypto.cpp index d56e58739..d6346ada6 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Crypto.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Crypto.cpp @@ -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); } diff --git a/unittests/ASM/Disabled_Tests_Simulator b/unittests/ASM/Disabled_Tests_Simulator index f3e4a6e03..0c542af3a 100644 --- a/unittests/ASM/Disabled_Tests_Simulator +++ b/unittests/ASM/Disabled_Tests_Simulator @@ -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 diff --git a/unittests/InstructionCountCI/VEX_map2.json b/unittests/InstructionCountCI/VEX_map2.json index 4170d0654..6600e2517 100644 --- a/unittests/InstructionCountCI/VEX_map2.json +++ b/unittests/InstructionCountCI/VEX_map2.json @@ -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": {