From 14d3d72aac6ea6c42d15e050f668896df5885e57 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Mon, 2 Apr 2018 21:52:46 +0100 Subject: [PATCH] IR: Implement VectorExtract, VectorExtractLower IR instructions --- src/backend_x64/emit_x64_vector.cpp | 32 +++++++++++++++++++++++++++++ src/frontend/ir/ir_emitter.cpp | 10 +++++++++ src/frontend/ir/ir_emitter.h | 2 ++ src/frontend/ir/opcodes.inc | 2 ++ 4 files changed, 46 insertions(+) diff --git a/src/backend_x64/emit_x64_vector.cpp b/src/backend_x64/emit_x64_vector.cpp index f21af1da..ac3db0c7 100644 --- a/src/backend_x64/emit_x64_vector.cpp +++ b/src/backend_x64/emit_x64_vector.cpp @@ -487,6 +487,38 @@ void EmitX64::EmitVectorEqual128(EmitContext& ctx, IR::Inst* inst) { } } +void EmitX64::EmitVectorExtract(EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + + const Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(args[0]); + const Xbyak::Xmm xmm_b = ctx.reg_alloc.UseScratchXmm(args[1]); + + const u8 position = args[2].GetImmediateU8(); + ASSERT(position % 8 == 0); + + code.psrldq(xmm_a, position / 8); + code.pslldq(xmm_b, (128 - position) / 8); + code.por(xmm_a, xmm_b); + + ctx.reg_alloc.DefineValue(inst, xmm_a); +} + +void EmitX64::EmitVectorExtractLower(EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + + const Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(args[0]); + const Xbyak::Xmm xmm_b = ctx.reg_alloc.UseScratchXmm(args[1]); + + const u8 position = args[2].GetImmediateU8(); + ASSERT(position % 8 == 0); + + code.psrldq(xmm_a, position / 8); + code.pslldq(xmm_b, (64 - position) / 8); + code.por(xmm_a, xmm_b); + + ctx.reg_alloc.DefineValue(inst, xmm_a); +} + void EmitX64::EmitVectorGreaterS8(EmitContext& ctx, IR::Inst* inst) { EmitVectorOperation(code, ctx, inst, &Xbyak::CodeGenerator::pcmpgtb); } diff --git a/src/frontend/ir/ir_emitter.cpp b/src/frontend/ir/ir_emitter.cpp index 5a6173bf..748bc557 100644 --- a/src/frontend/ir/ir_emitter.cpp +++ b/src/frontend/ir/ir_emitter.cpp @@ -872,6 +872,16 @@ U128 IREmitter::VectorEqual(size_t esize, const U128& a, const U128& b) { return {}; } +U128 IREmitter::VectorExtract(const U128& a, const U128& b, size_t position) { + ASSERT(position <= 128); + return Inst(Opcode::VectorExtract, a, b, Imm8(static_cast(position))); +} + +U128 IREmitter::VectorExtractLower(const U128& a, const U128& b, size_t position) { + ASSERT(position <= 64); + return Inst(Opcode::VectorExtractLower, a, b, Imm8(static_cast(position))); +} + U128 IREmitter::VectorGreaterSigned(size_t esize, const U128& a, const U128& b) { switch (esize) { case 8: diff --git a/src/frontend/ir/ir_emitter.h b/src/frontend/ir/ir_emitter.h index 783d4ea5..e965bee8 100644 --- a/src/frontend/ir/ir_emitter.h +++ b/src/frontend/ir/ir_emitter.h @@ -215,6 +215,8 @@ public: U128 VectorBroadcastLower(size_t esize, const UAny& a); U128 VectorEor(const U128& a, const U128& b); U128 VectorEqual(size_t esize, const U128& a, const U128& b); + U128 VectorExtract(const U128& a, const U128& b, size_t position); + U128 VectorExtractLower(const U128& a, const U128& b, size_t position); U128 VectorGreaterEqualSigned(size_t esize, const U128& a, const U128& b); U128 VectorGreaterEqualUnsigned(size_t esize, const U128& a, const U128& b); U128 VectorGreaterSigned(size_t esize, const U128& a, const U128& b); diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index 8eb1498c..30bfb532 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -233,6 +233,8 @@ OPCODE(VectorEqual16, T::U128, T::U128, T::U OPCODE(VectorEqual32, T::U128, T::U128, T::U128 ) OPCODE(VectorEqual64, T::U128, T::U128, T::U128 ) OPCODE(VectorEqual128, T::U128, T::U128, T::U128 ) +OPCODE(VectorExtract, T::U128, T::U128, T::U128, T::U8 ) +OPCODE(VectorExtractLower, T::U128, T::U128, T::U128, T::U8 ) OPCODE(VectorGreaterS8, T::U128, T::U128, T::U128 ) OPCODE(VectorGreaterS16, T::U128, T::U128, T::U128 ) OPCODE(VectorGreaterS32, T::U128, T::U128, T::U128 )