From da6627124bc4bf46d97e43554f6f4d9477accd23 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 15 Apr 2018 00:05:40 -0400 Subject: [PATCH] A64: Implement SHA1C --- src/frontend/A64/decoder/a64.inc | 2 +- src/frontend/A64/translate/impl/simd_sha.cpp | 32 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index 9a8bb9d2..76131e00 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -322,7 +322,7 @@ INST(AESMC, "AESMC", "01001 INST(AESIMC, "AESIMC", "0100111000101000011110nnnnnddddd") // Data Processing - FP and SIMD - SHA -//INST(SHA1C, "SHA1C", "01011110000mmmmm000000nnnnnddddd") +INST(SHA1C, "SHA1C", "01011110000mmmmm000000nnnnnddddd") //INST(SHA1P, "SHA1P", "01011110000mmmmm000100nnnnnddddd") //INST(SHA1M, "SHA1M", "01011110000mmmmm001000nnnnnddddd") INST(SHA1SU0, "SHA1SU0", "01011110000mmmmm001100nnnnnddddd") diff --git a/src/frontend/A64/translate/impl/simd_sha.cpp b/src/frontend/A64/translate/impl/simd_sha.cpp index a5df04db..153a8977 100644 --- a/src/frontend/A64/translate/impl/simd_sha.cpp +++ b/src/frontend/A64/translate/impl/simd_sha.cpp @@ -7,6 +7,38 @@ #include "frontend/A64/translate/impl/impl.h" namespace Dynarmic::A64 { +namespace { +IR::U32 SHAchoose(IREmitter& ir, IR::U32 x, IR::U32 y, IR::U32 z) { + return ir.Eor(ir.And(ir.Eor(y, z), x), z); +} +} + +bool TranslatorVisitor::SHA1C(Vec Vm, Vec Vn, Vec Vd) { + IR::U128 x = ir.GetQ(Vd); + IR::U32 y = ir.VectorGetElement(32, ir.GetQ(Vn), 0); + const IR::U128 w = ir.GetQ(Vm); + + for (size_t i = 0; i < 4; i++) { + const IR::U32 low_x = ir.VectorGetElement(32, x, 0); + const IR::U32 after_low_x = ir.VectorGetElement(32, x, 1); + const IR::U32 before_high_x = ir.VectorGetElement(32, x, 2); + const IR::U32 high_x = ir.VectorGetElement(32, x, 3); + const IR::U32 t = SHAchoose(ir, after_low_x, before_high_x, high_x); + const IR::U32 w_segment = ir.VectorGetElement(32, w, i); + + y = ir.Add(ir.Add(ir.Add(y, ir.RotateRight(low_x, ir.Imm8(27))), t), w_segment); + x = ir.VectorSetElement(32, x, 1, ir.RotateRight(after_low_x, ir.Imm8(2))); + + // Move each 32-bit element to the left once + // e.g. [3, 2, 1, 0], becomes [2, 1, 0, 3] + const IR::U128 shuffled_x = ir.VectorShuffleWords(x, 0b10010011); + x = ir.VectorSetElement(32, shuffled_x, 0, y); + y = high_x; + } + + ir.SetQ(Vd, x); + return true; +} bool TranslatorVisitor::SHA1SU0(Vec Vm, Vec Vn, Vec Vd) { const IR::U128 d = ir.GetQ(Vd);