IR: Implement SHA256Hash
This commit is contained in:
parent
81536e4630
commit
f0a4bf1f6a
6 changed files with 63 additions and 63 deletions
|
@ -286,6 +286,7 @@ if (ARCHITECTURE STREQUAL "x86_64")
|
|||
backend/x64/emit_x64_packed.cpp
|
||||
backend/x64/emit_x64_saturation.cpp
|
||||
backend/x64/emit_x64_sm4.cpp
|
||||
backend/x64/emit_x64_sha.cpp
|
||||
backend/x64/emit_x64_vector.cpp
|
||||
backend/x64/emit_x64_vector_floating_point.cpp
|
||||
backend/x64/emit_x64_vector_saturation.cpp
|
||||
|
|
51
src/dynarmic/backend/x64/emit_x64_sha.cpp
Normal file
51
src/dynarmic/backend/x64/emit_x64_sha.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2022 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#include "dynarmic/backend/x64/block_of_code.h"
|
||||
#include "dynarmic/backend/x64/emit_x64.h"
|
||||
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
|
||||
using namespace Xbyak::util;
|
||||
|
||||
void EmitX64::EmitSHA256Hash(EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
const bool part1 = args[3].GetImmediateU1();
|
||||
|
||||
ASSERT(code.HasHostFeature(HostFeature::SHA));
|
||||
|
||||
// 3 2 1 0
|
||||
// x = d c b a
|
||||
// y = h g f e
|
||||
// w = wk3 wk2 wk1 wk0
|
||||
|
||||
const Xbyak::Xmm x = ctx.reg_alloc.UseScratchXmm(args[0]);
|
||||
const Xbyak::Xmm y = ctx.reg_alloc.UseScratchXmm(args[1]);
|
||||
const Xbyak::Xmm w = ctx.reg_alloc.UseXmm(args[2]);
|
||||
|
||||
// x64 expects:
|
||||
// 3 2 1 0
|
||||
// src1 = c d g h
|
||||
// src2 = a b e f
|
||||
// xmm0 = - - wk1 wk0
|
||||
|
||||
code.movaps(xmm0, y);
|
||||
code.shufps(xmm0, x, 0b10111011); // src1
|
||||
code.shufps(y, x, 0b00010001); // src2
|
||||
code.movaps(x, xmm0);
|
||||
|
||||
code.movaps(xmm0, w);
|
||||
code.sha256rnds2(x, y);
|
||||
|
||||
code.punpckhqdq(xmm0, xmm0);
|
||||
code.sha256rnds2(y, x);
|
||||
|
||||
code.shufps(y, x, part1 ? 0b10111011 : 0b00010001);
|
||||
|
||||
ctx.reg_alloc.DefineValue(inst, y);
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::Backend::X64
|
|
@ -46,67 +46,6 @@ IR::U128 SHA1HashUpdate(IREmitter& ir, Vec Vm, Vec Vn, Vec Vd, SHA1HashUpdateFun
|
|||
|
||||
return x;
|
||||
}
|
||||
|
||||
IR::U32 SHAhashSIGMA0(IREmitter& ir, IR::U32 x) {
|
||||
const IR::U32 tmp1 = ir.RotateRight(x, ir.Imm8(2));
|
||||
const IR::U32 tmp2 = ir.RotateRight(x, ir.Imm8(13));
|
||||
const IR::U32 tmp3 = ir.RotateRight(x, ir.Imm8(22));
|
||||
|
||||
return ir.Eor(tmp1, ir.Eor(tmp2, tmp3));
|
||||
}
|
||||
|
||||
IR::U32 SHAhashSIGMA1(IREmitter& ir, IR::U32 x) {
|
||||
const IR::U32 tmp1 = ir.RotateRight(x, ir.Imm8(6));
|
||||
const IR::U32 tmp2 = ir.RotateRight(x, ir.Imm8(11));
|
||||
const IR::U32 tmp3 = ir.RotateRight(x, ir.Imm8(25));
|
||||
|
||||
return ir.Eor(tmp1, ir.Eor(tmp2, tmp3));
|
||||
}
|
||||
|
||||
enum class SHA256HashPart {
|
||||
Part1,
|
||||
Part2
|
||||
};
|
||||
|
||||
IR::U128 SHA256hash(IREmitter& ir, IR::U128 x, IR::U128 y, IR::U128 w, SHA256HashPart part) {
|
||||
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 low_y = ir.VectorGetElement(32, y, 0);
|
||||
const IR::U32 after_low_y = ir.VectorGetElement(32, y, 1);
|
||||
const IR::U32 before_high_y = ir.VectorGetElement(32, y, 2);
|
||||
const IR::U32 high_y = ir.VectorGetElement(32, y, 3);
|
||||
|
||||
const IR::U32 choice = SHAchoose(ir, low_y, after_low_y, before_high_y);
|
||||
const IR::U32 majority = SHAmajority(ir, low_x, after_low_x, before_high_x);
|
||||
|
||||
const IR::U32 t = [&] {
|
||||
const IR::U32 w_element = ir.VectorGetElement(32, w, i);
|
||||
const IR::U32 sig = SHAhashSIGMA1(ir, low_y);
|
||||
|
||||
return ir.Add(high_y, ir.Add(sig, ir.Add(choice, w_element)));
|
||||
}();
|
||||
|
||||
const IR::U32 new_low_x = ir.Add(t, ir.Add(SHAhashSIGMA0(ir, low_x), majority));
|
||||
const IR::U32 new_low_y = ir.Add(t, high_x);
|
||||
|
||||
// Shuffle all words left by 1 element: [3, 2, 1, 0] -> [2, 1, 0, 3]
|
||||
const IR::U128 shuffled_x = ir.VectorShuffleWords(x, 0b10010011);
|
||||
const IR::U128 shuffled_y = ir.VectorShuffleWords(y, 0b10010011);
|
||||
|
||||
x = ir.VectorSetElement(32, shuffled_x, 0, new_low_x);
|
||||
y = ir.VectorSetElement(32, shuffled_y, 0, new_low_y);
|
||||
}
|
||||
|
||||
if (part == SHA256HashPart::Part1) {
|
||||
return x;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
bool TranslatorVisitor::SHA1C(Vec Vm, Vec Vn, Vec Vd) {
|
||||
|
@ -247,13 +186,13 @@ bool TranslatorVisitor::SHA256SU1(Vec Vm, Vec Vn, Vec Vd) {
|
|||
}
|
||||
|
||||
bool TranslatorVisitor::SHA256H(Vec Vm, Vec Vn, Vec Vd) {
|
||||
const IR::U128 result = SHA256hash(ir, ir.GetQ(Vd), ir.GetQ(Vn), ir.GetQ(Vm), SHA256HashPart::Part1);
|
||||
const IR::U128 result = ir.SHA256Hash(ir.GetQ(Vd), ir.GetQ(Vn), ir.GetQ(Vm), true);
|
||||
ir.SetQ(Vd, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::SHA256H2(Vec Vm, Vec Vn, Vec Vd) {
|
||||
const IR::U128 result = SHA256hash(ir, ir.GetQ(Vn), ir.GetQ(Vd), ir.GetQ(Vm), SHA256HashPart::Part2);
|
||||
const IR::U128 result = ir.SHA256Hash(ir.GetQ(Vn), ir.GetQ(Vd), ir.GetQ(Vm), false);
|
||||
ir.SetQ(Vd, result);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -903,6 +903,10 @@ U8 IREmitter::SM4AccessSubstitutionBox(const U8& a) {
|
|||
return Inst<U8>(Opcode::SM4AccessSubstitutionBox, a);
|
||||
}
|
||||
|
||||
U128 IREmitter::SHA256Hash(const U128& x, const U128& y, const U128& w, bool part1) {
|
||||
return Inst<U128>(Opcode::SHA256Hash, x, y, w, Imm1(part1));
|
||||
}
|
||||
|
||||
UAny IREmitter::VectorGetElement(size_t esize, const U128& a, size_t index) {
|
||||
ASSERT_MSG(esize * index < 128, "Invalid index");
|
||||
switch (esize) {
|
||||
|
|
|
@ -236,6 +236,8 @@ public:
|
|||
|
||||
U8 SM4AccessSubstitutionBox(const U8& a);
|
||||
|
||||
U128 SHA256Hash(const U128& x, const U128& y, const U128& w, bool part1);
|
||||
|
||||
UAny VectorGetElement(size_t esize, const U128& a, size_t index);
|
||||
U128 VectorSetElement(size_t esize, const U128& a, size_t index, const UAny& elem);
|
||||
U128 VectorAbs(size_t esize, const U128& a);
|
||||
|
|
|
@ -272,6 +272,9 @@ OPCODE(AESMixColumns, U128, U128
|
|||
// SM4 instructions
|
||||
OPCODE(SM4AccessSubstitutionBox, U8, U8 )
|
||||
|
||||
// SHA instructions
|
||||
OPCODE(SHA256Hash, U128, U128, U128, U128, U1 )
|
||||
|
||||
// Vector instructions
|
||||
OPCODE(VectorGetElement8, U8, U128, U8 )
|
||||
OPCODE(VectorGetElement16, U16, U128, U8 )
|
||||
|
|
Loading…
Reference in a new issue