diff --git a/src/aarch32/assembler-aarch32.cc b/src/aarch32/assembler-aarch32.cc index 64126664..151c3f45 100644 --- a/src/aarch32/assembler-aarch32.cc +++ b/src/aarch32/assembler-aarch32.cc @@ -2694,6 +2694,97 @@ bool Assembler::adr_info(Condition cond, return false; } +void Assembler::aesd(Condition cond, DataType dt, QRegister rd, QRegister rm) { + VIXL_ASSERT(AllowAssembler()); + VIXL_ASSERT(dt.Is(Untyped8)); + CheckIT(cond); + + if (IsUsingT32()) { + // AESD{}{}.
, ; T1 + if (cond.Is(al) || AllowStronglyDiscouraged()) { + EmitT32_32(0xffb00340 | rd.Encode(22, 12) | rm.Encode(5, 0)); + AdvanceIT(); + return; + } + } else { + // AESD{}{}.
, ; A1 + if (cond.Is(al)) { + EmitA32(0xf3b00340 | rd.Encode(22, 12) | rm.Encode(5, 0)); + return; + } + } + Delegate(kAesd, &Assembler::aesd, cond, dt, rd, rm); +} + +void Assembler::aese(Condition cond, DataType dt, QRegister rd, QRegister rm) { + VIXL_ASSERT(AllowAssembler()); + VIXL_ASSERT(dt.Is(Untyped8)); + CheckIT(cond); + + if (IsUsingT32()) { + // AESE{}{}.
, ; T1 + if (cond.Is(al) || AllowStronglyDiscouraged()) { + EmitT32_32(0xffb00300 | rd.Encode(22, 12) | rm.Encode(5, 0)); + AdvanceIT(); + return; + } + } else { + // AESE{}{}.
, ; A1 + if (cond.Is(al)) { + EmitA32(0xf3b00300 | rd.Encode(22, 12) | rm.Encode(5, 0)); + return; + } + } + Delegate(kAese, &Assembler::aese, cond, dt, rd, rm); +} + +void Assembler::aesimc(Condition cond, + DataType dt, + QRegister rd, + QRegister rm) { + VIXL_ASSERT(AllowAssembler()); + VIXL_ASSERT(dt.Is(Untyped8)); + CheckIT(cond); + + if (IsUsingT32()) { + // AESIMC{}{}.
, ; T1 + if (cond.Is(al) || AllowStronglyDiscouraged()) { + EmitT32_32(0xffb003c0 | rd.Encode(22, 12) | rm.Encode(5, 0)); + AdvanceIT(); + return; + } + } else { + // AESIMC{}{}.
, ; A1 + if (cond.Is(al)) { + EmitA32(0xf3b003c0 | rd.Encode(22, 12) | rm.Encode(5, 0)); + return; + } + } + Delegate(kAesimc, &Assembler::aesimc, cond, dt, rd, rm); +} + +void Assembler::aesmc(Condition cond, DataType dt, QRegister rd, QRegister rm) { + VIXL_ASSERT(AllowAssembler()); + VIXL_ASSERT(dt.Is(Untyped8)); + CheckIT(cond); + + if (IsUsingT32()) { + // AESMC{}{}.
, ; T1 + if (cond.Is(al) || AllowStronglyDiscouraged()) { + EmitT32_32(0xffb00380 | rd.Encode(22, 12) | rm.Encode(5, 0)); + AdvanceIT(); + return; + } + } else { + // AESMC{}{}.
, ; A1 + if (cond.Is(al)) { + EmitA32(0xf3b00380 | rd.Encode(22, 12) | rm.Encode(5, 0)); + return; + } + } + Delegate(kAesmc, &Assembler::aesmc, cond, dt, rd, rm); +} + void Assembler::and_(Condition cond, EncodingSize size, Register rd, diff --git a/src/aarch32/assembler-aarch32.h b/src/aarch32/assembler-aarch32.h index bb7df840..883cfde9 100644 --- a/src/aarch32/assembler-aarch32.h +++ b/src/aarch32/assembler-aarch32.h @@ -1161,12 +1161,14 @@ class Assembler : public internal::AssemblerBase { QRegister /*rd*/, QRegister /*rm*/) { USE(type); - VIXL_ASSERT((type == kVabs) || (type == kVcls) || (type == kVclz) || - (type == kVcnt) || (type == kVneg) || (type == kVpadal) || - (type == kVpaddl) || (type == kVqabs) || (type == kVqneg) || - (type == kVrecpe) || (type == kVrev16) || (type == kVrev32) || - (type == kVrev64) || (type == kVrsqrte) || (type == kVswp) || - (type == kVtrn) || (type == kVuzp) || (type == kVzip)); + VIXL_ASSERT((type == kAesd) || (type == kAese) || (type == kAesimc) || + (type == kAesimc) || (type == kVabs) || (type == kVcls) || + (type == kVclz) || (type == kVcnt) || (type == kVneg) || + (type == kVpadal) || (type == kVpaddl) || (type == kVqabs) || + (type == kVqneg) || (type == kVrecpe) || (type == kVrev16) || + (type == kVrev32) || (type == kVrev64) || (type == kVrsqrte) || + (type == kVswp) || (type == kVtrn) || (type == kVuzp) || + (type == kVzip)); UnimplementedDelegate(type); } virtual void Delegate(InstructionType type, @@ -1971,6 +1973,18 @@ class Assembler : public internal::AssemblerBase { adr(al, size, rd, location); } + void aesd(Condition cond, DataType dt, QRegister rd, QRegister rm); + void aesd(QRegister rd, QRegister rm) { aesd(al, Untyped8, rd, rm); } + + void aese(Condition cond, DataType dt, QRegister rd, QRegister rm); + void aese(QRegister rd, QRegister rm) { aese(al, Untyped8, rd, rm); } + + void aesimc(Condition cond, DataType dt, QRegister rd, QRegister rm); + void aesimc(QRegister rd, QRegister rm) { aesimc(al, Untyped8, rd, rm); } + + void aesmc(Condition cond, DataType dt, QRegister rd, QRegister rm); + void aesmc(QRegister rd, QRegister rm) { aesmc(al, Untyped8, rd, rm); } + void and_(Condition cond, EncodingSize size, Register rd, diff --git a/src/aarch32/constants-aarch32.cc b/src/aarch32/constants-aarch32.cc index 75923617..3c3d09e3 100644 --- a/src/aarch32/constants-aarch32.cc +++ b/src/aarch32/constants-aarch32.cc @@ -46,6 +46,14 @@ const char* ToCString(InstructionType type) { return "addw"; case kAdr: return "adr"; + case kAesd: + return "aesd"; + case kAese: + return "aese"; + case kAesimc: + return "aesimc"; + case kAesmc: + return "aesmc"; case kAnd: return "and"; case kAnds: diff --git a/src/aarch32/constants-aarch32.h b/src/aarch32/constants-aarch32.h index 6d79834d..5774c151 100644 --- a/src/aarch32/constants-aarch32.h +++ b/src/aarch32/constants-aarch32.h @@ -126,6 +126,10 @@ enum InstructionType { kAdds, kAddw, kAdr, + kAesd, + kAese, + kAesimc, + kAesmc, kAnd, kAnds, kAsr, diff --git a/src/aarch32/disasm-aarch32.cc b/src/aarch32/disasm-aarch32.cc index 535f60c8..0111b302 100644 --- a/src/aarch32/disasm-aarch32.cc +++ b/src/aarch32/disasm-aarch32.cc @@ -1228,6 +1228,42 @@ void Disassembler::and_(Condition cond, os() << rn << ", " << operand; } +void Disassembler::aesd(Condition cond, + DataType dt, + QRegister rd, + QRegister rm) { + os().SetCurrentInstruction(kAesd, kNoAttribute); + os() << ToCString(kAesd) << ConditionPrinter(it_block_, cond) + << DtPrinter(dt, Untyped8) << ' ' << rd << ", " << rm; +} + +void Disassembler::aese(Condition cond, + DataType dt, + QRegister rd, + QRegister rm) { + os().SetCurrentInstruction(kAese, kNoAttribute); + os() << ToCString(kAese) << ConditionPrinter(it_block_, cond) + << DtPrinter(dt, Untyped8) << ' ' << rd << ", " << rm; +} + +void Disassembler::aesimc(Condition cond, + DataType dt, + QRegister rd, + QRegister rm) { + os().SetCurrentInstruction(kAesimc, kNoAttribute); + os() << ToCString(kAesimc) << ConditionPrinter(it_block_, cond) + << DtPrinter(dt, Untyped8) << ' ' << rd << ", " << rm; +} + +void Disassembler::aesmc(Condition cond, + DataType dt, + QRegister rd, + QRegister rm) { + os().SetCurrentInstruction(kAesmc, kNoAttribute); + os() << ToCString(kAesmc) << ConditionPrinter(it_block_, cond) + << DtPrinter(dt, Untyped8) << ' ' << rd << ", " << rm; +} + void Disassembler::ands(Condition cond, EncodingSize size, Register rd, @@ -26583,14 +26619,38 @@ void Disassembler::DecodeT32(uint32_t instr) { switch (instr & 0x00000080) { case 0x00000000: { // 0xffb00300 - UnimplementedT32_32("AESE", - instr); + unsigned rd = + ExtractQRegister(instr, + 22, + 12); + unsigned rm = + ExtractQRegister(instr, 5, 0); + if (((instr >> 18) & 0x3) != 0) { + UnallocatedT32(instr); + return; + } + aese(CurrentCond(), + Untyped8, + QRegister(rd), + QRegister(rm)); break; } case 0x00000080: { // 0xffb00380 - UnimplementedT32_32("AESMC", - instr); + unsigned rd = + ExtractQRegister(instr, + 22, + 12); + unsigned rm = + ExtractQRegister(instr, 5, 0); + if (((instr >> 18) & 0x3) != 0) { + UnallocatedT32(instr); + return; + } + aesmc(CurrentCond(), + Untyped8, + QRegister(rd), + QRegister(rm)); break; } } @@ -26601,14 +26661,38 @@ void Disassembler::DecodeT32(uint32_t instr) { switch (instr & 0x00000080) { case 0x00000000: { // 0xffb00340 - UnimplementedT32_32("AESD", - instr); + unsigned rd = + ExtractQRegister(instr, + 22, + 12); + unsigned rm = + ExtractQRegister(instr, 5, 0); + if (((instr >> 18) & 0x3) != 0) { + UnallocatedT32(instr); + return; + } + aesd(CurrentCond(), + Untyped8, + QRegister(rd), + QRegister(rm)); break; } case 0x00000080: { // 0xffb003c0 - UnimplementedT32_32("AESIMC", - instr); + unsigned rd = + ExtractQRegister(instr, + 22, + 12); + unsigned rm = + ExtractQRegister(instr, 5, 0); + if (((instr >> 18) & 0x3) != 0) { + UnallocatedT32(instr); + return; + } + aesimc(CurrentCond(), + Untyped8, + QRegister(rd), + QRegister(rm)); break; } } @@ -41045,12 +41129,32 @@ void Disassembler::DecodeA32(uint32_t instr) { switch (instr & 0x00000080) { case 0x00000000: { // 0xf3b00300 - UnimplementedA32("AESE", instr); + unsigned rd = + ExtractQRegister(instr, 22, 12); + unsigned rm = ExtractQRegister(instr, 5, 0); + if (((instr >> 18) & 0x3) != 0) { + UnallocatedA32(instr); + return; + } + aese(CurrentCond(), + Untyped8, + QRegister(rd), + QRegister(rm)); break; } case 0x00000080: { // 0xf3b00380 - UnimplementedA32("AESMC", instr); + unsigned rd = + ExtractQRegister(instr, 22, 12); + unsigned rm = ExtractQRegister(instr, 5, 0); + if (((instr >> 18) & 0x3) != 0) { + UnallocatedA32(instr); + return; + } + aesmc(CurrentCond(), + Untyped8, + QRegister(rd), + QRegister(rm)); break; } } @@ -41061,12 +41165,32 @@ void Disassembler::DecodeA32(uint32_t instr) { switch (instr & 0x00000080) { case 0x00000000: { // 0xf3b00340 - UnimplementedA32("AESD", instr); + unsigned rd = + ExtractQRegister(instr, 22, 12); + unsigned rm = ExtractQRegister(instr, 5, 0); + if (((instr >> 18) & 0x3) != 0) { + UnallocatedA32(instr); + return; + } + aesd(CurrentCond(), + Untyped8, + QRegister(rd), + QRegister(rm)); break; } case 0x00000080: { // 0xf3b003c0 - UnimplementedA32("AESIMC", instr); + unsigned rd = + ExtractQRegister(instr, 22, 12); + unsigned rm = ExtractQRegister(instr, 5, 0); + if (((instr >> 18) & 0x3) != 0) { + UnallocatedA32(instr); + return; + } + aesimc(CurrentCond(), + Untyped8, + QRegister(rd), + QRegister(rm)); break; } } diff --git a/src/aarch32/disasm-aarch32.h b/src/aarch32/disasm-aarch32.h index 679f47ba..bb67e35f 100644 --- a/src/aarch32/disasm-aarch32.h +++ b/src/aarch32/disasm-aarch32.h @@ -639,6 +639,14 @@ class Disassembler { void adr(Condition cond, EncodingSize size, Register rd, Location* location); + void aesd(Condition cond, DataType dt, QRegister rd, QRegister rm); + + void aese(Condition cond, DataType dt, QRegister rd, QRegister rm); + + void aesimc(Condition cond, DataType dt, QRegister rd, QRegister rm); + + void aesmc(Condition cond, DataType dt, QRegister rd, QRegister rm); + void and_(Condition cond, EncodingSize size, Register rd, diff --git a/src/aarch64/assembler-aarch64.cc b/src/aarch64/assembler-aarch64.cc index 1304ede2..b218b06f 100644 --- a/src/aarch64/assembler-aarch64.cc +++ b/src/aarch64/assembler-aarch64.cc @@ -3862,6 +3862,24 @@ void Assembler::usdot(const VRegister& vd, Emit(VFormat(vd) | 0x0e809c00 | Rm(vm) | Rn(vn) | Rd(vd)); } +// clang-format off +#define NEON_CRYPTO_AES_LIST(V) \ + V(aesd, NEON_AESD) \ + V(aese, NEON_AESE) \ + V(aesmc, NEON_AESMC) \ + V(aesimc, NEON_AESIMC) +// clang-format on + +#define VIXL_DEFINE_ASM_FUNC(FN, VEC_OP) \ + void Assembler::FN(const VRegister& vd, const VRegister& vn) { \ + VIXL_ASSERT(CPUHas(CPUFeatures::kNEON, CPUFeatures::kAES)); \ + VIXL_ASSERT(vd.Is16B() && vn.Is16B()); \ + \ + Emit(VEC_OP | Rn(vn) | Rd(vd)); \ + } +NEON_CRYPTO_AES_LIST(VIXL_DEFINE_ASM_FUNC) +#undef VIXL_DEFINE_ASM_FUNC + void Assembler::faddp(const VRegister& vd, const VRegister& vn) { VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kNEON)); VIXL_ASSERT((vd.Is1S() && vn.Is2S()) || (vd.Is1D() && vn.Is2D()) || diff --git a/src/aarch64/assembler-aarch64.h b/src/aarch64/assembler-aarch64.h index 65c55cc4..08a2821d 100644 --- a/src/aarch64/assembler-aarch64.h +++ b/src/aarch64/assembler-aarch64.h @@ -3382,6 +3382,18 @@ class Assembler : public vixl::internal::AssemblerBase { const VRegister& vm, int vm_index); + // AES single round decryption + void aesd(const VRegister& vd, const VRegister& vn); + + // AES single round encryption + void aese(const VRegister& vd, const VRegister& vn); + + // AES mix columns + void aesmc(const VRegister& vd, const VRegister& vn); + + // AES inverse mix columns + void aesimc(const VRegister& vd, const VRegister& vn); + // Signed saturating rounding doubling multiply subtract returning high half // [Armv8.1]. void sqrdmlsh(const VRegister& vd, const VRegister& vn, const VRegister& vm); diff --git a/src/aarch64/constants-aarch64.h b/src/aarch64/constants-aarch64.h index f7512b2c..7fb99449 100644 --- a/src/aarch64/constants-aarch64.h +++ b/src/aarch64/constants-aarch64.h @@ -1840,7 +1840,11 @@ enum Crypto3RegSHAOp { // Crypto - AES. enum CryptoAESOp { CryptoAESFixed = 0x4E280800, - CryptoAESFMask = 0xFF3E0C00 + CryptoAESFMask = 0xFF3E0C00, + NEON_AESE = CryptoAESFixed | 0x00004000, + NEON_AESD = CryptoAESFixed | 0x00005000, + NEON_AESMC = CryptoAESFixed | 0x00006000, + NEON_AESIMC = CryptoAESFixed | 0x00007000 }; // NEON instructions with two register operands.