diff --git a/src/backend_x64/emit_x64_vector.cpp b/src/backend_x64/emit_x64_vector.cpp index 65ce3043..6dd49336 100644 --- a/src/backend_x64/emit_x64_vector.cpp +++ b/src/backend_x64/emit_x64_vector.cpp @@ -1276,6 +1276,49 @@ void EmitX64::EmitVectorPopulationCount(EmitContext& ctx, IR::Inst* inst) { }); } +void EmitX64::EmitVectorReverseBits(EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + + const Xbyak::Xmm data = ctx.reg_alloc.UseScratchXmm(args[0]); + const Xbyak::Xmm high_nibble_reg = ctx.reg_alloc.ScratchXmm(); + + code.movdqa(high_nibble_reg, code.MConst(xword, 0xF0F0F0F0F0F0F0F0, 0xF0F0F0F0F0F0F0F0)); + code.pand(high_nibble_reg, data); + code.pxor(data, high_nibble_reg); + code.psrld(high_nibble_reg, 4); + + if (code.DoesCpuSupport(Xbyak::util::Cpu::tSSSE3)) { + // High lookup + const Xbyak::Xmm high_reversed_reg = ctx.reg_alloc.ScratchXmm(); + code.movdqa(high_reversed_reg, code.MConst(xword, 0xE060A020C0408000, 0xF070B030D0509010)); + code.pshufb(high_reversed_reg, data); + + // Low lookup (low nibble equivalent of the above) + code.movdqa(data, code.MConst(xword, 0x0E060A020C040800, 0x0F070B030D050901)); + code.pshufb(data, high_nibble_reg); + code.por(data, high_reversed_reg); + } else { + code.pslld(data, 4); + code.por(data, high_nibble_reg); + + code.movdqa(high_nibble_reg, code.MConst(xword, 0xCCCCCCCCCCCCCCCC, 0xCCCCCCCCCCCCCCCC)); + code.pand(high_nibble_reg, data); + code.pxor(data, high_nibble_reg); + code.psrld(high_nibble_reg, 2); + code.pslld(data, 2); + code.por(data, high_nibble_reg); + + code.movdqa(high_nibble_reg, code.MConst(xword, 0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAA)); + code.pand(high_nibble_reg, data); + code.pxor(data, high_nibble_reg); + code.psrld(high_nibble_reg, 1); + code.paddd(data, data); + code.por(data, high_nibble_reg); + } + + ctx.reg_alloc.DefineValue(inst, data); +} + enum class ShuffleType { LowHalfwords, HighHalfwords, diff --git a/src/frontend/ir/ir_emitter.cpp b/src/frontend/ir/ir_emitter.cpp index 13cef6a8..0187cf37 100644 --- a/src/frontend/ir/ir_emitter.cpp +++ b/src/frontend/ir/ir_emitter.cpp @@ -1143,6 +1143,10 @@ U128 IREmitter::VectorPopulationCount(const U128& a) { return Inst(Opcode::VectorPopulationCount, a); } +U128 IREmitter::VectorReverseBits(const U128& a) { + return Inst(Opcode::VectorReverseBits, a); +} + U128 IREmitter::VectorShuffleHighHalfwords(const U128& a, u8 mask) { return Inst(Opcode::VectorShuffleHighHalfwords, a, mask); } diff --git a/src/frontend/ir/ir_emitter.h b/src/frontend/ir/ir_emitter.h index 19623624..605aeb32 100644 --- a/src/frontend/ir/ir_emitter.h +++ b/src/frontend/ir/ir_emitter.h @@ -242,6 +242,7 @@ public: U128 VectorPairedAdd(size_t esize, const U128& a, const U128& b); U128 VectorPairedAddLower(size_t esize, const U128& a, const U128& b); U128 VectorPopulationCount(const U128& a); + U128 VectorReverseBits(const U128& a); U128 VectorShuffleHighHalfwords(const U128& a, u8 mask); U128 VectorShuffleLowHalfwords(const U128& a, u8 mask); U128 VectorShuffleWords(const U128& a, u8 mask); diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index 123b6571..ece3c33d 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -296,6 +296,7 @@ OPCODE(VectorPairedAdd16, T::U128, T::U128, T::U OPCODE(VectorPairedAdd32, T::U128, T::U128, T::U128 ) OPCODE(VectorPairedAdd64, T::U128, T::U128, T::U128 ) OPCODE(VectorPopulationCount, T::U128, T::U128 ) +OPCODE(VectorReverseBits, T::U128, T::U128 ) OPCODE(VectorShuffleHighHalfwords, T::U128, T::U128, T::U8 ) OPCODE(VectorShuffleLowHalfwords, T::U128, T::U128, T::U8 ) OPCODE(VectorShuffleWords, T::U128, T::U128, T::U8 )